Exorcizando demonios: el soporte técnico falso entrega Havoc Command & Control

Agradecimientos: Un agradecimiento especial a Matt Anderson y Craig Sweeney por sus esfuerzos en detectar y sacar a la luz este comportamiento.

Contexto 

Las estafas de soporte técnico falso no son nada nuevo, pero las cargas útiles que entregan están recibiendo una actualización seria. Lo que antes terminaba con la compra de una tarjeta de regalo de $300 ahora termina con un framework Havoc C2 modificado incrustado en tu entorno, que aprovecha syscalls indirectas para evadir EDR y C2 de respaldo basados en el registro que el Havoc estándar ni siquiera incluye.

En febrero de 2026, Huntress identificó un grupo de intrusiones en cinco organizaciones socias que siguieron este mismo patrón: spam por correo electrónico como carnada, una llamada telefónica de “soporte de TI” como anzuelo, y una cadena de entrega de malware por capas como remate. En una organización, el atacante avanzó desde el acceso inicial hasta nueve endpoints adicionales en el transcurso de once horas, desplegando una combinación de cargas útiles personalizadas de Havoc Demon y herramientas de RMM legítimas para mantener la persistencia, y la velocidad del movimiento lateral sugiere firmemente que el objetivo final era la exfiltración de datos, ransomware, o ambos.

El uso de ataques de spam coordinados y contacto de soporte técnico falso no es nada nuevo en el ámbito de la seguridad. Investigadores de Sophos previamente documentaron campañas similares con vínculos a Black Basta y FIN7  en enero de 2025. Sin embargo, la coincidencia entre esa investigación anterior y la actividad que observamos sugiere un vínculo más insidioso, uno que persiste a pesar de la disrupción de Black Basta. Los atacantes emplearon tácticas idénticas: almacenar parámetros de comando y control en el registro, aprovechar el sideloading extensivo de DLL para mantener la persistencia, y desplegar técnicas similares para plantar malware en los sistemas objetivo.

Se rumora que Black Basta quedó inactivo a fines de 2025 tras filtraciones de chats internos y presión coordinada de las fuerzas del orden de agencias alemanas y ucranianas, sin embargo su manual de estrategias distintivo parece seguir activo en el mundo real. Esto apunta a dos escenarios preocupantes: antiguos afiliados de Black Basta migraron a otras operaciones de ransomware y trajeron consigo sus técnicas, o actores de amenazas rivales están adoptando sus manuales de estrategias para la ingeniería social y la intrusión de redes.

Este blog recorre toda la cadena de ataque que observamos, desde el panel falso de Outlook Antispam que dio inicio a todo, pasando por el sideloading de DLL hasta el agente Havoc Demon modificado en el núcleo de todo esto. En el camino, compararemos dos implementaciones de loader muy distintas del mismo operador, desarmaremos el mecanismo de syscalls indirectas del Demon y examinaremos cómo el atacante personalizó un framework de código abierto para incorporar resiliencia operativa.

Puntos clave

Esta campaña demuestra una fusión muy efectiva de la ingeniería social tradicional con técnicas avanzadas de seguridad ofensiva (y algunos errores). Al analizar estas intrusiones, hemos identificado varios temas críticos:

  • El acceso inicial centrado en el ser humano está creciendo: Los adversarios siguen teniendo éxito al eludir los controles técnicos mediante interacción humana directa. Los adversarios están más que dispuestos a hacerse pasar por personal de TI, y no dudan en llamar a números de teléfono personales o participar en comunicación de voz directa para lograr sus objetivos.
  • La democratización de la evasión avanzada: Técnicas que antes se reservaban para ataques a grandes empresas o para campañas de espionaje ahora son comunes en ataques dirigidos a empresas de todos los tamaños. A medida que los EDR se han vuelto más sofisticados, los adversarios han tenido que evolucionar rápidamente sus técnicas para evadir la detección.
  • Personalización de frameworks para mayor resiliencia: Las variantes de malware comunes y los frameworks de comando y control tienen firmas muy reconocibles. Los adversarios han identificado la gran capacidad de los proveedores de seguridad para reconocer patrones asociados con configuraciones “predeterminadas”. Al modificar estos agentes para introducir nuevos comportamientos, el reconocimiento basado en patrones debilita las herramientas de detección heurística. 
  • Movimiento lateral agresivo: La velocidad del actor de amenazas es una preocupación principal; pasar del compromiso inicial a nueve endpoints adicionales en un período corto sugiere una operación “manual” bien practicada, coherente con una rápida exfiltración de datos y despliegue de ransomware. 
  • Estrategias de persistencia diversificadas: El adversario utilizó numerosas técnicas para mantener la persistencia, incluso después de que los esfuerzos de seguridad eliminaran técnicas avanzadas. A menudo, al analizar malware sofisticado o complejo, la simple actividad de RMM operada por el adversario puede pasar desapercibida.

Anatomía de la intrusión: Rastreando el camino hacia Havoc C2

Figura 1: Cadena de intrusión

Actividad de soporte técnico falso

El 17 de febrero de 2026, el equipo de Huntress Tactical Response recibió una notificación de una cadena anómala de ejecución de procesos de parte de nuestro equipo de Ingeniería de Detección y Threat Hunting (DE&TH) en un entorno de un socio. El análisis de los datos llevó a una investigación de varios días y múltiples intrusiones en cinco organizaciones socias de Huntress, lo que reveló un grupo de compromisos significativos y calculados.

El ataque comenzó con una campaña de spam, en la que el adversario atacó a organizaciones con correos masivos. La selección de cuentas fue deliberada, probablemente basada en la posibilidad de contactar al usuario final, como lo demuestra el uso del número de celular personal de un usuario como método de contacto elegido en un caso.

Una vez que los usuarios se vieron abrumados por el spam, los adversarios, haciéndose pasar por soporte técnico falso, los contactaron. Afirmaron falsamente que necesitaban acceso remoto al dispositivo del usuario para realizar actualizaciones de Outlook u otras "remediaciones" para detener el spam. Luego se persuadió a los usuarios de aprobar una sesión de QuickAssist o de instalar aplicaciones de acceso remoto como AnyDesk, lo que le dio al atacante acceso práctico a el endpoint.

Con el acceso obtenido, el adversario utilizó la herramienta de gestión remota para abrir un navegador web y navegar a un panel fraudulento de Microsoft alojado en Amazon AWS, todo mientras el usuario observaba. El atacante luego instruyó al usuario a ingresar su correo electrónico y acceder al “Panel de control antispam de Outlook”. Desde este panel falso, descargarían el “Parche antispam” e iniciarían una prueba de las "reglas". Este botón de "probar reglas" copiaba un script diseñado para reconstruir e implementar un payload de seguimiento.


Para mantener la ilusión de que un administrador remoto legítimo está ayudando con el spam, se incrusta un script dentro del botón de configuración de reglas. Este script activa una superposición que le pide al usuario su contraseña, seguida de una serie de actualizaciones de progreso falsas. Este mecanismo cumple dos propósitos: le permite al actor de amenazas (TA) recolectar credenciales, que, combinadas con el correo electrónico requerido, dan acceso al panel de control; al mismo tiempo, añade una capa de autenticidad a la interacción, convenciendo al usuario de que el proceso es genuino.

Figura 2: Falso panel de control antispam de Outlook creado por el adversario


El parche antispam en este caso es un archivo zip modificado con un título patch<numbers>.1 que se descarga a la carpeta de Descargas del usuario. El adversario luego usa una serie de comandos para desplegar este payload:

  1. Se crea el archivo resources.zip con el contenido PK, que es el encabezado de un archivo zip. 
  2. El resto del archivo zip (patch<numbers>.1) se agrega al contenido de resources.zip, reconstruyendo el payload como un archivo zip legítimo.
  3. El adversario luego crea el directorio %PROGRAMDATA%\Adobe\ARM 
  4. Luego extraen el archivo zip protegido con contraseña a esta ubicación de ARM y eliminan tanto resources.zip como patch<numbers>.1. 
  5. El contenido de este archivo zip está numerado del 1 al 6, para lo cual proporcionamos una referencia a continuación:

Número de archivo

Nombre del archivo

1

license.key

2

vcruntime140_1.dll

3

vcruntime140_2.dll

4

ADNotificationManager.exe

5

msvcp140.dll

6

vcruntime140.dll


  1. Luego se agregan dos valores de registro a HKCU\SOFTWARE\Classes\Local Settings\Software\Microsoft como UXMP y UCID. 
  2. El valor UXMP se elimina de la misma ubicación. Este valor de registro contiene la ubicación de instalación del archivo license.key, pero según nuestra experiencia, el malware ni el adversario lo configuraron nunca, por lo que esta eliminación probablemente sea superflua. 
  3. Luego el adversario ejecuta ADNotificationManager.exe (o binarios adicionales, que se analizan más adelante), lo que finalmente pone en marcha el malware.

Figura 3: Pantalla falsa de progreso de Outlook creada por el adversario

Carga lateral de DLL

Tras la actividad falsa de soporte técnico y, finalmente, la ejecución exitosa del payload en el endpoint, el análisis de los datos sugiere que la carga lateral de DLL fue el método elegido por el adversario para seguir causando daño en el sistema.

En nuestro análisis, observamos tres binarios legítimos que el adversario utilizó para cargar su payload malicioso en DLL: DLPUserAgent.exe, ADNotificationManager.exe y Werfault.exe. Estos archivos son benignos y están firmados legítimamente, y el adversario no los manipuló. En cambio, son vulnerables a una técnica conocida como "carga lateral de DLL", mediante la cual el adversario puede colocar un archivo .DLL creado maliciosamente dentro de la ruta de búsqueda de DLL, y la aplicación cargará ese archivo .DLL. Esta no es una táctica poco común en el malware moderno; sin embargo, varias de las técnicas que emplea el adversario sugieren que se trata de un actor de amenazas sofisticado y relativamente avanzado.

Al analizar los sistemas afectados, notamos que se colocaron archivos .DLL creados maliciosamente junto a sus aplicaciones legítimas, y mediante el uso de reenvío o proxy de DLL, también notamos que la versión legítima de la DLL estaba ubicada junto a la maliciosa, para evitar que las aplicaciones generaran errores al ejecutarse por falta de importaciones.


Aplicación de carga

DLL legítima

DLL maliciosa

ADNotificationManager.exe

vcruntime140_2.dll

vcruntime140_1.dll

DLPUserAgent.exe

mpclient2.dll

mpclient.dll

WerFault.exe

mscvp.dll

faultrep.dll

Figura 4: Tabla de exportación de la vcruntime140_1.dll maliciosa, que muestra las tres funciones exportadas reenviadas a la vcruntime140_2.dll legítima, lo que permite que ADNotificationManager.exe funcione con normalidad mientras se ejecuta código malicioso desde el punto de entrada de la DLL

Se observaron TTPs similares en ambos casos. El adversario reenvió las funciones legítimas necesarias desde la DLL legítima, con el prefijo "2", pero el punto de entrada de la DLL provocó la ejecución de un cargador avanzado y altamente ofuscado.

Figura 5: DLL Forwarding en el archivo malicioso mpclient.dll, que apunta a mpclient2.dll, con un total de 158 exportaciones reenviadas


El análisis de estos binarios se vio muy obstaculizado por las tácticas de ofuscación del adversario. Su método principal para dificultar la ingeniería inversa fue el uso intensivo de "trampolines" o saltos arbitrarios a otras posiciones en el código. Esta táctica se volvió aún más efectiva al insertar componentes sutiles de código malicioso necesario dentro de estos trampolines. Esto dificulta las herramientas de ingeniería inversa al "confundir" la comprensión del descompilador sobre el código en una posición determinada, y además complica razonar sobre qué argumentos y valores pueden existir en el marco de llamada en un momento dado. De hecho, el uso intensivo de trampolines por parte del adversario requirió que también tomara en cuenta la forma poco convencional en que usaron el lenguaje, específicamente durante el preámbulo de Hell's Gate, que analizaremos más a fondo más adelante.

mpclient.dll y faultrep.dll

Estas DLL cargadas lateralmente están comprimidas con UPX y son triviales de descomprimir/aplicar ingeniería inversa, pero implementan técnicas de evasión de EDR que se reconocerán más adelante en el artículo.

El punto de entrada de la DLL carga y descifra el archivo license.key en memoria, con una opción de respaldo para leer el valor UXMP del registro HKCU\SOFTWARE\Classes\Local Settings\Software\Microsoft. Luego se descifra usando la clave ChaCha20 06 83 33 23 c5 e3 1a 82 73 be 47 b0 df 70 b9 4c c8 f3 8d 44 35 93 3b 91 81 1d 8b dd 95 26 8f 86.

Se observa una ruta de código independiente, responsable de instalar hooks de ntdll basados en Detours; se conectan dos hooks.

  • ntdll!RtlExitUserProcess - Antes de resolver "RtlExitUserProcess", se entra en un bucle de espera de 5000ms, lo que impide que los procesos terminen/salgan. 
  • ntdll!LdrUnloadDll - Las DLL en este proceso no se pueden descargar: esto siempre devolverá 0, indicando al proceso que lo llama que la descarga de la DLL fue exitosa, incluso si no lo fue.

Estas son medidas para ayudar a la ejecución y potencialmente frenar cualquier intento de terminar procesos.

En última instancia, mpclient.dll y faultrep.dll simplemente ejecutan el payload de shellcode de Havoc license.key al final de la ruta de código maliciosa. Digo simplemente porque... nuestra siguiente sección no tiene nada de simple.

vcruntime140_1.dll

Nos enfocaremos en vcruntime140_1.dll para el resto del análisis, ya que emplea técnicas mucho más novedosas, y el adversario claramente se tomó algunas libertades creativas después de sus últimos payloads maliciosos.

El payload se almacenó en la sección .rsrc del binario, detrás de numerosos trampolines que configuran el proceso de descifrado XOR y la ejecución del shellcode incrustado.

El vcruntime140_1.dll malicioso emplea varias tácticas adicionales para pasar desapercibido ante el software de seguridad moderno, incluyendo tomar prestada una gran parte de su base de código de binarios legítimos de ESET y retrasos de temporización de bucle ajustado únicos, probablemente para prevenir o confundir la emulación, especialmente en emuladores con soporte débil de SIMD.

Figura 6: Bucle de retardo antiemulación único

Cabe destacar que, más allá de la simple ofuscación de flujo de control y los bucles de retardo, el cargador emplea las técnicas de evasión de hooks de ntdll Hell's Gate y Halo's Gate.

Hell's Gate y Halo's Gate

Desarrollado por @am0nsec y @vxunderground, Hell's Gate nació de la necesidad de los profesionales de seguridad ofensiva de mantenerse un paso adelante de las soluciones EDR. Las tácticas de monitoreo tradicionales se enfocan en marcar llamadas sospechosas a VirtualAlloc mediante la instalación de "hooks" o rutas de código de las que el EDR es principalmente responsable, y que dan visibilidad sobre la función que realiza la llamada. Al aprovechar las syscalls directamente, Hell's Gate puede evadir los hooks en espacio de usuario al rodear su ruta de código.

Hell's Gate analiza ntdll.dll en memoria, examinando la tabla de direcciones de exportación para resolver las direcciones de las funciones, y luego extrae los números de servicio del sistema (SSN) directamente de los stubs de syscall mediante la comparación de opcodes para ubicar el valor de SSN dentro de cada stub.

Halo's Gate, una variante derivada, también fue desarrollada por @vxunderground como respaldo en caso de que el EDR haya conectado efectivamente estas funciones de una manera que derrote la búsqueda basada en patrones de Hell's Gate. Si el stub que Hell's Gate seleccionaría parece tener un hook del EDR (es decir, se altera el patrón esperado mov r10, rcx; mov eax, <SSN>), el binario recorre los stubs de syscall vecinos y deriva el SSN correcto calculando el desplazamiento entre entradas limpias.

Una vez que se resuelve el SSN de NtAllocateVirtualMemory, se carga en EAX, mientras que R10 conserva el registro de convención de llamada según lo requiere el ABI de syscall de Windows x64.

Un trampolín final prepara y conserva el estado de los registros a través de las transferencias de control ofuscadas antes de emitir directamente la instrucción syscall, evadiendo los hooks de API en espacio de usuario colocados por las soluciones EDR.


Figura 7: Hell's Gate y hooking de EDR en VirtualAlloc

Esto es particularmente potente por varias razones: cuando las aplicaciones maliciosas asignan memoria virtual, suelen usar estas regiones de memoria para almacenar payloads desofuscados, como shellcode, que serán ejecutados en etapas posteriores del malware. Al evadir específicamente el hooking de EDR de estas funciones, estas técnicas ayudan a mantener los payloads cifrados/codificados sin ser examinados.

Con este conocimiento, podemos rastrear con esfuerzo las rutas de código y eliminar/aplanar los saltos irrelevantes, hasta finalmente llegar al payload de 144.735 bytes en la sección .rsrc de la .dll que Hell's Gate finalmente asigna. El descifrado y la ejecución de este payload se configuran principalmente en los trampolines, donde los registros transportan diversos valores relacionados con las direcciones y el descifrado del recurso, junto con los parámetros de creación de procesos, lo que dificulta inferir estáticamente el estado de un registro en rutas de código profundas.

Figura 8: Trampolines, incluida la configuración de flags para la asignación de memoria syscall (Hell's Gate).

Finalmente, se lee una clave XOR (28 79 3f 78 41 79 38 3c 39 64 55 72 68 54 21 32 40 66 3e 42 44 54 37 78 70 00) más allá del pool de direcciones del VirtualSize en la sección .text, lo que dificulta aún más su obtención mediante decompilación convencional. En este caso, tenemos una clave XOR de 26 bytes con un byte nulo al final, lo que deja el carácter 26 de cada payload igual. La penúltima acción es ejecutar la siguiente etapa del loader, que detallamos en secciones posteriores.

Figura 9: Gráfico de llamadas que hace referencia a la clave XOR más allá del VirtualSize

Matriz de comparación de DLL

Generamos la siguiente matriz de comparación para ambas DLL para dar un resumen rápido de las características vistas hasta ahora:


Identidad


vcruntime140_1.dll

mpclient.dll

Objetivo de suplantación

MSVC Runtime

Windows Defender

Payload de camuflaje

ESET Security Software

Ninguno

Empaquetado

Ninguno

UPX

Tabla de direcciones de importación

Resolución dinámica

IAT estática normal

Descifrado

Cifrado externo

XOR, clave de 26 bytes

Ninguno

Cifrado interno

ChaCha20 en license.key

Idéntico

Clave ChaCha20

06 83 33 23 c5 e3 1a 82 

73 be 47 b0 df 70 b9 4c c8 f3 8d 44 35 93 3b 91 81 1d 8b dd 95 26 8f 86

Idéntico

Nonce de ChaCha20

Nulo

Idéntico

Carga de Havoc (license.key)

Ruta principal

.\license.key (CWD)

Idéntico

Alternativa de registro

HKCU\SOFTWARE\Classes\Local Settings\Software\Microsoft

Idéntico

Nombre del valor de registro

UXMP

Idéntico

Ofuscación de cadenas

Carácter por carácter

Idéntico

Hooks de Detours

RtlExitUserProcess

Bucle infinito de Sleep(5000)

Idéntico

LdrUnloadDll

Devuelve 0

Idéntico

Ofuscación y evasión

Ruta de ejecución hacia DllMain

Cadena de trampolines de 29 etapas

Llamada directa desde el inicio de CRT

Anti-emulación

Bucle cerrado de 4M

No se observó ninguno

Suplantación de código

Ingresa a la ruta de código de ESET

No se observó ninguno

Método de syscall

Syscall directa (Hellsgate)

Importación estándar de la API de Win32

Dentro del cargador reflectivo

El payload almacenado en .rsrc y codificado con XOR es un cargador de shellcode personalizado junto con un PE DLL correspondiente, que emplea varios trucos propios además de las técnicas discutidas hasta ahora. Dado que el cargador de shellcode es relativamente poco interesante, analizaremos en su lugar el PE DLL, ya que, en última instancia, el cargador solo se encarga de pasar el control de vcruntime_1.dll al PE DLL cargado reflectivamente, titulado internamente loader_vcruntime140_1.dll.

El objetivo de nuestro DLL incrustado es simple: obtener y ejecutar el contenido de license.key, que contiene el shellcode cifrado para el Havoc Demon. Para garantizar una ejecución sin interrupciones, se utilizan varios hooks de evasión de ntdll que aprovechan la API Detours de Microsoft antes de la ejecución final del Havoc demon.

Loading Gist...

Primero, el payload se descifra con una clave ChaCha20 de 32 bytes. En nuestra muestra, esta clave era 06 83 33 23 c5 e3 1a 82 73 be 47 b0 df 70 b9 4c c8 f3 8d 44 35 93 3b 91 81 1d 8b dd 95 26 8f 86. Esta es la misma clave ChaCha20 que se encuentra en mpclient.dll. Además, utilizó un nonce compuesto solo por bytes nulos. Cabe destacar que se asume que license.key se encuentra en el mismo directorio de trabajo. Este cargador genera un intento de lectura de HKCU\SOFTWARE\Classes\Local Settings\Software\Microsoft, específicamente del valor UXMP. Este contendría la ruta de license.key si no estuviera ubicado en el mismo directorio. Dado que nuestro adversario elimina esta clave durante la ejecución, podría usarse como un método de exclusión mutua (mutex) para intentar evitar conflictos en la ejecución de varios implantes de Havoc, aunque consideramos más probable que se trate simplemente de código remanente o una función sin utilizar del cargador.

Una vez que el payload se descifra y existe en memoria, se utilizan los hooks de evasión para evitar interrupciones en la ejecución del proceso.

El primero crea un bypass en ntdll!RtlExitUserProcess. Cuando se llama a esta función, la API Detours permite al adversario generar su propio código para ejecutar antes de que se termine el proceso. En este caso, se llama a un bucle de suspensión de 5000 ms. Esto evita que la función se resuelva alguna vez, lo que significa que la ejecución del malware se mantiene incluso cuando se intenta terminar el proceso (específicamente a través de esta función de alto nivel de ntdll).

El segundo realiza hooking en ntdll!LdrUnloadDll, que, como su nombre indica, simplemente bloquea la descarga de DLL. Esto mantiene los estados de carga de DLL y ayuda a preservar las cadenas de ejecución, permitiendo que el malware se ejecute sin interrupciones por parte del software de seguridad. Lo hace simplemente devolviendo "0" antes de realizar cualquier otra acción, indicando al proceso que llama que la ejecución se terminó exitosamente sin errores.

Esto refleja la ejecución del hooking de ntdll basado en Detours que se encuentra en mpclient.dll.

A continuación, se genera el hilo que contiene el Havoc Demon. En nuestros casos, esto a menudo apuntaba a notepad.exe como destino de generación, pero creemos que esto no se ejecutó con éxito en uno de los casos examinados, lo que dificulta enumerar los procesos de destino.

Invocando al demonio: analizando el agente C2 Havoc modificado

¿Qué es Havoc?

Havoc es un framework de comando y control posterior a la explotación, de código abierto, moderno y maleable, creado por @C5pider, diseñado como una alternativa a herramientas comerciales como Cobalt Strike. Según la documentación oficial, el framework Havoc se divide en dos partes:

  • Teamserver: un servidor basado en Golang que gestiona a los operadores conectados, administra los listeners, analiza las devoluciones de llamada (callbacks) de los agentes y maneja los archivos descargados y las capturas de pantalla de los agentes. El Teamserver también construye los payloads de Demon (el agente implante de Havoc) en el momento de la generación, usando compiladores cruzados mingw y NASM. Utiliza perfiles de configuración Yaotl (.yaotl) para definir operadores, listeners y el comportamiento del C2. Soporta la funcionalidad ExternalC2 a través de endpoints de servicio, lo que permite que agentes de terceros personalizados (como Talon) interactúen con el Teamserver mediante una API intermedia de Python. Aunque Havoc soporta agentes de terceros como Talon, Demon es el agente integrado principal y el foco de este análisis.
  • Client: una interfaz de operador basada en C++/Qt donde los operadores se conectan al Teamserver, interactúan con los agentes, asignan comandos y reciben resultados. Este es el componente de interfaz de usuario, que no debe confundirse con el agente Demon en sí.

El repositorio de Havoc se archivó el 20 de febrero de 2026, lo que significa que el proyecto ya no recibe mantenimiento activo. Sin embargo, el código fuente completo sigue disponible públicamente, lo que permite a los actores de amenazas bifurcarlo (fork), modificarlo y crear variantes personalizadas.

Evadiendo a los guardianes

Los productos EDR realizan hooking en las funciones de ntdll.dll sobrescribiendo sus primeros bytes con un jmp hacia el código de monitoreo. El Demon evade estos hooks usando syscalls indirectos, así que en lugar de llamar a las funciones con hooking, extrae los Syscall Service Numbers (SSNs) y ejecuta la instrucción syscall desde dentro de la memoria propia de ntdll.

Cada función Nt* en ntdll sigue el mismo patrón de stub:

Loading Gist...

El Demon extrae el SSN de cada stub, lo que indica al kernel qué función ejecutar. También localiza la dirección de la instrucción syscall dentro de NtAddBootEntry en ntdll. Cuando el Demon necesita llamar a cualquier API Nt*, coloca el SSN extraído en EAX y salta a esa dirección de syscall dentro de ntdll, de modo que el puntero de instrucción (RIP) apunte a la memoria legítima de ntdll cuando se ejecuta la syscall, haciendo que parezca normal para el EDR.

Las aproximadamente 36 APIs comparten esta única dirección de syscall de NtAddBootEntry, lo cual es coherente con la documentación de Havoc, que describe los stubs de syscall "modificados para que la dirección de retorno apunte a NtAddBootEntry dentro del módulo ntdll.dll".

Figura 10: El ejecutor de syscall indirecto: carga el SSN extraído en EAX y luego salta a la instrucción syscall dentro de ntdll 

Ese jmp qword ptr [r11] es el syscall indirecto: salta a la instrucción syscall dentro de NtAddBootEntry en ntdll, por lo que la CPU lo ejecuta con RIP apuntando hacia la memoria legítima de ntdll. Esta única dirección de syscall se comparte como destino de salto para los aproximadamente 36 syscalls indirectos.

Durante la inicialización, Demon escanea alrededor de 36 funciones Nt* en ntdll en busca del patrón de bytes 4C 8B D1 B8 (mov r10, rcx; mov eax, <SSN>) para extraer el SSN de cada función de forma dinámica en tiempo de ejecución en lugar de codificarlo de forma fija; esta es la técnica conocida como Hell's Gate, mencionada anteriormente.

Si el EDR engancha el stub objetivo (se sobrescribe el patrón 4C 8B D1 B8), Demon no se rinde. Recorre las funciones Nt* vecinas, arriba y abajo en la memoria, hasta encontrar un stub limpio, y luego calcula el SSN correcto por desplazamiento (SSN_vecino - distancia o SSN_vecino + distancia). Esta técnica de respaldo se llama Halo's Gate y se mencionó anteriormente.

Figura 11: Respaldo de Halo's Gate: cuando un stub objetivo está enganchado, Demon recorre las funciones Nt vecinas, arriba y abajo en la memoria, hasta encontrar una limpia, y luego calcula el SSN correcto por desplazamiento

Cargador de shellcode

El agente Demon se entrega como un shellcode independiente de la posición. Antes de que Demon pueda ejecutarse, un cargador de shellcode debe inicializarlo: encontrar dónde está cargado en memoria, localizar ntdll, resolver algunas API importantes y mapear manualmente la DLL de Demon incluida en el proceso. Este es un shellcode de Havoc sin modificar, también conocido como KaynLdr (agradecemos a @C5pider por señalarlo).

El cargador se inicializa en tres pasos: primero, encuentra su propia dirección base; a diferencia de un EXE normal que se carga en una dirección conocida, el shellcode se inyecta en memoria arbitraria y no tiene idea de dónde está. El truco clásico call $+5 resuelve esto: call coloca la dirección de la siguiente instrucción en la pila, y luego pop rcx la captura, lo que le da al shellcode su propia ubicación para poder encontrar la DLL de Demon incluida en relación con esa posición. A partir de ahí, escanea hacia atrás en busca del encabezado MZ para encontrar la base de la imagen. Luego, recorre la InMemoryOrderModuleList del PEB para ubicar ntdll.dll mediante el cálculo de resúmenes criptográficos de cada nombre de módulo con DJB2. Finalmente, analiza la tabla de exportación de ntdll para resolver tres funciones NTAPI, calculando el resumen criptográfico de cada nombre exportado y comparándolo con los resúmenes objetivo: LdrLoadDll (0x14249D31), NtAllocateVirtualMemory (0x60B9BE9A), y NtProtectVirtualMemory (0xE77E3076). Estas se usan para mapear manualmente la DLL de Demon incluida en la memoria: NtAllocateVirtualMemory asigna espacio, el cargador copia las secciones del PE y procesa las reubicaciones, y NtProtectVirtualMemory establece los permisos de página correctos.

Figura 12: El shellcode captura su propia dirección mediante call $+5, y luego escanea en busca de la firma MZ/PE para ubicar la DLL de Demon incluida

El Demon resuelve todas las API de Windows en tiempo de ejecución usando cálculo de resúmenes criptográficos DJB2 con una semilla distinta a la del código fuente original:

Loading Gist...

Curiosamente, el binario contiene dos implementaciones de DJB2 independientes con semillas distintas. El cargador de shellcode usa la semilla 0x2673 y solo se usa durante la etapa inicial de mapeo del PE, resolviendo NtAllocateVirtualMemory, NtProtectVirtualMemory y LdrLoadDll desde ntdll. La función de hash propia del agente Demon usa una semilla distinta, 0x16AA, y maneja todas las resoluciones de API en tiempo de ejecución, incluidas las API Nt*, las búsquedas de módulos y la resolución de NtAddBootEntry para el gadget de syscall indirecta.

Configuración y C2

La configuración del Demon está incrustada en el binario como texto plano:

Loading Gist...

Los campos Spawn64/Spawn32 definen el proceso en el que Demon se lanza e inyecta para las operaciones de fork-and-run. Normalmente, se configura con un binario legítimo de Windows como C:\Windows\System32\notepad.exe, que es justo lo que observamos en otra muestra de Havoc Demon de la misma campaña. El valor 123.exe sin ruta completa es inusual y podría indicar una implementación de prueba o configurada apresuradamente.

Todas las cadenas de configuración se almacenan como cadenas anchas UTF-16LE en la región de configuración. Las rutas de URL de C2 están diseñadas para imitar endpoints de API legítimos y mezclarse con el tráfico web normal. Estos valores son configurados por el operador a través del perfil Yaotl del Teamserver al momento de generar el payload, lo que los convierte en IoC específicos de esta campaña, no en valores predeterminados de Havoc. La única excepción es demon.x64.dll, que es el nombre interno de PE predeterminado del código fuente de Havoc.

Las rutas de URL de C2 se configuran a través del perfil del listener del Teamserver de Havoc; definen los endpoints URI a los que se conecta el agente Demon para recibir tareas.

El Demon lee tres valores del registro en tiempo de ejecución. Los tres usan las mismas dos rutas del registro, con HKCU como valor principal y HKLM como respaldo:

  • Principal: HKCU\SOFTWARE\Classes\Local Settings\Software\Microsoft\
  • Respaldo: HKLM\SOFTWARE\Microsoft\SQMClient\

Los tres valores del registro cumplen cada uno un propósito distinto. UXMP probablemente almacena la ruta del archivo del payload de Demon en el disco; cuando el agente necesita realizar operaciones de fork-and-run, lee esta ruta, crea una tubería con nombre aleatorio (\\.\pipe\{GUID}) y llama a CreateProcessW para generar un proceso sacrificial con el fin de ejecutar tareas posteriores a la explotación.

Los valores UFID y UCID funcionan en conjunto: después de leer los datos del registro, el Demon configura un descifrado ChaCha20 usando la salida de UCID como material de clave, con un nonce fijo de 12 bytes (41 98 B6 39 77 EA 2B F0 A4 2D 42 22). El resultado descifrado se interpreta como una lista de entradas de C2 con dirección y puerto para la comunicación de respaldo.

Este mecanismo de recuperación de C2 basado en el registro no forma parte de Havoc estándar. En el framework predeterminado, las URLs de C2 están incrustadas en el blob de configuración en tiempo de compilación, y no existe un mecanismo de respaldo en el registro. Esta modificación le da al operador una capa de resiliencia; si los servidores C2 codificados son dados de baja o aislados (sinkholed), el Demon puede recuperar un nuevo conjunto de direcciones C2 desde el registro sin necesidad de ser redistribuido. Este es un indicador notable de que el operador personalizó el framework Havoc más allá de sus capacidades predeterminadas.


Figura 13: C2 cifrado y clave ChaCha20 en el registro

Figura 14: C2 descifrados (fuente: CyberChef)

De Havoc al caos

Tras la implementación exitosa del Havoc Demon en el endpoint de entrada inicial, los actores de amenazas comenzaron el movimiento lateral por el entorno de la víctima. Si bien la ingeniería social inicial y la entrega del malware mostraron algunas técnicas interesantes, la actividad práctica (hands-on-keyboard) que siguió fue comparativamente sencilla.

Preparación de payloads adicionales

Como el compromiso inicial ocurrió a las 20:18 UTC del 20 de febrero de 2026, el adversario no perdió tiempo. Apenas 50 minutos después, a las 21:08 UTC, ya se estaban creando tareas programadas en todo el entorno. Estas tareas se registraron en cuatro de los nueve endpoints comprometidos, cada una apuntando a un script por lotes ubicado en C:\Windows\SoftwareDistribution\Download\go.bat, un directorio que almacena temporalmente los archivos de Windows Update, elegido para mezclarse con la actividad legítima del sistema. Las tareas programadas aseguraban que, en cada arranque del sistema, el script por lotes se ejecutara, reconstruyendo y lanzando el payload del Havoc Demon, lo que le daba al adversario acceso persistente a C2 que sobrevivía a los reinicios:

Loading Gist...

En un detalle particularmente curioso, el adversario incluyó echo “Update completed” al final del script, de modo que si alguien llegaba a notar la breve ventana de consola que parpadeaba durante el arranque, asumiera que era solo una actualización rutinaria de Windows.

El adversario dividió su payload en varios archivos .dat con el prefijo c_, que se concatenaron en un archivo .cab, se expandieron y se renombraron con sus nombres de archivo finales. Esta técnica refleja la cadena de infección inicial observada en el punto de entrada: el payload se fragmentó para evadir la detección y se reensambló en disco en el momento de la ejecución. El payload final consistió en WerFault.exe (un binario legítimo de informes de errores de Windows), faultrep.dll (una DLL maliciosa de sideloading), msvcp.dll, y el ya conocido license.key que contiene el shellcode cifrado del Havoc Demon. El análisis de faultrep.dll confirmó que comparte la misma funcionalidad que mpclient.dll de la infección inicial: ambas están empaquetadas con UPX y usan la misma clave ChaCha20 para descifrar license.key. El uso de WerFault.exe como binario para el sideloading sigue el mismo patrón de sideloading de DLL establecido anteriormente en la cadena de ataque, sustituyendo una vez más un binario de Windows legítimo y firmado.

Los nombres de las tareas programadas en los endpoints afectados eran puramente numéricos (p. ej., 1771621617, 1771621855, 1771621990, 1771622115). Es probable que estos valores sean marcas de tiempo Unix epoch, cada una convertida a un momento de dos a siete minutos antes de que la tarea se registrara realmente en el endpoint de destino, lo que indica que el nombre de la tarea se generó en el momento en que el adversario inició la implementación, y el pequeño retraso refleja el tiempo que tomó llegar y ejecutar en cada endpoint. Las cuatro tareas programadas se crearon dentro de una ventana de nueve minutos, comenzando a los +50 minutos después del compromiso inicial y terminando a los +59 minutos, lo que indica una implementación rápida y secuencial.

BYORMM: trae tu propia herramienta de monitoreo y administración remota

Vale la pena notar que no todos los endpoints comprometidos recibieron el payload de Havoc mediante una tarea programada. El adversario también implementó herramientas legítimas de monitoreo y administración remota (RMM) en los endpoints restantes, diversificando sus mecanismos de persistencia en todo el entorno.

Level RMM fue la primera herramienta RMM implementada, apareciendo en dos endpoints a las 21:26 y las 21:44 UTC, poco más de una hora después del compromiso inicial. Se ejecutó con una clave de inscripción (--key uGTYwD7VzX3bnwX9PVGdXtiD) para registrar los agentes en un inquilino controlado por el adversario.

Figura 15: Detecciones de Huntress para la persistencia del agente Level RMM, que muestra la clave de inscripción usada para registrar el agente en un inquilino controlado por el adversario

XEOX, un agente RMM menos conocido, apareció en tres endpoints adicionales aproximadamente once horas después del compromiso inicial, comenzando a las 07:14 UTC del 21 de febrero.


Figura 16: Detecciones de Huntress para la persistencia del agente XEOX RMM mediante tareas programadas


En total, el adversario se movió desde el punto de apoyo inicial hacia nueve endpoints adicionales, implementando tres mecanismos de persistencia distintos en todo el entorno: payloads de Havoc Demon mediante tareas programadas en cuatro endpoints, Level RMM en dos endpoints y XEOX RMM en tres endpoints. Ningún endpoint individual recibió las tres herramientas; en cambio, el adversario distribuyó diferentes herramientas entre distintos endpoints, lo que aseguraba que el descubrimiento y la remediación de un mecanismo de persistencia no eliminara el acceso a todo el entorno. El uso de herramientas RMM legítimas como mecanismos de persistencia presenta un desafío de detección particular: se trata de aplicaciones firmadas y confiables que suelen encontrarse en entornos administrados, lo que dificulta distinguirlas del uso autorizado sin contexto adicional o correlación con otra actividad sospechosa. La brecha de aproximadamente diez horas entre las implementaciones de Level y XEOX podría sugerir una pausa operativa antes de que el adversario regresara al entorno para establecer persistencia adicional.

Conclusión

Lo que comienza como una llamada telefónica de “soporte de TI” termina en un compromiso de red totalmente instrumentado: Havoc Demons modificados implementados en los endpoints, herramientas RMM legítimas reutilizadas como persistencia de respaldo. Esta campaña es un caso de estudio de cómo los adversarios modernos añaden sofisticación en cada etapa: ingeniería social para entrar, sideloading de DLL para permanecer invisibles, y persistencia diversificada para sobrevivir a la remediación.

Dicho esto, el contraste entre las docenas de trampolines con llamadas al sistema HellsGate de vcruntime140_1.dll y el hecho de que mpclient.dll esté empaquetado con UPX sugiere que el compromiso del adversario con la sofisticación es algo inconsistente. Un cargador recibió el tratamiento completo de un equipo rojo; el otro se lanzó un viernes por la tarde.

La distribución de tres mecanismos de persistencia distintos en nueve endpoints podría no reflejar una planificación operativa deliberada, sino más bien un adversario que se adapta sobre la marcha cuando los métodos iniciales no funcionan bien. Sin importar la intención, el resultado final sigue siendo un desafío de remediación: limpiar un mecanismo de persistencia de un solo endpoint no garantiza que el entorno esté libre, y la combinación de malware personalizado con herramientas RMM legítimas hace que el análisis completo del alcance sea esencial.

La velocidad del movimiento lateral, con tareas programadas que se implementan en cuatro endpoints dentro de la hora posterior al acceso inicial, sugiere firmemente que el objetivo final era la exfiltración de datos, el despliegue de ransomware, o ambos. Un adversario que se mueve a esta velocidad no está instalando una operación de espionaje a largo plazo; está corriendo para maximizar el acceso antes de que los defensores puedan responder.

Si tu estrategia de detección depende únicamente de atrapar el malware, ya perdiste la batalla; esta comienza en el momento en que un usuario final contesta el teléfono. User awareness training, la lista de aplicaciones aceptadas y la detección por capas no son opcionales: marcan la diferencia entre detectar esto en la etapa de ingeniería social y descubrirlo después de que varios endpoints ya estén comprometidos.

Recomendaciones

1. Adopta una defensa centrada en las personas

Debido a que el acceso inicial se basó en el spam y en un pretexto de soporte de TI, los controles técnicos suelen ser insuficientes para prevenir cierto grado de acceso inicial.

  • Security awareness training (SAT) - Considera ampliar la capacitación más allá de las tácticas simples. Las estafas de soporte técnico falso no son nada nuevo, y los usuarios siempre deben practicar un nivel de escepticismo saludable al usar las computadoras. Los usuarios capacitados representan la mayor barrera contra el acceso inicial del adversario. 
  • Exige autenticación fuera de banda - Exige la verificación de las solicitudes de los administradores de TI a través de un canal de comunicación secundario, como una llamada telefónica directa, un mensaje de texto o un sistema de mensajería interno separado de la solicitud inicial. Este simple paso ayuda a confirmar la legitimidad y puede frustrar los ataques de ingeniería social que suplantan al personal de TI. Realiza ejercicios de simulación con tu equipo para practicar cómo distinguir entre solicitudes de administrador de TI fraudulentas y legítimas.


2. Restringe y monitorea la ejecución de aplicaciones

El adversario abusó de varias aplicaciones legítimas de Windows y Adobe para distribuir su malware, pero esto no significa que debamos ignorar otras tácticas adicionales.

  • Usa una lista de aceptados para la ejecución de aplicaciones - La ejecución de aplicaciones de administración remota no debería pasar desapercibida para el personal de TI local; la forma más fácil de mitigar el abuso de herramientas de monitoreo y administración remota (RMM) es simplemente prohibir su ejecución en los entornos. La mayoría de las organizaciones utiliza una o dos; el uso de RMM adicionales siempre debería ser motivo de preocupación.
  • Audita regularmente el propósito de las RMM - Crea un inventario completo de qué agentes RMM pertenecen a qué organizaciones y audítalo con regularidad. No es inusual que Huntress reporte RMM anómalas de años de antigüedad en endpoints recién incorporados.


3. Evita el movimiento lateral

Una vez que se obtiene acceso local, los adversarios se moverán rápidamente por las redes, como lo demuestra este caso. Crear barreras al movimiento lateral a menudo les da a los defensores tiempo crítico para clasificar y responder a las intrusiones en la red.

  • Bloquea la comunicación horizontal - Las tácticas comunes suelen indicar que los atacantes se moverán lateralmente a través de TCP/3389 (RDP) o TCP/445 (SMB). La comunicación horizontal (de estación de trabajo a estación de trabajo) a través de estos protocolos suele ser innecesaria, si no indeseable. Usa políticas de firewall basadas en el endpoint para restringir el acceso a través de estos canales. 

Detección

Extracción de archivo tar a una ubicación específica


Posible carga lateral de DLL mediante ADNotificationManager.exe


Posible carga lateral de DLL mediante DlpUserAgent.exe

Indicadores de compromiso (IOC)


Elemento

Descripción

388c53e8ff438f0cf101fe0322ad8f32bae140ff85da9b71b0fa366a76097408

SHA-256: DLPUserAgent.exe (Legítimo)

6fbd98bbdb8a34dd563f29f45c66adf5c53b1aff225269af3ceb56d76ecd677d

SHA-256: mpclient.dll (Cargador malicioso)

64ec615c046a59c08f0ddf3fe9f93e0c9e1bed227d980628cc09600e94adcd25

SHA-256: mpclient2.dll (Legítimo)

1175b1c56d59b736fe25495674ee3f83848e7785fde8ba9e207d283fed9b36c7

SHA-256: license.key (Havoc)

c10e144c25c1bac0692ed0b31dd626ab9195c5285b82430371a4ecdbd6d7f3fd

SHA-256: ADNotificationManager.exe (Legítimo)

b1ccee3d0dc7a85c117580cc08b8edcb8118b5612669300d4b006f50663b387e

SHA-256: vcruntime140_1.dll (Cargador malicioso)

e30b3f4979b63b50438d061858c9cde962f4494e585c627a11c98b6c5b7b2592

SHA-256: vcruntime140_2.dll (Legítimo)

0dce1175dc50d20da0fc009d0eed30fb75a004389fca0fbe0abe9835631d745c

SHA-256: loader_vcruntime140_1.dll (Cargador malicioso)

59014e97287b5602bba192a04535c59c60c6eb3a9770a94293551dfd5390c5c2

SHA-256: Decrypted license.key (Havoc)

d96d8b01d034ca1b9b232c70d57a863320cc107e07245ef7308cbdb069031e61

SHA-256: faultrep.dll (Cargador malicioso)

96c3b7ec47ca5ffaac5da1fda25b1ad1afa91e57e1586165deec1e541f3def2e

SHA-256: go.bat (Archivo por lotes malicioso usado para implementar Havoc)

arcupondepago[.]com

URL: Havoc C2

alatastro[.]com

URL: Havoc C2

egravy[.]com

URL: Havoc C2

agricularly[.]com

URL: Havoc C2

bongsebing[.]com

URL: Havoc C2

afzarkara[.]com

URL: Havoc C2

También te podría interesar

Más información sobre Cómo combatir el desorden de IA en bases de código de producción: así mejoró Huntress el recall de la API en Fable 5.1
Cómo combatir el desorden de IA en bases de código de producción: así mejoró Huntress el recall de la API en Fable 5.1
Blog

Tres cambios en los harnesses de codificación de Huntress duplicaron la tasa de precisión de evaluación de recall de API de Claude Fable 5.1.

Más información sobre Uso indebido de Velociraptor, parte II: el ojo de la tormenta
Uso indebido de Velociraptor, parte II: el ojo de la tormenta
Blog

Los actores de amenazas de la parte I no habían terminado. La parte II analiza qué sucedió después de que la explotación de WSUS puso una herramienta forense legítima en las manos equivocadas, y cómo respondió Huntress.

Más información sobre #ShadyHacks con Kyle Hanslovan
#ShadyHacks con Kyle Hanslovan
Blog

Los hackers no necesitan exploits de élite cuando Microsoft 365 tiene funciones integradas que pueden encadenar para eludir todo tu stack de seguridad. Kyle Hanslovan muestra exactamente cómo se hace.