martes, 1 de abril de 2014

Un pequeño desafío - La solución (y II)

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.

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
.
.
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