En el anterior post ya dejamos confeccionado el exploit aunque avisaba de que todavía no estaba listo y que quedaba ajustes técnicos.
Estos ajustes tienen más que ver la técnica de programación de shellcodes que con la lógica del exploit.
Estos ajustes tienen más que ver la técnica de programación de shellcodes que con la lógica del exploit.
Malditos ceros binarios
En el código que desarrollamos en la primera parte ya tuvimos que realizar algo que parecía sin sentido pero necesario que era el conocimiento de la ubicación de nuestro programa en memoria.
call ubica1
ubica1:
pop ebx
ubica1:
pop ebx
.
.
Con estas tres líneas lográbamos llevar al registro ebx la dirección de la instrucción pop ebx y por lo tanto donde esta nuestro programa.
Sumando o restando valores a ese registro podríamos colocarnos en cualquier zona de nuestro programa.
Veamos ahora el siguiente problema al que se enfrenta un programador de shellcodes.
El código inyectado a través de una vulnerabilidad antes de ser ubicado en la pila será manejado por alguna de las múltiples funciones de manipulación de cadenas de caracteres. Cualquier función de este tipo identifica el fin de la cadena por el cero binario (Null-byte) 0x00.
Si encuentra este carácter en la cadena cortará el exploit y cargará sólo el primer trozo en la pila. Veamos nuestro programa como queda en código máquina
La primera en la frente. Nuestro programa empieza con una preciosa cadena de cuatro ceros binarios, a falta de uno tenemos cuatro.
Como ironía del destino, esos cuatro ceros binarios son la consecuencia de la instrucción call ubica1 que nos hemos vistos obligados a introducir para cargar la ubicación. Veamos como evitarlo.
Existen ciertas combinaciones de instrucciones que son tiene el mismo efecto pero eliminar los ceros binarios como las siguientes:
Instrucción con Null-byte |
Codificación binaria |
Instrucción sin Null-Byte |
Codificación binaria |
mov eax,5 | B8 00000005 | mov al,5 | B0 05 |
call next | E8 00000000 | jmp next/call prev | EB 05/ E8 F9FFFFFF |
cmp eax,0 | 83F8 00 | test eax,eax | 85C0 |
mov eax,0 | B8 00000000 | xor eax,eax | 33C0 |
En nuestro caso nos interesa la segunda instrucción y su alternativa
Nuestro código en su inicio queda así:
jmp next
prev:
pop ebx
jmp ebx
next:
call prev
ubica1
Si se siguen las instrucciones veremos que cuando lleguemos a ubica1 tendremos en el registro ebx el valor de ubica1, que es lo que necesitamos
La siguiente instrucción con null-byte nos la encontramos en el salto a la instrucción que llama a la función system.
La solución en este caso va a ser bastante trivial, pondremos en el shellcode su complementario y sobre este valor dentro del código ejecutaremos la operación NOT para obtener el valor deseado:
mov eax, 0FFBFEF70h
not eax
jmp eax
Ensamblamos el programa y lo arrancamos con ollydbg et voilà.
Ya tenemos nuestro shellcode sin null-byte.
Ejecutando el exploit
En este enlace podéis descarga un fichero comprimido que contiene:
- Fuente del programa a explotar: exploitthis.c
- Ejecutable del programa a explotar: exploitthis.exe (compilado con tinyc)
- Fuente del shellcode: exploitthis2.asm
- Cadena de caracteres maliciosa: test1.txt
- Fichero readme.txt
Para simplificar el trabajo vamos a meter tanto el exploit como la shellcode en un fichero. Para el manejo de datos en hexadecimal yo uso notepad++ que es un editor de texto gratuito muy potente.
Colocamos tanto el inicio del buffer de entrada(entre marcas rojas), la dirección de retorno que sobreescribirá el EIP, (entre marcas verdes), y el payload, (entre marcas azules). Queda así el fichero con la cadena maliciosa:
Solo nos quedaría ejecutar el siguiente comando:
type test1.txt | exploitthis
Y se nos abrirá una ventana de ejecución de comandos
No hay comentarios:
Publicar un comentario