Resumen

 

Es probable que Emotet sea el malware más prolífico dentro de las operaciones recientes de distribución de malware. Los hackers suelen cambiar su malware para asegurarse de que no es detectado por ningún software antivirus. A pesar de que la botnet Emotet se está actualmente tomando un descanso en la distribución de spam, se han detectado recientemente cambios en un componente del malware. En este artículo, los expertos del Security Lab de Hornetsecurity analizan la última versión de Emotet.

Emotet ha añadido nuevas técnicas de ofuscación de código para prepararse para sus próximas acciones.

Las actualizaciones del descargador de Emotet no afectan a los filtros de Hornetsecurity, ya que el descargador de Emotet nunca se envía adjunto a un correo electrónico. Sin embargo, el análisis aquí presentado y unos scripts de Ghidra descargables pueden ayudar a otros investigadores a iniciar su ingeniería inversa de Emotet a pesar de la ofuscación adicional.

 

Antecedentes

 

El malware ahora comúnmente conocido como Emotet fue observado por primera vez en 2014. Se trataba de un troyano bancario que robaba datos sensibles y credenciales de acceso a los bancos de sus víctimas. Además, llevó a cabo una campaña de malware como servicio (MaaS) que proporcionaba servicios de distribución de malware a otros ciberdelincuentes.

 

La cadena de infección de Emotet

 

En el siguiente diagrama de flujo se describe al menos el principio de la cadena de infección de Emotet y las tácticas y técnicas utilizadas según lo definido por el framework MITRE ATT&CK.

 

El aspecto más interesante es que Emotet roba los correos electrónicos de las víctimas y los utiliza como plantillas para su nuevo “malspam” (una combinación de malware y spam). Utiliza una técnica conocida como secuestro de hilos de correo, respondiendo a antiguos hilos de correo con uno de sus mensajes maliciosos. Hay más probabilidades de que las víctimas abran mensajes de destinatarios conocidos, y especialmente cuando éstos se reciben dentro de un hilo de correo previo. En consecuencia, las campañas de distribución de Emotet han tenido mucho éxito.

Este tipo de ataques son una de las principales razones por las que los líderes en ciberseguridad necesitan invertir en formación y concienciación para mitigar los riesgos de seguridad informática a través de las personas.

La gran peligrosidad de Emotet se debe a que, además de emplear sus propios módulos para robar correos electrónicos de víctimas y hacer un uso indebido de sus ordenadores a modo de servidores de C2 y de spam, incluye otros elementos de malware tales como TrickBot, que en última instancia provoca una infección con el ransomware Ryuk. De hecho, incluso si una víctima elimina la infección Emotet, puede ser que ya tengan malware adicional ejecutándose en sus sistemas que no formase parte de la infección inicial con Emotet.
Las víctimas infectadas con Emotet pasan a formar parte de la botnet Emotet.

 

Botnet

 

La botnet Emotet está dividida en botnets independientes. Los investigadores las dividían en las épocas 1 y 2 por haber recibido actualizaciones de carga útil en diferentes momentos. Cada época tiene su propia clave RSA única utilizada para su comunicación C2. El 17 de septiembre de 2019, una parte de la botnet de época 1 se escindió para formar la botnet de época 3.

Cada bot se conecta a los servidores de C2 de su época. Si una víctima está infectada por un documento Emotet perteneciente a la época 1, el documento descargará el descargador Emotet de la infraestructura de la botnet de época 1 y posteriormente pasará a formar parte de la botnet de época 1.

La estructura actual de los servidores de C2 de nivel 1 de la botnet Emotet es la siguiente:

Los cambios se implementan primero en la botnet de época 2. Posiblemente se trate de una prueba para asegurarse de que, en caso de que los cambios introducidos provoquen una ruptura, sólo se pierda una parte de la botnet total.

 

Acontecimientos recientes

 

Si bien podríamos profundizar en la intrincada historia de Emotet, en sus orígenes y el código que comparte con Feodo, así como en sus relaciones con Cridex y Dridex, en esta ocasión nos centraremos en los acontecimientos más recientes.
Por suerte, todo el mundo sabe que actualmente (a fecha de redacción) la botnet Emotet no envía spam. La botnet se toma estos descansos a menudo. Lamentablemente, también suele volver tras estas pausas con actualizaciones que lo hacen más peligroso que antes. Este cronograma muestra “pausas de spam” recientes:

 

 

 

El 31 de octubre de 2018, Emotet publicó un nuevo módulo de robo de correo electrónico. En su vuelta a la actividad del 16 de septiembre de 2019, la botnet de época 3 se escindió de la de época 1. Mientras preparábamos esta publicación, el 29 de abril de 2020 se ha observado a TrickBot (un famoso malware frecuentemente distribuido a través de Emotet) distribuyendo el descargador Emotet. Se sospecha que, debido a la larga ausencia del malspam de Emotet empleado para sembrar la botnet con nuevos bots, así como a la constante limpieza de las infecciones existentes, el número de bots de Emotet pueda haberse reducido hasta una nivel crítico y los responsables del malware TrickBot estén ahora sembrando bots de Emotet como contrapartida a la distribución de TrickBot que realizó en su día Emotet. Sin embargo, solo se trata de conjeturas, y por ahora no hay nada claro.
Lo que sabemos es que actualmente hay cambios en el descargador Emotet distribuido por la botnet de época 2 a partir del 20 de abril de 2020. La pregunta es, ¿cuándo volverá Emotet y qué nuevos trucos habrá aprendido esta vez?

Por tanto, el Security Lab de Hornetsecurity ha analizado los cambios recientes en el malware de Emotet.

El 31 de octubre de 2018, Emotet publicó un nuevo módulo de robo de correo electrónico. En su vuelta a la actividad del 16 de septiembre de 2019, la botnet de época 3 se escindió de la de época 1. Mientras preparábamos esta publicación, el 29 de abril de 2020 se ha observado a TrickBot (un famoso malware frecuentemente distribuido a través de Emotet) distribuyendo el descargador Emotet. Se sospecha que, debido a la larga ausencia del malspam de Emotet empleado para sembrar la botnet con nuevos bots, así como a la constante limpieza de las infecciones existentes, el número de bots de Emotet pueda haberse reducido hasta una nivel crítico y los responsables del malware TrickBot estén ahora sembrando bots de Emotet como contrapartida a la distribución de TrickBot que realizó en su día Emotet. Sin embargo, solo se trata de conjeturas, y por ahora no hay nada claro.
Lo que sabemos es que actualmente hay cambios en el descargador Emotet distribuido por la botnet de época 2 a partir del 20 de abril de 2020. La pregunta es, ¿cuándo volverá Emotet y qué nuevos trucos habrá aprendido esta vez?

Por tanto, el Security Lab de Hornetsecurity ha analizado los cambios recientes en el malware de Emotet.

Análisis técnico

 

Debido a reciente ausencia del spam de Emotet, no podemos analizar ningún correo electrónico o documento malicioso. Por tanto, presentamos un análisis del código binario del descargador de Emotet.

 

Código binario del descargador de Emotet

 

Analizamos tanto la versión «antigua», distribuida por la botnet de época 1 el 20 de febrero de 2020 (sin cambios notables desde la actualización del 5 de febrero de 2020), y la «nueva» versión distribuida por la botnet de época 2 a partir del 20 de febrero de 2020.

 

Compresor

 

Los metadatos de la nueva versión contienen fragmentos de texto de artículos periodísticos. Los textos de los campos de descripción del archivo (FileDescription), nombre interno (InternalName), nombre de archivo original (OriginalFilename), nombre del producto (ProductName) y copyright están rellenados con fragmentos de artículos periodísticos:

 

 

Esto es otro indicio de que Emotet utiliza el mismo compresor que Trickbot, que se ha visto con textos periodísticos en sus metadatos poco antes de que Emotet presentara el mismo tipo de textos. Los investigadores han denominado a este cifrador «Exes’r’rus» [JRoosen].

 

Debido a que el compresor cambia con frecuencia, esta diferencia no es inusual. Se ha observado alrededor del 14 de febrero de 2020, pero la carga útil del descargador de Emotet todavía se puede extraer a través de mecanismos de descompresión genéricos (y automatizados).

 

Ofuscación

 

Emotet ha añadido más ofuscación. El cambio más notable es un aplanamiento del flujo de control y la adición de código basura. Esto dificulta el análisis del código binario y permite realizar cambios polimórficos de un modo más sencillo. La mayor parte de la ofuscación ya se agregó en la actualización del 5 de febrero de 2020.

Aplanamiento del flujo de control

El aplanamiento del flujo de control es una técnica de ofuscación. Divide una secuencia de código en varias partes y la reorganiza de un modo más difícil de seguir. Un método habitual consiste en colocar las partes de código en un bucle y ejecutar diferentes partes del cuerpo del bucle en cada ejecución del mismo en función de una variable de estado.

 

Sequencia del código:

CODE_1;
CODE_2;
CODE_3;
return;

se convierte en::

state = STATE_1
do
{
	if ( state > MAGIC_VALUE_1 )
	{
		if ( state == STATE_2 )
		{
			CODE_2;
			state = STATE_3;
		}
		if ( state == STATE_1 )
		{
			CODE_1;
			state = STATE_2;
		}
	}
	else if ( state == JUNK_STATE_1 )
	{
		JUNK_CODE_1;
		state = STATE_4
	}
	else
	{
		if ( state == STATE_3 )
		{
			JUNK_CODE_2;
			state = JUNK_STATE_1;
		}
		if ( state == STATE_4 )
		{
			CODE_3;
			return;
		}
	}
} while(1);

Aunque semánticamente es idéntico, el segundo código es más difícil de seguir.

En Emotet, la ofuscación tiene el siguiente aspecto:

 

 

Emotet utiliza esto para mover bloques de código, como se puede ver en este ejemplo, donde el bloque de código que configura los encabezados de la comunicación HTTP C2 está cerca del principio de la función en un archivo binario y cerca del final de la función en otro:

 

Código basura

 

Otra técnica que usa Emotet se denomina código basura, consistente en añadir código inútil que no cambia la semántica de un programa.
La secuencia de código:

unsigned int function(unsigned int n) 
{ 
    if (n == 0) 
        return 1; 
    return n * function(n - 1); 
}

se convierte en:

unsigned int function(unsigned int n) 
{
    unsigned int a = 1234;
    unsigned int b = 4321;
    a = n + b;
    b = n + a;
    if (n == 0 && a > 10 && b > 20)
    {
        b = n - a;
        n = b;
        return 1;
    }
    a = b + 42;
    return n * function(n - 1); 
}

 

Aquí, los cálculos relativos a las variables a y b son código irrelevante. No influyen en el resultado del código en absoluto. Sin embargo, un analista no sabe qué cálculos son importantes y cuáles no. Por lo tanto, aunque sea semánticamente idéntico, el segundo código es más difícil de entender.

 

Por suerte, el software de análisis moderno es capaz de simplificar el código artificialmente más complicado. Así, una función de aspecto complejo como ésta:

 

 

Se reduce automáticamente al retorno de un valor estático:

 

 

Esto se utiliza en el siguiente método de ofuscación.

Predicados opacos

 

Los predicados opacos son condiciones de salto para las que ya se conoce el resultado, pero que aún deben evaluarse en tiempo de ejecución. Un ejemplo sería un código que obtiene la hora actual dos veces. Debido a que el tiempo nunca corre hacia atrás, el primer valor nunca será mayor que el segundo:

time_t a = time(NULL);
time_t b = time(NULL);
if ( a <= b )
    CODE;
else
    JUNK_CODE;

Mientras que, para una persona, esto sería lógico, una máquina tendría que evaluar los valores de a y b antes de determinar si dar el salto o no.

Emotet utiliza funciones con un valor de retorno estático (véase el anterior ejemplo de código basura) y utiliza sus valores retornados como condición de salto:

 

 

 

Los saltos empleados para el aplanamiento del flujo de control también usan predicados opacos, ya que la variable de estado cambia de forma predecible, pero debe evaluarse en tiempo de ejecución.

 

Biblioteca dinámica y resolución de funciones

 

Todas las llamadas a la biblioteca se resuelven dinámicamente por hash. Las versiones anteriores almacenaban las funciones resueltas. Ahora se resuelven sobre la marcha antes de cada llamada.

 

Para cada llamada a la biblioteca, primero se obtiene la biblioteca (emotet_get_lib()). A continuación, se obtiene la dirección de la función deseada (emotet_get_func):

 

 

Las bibliotecas se resuelven a través de InLoadOrderModuleList, accesible desde el bloque de entorno de proceso (PEB, por sus siglas en inglés) (FS:[0x30]):

 

 

A continuación, al DllBaseName de cada módulo cargado se le aplica una función hash y se compara con el hash consultado actual. Si el hash coincide, se devuelve el DllBase. El GET_LIB_XOR_VALUE varía para cada binario. Esto significa que los hashes de biblioteca cambian de muestra a muestra y no se pueden calcular con antelación. Deben calcularse individualmente para cada muestra.

Las direcciones de las funciones se obtienen a través de recorrido manual, en este caso, de la estructura de datos del directorio de exportación. Se itera sobre cada nombre de función exportado de la imagen de DLL resuelta y se le aplica una función hash. Si el hash coincide, se devuelve la dirección de la función:

 

 

Emotet todavía utiliza el algoritmo de hashing de versiones anteriores:

 

 

La función emotet_get_func() utiliza una variación sin asignar los caracteres en mayúsculas a caracteres minúsculas, es decir, que su hash distingue entre mayúsculas y minúsculas e ingiere cadenas de char en lugar de una cadena de wchar. La función emotet_hash() también está muy cargada de código basura que, por suerte, el descompilador ya simplifica o descarta.

 

Con los scripts de análisis de Ghidra emotet_lib_imports.py y emotet_func_imports.py, es posible reconstruir los nombres de biblioteca y función llamados a partir de sus hashes:

 

 

Las siguientes bibliotecas, que normalmente no se cargan en un proceso por defecto, se cargan a través de LoadLibraryW:

shell32.dll
userenv.dll
urlmon.dll
wininet.dll
wtsapi32.dll
advapi32.dll
crypt32.dll
shlwapi.dll

Los identificadores de las bibliotecas se almacenan en la memoria asignada. Pero nunca fueron usadas. Hemos encontrado otras funciones y rutas de código que nunca se utilizan. Es probable que se haya eliminado el código sobrante que no se quitó durante las actualizaciones de código.

 

Ofuscación XOR

 

Las cadenas y la clave RSA, como en versiones anteriores, están ofuscadas mediante XOR. Se utiliza la siguiente estructura:

typedef emotet_xor_data_t {
    uint32_t xor_key;
    uint32_t len;
    uint32_t data[];
} emotet_xor_data_t;

Se descifran, en primer lugar, mediante disyunción exclusiva de len with xor_key. A continuación, la longitud len de data se descodifica y redondea al siguiente múltiplo de 4 y se efectúa su disyunción exclusiva con xor_key:

 

 

Aunque la clave XOR cambia de código binario a código binario, el proceso de decodificación se puede automatizar. Por ejemplo, el script emotet_string_decode.py script puede decodificar cadenas usadas:

 

 

Por tanto, se descifran a petición para una nueva asignación de memoria sobre la marcha. La asignación de memoria que contiene la cadena descifrada se elimina después de cada uso de la cadena.

 

Tutorial de análisis estático

 

Con los conceptos básicos de las nuevas técnicas de ofuscación cubiertos, a continuación, describimos brevemente cómo es posible analizar Emotet.

  1. Saca tu muestra de Emotet (por ejemplo, utilizando la sandbox CAPE, una herramienta gratuita de código abierto y desarrollo comunitario [CAPE]).
  2. Importa la muestra a Ghidra [GHIDRA].
  3. Ejecuta el análisis automático.
  4. Ejecuta py con currentAddress en la 2ª función llamada en la función entry (la función emotet_get_lib).
  5. Ejecuta py (seleccionando func_names.txt) con currentAddress en la 3ª función llamada en la función entry (la función emotet_get_func).
  6. Ejecuta py con currentAddress en la funci´no emo_* _LoadLibraryW.
  7. Ejecuta py con currentAddress en la 1ª función llamada en la función emo_* _LoadLibraryW.

 

De este modo se obtiene lo siguiente:

  • Comentarios para la resolución de bibliotecas y funciones.
  • Dos tipos de enumeración emotet_-lib,func-_hash con enumeraciones para los hashes de bibliotecas y funciones, que puedes aplicar opcionalmente a las funciones emotet_get_-lib,func.
  • Cadenas de Emotet descifradas y puestas en comentario, etiquetas, así como marcadores localizables.

 

La comunicación C2 se encuentra buscando el uso de la función HttpSendRequestW.  El tipo de solicitud y los encabezados de las solicitudes se pueden encontrar retrocediendo a HttpSendRequestW desde el primer parámetro (hRequest). Como alternativas al uso de la función HttpOpenRequestW, la función InternetConnect, la cadena POST o la cadena Referer: http://%s/%s … producen el código correspondiente.

El almacenamiento de direcciones IP para C2 se puede encontrar buscando la cadena %u.%u.%u.%u. Estos octetos se rellenan mediante una asignación que denominamos emotet_c2_data. Los datos de la asignación proceden de una ubicación de datos que hemos denominado emotet_c2_list. Si ejecuta emotet_ip_decode.py con currentAddress conteniendo la dirección de emotet_c2_list, la lista de C2 se descodifica y se anota como un comentario.

La plantilla de solicitud de HTTP de C2 tiene el siguiente aspecto:

POST
Referer: http://%s/%s
Content-Type: multipart/form-data; boundary=%s

--%S
Content-Disposition: form-data; name="%s"; filename="%s"
Content-Type: application/octet-stream

 

Busca funciones que usen la función OpenSCManagerW. Una función contendrá una asignación a una ubicación de datos. Emotet emplea OpenSCManagerW para comprobar si tiene derechos de administrador o no. Aquí es donde se activa lo que llamamos la bandera is_admin. Utiliza «Auto Create Structure» en la referencia de datos y llámalo emotet_data. A continuación, nombra el campo al que se ha asignado el valor 1 es_admin.

 

Busca funciones que usen la cadena %s\%s.exe. Aquí es donde se construye la ruta del ejecutable. En su proximidad se accede a la ubicación de los datos de emotet_data. Determina, por su uso como parámetros de la función _snwprintf, cuál de los dos campos de la estructura emotet_data es la ruta exe_ y cuál es el nombre exe_.

 

A continuación, usa «References -> Find use of emotet_data_t.exe_name» para averiguar cómo se genera el exe_name. Haz lo mismo con el exe_path. El exe_name también se usará para generar el nombre del servicio. El código relevante se encuentra buscando en CreateServiceW.

La persistencia a través de las claves de ejecución se encuentra a través de RegCreateKeyExW y/o la cadena SOFTWARE\NMicrosoftWindows\NCurrentVersion\NRun.

Buscando el uso de la cadena %s:Zone.Identifier se encuentra el punto en que Emotet borra su ADS Zone.Identifier, que en Windows se utiliza para marcar los archivos descargados de sitios externos como potencialmente peligrosos.

Como nota interesante, las versiones nuevas menos recientes contenían código que eliminaba los antiguos archivos binarios de Emotet cuyos nombres se generaban a partir de listas de palabras:

 

 

Esta funcionalidad se ha eliminado de la versión más reciente, lo que indica que la migración a la nueva versión se ha completado para la botnet de época 2 y ya no es necesario eliminar archivos binarios antiguos:

 

 

(O también puede ser que la función se haya movido y no ha sido detectada por nuestro script de desofuscación de cadenas.)

El siguiente vídeo muestra cómo puedes utilizar nuestros scripts para iniciar tu propio análisis del descargador de Emotet:

Reproductor de vídeo:

 

 

Descarga nuestros scripts en Github.

 

 

Geolocalización de servidores de C2 de nivel 1

Los servidores y proxies de C2 de nivel 1 de Emotet están geolocalizados en todo el mundo:

(Lista de IP C2 observada 2020-04-20.)

 

Conclusión y soluciones

 

 

Para protegerse contra Emotet, el CERT de EE. UU. recomienda “implementar filtros en la puerta de enlace de correo electrónico para descartar los correos electrónicos con indicadores de malspam conocidos» [USCERT].

 Spam and Malware Protection de Hornetsecurity, con las tasas de detección más altas del mercado, no se ve afectado por las actualizaciones del descargador de Emotet (ya que el descargador nunca se envía directamente a través de correos electrónicos) y por lo tanto seguirá bloqueando todos los indicadores de malspam de Emotet, tales como documentos con macros utilizados para la infección, así como los enlaces de descarga de Emotet conocidos.  Advanced Threat Protection de Hornetsecurity amplía esta protección mediante la detección de enlaces maliciosos desconocidos mediante la descarga dinámica y la ejecución del contenido potencialmente malicioso en un entorno supervisado y aislado. Por tanto, incluso si el descargador de Emotet cambia y adopta nuevas tácticas de distribución, ¡en Hornetsecurity estamos preparados!

 

Además de bloquear los correos electrónicos entrantes de Emotet, los expertos en ciberseguridad pueden emplear la información hecha pública por el equipo de Cryptolaemus, un grupo de voluntarios formado por expertos en seguridad informática para luchar contra Emotet. En su sitio web [CryptolaemusWeb] proporcionan información nueva a diario. Allí podrás obtener la última lista de IPs de C2 para encontrar y/o bloquear el tráfico de C2. Para obtener actualizaciones en tiempo real, puedes seguir su cuenta de Twitter [CryptolaemusTwitter].

Somos conscientes de que el análisis que hemos presentado sólo araña la superficie del complejo de malware Emotet, pero cuando Emotet regrese también lo haremos nosotros, con análisis actualizados de nuevos documentos maliciosos y cualquier otra novedad.

 

Referencias

Muestras utilizadas

 

Hashes

SHA256 Descripción
cc96711da9ef7b63d5f1749d8866b0149f84506f9d53d79de018dac92e9443a0 Muestra de época 1 («versión antigua») 2020-04-20
Muestra de carga útil de época 1 desempaquetada 2020-04-20
4250a3ab9044b4a3a5f8319e712306bb06df61b1dee8b608505c026bacba4aa1 Muestra de época 2 (versión «nueva») 2020-04-20
14f8463a86bbae338925fbbcb709953ae7f1bffdb065fee540b6fa88fbbce70e Muestra de carga útil de época 2 desempaquetada 2020-04-20