HackTheBox - Find The Easy Pass (Guía)

Segundo desafío del "Beginner Path" de HackTheBox




En esta ocasión no se trata de una máquina al uso, sino de un reto de ingeniería inversa donde tendremos que hacernos con la contraseña que se encuentra dentro de un binario.


Tenéis el 💀MODO HARDCORE💀 al final del post. No es nada del otro mundo, pero para los que empiezan como yo y siempre han tenido curiosidad por saber "qué es parchear" un .exe, ahí tienen el ejemplo práctico.


Vamos al lío, crackers!


Índice



Reconocimiento



Introducción

Antes de nada, comentaros que para este ejercicio voy a usar como sistema "Commando VM"; una versión de windows modificada por FireEye. Podríamos decir que si hubiera un homólogo de Kali Linux para windows, esto sería lo más parecido, aunque yo por ahora la uso concretamente para hacer ingeniería inversa en binarios para Windows, puede usarse para cualquier tipo de entorno pentesting y es muy efectiva contra ciertos entornos de Microsoft.


Aquí os dejo el enlace al repositorio de Commando VM: https://github.com/fireeye/commando-vm

Como extra, os dejo por aquí REMnux, una distribución Linux muy enfocada al análisis de malware y que viene muy bien para ingenieria inversa.


No obstante, Kali linux o ParrotOS son perfectísimamente capaces de realizar estas tareas. Aunque personalmente prefiero aislar las máquinas que uso para ingeniería inversa (una pequeña manía)


¡Vamos a reventar ese .exe!



Observando el comportamiento del binario

Lo primero que debemos hacer (medidas de seguridad para malware a parte, sabiendo que este no es el caso), es ejecutar el programa para ver cómo se comporta.


Sé que en cuanto tengáis el archivo en vuestras manos, surgirán esos impulsos de ponerse a bichear como locos, pero recordad: Disciplina y Proceso y no habrá reto que se os resista.


Si queremos romper el programa, primero tendremos que saber qué hace ese programa. Así que vamos con ello.


Parece sencillo. Un campo para introducir la contraseña y un botón que comprueba si es correcta.


El resultado nos lo muestra mediante un pequeño pop-up:



Si jugamos un poco con el programa comprobaremos lo siguiente:

  • No tiene límite de longitud en la contraseña

  • Permite un input vacío

  • No tiene más funcionalidades aparentemente que la ya mencionada


Analizando el binario

Lo primero que deberíamos hacer ahora es analizar el binario.


Ghidra va a ser perfecto para todo el trabajo que vamos a tener que hacer, aunque pueda ser un poco overkill, es una herramienta muy buena que me gustaría aprender a usar, así que este es un buen momento para empezar.


Si importamos el binario, veremos algunos datos básicos sobre él:


Vemos que tiene una cantidad de funciones inusualmente grande para un tipo de binario que en principio es sencillo, concretamente 237.


Algo que nos debería también llamar la atención es que tiene pinta de que el lenguaje de programación utilizado es "Pascal". Al menos así nos lo indica el compilador, aunque también podría tratarse de "Delphi" o "Fortran". Esto es algo que más tarde podremos confirmar "parcialmente" cuando busquemos funciones. Si está programado en C/C++, nos encontraremos con la función "main". De lo contrario, se tratará de otro lenguaje



Buscando la pista

Bien, ahora debemos intentar buscar algo que nos indique por dónde empezar a buscar en esta marabunta de código.


Como comenté líneas atrás, vamos a revisar las funciones en busca de un "main":


Parece ser que el lenguaje no es C/C++, así que por este lado no encontraremos nada relevante por ahora.


¿Qué estamos buscando? ¿Qué nos pide el programa? Una "password".


Vamos a ver si encontramos alguna string en la ejecución del código utilizando la palabra que estamos buscando:




Alteración




Localizando funciones


Ahora tenemos que buscar la dirección "00454200" que es la contiene la string que nos salta cuando insertamos la contraseña incorrecta.


En este punto, debemos buscar la función que llama a este trigger de error, porque seguramente sea la misma función que buscamos la que llame al aviso de "contraseña correcta".


Vamos retrocediendo hacia atrás hasta que encontramos la primera función completa, en este caso "LAB_0045514e". Eso nos lleva al árbol de funciones de la parte derecha, donde vemos las 8 funciones de las que se compone el fragmento.


Ahora tenemos que localizar la función que debería encontrarse justo antes de un salto, en este caso un "JNZ" (Jump if not zero):



Rompiendo el proceso

La función "FUN_00404628" localizada en la dirección "00454131" es la que nos da la guía. Por lo que metemos el breakpoint en la dirección de memoria siguiente "00454136". Ahí vemos que la contraseña correcta debe estar en el registro "EBP-4" o "EBP-28".


Si ejecutamos ahora el binario con "x36dbg":


Bingo, ahí tenemos la contraseña errónea que hemos introducido junto a la flag.


💀MODO HARDCORE💀


Y aquí viene el minitruco final. Si alguna vez habéis tenido curiosidad por saber qué hay detrás del proceso de "Skidrow" y similares (salvando las abismales distancias, obviamente jajaja) aquí lo tenéis:


Crackeando el binario: Password siempre válida

Vamos a parchear el binario para que siempre nos de el OK a todo lo que metamos.


Como hemos visto, la dirección "00454136" contiene un "JNE" que es una orden normalmente utilizada tras una comparación. Lo que sabemos es que si la contraseña no es correcta, nos llevará a la dirección "00454144" que hará saltar el pop-up de contraseña incorrecta.


Para que nuestro input siempre sea válido, bastará con sustituir:

jne 0x00454144

por

jmp 0x00454138 

Cuya orden hará que siempre saltemos a la dirección "00454138" donde el programa continúa a partir del "Contraseña correcta".


Ahora simplemente tenemos que aplicar el parcheado y exportar nuestro nuevo binario.