Reto CTF Exploiting 2019

Exploiting.cl
Apr 8, 2019 · 7 min read

Primero que todo verificamos las protecciones que tiene el binario utilizando Process Hacker u otro a gusto del usuario, podemos observar que no existe nada DEP y ASLR Disable para el binario así que no tendremos problemas.

Image for post
Image for post
protecciones

Ahora como el binario necesita a exploiting.dll para su ejecución ponemos en análisis esta dll y encontramos una función Prt la cual nos puede servir para encontrá un salto al stack si fuese necesario. Ahora de todas maneras lo revisaremos mas adelante.

Image for post
Image for post
exploiting_dll

Empecemos con el juego, entonces ejecutamos el binario a ver que esta pasando o si el mismo necesita algún ej: (archivo, argumentos, data input, etc).

En la primera ejecución nos muestra el siguiente mensaje “Estas muy cerca de tu bof amigo… pero esto no puede ser si no he hecho nada, bueno sigamos viendo que pasa.

Image for post
Image for post
ejecución_1

Entonces cargamos el binario en un debugger. a partir de aquí vemos que el binario necesita unos argumentos para decidir porque flujo seguir.

Ahora como se puede ver claramente la flecha roja apunta al mensaje que obtuvimos sin hacer nada esto paso porque no utilizar argumentos. no nos sirve 😔.

Image for post
Image for post
argumentos_0

Probemos con un argumento y nos muestra el siguiente mensaje “Ups!! Try Harder amigo…”.

Image for post
Image for post
ejecución_2

Este flujo sigue el camino del primer cuadro morado img:argumento_0 al reconocer un argumento ingresado, donde entra a la funcion _main(char * argu). Aquí nos encontramos con lo siguiente que puede ser interesante, 2 comparaciones de un largo de cadena y una función strcpy() 🤔 prometedor.

Image for post
Image for post
argumento_1

Como ya se observa si el argumento no cumple cierta condición se va por la flecha roja e imprime el mensaje Ups!.

De lo contrario toma el largo de la cadena ingresada y lo compara con 0x5A y luego con 0x63, esto quiere decir que si el largo de la cadena esta entre estos valores podemos llegar a la función strcpy(), Acá se copiando una cadena de largo 90 y 99 bytes a un buffer (IsDebuggerPresents) de tamaño 100 bytes asi que no existe overflow 😔.

Image for post
Image for post
sudoC_argumento_1

Por ahora entendemos que al ingresar un argumento es importante para seguir el flujo pero si volvemos a ver img:argumento_0 nos damos cuenta que necesita 3 argumentos en total.

Si ingresamos 2 argumento nos muestra el mensaje de img:ejecución_1, pero con 3 argumentos cargamos exploiting.dll que utiliza el programa con LoadLibrary() y hace una llamada a Prt() con GetProcAddress(), donde cargara código que utilizaremos mas adelante.

Image for post
Image for post
load_exploiting.dll

Entonces solo nos queda analizar este flujo, si o si va por aquí 😏. Entonces después de cargar la *.dll en memoria esta pasa 2 argumentos argu_1 y argu_2 a una función _atoi(x,x) que claramente no es atoi así que veamos que hace.

Image for post
Image for post
argumentos_2_y_3

Ahora que condiciones deben cumplir estos 2 argumentos pasados a _atoi() para evitar los mensajes molestos de “El curso te espera amigo :)...” y “Vamos tu puedes no te alejes…”.

Primero verifica que el segundo argumento no sea 0, cumpliendo esto se enviá a strchr() para hacer una búsqueda de 0x2E (es igual a “.”) en la cadena. Si ese byte existe llegamos a la funcion _seek() donde se pasa el tercer argumento ingresado, sigamos...

Image for post
Image for post
funcion_atoi()

Ya dentro de _seek() nos encontramos lo siguiente, que el largo del tercer argumento debe ser mayor a 0x64 siendo así entramos a _printf() enviando nuevamente el tercer argumento. De lo contrario veremos un mensaje que dice “Frio Frio…”.

Image for post
Image for post
funcion_seek()

Ahora que estamos en _printf() y esperemos que sea el ultimo flujo 😅. Bueno vemos que el largo del tercer argumento es comparado 0x65, entonces debemos concluir que el tercer argumento debe tener un tamaño mayor 100 y menor a 102. Si este tamaño es mayor entra en un ciclo de 10 vueltas donde imprime un Sending — num*.

Ya cumpliendo todas las condiciones, lo siguiente es super simple, el binario ejecuta un scanf() y espera que el usuario ingrese datos por teclado estos son almacenados en un buffer de tamaño 6000 creado en el heap y luego son imprimido con el mensaje “LOL:AAAAAA…”.

Después este buffer es pasado a otra función strchr() para buscar dentro si contiene un byte 0x2D (es igual “-”). Existiendo esto nos saltamos el mensaje “El curso te espera amigo :)…” y entramos en recta final a un strncpy() el cual no debería ser vulnerable ya que se controla el tamaño a copiar pero bueno esto no siempre es correctamente aplicado.

Que sucede aqui copiamos en un la data obtenida por scanf() en un buffer de 1000 con un tamaño de 1100 strncpy(*buffer, data,1100) despues hacer la copia de los bytes sobreescribimos el retorno 😎.

Image for post
Image for post
funcion_printf()

Como conclusión necesitamos cumplir las siguiente condiciones para llegar el desbordameinto:

  • argu_1 -> ‘a’ (lo que sea)
  • argu_2 -> ‘.’ (condición)
  • argu_3 -> ‘b’ *101 (condición)
  • guion -> ‘-’ (para la data)

Si ejecutamos el script podemos ver que inyectara lo mismo que hice manuelmente.

Image for post
Image for post
manual

Bien si ya tenemos todo solo nos queda crear el exploit. Primero cargaremos unas librerias comunes y seteamos las variables que ya sabemos y lo enviamos como argumento al binario con popen4.

Image for post
Image for post
exploit_parte1

Despues del envio de argumentos enviamos la data que esta esperando scanf().

Image for post
Image for post
exploit_parte2

Despues de la ejecucion vemos que el retorno esta pisado con A’s, lo podemos observar en el stack y dump de memoria, ahora nos queda buscar algo para poder saltar al inicio del stack.

Image for post
Image for post
crash

El siguiente paso sera encontrar el offset exacto el cual pisa el retorno y para eso utilizaremos un pattern especialmente uno propio.

create_pattern

Ya podemos ver que el retorno fue pisado con 0x326A4231 donde lo calculamos con la tool y obtendremos el valor exacto de 1055 para llegar donde queremos que es EIP.

Image for post
Image for post
eip
Image for post
Image for post
offset_pattern

Solo no quedabuscar un salto tipico como jmp, call o un retn al registro de ESP, para ello veremos las protecciones de los modulos. Vemos que el binario y la dll no estan protegidas asi que usaremos la dll y no el binario para saltar ASLR ya que le binario contiene nullbyte y no estamos con un exploit unicode.

Image for post
Image for post
modulos

Pero como pudimos ver al inicio cuando analizamos exploiting.dll encontramos un jmp esp en la dirección 0x6D881457 en la función _Prt(). Usaremos esta direccion para pisar el retorno, modificando el flujo para que nos lleve de vuelta al stack donde pondremos nuestra shellcode quedando de la siguiente manera.

Image for post
Image for post
exploit_parte3
Image for post
Image for post
control_retorno

Ya tenemos el control y todo pero nos encontramos con un pequeño problema que es facilmente solucionable. Cual es este problema?

Tenemos poco estapacio de memoria donde caemos despues del retorno por eso necesitamos alinear un poco la parte alta del stack con el registro ESP.

para esto hay muchas formas de hacerlo pero en esta ocacion utilizaremos un sub esp, *?* para que decremente la direccion de ESP y asi suba al inicio del buffer y luego hacemos una llamada a ESP con un call ESP o un jmp ESP.

Image for post
Image for post
control_buffer

El exploit quedara de la siguiente manera, entonces cuando lo ejecutamos nos detenemos en el salto ESP para validar la resta.

Image for post
Image for post
exploit_parte4

Entes de la resta.

Image for post
Image for post
alineacion_esp1

Despues de la resta fijarse en el registro ESP donde queda apuntando ahora tenemos 0x1f7 que son 503 bytes para poner nuestra shellcode 😎.

Image for post
Image for post
alineacion_esp2

Ya nos queda la parte final y solo es validar los badchar con un simple array para saber cual es permitido o del gusto del binario.

Image for post
Image for post
badchar

Como resultado obtenemos estos byte malos ‘\x00\x20\x1a\x09\x0a\x0c\x0d\x0b’, ahora queda lo facil crear una shellcode con metasploit filtrando estos bytes o simplemente crear una shellcode de forma manual e ir jugando con las codificaciones xor como las tipicas shellcode polimórficos.

Image for post
Image for post
Ejecucion_final_exploit

Exploit:

https://github.com/s1kr10s/Reto-CTF-Exploiting-2019

www.exploiting.cl By Miguel Méndez Z.

By3…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store