© FUOC • PID_00208393 21 Shellcodes
6. La shellcode en ensamblador
Una vez que se conoce la dirección donde se encuentra la función que desea-
mos ejecutar, hay que modificar el código anterior mediante un desborda-
miento para conseguir que el control de programa se entregue a esta dirección
en lugar de a la dirección original de retorno.
El código que queremos que se ejecute, es decir la shellcode, es el que nos per-
mitía llamar a la función de retardo de 5 segundos. Como vimos anteriormen-
te, este código se puede escribir de la siguiente forma:
XOR EAX, EAX
MOV EBX, 0x7c802446
MOV AX, 5000
PUSH EAX
CALL EBX
© FUOC • PID_00208393 22 Shellcodes
7. La shellcode en binario
Para que este código ensamblador se pueda convertir a binario, vamos a compi-
larlo y linkarlo. Para realizar esta tarea podemos utilizar las herramientas nasm
y ld nasm. Con el uso de este conocido compilador de ensamblador vamos a
conseguir generar código máquina a partir del código escrito en ensamblador.
ld nos permitirá linkar el fichero objeto generado por el compilador nasm y
nos generará un fichero ejecutable en binario. Los pasos a realizar serían:
Compilado y linkado de la shellcode
Si se ejecuta el programa que acabamos de crear, veremos que la ejecución
realiza una pausa de 5 segundos y posteriormente termina correctamente.
Una vez generado el programa ejecutable necesitamos obtener el código bina-
rio del programa en hexadecimal. Para realizar esta tarea vamos a hacer uso del
programa objdump, que mostrará las equivalencias entre código hexadecimal
y las instrucciones en ensamblador.
Salida objdump de la shellcode
Este proceso se podría haber realizado también haciendo un sencillo debugging
con Ollydbg o gdb y accediendo al código en hexadecimal del programa. De
esta forma la parte que necesitamos se puede ver fácilmente en _start.
El código en hexadecimal estará formado por:
31 c0
Bb 46 24 80 7c
66 b8 88 13
50
© FUOC • PID_00208393 23 Shellcodes
Ff d3
que, tras situarlo en formato introducible por la entrada, quería como sigue:
\x31\xc0\xbb\x46\x24\x80\x7c\x66\xb8\x88\x13\x50\xff\xd3
© FUOC • PID_00208393 24 Shellcodes
8. El exploit con la shellcode
Para que esta shellcode se pueda ejecutar, hay que conocer en qué dirección
va a ser cargada. Para ello, introducimos la shellcode en el programa en Perl y
vemos con Ollydbg la dirección donde comienza.
Shellcode en memoria
Como se puede ver en la figura "Salida objdump de la shellcode", la shellcode
comienza en la dirección 0x0012FB8C y es ahí donde deberá apuntar la direc-
ción de retorno de la función actual.
Para sobrescribir esa dirección de retorno deberemos saber exactamente cuán-
tas posiciones hay que desbordar la variable. Para ello, con Ollydbg podemos
comprobar la distancia de la variable nombre a la dirección de retorno.
Dirección de retorno en memoria antes y después de ser sobrescrita
Sabemos que la variable nombre comienza en la dirección 0x0012FB8C y aca-
ba en la posición 0x0012FF8C (posición inicial más longitud, 1024). Como se
puede ver en la imagen, la dirección de retorno se encuentra en la posición
© FUOC • PID_00208393 25 Shellcodes
0x12FF90 y ocupa 4 bytes. Por lo tanto, hay que desbordar 8 bytes el valor de
nombre, o sea que deberemos introducir una cadena de 1032 bytes que incluya
la shellcode al principio, y al final, la nueva dirección de retorno de la función.
Ejecución del programa mostrada por OllyDbg
El programa no ha podido ser ejecutado desde la consola de Windows debido
a que ni la dirección de retorno ni la Shell estaban formados por caracteres
ASCII. En un entorno real se crearía un programa que ejecutase la aplicación
vulnerable pasándole como parámetro el argumento desbordado con todo tipo
de caracteres menos el 00, que como se ha comentado anteriormente, es fin
de cadena.
Ejecución de shellcode en memoria
Por último se puede observar cómo se ejecuta correctamente la shellcode desde
OllyDbg.