Hace poco más de tres semanas anunciamos un desafío de reversing en Windows, con el objetivo de premiar a quien lo resolviera correctamente con una entrada para ekoparty. Se trata de una de las conferencias de hacking y seguridad más importantes de Latinoamérica y queremos que nos acompañen.

Así que hoy anunciaremos al ganador, el primero en publicar una solución correcta y completa al Desafío ESET #33: Everth J. Gallegos Puma. ¡Felicitaciones! Podrá asistir en forma gratuita a ekoparty y presenciar las charlas que se brindarán los días 26, 27 y 28 de octubre.

Veamos ahora cuál era la solución del desafío y el proceso para llegar a ella.

El archivo a analizar es un ejecutable .cpl. Dado que en realidad los cpl son dll, es necesario hacer el debugging mediante otro exe que invoque al cpl, tal como había explicado previamente en WeLiveSecurity. Si se hace doble clic en el archivo, para probar su comportamiento, veremos que el resultado de la ejecución es la escritura de un archivo de imagen a disco:

problem

Evidentemente el programa ha detectado algo indebido y ha cambiado su comportamiento. Como primer paso del análisis, vemos que el archivo está empaquetado con UPX. Su desempaquetamiento es trivial, con la misma herramienta de UPX. Una vez extraído podemos comprobar que es un cpl escrito en Delphi, cuyo entry point es la rutina CPlApplet. Cuando a esa rutina se le pasa el mensaje de doble clic, se entra a la rutina principal del payload. Ésta se observa a continuación:

payload

Pueden verse unas strings relacionadas con wine. En particular, sub_4CE738 verifica si la aplicación está siendo ejecutada a través de wine o no. Así, si se detecta wine, la ejecución continúa normalmente. De lo contrario, se va a una rutina que descarga la imagen “problem?” y se termina la ejecución. Si no estamos en wine, podemos cambiar el valor de zero flag justo antes de que se ejecute el salto, posterior a la comprobación.

Luego se realiza otra comprobación, aunque vemos que hay una string cifrada. La rutina que se encuentra inmediatamente después de esa string, sub_   4CE218, es la encargada de descifrar todas las strings del ejecutable. Podemos observar en olly cuál es el resultado del descifrado:

whiskas

La aplicación verifica que exista un archivo whiskas.wow en la carpeta ProgramData y que su tamaño sea exactamente de 10 bytes (o 0xA, como se ve en la imagen previa). Si se cumple la condición, continúa la ejecución. Vemos también que al principio de la rutina se asigna la clave de descifrado: “WMRY…..”.

Ahora bien, contamos con la clave de descifrado y sabemos cuál es la rutina de descifrado. Eso, sumado al hecho de que es fácil encontrar la parte del código donde se hace la descarga y ejecución de otro ejecutable (y, por lo tanto, ahí está la solución), podría hacernos pensar que podemos correr solo el código de esa rutina para obtener la URL de descarga.

Sin embargo, esto es erróneo, ya que para la URL que nos interesa, la rutina de descifrado utiliza una clave distinta almacenada en una variable global. Y, a su vez, esa clave es cargada desde un resource del ejecutable, que se encuentra cifrado con RC4. En la siguiente imagen se ve parte de esa rutina de descifrado y cómo también controla si se está corriendo bajo wine:

anti en rc4

Debajo de todo vemos la llamada a CryptDecrypt, a la cual llega si pasa las comprobaciones. Además, vale la pena destacar que esas comprobaciones se realizan una única vez, cuando el descifrado va por el byte 512 (o 200h, tal como aparece en la imagen, arriba). Vemos que la rutina que comprueba la presencia de wine es la misma de antes, sub_4CE738, con la diferencia de que ahora la ejecución termina si se detecta wine; de lo contrario continúa.

Adicionalmente, sub_4CE914 verifica si se está ejecutando en VMware, Wine (sí, nuevamente es la misma comprobación, aunque con las strings cifradas, para confundir un poco) o VirtualBox. Cualquiera que se detecte termina la ejecución, descargando la falsa imagen. En la siguiente imagen se observa la parte de VMware. De estas comprobaciones ya habíamos hablado en nuestro blog.

vmware

Queda una tercera rutina, sub_4CED34, que comprueba si la aplicación está siendo debuggeada. Para ello utiliza tres técnicas: buscar la ventana de ollydbg, revisar el Process Environment Block (comprueba, a su vez, 3 valores: el flag BeingDebugged, flag ProcessHeap y NTGlobalFlag) y realizar una llamada a NtQueryInformationProcess. Todo esto puede parecer muy complicado de entender a primera vista, pero con simplemente parchear el resultado de sub_4CED34, podemos continuar sin problemas, aún sin entender el funcionamiento de esa rutina.

olly

Una vez que hemos pasado esa parte, la rutina termina de descifrar el resource, con lo cual se obtiene un conjunto de caracteres del alfabeto hexadecimal. A eso se le hace un XOR y otras operaciones sencillas, obteniendo la clave de descifrado para nuestra solución:

key

Luego la aplicación obtiene el path hasta AppData\Roaming, descifra la URL, realiza la descarga de un ejecutable e inicia su ejecución. Sin embargo, hay que tener en cuenta un detalle más: la rutina de descifrado de strings comprueba qué clave se está utilizando, y si es la clave obtenida desde el resource, nuevamente se realizan comprobaciones en el sistema.

descifrar

Son las mismas comprobaciones de antes: anti-vm y anti-debug. Aunque agrega una comprobación más, también repetida: en el último bloque de la imagen anterior vemos que se llama a sub_40A24C, que al principio vimos que era la rutina que verificaba la existencia del archivo whiskas.wow. La diferencia es que ahora verifica que su tamaño sea de 20 bytes, no 10 bytes.

La URL de descarga del ejecutable termina en .jpg, pero al descargarlo se le cambia el nombre a 9KmAKvXG.exe. Dado que a las pocas horas de haber puesto el desafío a disposición de nuestros lectores el enlace de descarga fue dado de baja, aceptamos como solución esa URL: "https://cld.pt/dl/download/6009254e-b5a6-41d5-9714-198d5e59731c/generic.jpg".

nyan

El ejecutable es muy sencillo, se encuentra empaquetado con UPX y la solución está en las strings:

respuesta

Las respuestas de Everth y los demás participantes ya fueron publicadas en los comentarios del post anterior. Gracias por su aporte, ¡los esperamos en el próximo Desafío ESET!