[size=85%]
Como ya comentamos en un anterior post, simultáneamente a las conferencias de la RootedCon tuvo lugar un wargame en el que se debían resolver diversas pruebas. A continuación se muestra una posible solución para una de ellas, que se presentaba a modo de crackme.
Para pasarla, se debía generar un password correcto para el usuario admin:
[/size]You are not allowed to view links.
Register or
Login[size=85%]
Un buen punto de entrada habitual en este tipo de crackmes puede ser lanzar el programa con el depurador y poner un punto de ruptura en la API MessageBox, de modo que la ejecución se detenga al mostrar el mensaje de error producido al introducir un valor incorrecto, y suponiendo que nos encontraremos cerca de la rutina de comprobación del password.
En este caso no es tan simple, puesto que el creador del crackme ha añadido algún truco anti-debug. Al lanzar el crackme en el depurador, éste se detiene debido a instrucciones int3, como se puede ver a continuación:[/size]You are not allowed to view links.
Register or
Login[size=85%]
Por supuesto, no se trata de un error de programación, sino que las funciones más importantes del programa han sido cifradas con un código similiar al siguiente:
[/size]
You are not allowed to view links.
Register or
Login[size=85%]
Como bien sabemos, habitualmente las subrutinas comienzan con el siguiente prólogo:[/size]
You are not allowed to view links.
Register or
Login[size=85%]
Podemos comprobar que si ciframos está función con el algoritmo mencionado, dado que la clave de cifrado inicial es 0x99 y la función comienza con 0x55, con un XOR obtenemos 0xCC, que se corresponde con el int3. De esta manera, garantizamos que las funciones cifradas comenzaran con int3, y la función de descifrado será almacenada en el manejador de excepciones para que pueda ser descifrada en ejecución y ejecutada sin problema alguno.
Sabiendo cómo se cifran las funciones, podemos decodificarlas todas, y podemos tener un fichero más cómodo de estudiar. El crackme utiliza la API GetDlgItemTextA para obtener los valores introducidos en los TextBox, llegando al siguiente código:
[/size]
You are not allowed to view links.
Register or
Login[size=85%]
Aquí podemos encontrar la subrutina que valida nuestro código, protegido por tres detecciones de depurador antes y después de su ejecución y, para complicar más el asunto, el código de validación, a diferencia de las demás funciones, vuelve a ser cifrado después de ejecutarse, siendo únicamente visible mientras la contraseña está siendo comprobada. El string "iddqd-idkfa!" no se trata de la contraseña, habrá que trabajárselo un poco más
Dentro de la rutina de comprobación podemos diferenciar varias partes, como la comprobación del inicio del password, que debe coincidir con "r00ted-" para que la rutina siga comprobando las siguientes condiciones:
[/size]
You are not allowed to view links.
Register or
Login[size=85%]
Siguiendo el análisis de la rutina, se puede comprobar que el password correcto debe contener un guión ("-") y algunos "Hi" y/o "Lo", llegando a la conclusión de que el password debe seguir el siguiente esquema:
[/size]
[size=85%]r00ted-XXXXXX-YYY[/size]
[size=85%]
XXXXXX consiste en una combinación de Hi y Lo, mientras que YYY se trata del valor introducido por el usuario que, como veremos más adelante, deberá cumplir ciertas condiciones.
Veamos ahora como son generados los mensajes de error. Podemos encontrar un array de punteros a diferentes mensajes de error, aunque están cifrados. Encontramos dicho array en la dirección 0x426000.
[/size]You are not allowed to view links.
Register or
Login[size=85%]
Posteriormente, son inicializados en el siguiente orden, contando desde 0 hasta 7:[/size]
You are not allowed to view links.
Register or
Login[size=85%]
El más importante es el 5º elemento, porque contiene la subrutina que muestra el mensaje que nos dice que hemos acertado el password. Lo único que nos falta es como hacer que el flujo del programa termine llegando a esta rutina.
La solución consiste en que la segunda parte de la contraseña debe apuntar a dicho valor, esto es, el quinto, para lo que, valiendo Hi 1 y Lo 0, necesitamos el valor 101
[/size]
[size=85%]
Ahora tan solo falta la última parte del password. El crackme calcula el checksum (un simple XOR) de las dos primeras partes (azul) y lo compara con el checksum de la última parte (verde):
[/size]
[size=85%]r00ted-HiLoHi-YYY[/size]
[size=85%]Por lo tanto, necesitamos el valor YYY que haga coincidir los dos checksums, y una combinación de caracteres para que esto sea real es r00ted-HiLoHi-Ap8
[/size][size=85%]
Solo como curiosidad, otros mensajes ocultos en el programa son:
- You are tracing me!
- ALLMOST!! Bad bad bad ....
- ALLMOST!! This one is not good : /((
- INVALID, No luck .....
- KEEP WORKING, Bad bad bad ....
- INFO, Keep the good work ...
- IN-VALID The password doesn't look OK
- Not Good, Still not there ...
Un crackme muy interesante![/size]