Desarmando las capas del malware de .NET

Los atacantes cibernéticos desarrollan constantemente formas creativas de ofuscar su código para ocultar la presencia (y el propósito) de su malware.

En este blog, analizamos un ejecutable que encontramos que compila un archivo DLL sobre la marcha, carga la DLL y luego decodifica una imagen incrustada en el ejecutable original que contiene el payload real. Acompáñanos mientras recorremos cada capa para descubrir la verdadera intención de este malware de .NET ofuscado.

Todo comenzó el otro día cuando descubrimos un archivo sospechoso de acceso directo de Internet dentro del directorio de inicio de un usuario:

ijrhojllknmbkq4p.url

En lugar del comportamiento típico de abrir un navegador y mostrar un sitio web, este archivo .URL apuntaba a un archivo local C:\Users\<USER>\doc06421,pdf.exe.

Como puedes ver, ambos nombres de archivo son claramente sospechosos. Como no hubo coincidencias con el hash del ejecutable en VirusTotal, era momento de que nuestro equipo del SOC investigara más a fondo.

Primero usamos la utilidad file para identificar el tipo de ejecutable, que resultó ser una aplicación de .NET. Luego lo cargamos en dnSpy (un depurador y editor de ensamblados de .NET) y descubrimos tres funciones: Compile(), Main() y XorEncrypt().

dnSpy

La función XorEncrypt() me llamó la atención de inmediato. Para quienes son nuevos en el análisis forense, el malware a menudo usa XOR para ofuscar su funcionalidad maliciosa. En resumen, este ejecutable “desencripta” mediante XOR la variable datastring (que contiene código fuente en C#), compila el código fuente en una DLL, crea un hilo e inyecta la DLL. Este comportamiento grita malware.

Al reimplementar la función XorEncrypt() en Python, pudimos examinar el código fuente desofuscado. Curiosamente, el nuevo código (y la DLL resultante) no hace gran cosa. Su función Main() carga un recurso, lo procesa de alguna manera y luego ejecuta el recurso procesado en un nuevo hilo.

Main() from the deobfuscated DLL source code that loads and processes an embedded resource

Main() del código fuente desofuscado de la DLL que carga y procesa un recurso incrustado

Ahora era momento de ver si podíamos encontrar el recurso referenciado. Usando Resource Hacker, examinamos el ejecutable original. Efectivamente, tiene un recurso HTML con el ID 130.

Original executable has an embedded HTML resource with a PNG header

El ejecutable original tiene un recurso HTML incrustado con un encabezado PNG

Como se destaca en la captura de pantalla anterior, el recurso 130 parece ser un archivo .PNG. Sin embargo, sabemos por el código fuente que este recurso era procesado o aprovechado de alguna manera por el malware. En lugar de reimplementar la rutina de decodificación esta vez, decidimos guardar el recurso en un archivo y simplemente modificar la función Main() para usar el malware en su contra.

Con las siguientes modificaciones, el proceso se ejecutará tal como lo haría en condiciones normales. Sin embargo, en lugar de usar FindResource() y terminar ejecutando el “payload”, hicimos que el malware leyera el recurso desde un archivo y guardara el “payload” extraído de la falsa imagen .PNG.

Cargamos el nuevo archivo del “payload” en dnSpy y de nuevo nos encontramos con más ofuscación:

Por suerte, existen herramientas para lidiar con archivos .NET ofuscados. Después de ejecutar el binario a través de de4dot, obtuvimos algo un poco más comprensible.

Este nuevo código usa GetExecutingAssembly() para obtener una copia de sí mismo y luego se modifica a sí mismo durante la ejecución. Usando dnSpy como depurador, recorrimos el código paso a paso para observar qué estaba cambiando.

Cerca del final de la función había dos variables de interés (xnnXVZCo y xnnXVZCo2). Estas variables se usaban inicialmente para almacenar el ensamblado original (archivo .NET PE).

NET PE file

Después de guardar el contenido de la variable en un archivo, usamos dnSpy una vez más para seguir explorando. Tras pasar por media docena de capas de ofuscación e indirección, ¡finalmente dimos con el premio!

Este malware tenía todo tipo de capacidades que le permitían a un atacante deshabilitar aplicaciones antivirus, robar contraseñas, registrar pulsaciones de teclas y controlar la cámara web de una víctima, por nombrar solo algunas.

Function names indicate capabilities of the malware

Los nombres de las funciones indican las capacidades del malware

No hace falta decir que el malware .NET puede representar un riesgo significativo para laptops, estaciones de trabajo, servidores Windows, etc. Aunque el antivirus y otros productos de seguridad preventiva hacen todo lo posible por detener cada ataque, esta muestra ilustra hasta dónde están dispuestos a llegar los hackers para evadir la detección. Por suerte, nuestros partners pueden estar tranquilos sabiendo que están protegidos por el equipo del Huntress SOC.

¿Tienes curiosidad por saber si estás comprometido?

Ofrecemos una prueba gratuita de Huntress para un número ilimitado de computadoras. Simplemente despliega nuestro agente, configura una integración de reportes con tu sistema de tickets y te entregaremos procedimientos de remediación paso a paso para cada endpoint comprometido que descubramos.

También te podría interesar