Obtener argumentos pasados al programa

Iniciado por ivancea96, 29 Marzo 2014, 14:13 PM

0 Miembros y 2 Visitantes están viendo este tema.

ivancea96

Hola, tengo la duda de cómo conseguir los argumentos pasados al programa.
La cantidad de argumentos, seguido de la ruta del programa y de las demás cadenas.
Tenía entendido que se almacenaban en el stack, pero ahí no los ví, así que pregunto por aquí :3

PD: Uso FASM

Eternal Idol

¿S.O.? Para Windows llama a GetCommandLine y extrae los parametros de la cadena devuelta.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

ivancea96

Okay, thanks. Pensé que se podría hacer sin la API de windows. Pero veo que hay mucho monopolio jaja

cpu2

Pues claro que se puede hacer sin la API, si es cierto esta en el stack pero en la parte superior, yo en el primer pop sin tocar la pila me dice los numeros de parametros que pase en la shell.

ktrace ./prueba parametro

Código (asm) [Seleccionar]
popq %rdi
incl %eax
syscall


Obtendria 0x2, en rdi.

Si sigo augmentando en la pila vere las cadenas las rutas y los parametros.

Código (asm) [Seleccionar]
movq 8(%rsp), %rdi
movq (%rdi), %rdi   ; piensa que es un puntero


Depende de los bytes que quiera imprimir la cadena sera mas extensa o no, por cierto todo esto esta probado en unix-like, no se si te valdra para Windows creo que si.

Un saludo.

ivancea96

Había hecho pruebas, pero en la pila no encontré el número de parámetros, ni tampoco las cadenas. Eché un vistazo a la pila con el OllyDBG, y tampoco encontré nada. No se. Yo uso Win7, pero no creo que tenga que ver con eso.

Por cierto, veo que usas el registro DI. Tengo entendido que es el "índice de destino", y que tiene un par de instrucciones especiales que solo funcionan con él y con SI.
¿Se pueden usar como si fueran registros generales? ¿O hay alguna pega?

:3 thx

Eternal Idol

Cita de: cpu2 en 29 Marzo 2014, 18:33 PMPues claro que se puede hacer sin la API, si es cierto esta en el stack ... en unix-like, no se si te valdra para Windows creo que si.

No, no lo esta, por eso pregunte para que S.O. era, si escribis un programa en C/C++ podras ver como la RTL se encarga de llamar a GetCommandLine y parsear la cadena para obtener argc y argv.

ivancea96: no pierdas el tiempo.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

cpu2

@Eternal Idol

Simplemente pense que se podrian conseguir esos valores igual que en sistemas Unix-like, error mio, tampoco lo veo una perdida de tiempo saber como funcionan las cosas sin llamar a una API.

@ivancea96

Y bueno sobre lo que preguntas sobre el registro DI, utilizo DI porque es el primer parametro para pasar los valores a las syscall de sistemas Unix-like, claro DI no deja de ser un registro de general purpose, DI y SI estan enlazados por instrucciones para mover cadenas ejemplo movs etc...

Un saludo.

Eternal Idol

#7
Cita de: cpu2 en 29 Marzo 2014, 20:33 PMSimplemente pense que se podrian conseguir esos valores igual que en sistemas Unix-like, error mio, tampoco lo veo una perdida de tiempo saber como funcionan las cosas sin llamar a una API.

No, perder el tiempo seria continuar buscando en la pila lo que no esta ella, por eso se lo dije a otra persona y no a vos. Saber como funcionan la cosas es muy util, nadie dijo lo contrario. La linea de comandos esta en el PEB (Process Environment Block).

0:000> u kernel32!getcommandlinew
kernel32!GetCommandLineW:
00000000`775ac428 ff25ea160800    jmp     qword ptr [kernel32!_imp_GetCommandLineW (00000000`7762db18)]

0:000> u poi(7762db18)
KERNELBASE!GetCommandLineW:
000007fe`fd5ecb70 488b05713b0500  mov     rax,qword ptr [KERNELBASE!BaseUnicodeCommandLine+0x8 (000007fe`fd6406e8)]
000007fe`fd5ecb77 c3              ret

0:000> du poi(000007fe`fd6406e8)
00000000`003034ac  "C:\Windows\System32\calc.exe"

0:000> !peb
PEB at 000007fffffdf000
....

0:000> dt ntdll!_PEB 000007fffffdf000
  +0x000 InheritedAddressSpace : 0 ''
  +0x001 ReadImageFileExecOptions : 0 ''
  +0x002 BeingDebugged    : 0x1 ''
  +0x003 BitField         : 0x8 ''
  +0x003 ImageUsesLargePages : 0y0
  +0x003 IsProtectedProcess : 0y0
  +0x003 IsLegacyProcess  : 0y0
  +0x003 IsImageDynamicallyRelocated : 0y1
  +0x003 SkipPatchingUser32Forwarders : 0y0
  +0x003 SpareBits        : 0y000
  +0x008 Mutant           : 0xffffffff`ffffffff Void
  +0x010 ImageBaseAddress : 0x00000000`ff170000 Void
  +0x018 Ldr              : 0x00000000`777e2640 _PEB_LDR_DATA
  +0x020 ProcessParameters : 0x00000000`00302690 _RTL_USER_PROCESS_PARAMETERS
.....


0:000> dt -b ntdll!_RTL_USER_PROCESS_PARAMETERS CommandLine. 0x00000000`00302690
  +0x070 CommandLine  :  "C:\Windows\System32\calc.exe"
     +0x000 Length       : 0x38
     +0x002 MaximumLength : 0x3a
     +0x008 Buffer       : 0x00000000`003034ac  "C:\Windows\System32\calc.exe"

De yapa, sabiendo lo anterior y como obtener el PEB se puede obtener la linea de comandos sin API en x64:

0:000> u ntdll!RtlGetCurrentPeb
ntdll!RtlGetCurrentPeb:
00000000`77760600 65488b042530000000 mov   rax,qword ptr gs:[30h]
00000000`77760609 488b4060        mov     rax,qword ptr [rax+60h]
00000000`7776060d c3              ret

Eso si, el PEB podria cambiar en cualquier momento como dice la documentacion. Por eso mejor usar la simple API en este caso.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón

Danyfirex

Hola. otra cosa que podrías hacer es usar CommandLineToArgv y obtener pNumArgs.


Saludos

Eternal Idol

Con CommandLineToArgvW (no hay version ANSI) obtenes los argc (pNumArgs) y argv (eax) de C/C++ pero a esa funcion igual le tenes que pasar la linea de comandos, es un complemento no una alternativa.
La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón