Guien a un novato en Overflow en Linux

Iniciado por Glaas2, 25 Septiembre 2013, 01:01 AM

0 Miembros y 1 Visitante están viendo este tema.

Glaas2

Bueno, seré breve... Estoy comenzando con estos temas de seguridad,
me metí a un "taller" en mi escuela llamado "Buffer Overflow" y me han dejado que de un programa dado
(que al ejecutarse siempre sale "fail...") con el debugger de linux, saque el mensaje "win!"...
pero soy un principiante en todo esto y no se por donde ir...

Obviamente no quiero la respuesta, ya que perderia todo sentido, solo quiero un poco de guia...
sin más les postearé el volcado que me da el debugger... pero de ahí en fuera no se que más hacer...
Por su ayuda, gracias.

(gdb) set disassembly-flavor intel
(gdb) disas main
Dump of assembler code for function main:
   0x080483fc <+0>:    push   ebp
   0x080483fd <+1>:    mov    ebp,esp
   0x080483ff <+3>:    and    esp,0xfffffff0
   0x08048402 <+6>:    cmp    DWORD PTR [ebp+0x8],0x3
   0x08048406 <+10>:    jne    0x804840f <main+19>
   0x08048408 <+12>:    call   0x80483d4 <win>
   0x0804840d <+17>:    jmp    0x8048414 <main+24>
   0x0804840f <+19>:    call   0x80483e8 <fail>
   0x08048414 <+24>:    mov    eax,0x0
   0x08048419 <+29>:    leave 
   0x0804841a <+30>:    ret   
End of assembler dump.
(gdb) disas win
Dump of assembler code for function win:
   0x080483d4 <+0>:    push   ebp
   0x080483d5 <+1>:    mov    ebp,esp
   0x080483d7 <+3>:    sub    esp,0x18
   0x080483da <+6>:    mov    DWORD PTR [esp],0x80484f0
   0x080483e1 <+13>:    call   0x80482f0 <puts@plt>
   0x080483e6 <+18>:    leave 
   0x080483e7 <+19>:    ret   
End of assembler dump.
(gdb) disas fail
Dump of assembler code for function fail:
   0x080483e8 <+0>:    push   ebp
   0x080483e9 <+1>:    mov    ebp,esp
   0x080483eb <+3>:    sub    esp,0x18
   0x080483ee <+6>:    mov    DWORD PTR [esp],0x80484f5
   0x080483f5 <+13>:    call   0x80482f0 <puts@plt>
   0x080483fa <+18>:    leave 
   0x080483fb <+19>:    ret   
End of assembler dump.


EDIT: Actualización: De alguna manera... no se por qué ni como... pero pude lograr sacar el mensaje de "win!" ... simplemente corriendo el comando
"run 1 1" ... pero no se si esto sea lo que debía hacer y no se por qué salio... :S , disculpas por preguntar cosas tan "triviales"

MCKSys Argentina

El jne de 0x08048406 es quien decide el flujo de ejecucion del programa.

El valor del flag que determina el salto se establece en la instruccion anterior: 0x08048402 (el cmp)

Y con eso ya sabes como hacer para que salga el win!

Saludos!
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


.:UND3R:.

¿Podrías subir el programa por favor, para poder mirarlo más de cerca?, saludos.

Solicitudes de crack, keygen, serial solo a través de mensajes privados (PM)

tincopasan

no sé de que programa estás hablando y menos en linux, pero supongo que en la comparación busca que el valor ingresado sea de 3 caracteres o más por lo de "Buffer Overflow", desbordamiento de pila, probá cambiando los parametros pasados y anda viendo que hace, se supone q sería más un exploit que un reverse en si.
Por supuesto puedo estar totalmente equivocado.

Glaas2

Bueno, he logrado sacar el mensaje de win pasandole 2 argumentos (./lol 1 1) solo funciona con 2, no con 1 ni con 3... supongo que es porque tiene 2 funciones? (Win/Fail) ? el programa lo subo, pero no tengo el codigo fuente, ya que ese es el chiste... pero aqui se los pongo (es para Linux 32 bits)

Y referente a la instruccion and    esp,0xfffffff0 para que sirve? porque tengo entendido que lo comun es que tenga un sub no?...

El programa http://www.mediafire.com/?w8hlhehm2yd3hrk

MCKSys Argentina

Al hacer and esp,0xfffffff0 lo que logra es poner el byte de menor peso de ESP en 0.
MCKSys Argentina

"Si piensas que algo está bien sólo porque todo el mundo lo cree, no estás pensando."


.:UND3R:.

#6
Bienvenidos sean los crackmes de linux (me estoy iniciando en linux y estos me vendrán muy bien, por lo que tengas o no dudas, te pediría que los fueras subiendo, así todos vamos aprendiendo).

Iré escribiendo el tutorial online (ya no tengo mucho tiempo como solía tenerlo):

Antes que todo verificamos información del archivo:
Citarroot@kali:~/Desktop# file lol
lol: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.24, BuildID[sha1]=0x05972cc870c77c1b1a71f65e1696b480b725a32e, not stripped

- Nos muestra que posee librerías dinámicas (estas no están dentro del ejecutable por lo que llama las del sistema).
- Nos dice que el ejecutable es not stripped (posee los símbolos del programa, no ha pasado por el programa strip).

Verificamos las strings y las direcciones de estas:
Citarroot@kali:~/Desktop# strings -t x lol
   154 /lib/ld-linux.so.2
   21d __gmon_start__
   22c libc.so.6
   236 _IO_stdin_used
   245 puts
   24a __libc_start_main
   25c GLIBC_2.0
   328 PTRh
   420 UWVS
   47c [^_]
   4f0 Win!
   4f5 Fail...
   57b ;*2$"

Ya que el ejecutable está linkeado (enlazado) de forma dinámica, procederemos a la utilización de ltrace, el cual nos mostrará las llamadas a las funciones:
Citarroot@kali:~/Desktop# ltrace -i ./lol
[0x8048341] __libc_start_main(0x80483fc, 1, 0xbfc80fa4, 0x8048420, 0x8048490 <unfinished ...>
[0x80483fa] puts("Fail..."Fail...
)                      = 8
[0xffffffff] +++ exited (status 0) +++

Usamos readelf para obtener el Entry Point:
Citarroot@kali:~/Desktop# readelf -l lol

Elf file type is EXEC (Executable file)
Entry point 0x8048320

Generamos un desensamblado del ejecutable:
Citarobjdump -M intel -d lol > objdump.txt

Recopilamos siguiente información:08048320 <_start>:
Citar8048320:   31 ed                   xor    ebp,ebp
8048322:   5e                      pop    esi
8048323:   89 e1                   mov    ecx,esp
8048325:   83 e4 f0                and    esp,0xfffffff0
8048328:   50                      push   eax
8048329:   54                      push   esp
804832a:   52                      push   edx
804832b:   68 90 84 04 08          push   0x8048490
8048330:   68 20 84 04 08          push   0x8048420
8048335:   51                      push   ecx
8048336:   56                      push   esi
8048337:   68 fc 83 04 08          push   0x80483fc
804833c:   e8 cf ff ff ff          call   8048310 <__libc_start_main@plt>

Si buscamos información sobre __libc_start_main, obtendremos:
Citarint __libc_start_main(int (*main) (int, char * *, char * *), int argc, char * * ubp_av, void (*init) (void), void (*fini) (void), void (*rtld_fini) (void), void (* stack_end));

Debido a que se realiza una llamada a una función con convención C, los parámetros son empujados en orden inverso, por lo cual podemos deducir que:
Citar8048337:   68 fc 83 04 08          push   0x80483fc
Es la dirección en donde se encuentra la función main(), la cual es donde generalmente se comienza a escribir código (por parte del programador). Si verificamos su contenido:
080483fc <main>:
80483fc:   55                              push   ebp
80483fd:   89 e5                   mov    ebp,esp
80483ff:   83 e4 f0                and    esp,0xfffffff0
8048402:   83 7d 08 03             cmp    DWORD PTR [ebp+0x8],0x3
8048406:   75 07                   jne    804840f <main+0x13>
8048408:   e8 c7 ff ff ff          call   80483d4 <win>
804840d:   eb 05                   jmp    8048414 <main+0x18>
804840f:   e8 d4 ff ff ff          call   80483e8 <fail>
8048414:   b8 00 00 00 00          mov    eax,0x0
8048419:   c9                              leave  
804841a:   c3                              ret

Se compara el segundo parámetro recibido, desde __libc_start_main por main(), si verificamos es un:
Citar8048336:   56                      push   esi

El cual contiene la cantidad de argumentos recibidos + 1.

Por lo cual la solución es poner dos argumentos.

PD: No recuerdo por que se contaban como 3, si alguien me puede recordar, se lo agradecería.

EDIT: Es el número de argumentos + 1, debido a:

int main (int argc, char *argv)

donde argc = contador de argumentos
*argv (puntero a un arreglo tipo char)
argv[0]=Nombre del ejecutable.
argv[1]=Parámetro 1.
argv[2]=Parámetro 2.
.....
..
.

Por lo cual argc sin parámetros, contendrá el valor 1, con un parámetro 2, con dos parámetros argc 3

Solicitudes de crack, keygen, serial solo a través de mensajes privados (PM)

Glaas2

Muchisimas gracias por tu ayuda .:UND3R:. no sabía nada de eso haha, excepto a ver el volcado en ASM... No comprendi todo pero si algo... y pues lo demás lo investigaré que para eso estoy aprendiendo... y los programas con mucho gusto los subire cada que nos den uno... Esta semana no se presentó el que da ese curso... veremos la siguiente semana... Muchas gracias de nuevo :D

.:UND3R:.

No te preocupes, para eso estamos. Si tienes dudas pregunta acá no es necesario andar indagando, saludos.

Solicitudes de crack, keygen, serial solo a través de mensajes privados (PM)