Buenas de nuevo, retomo esto en un "ratillo" que he sacado para ir dándole un poco de contenido al blog.
Hoy nos ponemos con el resto Eat the cake! de HTB, ya que el otro día me calenté e hice un par de retos para ver lo oxidado que estaba... La verdad que bastante! 😑
El fichero os lo podéis bajar directamente de la página, cuyo SHA256:bd2efc7a1b23885d88d401b2a1fa1d4b307f6efcd76ee0a7d9486f0a8b06e586
Bueno vemos a ponernos manos a las obra, es un ejecutable por lo tanto nos iremos a nuestra máquina Windows que tenemos preparada para este tipo de retos, y abrimos el archivo con el software PEiD para ver si esta empaquetado/ofuscado, pero vamos que ya os digo que sí.
Vemos que PEiD nos dice que esta empaquetada con UPX 0.89.6 -1.02 / 1.05 - 2.90 --> Markus & Laszlo.
Intentamos desempaquetar la muestra, usando UPX directamente con "upx -d" y tras desempaquetarlo, comprobamos si se ha hecho de manera correcta, procediendo a su ejecución y esperando a que sea correcta.
Pero al intentar ejecutarlo, vemos que hay algún problema pues el programa no corre con normalidad (vamos un gatillazo en toda regla) .
Echamos un vistazo, sobre cual puede ser el motivo de que el programa no funcione tras desempaquetarse.
Algunos ejecutables, vienen por defecto con el ASLR activo al compilarse y al desempaquetar el paquete puede provocar que el programa deje de funcionar correctamente, para solucionar este problema llamamos a la puerta de un referente en esto del reversing y las "free tools" @Didier Stevens y su programa setdllcharacteristics.
Con este programa primero veremos los flags con los que han sido compilado el programa y luego podemos modificar dichos flags fácilmente, en nuestro caso modificaremos el flag dynamic_Base, la cual pondremos a '0' para desactivar el ASLR.
Vemos que ahora podemos ejecutar el programa sin ningún problema:
Una vez que ya tenemos el programa corriendo, re-nombramos el archivo y lo llamamos cake - copia.exe y lo abrimos con IDA para empezar a investigarlo un poco. Lo primero que hacemos es ver si en las Strings vemos algo interesante, para ahorrarnos bastante trabajo (y así es).
Por lo que vemos esa string sera donde queremos llegar, por lo que vamos a ver donde es llamada en el programa, para ello hacemos doble "click" sobre la string y luego pulsamos "x" sobre ella para ver las referencias a la misma.
y nos encontramos el siguiente fragmento del programa, donde se muestra por pantalla ("printea") dicha string (Donde queremos llegar).
Por lo que ya nos podemos poner a reversear, para ello vamos a ir yendo hacia atrás en el ciclo de ejecución del programa para identificar en que parte el programa hay comparaciones/saltos/Llamadas_a_funciones que nos parezcan interesantes.
Vemos que si subimos un poco mas arriba podemos localizar donde están los mensajes que nos solicitaban al arrancar el programa que era: "Please enter a 10-password input (only number and Letters"). Tras ver la función que "printea" el mensaje, vemos que hay un scanf() y lo que hace es coger la la contraseña que introducimos y comparar su longitud con 0xF(15 en decimal) es decir mientras no insertemos una contraseña de tamaño 15, le da igual y avanza la ejecución, sin embargo si el tamaño es 15 nos muestra un mensaje de error y se sale del programa:
Pasamos ahora a la segunda parte, donde se nos pide introducir una contraseña de 15 caracteres:
Aquí empieza lo interesante, nos vamos a a donde se imprime el segundo mensaje y vemos que tras hacer el scanf() comprueba la longitud con 0xF, y mientras no sea ese valor, se queda en un bucle enganchado pidiendonos la contraseña.
Tras pasarle una entrada de tamaño 15, se llama a la función strncpy() el cual, el software usa para copiar la información que hemos introducido del scanf() en otra posición de la memoria con un tamaño de 400(nos da de sobra).
En ese strncpy() he puesto un breakpoint para depurar el programa e ir viendo las comprobaciones que se han ido haciendo.
En el binario mostrado, la variable "pass_introducida" es un array([]) que he creado yo de tamaño 15, porque he visto que era donde se guardaba la contraseña que estábamos introduciendo, para ello hemos tenido que re-definir algunas variables que IDA había interpretado de forma distinta (tal y como muestran las siguientes imagenes), para que nos sean mas intuitivas.
Antes:
Después:
Una vez tenemos definidas correctamente las variables vamos a ver el desensamblado de IDA, mucho mas sencillo, de hecho gran parte de la contraseña que necesitamos introducir la extraeremos a simple vista.
Obteniendo directamente de las comprobaciones anteriores : h@ck_h__arad_$E
Nos quedan aun por conocer los valores de [pass_introducida + 4], [pass_introducida + 6], [pass_introducida + 7] y [pass_introducida + 0xC].
Para ello "debuggeamos" un poco y nos metemos en una función que he definido previamente como funcion_interesante.
En ella, ponemos un breakpoint al ser llamada y accedemos con un step_into (F7) vemos que el valor del registro ebx="h@ckth3parad1$E" que es la contraseña que hemos puesto de prueba de entrada, y que luego comprobaremos que es tambien password requerida:
Posteriormente, re-definimos ebx como pass_introducida para que nos sea mas fácil seguir analizando el código y vemos que ahí se encuentran el resto de caracteres de la contraseña que nos faltaban:
Hoy nos ponemos con el resto Eat the cake! de HTB, ya que el otro día me calenté e hice un par de retos para ver lo oxidado que estaba... La verdad que bastante! 😑
El fichero os lo podéis bajar directamente de la página, cuyo SHA256:bd2efc7a1b23885d88d401b2a1fa1d4b307f6efcd76ee0a7d9486f0a8b06e586
Vemos que PEiD nos dice que esta empaquetada con UPX 0.89.6 -1.02 / 1.05 - 2.90 --> Markus & Laszlo.
Intentamos desempaquetar la muestra, usando UPX directamente con "upx -d" y tras desempaquetarlo, comprobamos si se ha hecho de manera correcta, procediendo a su ejecución y esperando a que sea correcta.
Echamos un vistazo, sobre cual puede ser el motivo de que el programa no funcione tras desempaquetarse.
Algunos ejecutables, vienen por defecto con el ASLR activo al compilarse y al desempaquetar el paquete puede provocar que el programa deje de funcionar correctamente, para solucionar este problema llamamos a la puerta de un referente en esto del reversing y las "free tools" @Didier Stevens y su programa setdllcharacteristics.
Vemos que ahora podemos ejecutar el programa sin ningún problema:
Por lo que vemos esa string sera donde queremos llegar, por lo que vamos a ver donde es llamada en el programa, para ello hacemos doble "click" sobre la string y luego pulsamos "x" sobre ella para ver las referencias a la misma.
y nos encontramos el siguiente fragmento del programa, donde se muestra por pantalla ("printea") dicha string (Donde queremos llegar).
Por lo que ya nos podemos poner a reversear, para ello vamos a ir yendo hacia atrás en el ciclo de ejecución del programa para identificar en que parte el programa hay comparaciones/saltos/Llamadas_a_funciones que nos parezcan interesantes.
Vemos que si subimos un poco mas arriba podemos localizar donde están los mensajes que nos solicitaban al arrancar el programa que era: "Please enter a 10-password input (only number and Letters"). Tras ver la función que "printea" el mensaje, vemos que hay un scanf() y lo que hace es coger la la contraseña que introducimos y comparar su longitud con 0xF(15 en decimal) es decir mientras no insertemos una contraseña de tamaño 15, le da igual y avanza la ejecución, sin embargo si el tamaño es 15 nos muestra un mensaje de error y se sale del programa:
Pasamos ahora a la segunda parte, donde se nos pide introducir una contraseña de 15 caracteres:
Aquí empieza lo interesante, nos vamos a a donde se imprime el segundo mensaje y vemos que tras hacer el scanf() comprueba la longitud con 0xF, y mientras no sea ese valor, se queda en un bucle enganchado pidiendonos la contraseña.
Tras pasarle una entrada de tamaño 15, se llama a la función strncpy() el cual, el software usa para copiar la información que hemos introducido del scanf() en otra posición de la memoria con un tamaño de 400(nos da de sobra).
En el binario mostrado, la variable "pass_introducida" es un array([]) que he creado yo de tamaño 15, porque he visto que era donde se guardaba la contraseña que estábamos introduciendo, para ello hemos tenido que re-definir algunas variables que IDA había interpretado de forma distinta (tal y como muestran las siguientes imagenes), para que nos sean mas intuitivas.
Antes:
Después:
Obteniendo directamente de las comprobaciones anteriores : h@ck_h__arad_$E
Nos quedan aun por conocer los valores de [pass_introducida + 4], [pass_introducida + 6], [pass_introducida + 7] y [pass_introducida + 0xC].
Para ello "debuggeamos" un poco y nos metemos en una función que he definido previamente como funcion_interesante.
En ella, ponemos un breakpoint al ser llamada y accedemos con un step_into (F7) vemos que el valor del registro ebx="h@ckth3parad1$E" que es la contraseña que hemos puesto de prueba de entrada, y que luego comprobaremos que es tambien password requerida:
Posteriormente, re-definimos ebx como pass_introducida para que nos sea mas fácil seguir analizando el código y vemos que ahí se encuentran el resto de caracteres de la contraseña que nos faltaban:
Obteniendo la contraseña: h@ckth3parad1$E y comprobamos que es correcta.
Un saludo peludo!
Comentarios
Publicar un comentario