007 - Decodificando XWorm: Exploración inicial y técnicas anti-análisis
This article is also available in english
- Introducción
- Exploración inicial y técnicas anti-análisis
- Próximamente: Evasión de defensas y persistencia
- Próximamente: Movimiento lateral
- Próximamente: Keylogger y captura de criptomonedas
- Próximamente: Comunicación con Telegram, obtención de nueva variante
- Próximamente: Comando y Control
Si quieres enterarte cuando se publiquen los nuevos posts de esta serie, no olvides suscribirte al blog!
1. Introducción
En este artículo, segundo de la serie, continuaremos explorando XWorm. En el artículo anterior identificamos que el RAT está hecho con el framework .NET, lo que nos permite analizarlo fácilmente debido a la cantidad de información que contienen los binarios creados con dicho framework.
2. Exploración inicial
Al abrir XWorm en DNSpy verificamos que los nombres de las clases y objetos están ofuscados:
Sería tedioso revisar cada clase para identificar la función donde se empieza a ejecutar el programa; afortunadamente, DNSpy nos muestra la clase y función de entrada como comentario:
Al hacer click al nombre de la función DNSpy nos lleva directamente a esta, donde vemos el código que se ejecuta al iniciar el malware:
Una vez la ejecución comienza el malware llama a Thread.Sleep, pasándole como parámetros el valor almacenado en la variable sWpIi59HVTjtB0r6P7SRQdLwgcnM2a0ZVHXvX multiplicado por 1000; al hacer click en la variable verificamos que esta cuenta con el valor de 2, por lo que el valor pasado a Thread.Sleep es de 2000. Una de las ventajas de analizar código .NET con DNSpy es que este cuenta con información sobre las distintas funciones y métodos nativos de los lenguajes que utilizan este framework, por lo que al poner el mouse sobre la función vemos que esta es utilizada para pausar el hilo que se está ejecutando N milisegundos; dado que el valor que se le pasa a la función es de 2000, el programa se detiene por 2 segundos.
Luego de dormir por 2 segundos, el malware entra a un bloque de try/catch, donde intenta ejecutar un número de operaciones; si el ejecutar estas operaciones falla, el programa se cierra mediante la función Environment.Exit(0).
En un primer análisis puede parecer un poco raro lo que realiza el malware, ya que asigna a una variable el resultado de una operación sobre dicha variable:
Clase.variable1 = Conversions.ToString(lnZZgsJ1tVOV.FbmCgvom7sJS(Clase.variable1));
Si hacemos click a la primera variable,qsurotxVBQWuN1wXL7Sl3R7UMOoGherwjkt90, vemos que tiene como valor nz4SABi5PYTEufPjSTbCd8mMnZZi6YWaGiwAg1FVXfo=
Por el tipo de caracteres parece ser estar codificado en Base64; sin embargo, el tratar de decodificar el valor no obtenemos caracteres legibles:
3. Desencriptado en memoria
Si hacemos click a la función FbmCgvom7sJS podemos entender qué operaciones realiza sobre la variable:
public static object FbmCgvom7sJS(string TEFe4AuGLs1t)
{
RijndaelManaged rijndaelManaged = new RijndaelManaged();
MD5CryptoServiceProvider md5CryptoServiceProvider = new MD5CryptoServiceProvider();
byte[] array = new byte[32];
byte[] array2 = md5CryptoServiceProvider.ComputeHash(TFIW2FSLtw9S.fOEct6S2qWNI(Dwre7AimAttsSDe9ONtyGoMXtbA3NNJR6lGec.eCx5LqBibLns0nMQEXWWSiIdLt37W7nhFgXiM));
Array.Copy(array2, 0, array, 0, 16);
Array.Copy(array2, 0, array, 15, 16);
rijndaelManaged.Key = array;
rijndaelManaged.Mode = CipherMode.ECB;
ICryptoTransform cryptoTransform = rijndaelManaged.CreateDecryptor();
byte[] array3 = Convert.FromBase64String(TEFe4AuGLs1t);
return TFIW2FSLtw9S.kX1tPkTzXln3(cryptoTransform.TransformFinalBlock(array3, 0, array3.Length));
}
La función realiza lo siguiente:
- Inicializa una instancia de RijndaelManaged, la cual es una clase utilizada en operaciones criptográficas.
- Inicializa una instancia de MD5CryptoServiceProvider, que nos permite realizar operaciones de hasheo MD5.
- Crea un array llamado array (1) de 32 bytes.
- Crea otro array llamado array2 (2) que contiene el hash MD5 de la variable eCx5LqBibLns0nMQEXWWSiIdLt37W7nhFgXiM
- Copia el hash MD5 que está en la variable array2 (2) a los 16 primeros bytes del primer array (1).
- Copia nuevamente el hash MD5 de la variable array2 (2) al primer array (1) empezando en el quinceavo byte; al hacer esto se sobreescribe el quinceavo byte, que era el último copiado en el paso 5.
- Configura el array de 32 bytes(1), el cual ahora contiene los valores derivados del MD5, como llaves del algoritmo criptográfico e inicializa el método para desencriptar.
- Obtiene el valor que se pasó como parámetro a la función y lo decodifica de Base64.
- Finalmente, desencripta el conjunto de bytes resultante del paso anterior con la llave configurada en el paso 7.
Con analizar la función entendemos el propósito de esta: ciertas variables están cifradas y el malware las descifra en ejecución, posiblemente para evitar que valores como URLs o IPs sean identificadas fácilmente como Indicadores de Compromiso (IOCs) en un análisis estático.
Si bien podemos crear un script para automatizar el desencriptado de las variables, podemos utilizar la función de debugging de DNSpy para obtener los valores; podemos presionar F9 sobre la fila donde se desencripta la variable y analizar el resultado, utilizando F10 para pasar por cada instrucción:
De las variables desencriptadas, identificamos algunas potencialmente interesantes:
- Una URL de DDNS.net, un servicio de DNS dinámico.
- Lo que parece ser un puerto.
- La cadena de texto “<Xwormmm>”
- La cadena de texto “USB.EXE”
Adicionalmente, vemos que se desencriptan algunos valores que no aún llegamos a entender y probablemente tengamos que inferir su uso en base al contexto de la función que los invoque.
4. Uso de Mutex
Luego de desencriptar los valores, el malware entra a la función XykaLtFvQmKZ, la cual intenta generar un Mutex con un nombre en específico, almacenado en la variable eCx5LqBibLns0nMQEXWWSiIdLt37W7nhFgXiM:
Los Mutex usualmente se utilizan en programación concurrente para bloquear ciertas partes del código y evitar que sean accedidas cuando están en uso/aún no están listas; esto sucede debido a que, cuando uno maneja múltiples hilos, puede ocurrir lo que se conoce como un race condition, donde un hilo termina antes que el hilo que esperábamos termine primero.
Los parámetros para crear un Mutex son los siguientes:
- initiallyOwned: No afecta el objetivo del malware.
- name: nombre del Mutex.
- createdNew: True si se creó el Mutex, False si ya existía un Mutex con ese nombre.
En este caso el malware se está ejecutando en un solo hilo, pero los autores de malware utilizan creativamente dicho tipo de objeto mediante el parámetro de respuesta createdNew; de este modo, si se inicia una nueva instancia del malware cuando otra ya se está ejecutando, el Mutex con el nombre definido por el malware ya estará creado, por lo que el resultado sería False y el programa se cerraría. Al hacer esto los autores del malware pueden asegurarse que solo una copia esté en ejecución en todo momento, y así evitar impactar el rendimiento del sistema y levantar sospechas.
5. Anti-análisis
Luego de desencriptar las variables y asegurarse que sea la única instancia en ejecución, el malware ingresa a la función w8r25j4la24nAJZBLOLGewTPs69UXozPFVUsT; con ver a alto nivel la función evidenciamos que realiza múltiples validaciones y procede a cerrar el programa si una de estas falla:
Analizando función por función, estas realizan lo siguiente:
-
Verifica si el malware se está ejecutando en VMWare o VirtualBox: Para ello, el malware obtiene el fabricante del sistema utilizando Select * from Win32_ComputerSystem y lo compara con las cadenas de texto “vmware” y “VirtualBox”
-
Valida si está siendo analizado:
El malware importa la función CheckRemoteDebuggerPresent de la librería Kernel32.dll para verificar si el proceso actual está siendo analizado por un depurador externo (de un proceso diferente, no necesariamente otra PC).
- Verifica si la librería SbieDll.dll está presente:
La librería SbieDll.dll pertenece a Sanboxie, un programa que permite contenerizar y analizar programas con el fin de prevenir infecciones. XWorm utiliza la función GetModuleHandle para verificar si la librería está activa.
-
Verifica si se está ejecutando en Windows XP:
-
Verifica si se está ejecutando en un proveedor cloud: El parámetro hosting de la web ip-api.com indica si la IP pertenece a un proveedor Cloud.
Dichas validaciones pueden cumplir distintos fines:
- La validación de si el ambiente es virtualizado, que no sea XP y que no sea un proveedor Cloud pueden ser debido a las capacidades del malware, el cual puede necesitar hardware físico.
- La validación de si se está ejecutando en un proveedor Cloud puede buscar impedir el análisis de soluciones como VirusTotal o AnyRun, las cuales se ejecutan en servicios en la nube (AWS/GCP/Azure).
- La validación de si está siendo analizado y si la librería de Sandboxie está presente puede ser para dificultar su detección por parte de herramientas de análisis dinámico.
Si continúasemos con el análisis dinámico en una PC con VMWare o VirtualBox, el programa se cerraría debido a la primera validación:
Para evitar ello podemos configurar un breakpoint antes de que se valide el fabricante y cambiar en memoria el nombre de este:
También es posible guardar el programa luego de parchar la validación; sin embargo, no lo recomiendo hasta terminar de comprender qué hace el malware. El malware podría proceder a corromper archivos o cifrar el sistema, por lo que es bueno mantener su función inicial y permitir que se cierre si lo ejecutamos por error o por si este se configura para iniciar automáticamente mediante técnicas de persistencia.
4. Conclusiones
En este análisis, hemos profundizado en las primeras etapas de ejecución de XWorm, revelando varias técnicas que utiliza para dificultar su análisis y asegurar su ejecución en entornos específicos. Entre los aspectos destacados podemos mencionar:
Ofuscación y desencriptado dinámico
XWorm emplea un cifrado basado en Rijndael y codificación Base64 para proteger cadenas sensibles como URLs, puertos y nombres de archivos. Este enfoque busca ocultar posibles indicadores de compromiso (IOCs) hasta que se ejecuten en memoria.
Uso de Mutex
El malware asegura que solo una instancia esté en ejecución mediante la creación de un Mutex único. Esto previene conflictos de recursos y evita levantar sospechas por consumo excesivo del sistema.
Validaciones anti-análisis
Las múltiples comprobaciones de XWorm, como la detección de entornos virtualizados, depuradores externos y la presencia de librerías de análisis como Sandboxie, dificultan el análisis dinámico y buscan evitar la ejecución en entornos controlados.
Estas técnicas no solo muestran un alto nivel de refinamiento en el desarrollo de XWorm, sino que también refuerzan la importancia de las herramientas y metodologías avanzadas en el análisis de malware. Al superar estas barreras, podemos comprender el comportamiento de este tipo de amenazas, anticiparnos a sus movimientos y desarrollar mejores defensas.
Próximos pasos
En los próximos artículos de la serie, exploraremos las estrategias de evasión de defensas, las técnicas de persistencia y los módulos funcionales de XWorm, como el keylogger y la captura de criptomonedas. Esto permitirá un análisis más profundo de su impacto y capacidades.
¡Nos vemos en el siguiente artículo!
¿Tienes algún comentario o sugerencia? ¡Puedes dejar tu feedback en el formulario de abajo!