El 18 de junio lanzamos el desafío ESET#45 en el cual había que realizar ingeniería inversa sobre una muestra para encontrar la flag oculta. En esta oportunidad, ningún participante logró resolver el desafío en el tiempo establecido, por lo que no hubo ganadores. A continuación, presentamos la solución para comprender dónde estaba la clave para llegar a la solución.

Solución al desafío ESET#45

Para resolver este desafío primero debemos leer y seguir el instructivo:

  1. Descargar el archivo AnomalyLand.zip que contiene al archivo AnomalyLand y descomprimirlo utilizando la contraseña: infected
  2. Analizar y descubrir qué es realmente el archivo AnomalyLand. En su interior existe un archivo con una pista que te ayudará a descifrar la flag que se encuentra oculta en el PE.
  3. ¿Acaso el PE está corrupto? Encontrar la manera de remediar el problema para poder restaurar su estructura y así poder seguir las pistas que llevaran hacia la segunda anomalía.
  4. Descubrir qué es lo que falta en la segunda anomalía y restaurarlo para poder ver el camino a la flag.

Descubriendo qué es AnomalyLand

Una vez descomprimido, obtenemos el archivo AnomalyLand. Primero, echémosle un vistazo al archivo utilizando un editor hexadecimal (por ejemplo, HxD):

Imagen 1. Primeros bytes del archivo AnomalyLand en el editor hexadecimal HxD

Como dice el segundo punto, existe un archivo PE en AnomalyLand, y siendo que esta ubicado en el offset 0, podemos abrirlo directamente con algún explorador de PE sin extraerlo:

Imagen 2. Información general del PE en AnomalyLand según el programa CFF Explorer

Lo primero que podemos notar es que el tamaño de AnomalyLand excede por casi el doble del tamaño del PE esto lo podemos saber ya que el tamaño físico del PE es la suma de PointerToRawData + SizeOfRawData de la última sección). Este es un buen indicador de que existen datos al final de PE, por lo que debemos calcular el offset del final del PE y continuar observando hasta encontrar algo interesante.

Imagen 3. Después del final del archivo PE, en AnomalyLand se pueden encontrar muchos 00, y algunas cadenas misteriosas.

Si nos dirigimos al offset 0x9600, donde estaría el final del PE, 0x200 después hay una cadena “ACIDBURN”, que parece ser simplemente una referencia a un personaje de la película Hackers, pero no parece ser de mucha ayuda. Así que continuamos moviéndonos hacia el final ya que parece estar vacío (lleno de 00) o con datos poco útiles, hasta que encontramos lo siguiente:

Imagen 4. Comienzan a aparecer datos más prometedores

Una gran cantidad de datos y la cadena “CD001”, ¿una especie de firma? Si buscamos más información en Google sobre esta cadena encontraremos que es parte del formato ISO-9660:

Imagen 5. La cadena "CD001" aparece en la descripción del formato ISO-9660 en Wikipedia. Fuente.

¡Prometedor!

Si volvemos al instructivo, este dice que en el interior de AnomalyLand existe un archivo con una pista, si este es realmente un archivo ISO lo podremos abrir fácilmente con WinZip, WinRAR, o 7zip. Hagamos el intento:

Imagen 6. Lo que podemos observar al abrir AnomalyLand con el programa 7zip.

¡Excelente! Parece que funcionó, pero ¿por qué hay una entrada llamada “.” con el icono de un disco? Si intentamos Ver (tecla F3) el archivo, por ejemplo, con Notepad.exe, nos mostrará que contiene un solo carácter:

Imagen 7. El contenido del archivo de nombre "." es un solo carácter.

Debemos prestar atención al hecho de que este primer intento fue con el programa 7-zip, ¿qué hubiera sucedido si utilizaba WinRAR?

Imagen 8. Lo que podemos observar cuando abrimos AnomalyLAnd con el programa WinRAR.

Ahora nos aparece una entrada con “..”que dice “File Folder”, así que no podremos abrirlo como antes. Pero una entrada con ese nombre no debería ser válida, ya que no es posible crear un archivo en Windows con ese nombre. Cada vez que intentamos acceder al Folder nos llevará hacia la carpeta anterior, como lo es en el caso de la entrada Local Disk que aparece por defecto en WinRAR. Este un indicio de que estábamos en lo correcto en cuanto a que este archivo podría ser un ISO, ya que el formato permite contener archivos e indexarlos como en un sistema de archivos, por lo tanto, debemos intentar encontrar la estructura que describe esta entrada de archivo dentro del ISO.

Volviendo a la página de Wikipedia, podemos obtener algunos datos interesantes, por ejemplo:

Imagen 9. Según Wikipedia, los primeros 32,768 bytes del archivo de formato ISO-9660 no son utilizados. Después de eso continúa el área de datos. Fuente.

Los primeros 32,768 bytes del archivo no son utilizados por el formato, por lo que no es llamativo que, aunque haya un PE ocupando ese espacio, todavía sea un archivo ISO válido. Si calculamos el offset donde comienza el área de datos, entonces iríamos a 0x8000 y encontraremos esto:

Imagen 10. Comienzo del área de datos.

Ahora ya sabemos dónde deberíamos comenzar a buscar. Otro dato interesante es que el nombre de cualquier archivo está sujeto a ciertas reglas. Entre ellas, ISO-9660 dice que el nombre de un archivo no puede contener más de un “.”. El falso Folder contiene dos, así que podemos intentar buscarlo directamente; sería lo más rápido. Sin embargo, si intentamos buscar 0x2e2e no encontraremos nada, así es que probemos con 0x002e002e o 0x2e002e00:

Imagen 11. Encontramos la entrada del falso Folder ".."

¡Tenemos un resultado! Intentemos normalizar el nombre cambiando los caracteres “.” Por “E”:

Imagen 12. El cambio de los bytes "." por "E" se ve reflejado en rojo en el editor hexadecimal HxD

Abrimos con WinRAR:

Imagen 13. Ahora que cambiamos el nombre del archivo a uno válido, podemos abrirlo tal como hicimos con 7zip.

Ya podemos dar por concluido el segundo punto del instructivo:

  • AnomalyLand en realidad es un archivo ISO-9660
  • Existe un archivo oculto llamado “..” que contiene un solo carácter ^ que podría ser la pista

Resolviendo el problema del PE

Ahora debemos volver a enforcarnos en el archivo PE que se encuentra dentro del ISO. Recordemos que, al principio de nuestra investigación, observamos en el editor hexadecimal el DOS header en el offset 0 y se podía observar el siguiente mensaje:

Imagen 14. Mensaje que aparece al final de la DOS header en el PE

“leetspeak is fun” hace referencia al lenguaje informal “leetspeak”, en el cual algunos caracteres se reemplazan por otros que se asemejan a letras en apariencia; por ejemplo, en hexadecimal 0xB4B01 podría interpretarse como “BAD BOY”, o 0xC4F3 podría ser “café”. ¡Leetspeak es divertido!

Inicialmente, CFF Explorer nos dice que el PE es de 32-bit, por lo que, si observamos el header FileHeader, no deberíamos encontrar nada extraño:

Imagen 15. FileHeader del PE como se ve en CFF explorer.

¡Ohh! El miembro “Machine” contiene un valor 0x8664, lo cual significa que la máquina donde debería ejecutarse es de la arquitectura x86-64. Todo lo demás parece correcto, así que continuemos hacia la OptionalHeader:

Imagen 16. OptionalHeader como se ve en CFF Explorer. En el cuadro rojo podemos observar un grupo de valores extraños.

Marcados en rojo hay un grupo de miembros con valores extraños que le indican a Windows que debería crear espacios de memoria para la heap y el stack con un cierto tamaño que se ajuste mejor a las necesidades del programa en particular. NumbersOfRvaAndSizes debería ser 0x10, o menor, ya que un valor superior excede la lista de directorios especificados por el formato PE.

El valor de Magic indica que la OptionalHeader debería ser interpretada para la arquitectura x86, o mas bien que el PE es un PE de 32-bits. Es evidente entonces que CFF Explorer toma el valor de Magic para hacer su interpretación. Si FileHeader dice que el archivo es 0x8664, podríamos intentar cambiar el valor de Magic para ver qué sucede. Recordemos que para que haga efecto el cambio es necesario guardar el archivo en el disco. Yo lo guardo como “al-pe-patched”. Veamos qué ocurre:

Imagen 17. Comparación de ambos PEs. Izquierda: PE anómalo, versión de OptionalHeader de 32-bits. Derecha: PE normalizado, versión de 64-bits.

Podemos observar varios cambios: el PE dejó de contener datos en el directorio de MSIL y Exception y ahora posee un directorio Debug y Relocations. El valor de NumberOfRvaAndSizes se ha normalizado a uno más frecuente 0x10, ¡Por lo que podemos pensar que ahora está corregido el PE! Sin embargo, cambiaron o se “acomodaron” los valores del grupo de Sizes*, aunque todavía se ven extraños.

¿Qué tal si aplicamos leetspeak?

Imagen 18. El grupo de valores al final de la OptionalHeader parecen contener un mensaje interesante.

“100C A7 5EC7 4” podría interpretarse como “look at sect 4”, o “mira la sección 4”. Pero antes de eso, ya resolvimos las instrucciones del punto 3:

  • Remediamos el problema y lo restauramos
  • Eso revelo las pistas para continuar hacia la segunda anomalía del PE

Segunda anomalía: algo no es lo que parece

Si vemos los section headers observaremos que hay una sección que tiene un nombre muy específico, ya que contiene parte de la información para el uso de Thread Local Storage (TLS). Sin embargo, como podemos observar en el navegador de la izquierda, no hay una entrada para el directorio de TLS:

Imagen 19. La tabla de secciones y el explorador del archivo a la izquierda, como se puede ver en CFF explorer.

Esto quiere decir que no hay una entrada de TLS en Data Directories. Así es que esta sección “.tls” no es lo que parece, pero si no es “.tls” ¿qué puede ser?

Si lo pensamos, hay algo que un PE32+ debería contener casi seguro, considerando lo grande que es el código: manejadores de errores, o Exception Handlers. Para código de 64-bits, Windows introdujo un nuevo tipo de manipuladores de errores, que son creados dinámicamente partiendo de metadata que usualmente reside en una sección llamada “.pdata”.

Intentemos poner los valores de la sección “.tls” en la entrada de Exception Table en Data Directories, y guardemos el archivo de manera que hagan efecto los cambios en el programa.

Imagen 20. En el recuadro rojo los miembros del Exception Table o Exception Directory en Data Directories.

Y obtenemos lo siguiente:

Imagen 21. Nuevamente parece que nos encontramos con otro mensaje en leetspeak.

Si nos fijamos, las primeras entradas de la tabla tienen sentido: están organizadas en orden creciente por RVA y al igual que las RVA en UnwindData, parecen estar bien. Bueno, las primeras, excepto la primera. La primera entrada se asemeja a lo que vimos en OptionalHeader.

DEC 00F5E7 00005350” o “decrypt offset 0x5350”.

Con esto ya pudimos resolver el punto 3:

  • Restauramos lo que falta
  • Podemos “ver” el camino a la flag

Descifrando la flag

Si vamos al offset 0x5350 del archivo con el mismo editor hexadecimal de CFF Explorer, nos encontramos con un montón de texto, que bien o está cifrado o es código:

Imagen 22. Vista en editor hexadecimal propio de CFF Explorer. Podemos observar los datos que se encuentran en ese offset al que nos llevó el mensaje.

No sabemos cuál es la longitud exacta de la suma de caracteres que componen la flag, ni la clave, ni cómo fue cifrada. Sin embargo, tenemos dos pistas:

  1. La flag cifrada comienza con la letra “E”
  2. La pista que conseguimos en el archivo oculto “^” que nos ayudara a descifrar la flag.

El carácter “^” es conocido por ser el operador XOR en varios lenguajes de programación. XOR también tiene la particularidad de ser reversible, si conocemos uno de los valores. De manera que, si tomamos el primer valor en el offset 0x5350 y le aplicamos XOR 0x45 (en ASCII, 0x45 corresponde al valor hexadecimal del carácter “E”), deberíamos obtener la clave: 0xAC. Entonces, intentemos hacerlo con una multitud de bytes:

Imagen 23. Como seleccionar y editar un grupo de bytes en CFF Explorer. La modificación le aplicará la operación XOR 0xAC a cada byte del grupo seleccionado.

Y conseguimos:

La flag es: ESET_Ch411eng3C0mpl37!

Esperamos que les haya resultado entretenido y los esperamos para el próximo desafío.