Introducción al Reversing – 0x05 Reverser.exe

Muy buenas a todos seguimos con los tutoriales, siendo este enfocado exclusivamente en el uso de radare2 con un Crackme hardcodeado. En la primera entrada podéis localizar un índice con todos los enlaces de los seis tutoriales realizados hasta el momento.

Crackme Hardcoded 4

Enlace de descarga:

Reverser.exe

Radare2 es una tool que sigue la filosofía de Unix y hay que tener presente que no es tan intuitiva como puede ser otras tools de Reversing con su interfaz gráfica, pero el potencial que tiene radare2 hace que la curva de nivel de su aprendizaje sea compleja y una vez se consigue su dominio la eficacia puede verse patente en los trabajos que se realicen de ingeniería inversa. Es una tool completamente CLI y estar acostumbrado al manejo de Linux es un punto a favor, aunque como ya hemos visto hace dos entradas tiene modo de visualizaciones que nos facilitan el trabajo. Además es open-source lo que la hace ganar puntos con respecto otras tools de pago.

Tools útiles en radare2

rabin2

Sirve para extraer información de un binario como los símbolos o las secciones. Con el parámetro -L nos listará los plugins y mostrará un listado de los formatos de ficheros soportados:

rabin2 -L

Con el parámetro -i nos muestra información de los imports, mostrando todas las funciones o apis que se importa en el programa:

rabin2 -i Reverser.exe

Para ver las librerías usamos el parámetro -l:

rabin2 -l Reverser.exe

Las secciones del programa con -S:

rabin2 -S Reverser.exe

Para mostrar las Strings con el parámetro -z, visualizando la dirección de memoria donde se localiza, la sección, el tamaño, longitud y el tipo entre otros:

rabin2 -z Reverser.exe

rasm2

Sirve para desensamblar y ensamblar. Es útil para saber que Bytes hay que escribir en un binario para parchear. Con -L listamos todas las arquitecturas disponibles:

rasm2 -L

Si escribimos una instrucción, nos mostrará los Bytes:

rasm2 "mov eax, 90"

Para hacer la inversa, con el parámetro -d:

rasm2 -d 55

radiff2

Nos sirve para encontrar diferencias entre dos binarios. En este caso comprueba la diferencia entre el original y el parcheado donde estará modificado:

radiff2 Reverser.exe ReverserParcheado.exe

rafind2

Nos permite buscar algún patrón como Strings con -s  en el binario y nos devuelve la dirección de memoria, por ejemplo:

rafind2 -s "Good reverser" Reverser.exe

rax2

Sirve para conversiones de base, por ejemplo de Decimal a Hexadecimal o a la inversa:

rax2 20

Comandos básicos en r2

Vamos a usar el Crackme para ver ciertos comandos necesarios para el manejo de radare2 y posteriormente realizar el análisis estático del mismo. Para ver el help de cualquier comando nos sirve haciendo <nombreComando> <?>. Primero antes de nada analizamos con la opción aaaa (strings,funciones,flags…):

Si queremos movernos a una dirección de memoria en concreto hacemos «Seeking» y como podéis observar varía el prompt:

Con s- volvemos hacía atrás, y con px o x podemos visualizar el Volcado en hexadecimal:

Si insertamos en el CLI pi nos mostrará las instrucciones en assembly del main ya que cuando hicímos «Seeking» nos situamos en dicha función:

El desensamblado con pd:

Ahora si lo que queremos es escribir en el binario, lo abrimos en modo escritura con -w. Escribimos un nop en esta dirección de memoria:

Para ello hacemos «Seeking» a dicha dirección y escribimos la isntrucción con wa:

Y ahora miramos el desensamblado, y vemos nuestro nop en dicha dirección de memoria:

Si queremos ver las diferencias entre este binario y el original usamos radiff2 y vemos el cambio en hexadecimal que hay con respecto el original. 90 que corresponde a la instrucción nop y 75 correspondiente a jne:

Al iniciar radare2 siempre nos situa en el EntryPoint. Para comprobarlo podemos usar ie:

Con iz vemos las Strings:

Y si hacemos izj~{} visualizamos en JSON cuyas Strings esta en base64:

Con is vemos los Símbolos:

Con iS las Secciones:

Si hacemos S= obtenemos el mismo resultado:

Y con iSj~{} la salida en JSON:

Si queremos desensamblar 6 instrucciones podemos hacerlo con pd 6:

Y si queremos 60 Bytes lo hacemos con pD 60:

Con pdsf vemos el «Summary» del desensamblado del main en concreto visualizamos Strings y llamadas a funciones:

Si introducimos pdc vemos el desensamblado en pseudo de sintaxis en C:

Si hacemos pd~call grepeamos en el desensamblado de la función todo aquello que sean llamadas call:

Ya para terminar de ver los comandos básicos de radare2, cabe mencionar los modos de visualización con V luego con p y si queremos verlo en modo grafo presionamos V de nuevo:

Para los zoom con +-:

Análisis estático del Crackme

Una vez visto radare2 vamos a ver estáticamente el código del Crackme. Primero antes de haber analizado el programa, listamos todas las funciones y observamos que el EntryPoint no se situa directamente en el main:

También podemos hacer iz para ver las Strings que usa el programa. Una vez localizadas las Strings que nos interesa podemos desensamblar las 6 instrucciones a partir de la dirección de memoria asociada a la cadena de caracteres. Radare2 nos muestra en forma de comentario DATA XREF la referencia de dónde es llamada en la sección .text de la función main. También vemos que dicha dirección contiene una String mostrando la longitud:

Si queremos saber en que sección se localiza la dirección de memoria 0x00402108, hacemos un S= y observamos que la String esta en la sección .rdata:

Realizamos un desensamblado del prólogo de la función main. Lo primero que nos encontramos dentro de la función es el prólogo colocando el puntero base en la pila o el Saved EBP, seguidamente mueve el contenido del puntero de pila al puntero base con el objetivo de colocar a este último en el Top del stack y finalmente resta el valor en hexadecimal 0x7C al puntero base, con el fin dejar espacio en la pila disponible para las variables locales.

Ahora pushea la String siendo argumento de la siguiente función, que seguramente sea un printf:

Mueve la dirección de memoria correspondiente a la variable local o ebp-0x7C del Stack, al registro EAX y posteriormente las dos siguientes instrucciones pushea un valor en hexadecimal 0x14 y el registro a la pila que serán los argumentos de la api gets_s:

Si miramos en la página de Microsoft, esta api lo que hace es pasarle como argumentos un buffer (la variable local_7ch) y el tamaño máximo que nos permite introducir por teclado:

Ahora mueve la dirección de memoria de local_7ch al registro EAX, siendo un puntero al contenido de la variable en la pila y se le pasa como argumento a la api atoi:

Esta api lo que hace es convertir las cadenas de caracteres introducidas por teclado a tipo de datos Integer:

Vemos que el valor devuelto por la api corresponde al mismo registro EAX, ya que una vez termina de ejecutarse la api mueve el contenido al registro ESI y luego de imprimir la String que introdujimos llamando a otra función, compara el valor de ESI con el valor en hexadecimal 0x124578.

Dependiendo del resultado de la comparación activará la eflag o no. Con el salto condicional jne salta si no es igual o no es cero (ZF=0). Por tanto mirando el grafo saltará (true=verde) cuando su ZF=0, es decir, no son iguales dirigiendo el flujo de ejecución del programa a la dirección de memoria 0x401094 mostrando la String de «Bad Reverser». Esto lleva a la conclusión que el valor correcto es 0x124578 que en decimal corresponde a:

Ejecutamos la aplicación y listo!:

En esta entrada vimos las posibilidades que nos da radare2. Un saludo Naivenom.