CLABE Finder (Pwn 100)

By @hextupid

Descripcion:


Hay un servicio corriendo en el servidor del Banco, no sabemos que hace pero 
nuestro contacto interno encontro el binario que se ejecuta, 
desafortunadamente no pudo conseguir el codigo fuente.

Hazle ingenieria inversa, y trata de encontrar una vulnerabilidad que nos de 
una shell remota!

Aquí los detalles de conexión:

> IP: 70.37.x.x  Port: 1560



Iniciamos ejecutando el binario de manera normal. Podemos ver que nos muestra un mensaje en binario (01100100 01101001 01110000 01110101 01110100), el cual traducido a ASCII dice “diput”. Esto no nos aporta nada.

Adicional al mensaje anterior, el programa solicita que ingresemos una CLABE para buscar. Si ingresamos una cadena inválida, obtendremos el mensaje “:’v”.


Si revisamos los mecanismos de protección habilitados, veremos que no cuenta con algunos de ellos. Esto nos será útil más tarde.





Comenzando con la ingeniería inversa, podemos ver que existen algunas funciones interesantes como:



De esas funciones, vemos que fake es falsa y solo sirve para despistar. Parece que se trata de un reto troll.



Observamos que si ingresamos la cadena “_ITM_deregisterTMCloneTable”, podremos saltar a la función “get_flag” automáticamente.



Lo malo es que al intentarlo, obtendremos una flag falsa. De nuevo siendo troll.


Las siguientes funciones que podrían resultar interesantes, son System y System_old, mismas que son muy similares pero cada una abre un archivo diferente, por lo que podemos asumir que alguno de los dos se trata de la flag verdadera.

Para llegar a System, debemos buscar alguna función que nos lleve a ella, o forzar el retorno de otra función a través de un ataque de buffer overflow.
Analizando la función f_flush vemos que ésta nos lleva a System después de cumplir (o inclumplir) algunas condiciones.
Por ejemplo, se observa que f_flush lleva a cabo dos comparaciones con el carácter 0x69 (i), en caso de ser válida la comparación, se lleva a cabo una segunda comparación con el caracter 0x64 (d). En caso de ser válidas ambas comparaciones, llegaremos a la función “System”.
 



El problema que vemos ahora, es cómo podemos primero llegar a f_flush.
Revisando la función “diput”, vemos que se lleva a cabo una comparación más de una de sus variables, si es diferente de “:”, entonces nos mostrará un mensaje falso de stack smashing detected: recordemos que esta protección no está habilitada realmente. Después de este mensaje, llegaremos a f_flush.



Para esto necesitamos evitar que el registro al, sea diferente al caracter 0x3A (“:”).
Vemos que, en tiempo de ejecución, enviando solo 4 bytes, este valor se mantiene intacto.



Probablemente es momento de intentar un overflow, considerando que el contexto de la función es de 0x30 bytes, podemos intentar enviar esa cantidad de “A”.




Y vemos que funciona, conseguimos sobrescribir el valor:



OPCIÓN 1:

Después de encontrar la posición exacta del carácter (45), solo necesitamos enviar un carácter DISTINTO a “:” para poder llegar a f_flush.­­

Este pequeño exploit nos podría servir para eso:



python -c 'print "A"*44 + "B" + "A" + "id"'

Una vez estando en f_flush, necesitamos una vez más encontrar la posición de los caracteres que nos permitirán llegar a System.  Recordemos dicha logica:




Así que una vez más, sin perder el buffer anterior y de la misma manera que encontramos la posición exacta del carácter, encontraremos la posición de los dos nuevos caracteres (47 y 48).

El siguiente exploit nos podrá llevar a System.

python -c 'print "A"*44 + "B" + "A" + "id"'




Como vemos, esta no es la flag y parece que solo es otro distractor, puesto que el mensaje impreso SIMULA ser la salida del comando “id” de bash, pero recordemos que la función “System” imprimía un archivo, así que, de nuevo es falso.

SIN EMBARGO, vemos que la ejecución del programa termina con un Segmentation fault (core dumped) lo cual nos indica que estamos intentando acceder a un espacio de memoria al cuál no podemos. En pocas palabras, podríamos intentar saltar arbitrariamente a cualquier parte del programa. Esto nos resulta sumamente útil, puesto que no hay ninguna función que llame a System_old.

De esta forma, solo hace falta encontrar la posición del return, y esto se puede hacer fácilmente incrementando el tamaño del buffer hasta lograr sobrescribir la posición donde se almacena la dirección de return de alguna función en el stack. En este caso utilizaremos el return de diput:


python -c 'print "A"*44 + "B" + "A" + "id" + "C"*8 + "\xef\xbe\xad\xde"'

 
Una vez conseguido esto, es trivial el salto a System_old ejecutando el siguiente exploit:

python -c 'print "A"*44 + "B" + "A" + "id" + "C"*8 + "\xbf\x13\x40"'


Y vemos que esta es la verdadera bandera!!!

OPCIÓN 2:

Mantenemos íntegro el carácter “:” para evitar caer en el mensaje de stack smashing detected. Esto se logra reintroduciendo en el buffer el carácter en la posición correcta (45).
Después solo es necesario incrementar el tamaño del buffer hasta poder sobrescribir el return de la función. Esto se logra con 11 caracteres más después del carácter “:”

python -c 'print "A"*44 + ":" + "C"*11 + "\xbf\x13\x40"'


De esta forma se obtiene la flag mas directamente! Sin pasar por la función System ni f_flush.

Versión elegante del exploit:

from pwn import *

context.log_level="debug"
# win @ 40080a

p = process("./CLABEFinder")

p.sendline("A"*44 + ":" + "B"*11 + p32(0x4013BF))

p.interactive()



Comments