Descripciones de malware

Archivos del SOC: Hora de “Sapecar”, análisis de una nueva campaña de Horabot en México

Introducción

En el episodio de hoy de nuestra serie Archivos del SOC, analizaremos paso a paso una campaña selectiva que nuestro equipo de MDR identificó y neutralizó hace unos meses. Esta campaña involucra una amenaza conocida como Horabot, un kit malicioso que combina un troyano bancario con un módulo de propagación por correo electrónico, y se distingue por su cadena de ataque de gran complejidad.

Si bien investigaciones previas ya han documentado campañas de Horabot (aquí y aquí), nuestro objetivo actual es resaltar lo activa que sigue esta amenaza y compartir algunos aspectos que no se abordaron en esos análisis.

El punto de partida

Como es habitual, nuestra historia comienza con una alerta que se disparó en el entorno de uno de nuestros clientes. La regla que la activó es genérica, pero efectiva para detectar actividad sospechosa de mshta. El caso avanzó a partir de esa alerta inicial, pero por suerte tuvo un desenlace positivo. Kaspersky Endpoint Security intervino, terminó el proceso malicioso (a través del PDM, el módulo de defensa proactiva) y eliminó los archivos relacionados antes de que la amenaza pudiera avanzar.

Más adelante, el incidente se presentó para discusión en una de nuestras reuniones semanales. Eso fue suficiente para despertar la curiosidad de uno de nuestros analistas y llevarlo a profundizar un poco más en las técnicas utilizadas en esta campaña.

La cadena de ataque

Después de investigar y de indagar a fondo en la infraestructura del adversario, nuestro equipo logró trazar la cadena de ataque completa. En esta sección, desglosaremos cada etapa y explicaremos cómo se desarrolla la operación.

Etapa 1: El señuelo inicial

Siguiendo las pistas observadas en el incidente reportado, la actividad parece comenzar con una página de CAPTCHA falsa, un señuelo común y corriente. En el incidente que mencionamos, la página se alojaba en la URL https://evs.grupotuis[.]buzz/0capcha17/ (los detalles sobre su contenido se pueden encontrar aquí).

Página falsa de CAPTCHA en la URL https://evs.grupotuis[.]buzz/0capcha17/

Página falsa de CAPTCHA en la URL https://evs.grupotuis[.]buzz/0capcha17/

Al igual que en el caso de Lumma y Amadey, esta página pide al usuario que abra el cuadro de diálogo Ejecutar, pegue un comando malicioso y lo ejecute. Tras caer en el engaño, la víctima pegaba un comando similar a este:

El archivo HTA recuperado y ejecutado por este comando contenía esto:

Es, en esencia, un pequeño loader. Al ejecutarse, abre una ventana en blanco y acto seguido descarga y ejecuta un payload JavaScript externa alojada en el dominio del atacante. El cuerpo contiene un gran bloque de palabras aleatorias sin sentido que sirven como relleno.

Etapa 2: Un toque de polimorfismo del lado del servidor

El payload por el archivo HTA crea dinámicamente un nuevo elemento <script>, establece que su origen es un VBScript externo alojado en otro dominio controlado por el atacante y lo inyecta en la sección <head> de una página definida estáticamente en el HTA. El contenido completo de la página se puede ver en el recuadro a continuación. Tras agregarse, el script VBS externo se descarga y ejecuta al instante, llevando el ataque a su etapa siguiente.

El contenido VBS de la siguiente etapa es similar al ejemplo que se muestra a continuación. Durante nuestro análisis, observamos el uso de polimorfismo de servidor, ya que cada acceso al mismo recurso devolvía una versión ligeramente diferente del código, pero que conservaba la misma funcionalidad.

El script está ofuscado y emplea una rutina de codificación de cadenas personalizada. A continuación, se muestra una versión más legible, con sus cadenas decodificadas y reemplazadas mediante un pequeño script en Python que replica la rutina decode_str().

El script cumple casi la misma función que el archivo HTA inicial. Accede a un cargador de JavaScript, que luego inyecta y ejecuta otro script VBS polimórfico.

A diferencia del primer script, este es mucho más complejo, con más de 400 líneas de código. Actúa como el “brazo fuerte” de la operación. A continuación, un breve resumen de sus principales características:

  • Ofuscación avanzada: el script utiliza múltiples capas de ofuscación para ocultar su comportamiento.
  • Decodificador de cadenas personalizado: emplea la misma rutina de decodificación presente en el primer script VBS para reconstruir cadenas en tiempo de ejecución.
  • Anti-VM y “anti-Avast”: realiza comprobaciones básicas del entorno y finaliza si detecta una carpeta específica de Avast o artefactos de máquina virtual.
  • Recopilación y exfiltración de información: recopila la IP del host, el nombre del host, el nombre de usuario y la versión del sistema operativo, y luego envía estos datos a un servidor C2.
  • Descarga de componentes adicionales: obtiene un ejecutable de AutoIt, su compilador (Aut2Exe), un script (au3) y un archivo blob, y los coloca en la ruta predefinida “C:\Users\Public\LAPTOP-0QF0NEUP4″.
  • Ejecución de comandos de PowerShell: ejecuta comandos de PowerShell que se conectan a dos URL diferentes (una no disponible y la otra que lleva al primer stage del propagador, que describiremos más adelante).
  • Configuración de persistencia: crea un archivo LNK y lo coloca en la carpeta Inicio para mantener la persistencia.
  • Rutinas de limpieza: elimina archivos temporales y finaliza determinados procesos.

Durante el análisis del “heavy lifter”, específicamente dentro de la rutina de exfiltración, identificamos el destino al que se enviaban los datos recopilados. Tras explorar la URL asociada y eliminar la parte “salvar.php”, descubrimos una página web accesible públicamente que el atacante usaba para enumerar a todas sus víctimas.

Como habrán notado, la tabla está en portugués de Brasil y enumera víctimas desde mayo de 2025 (esta captura de pantalla se tomó en septiembre). En la columna “Localização”, el adversario hasta incluyó las coordenadas geográficas de las víctimas, que están tachadas en la captura de pantalla. Un desglose rápido muestra que de 5384 víctimas, 5030 se encontraban en México, lo que representa cerca el 93 % del total.

Etapa 3: La combinación maléfica de AutoIT y el troyano bancario.

Ahora es momento de centrarnos en los archivos descargados por el “heavy lifter”. Como se mencionó antes, en el disco se colocaron tres componentes de AutoIT: el ejecutable (AutoIT3), el compilador (Aut2Exe) y el script (au3), junto con un archivo blob cifrado. Como tenemos acceso al código del script de AutoIt, podemos analizar sus rutinas. El problema es que contiene más de 750 líneas de código muy ofuscado, así que, de nuevo, nos centraremos solo en lo realmente importante.

La rutina más importante se encarga de descifrar el archivo blob (utiliza AES-192 con una clave derivada del valor semilla 99521487), cargarlo directamente en memoria y luego invocar la función exportada B080723_N. El blob descifrado es una DLL.

Aquí también logramos replicar la lógica de descifrado con un script de Python y extraer la DLL (0x6272EF6AC1DE8FB4BDD4A760BE7BA5ED) manualmente. Después de un análisis inicial y una ejecución básica en un entorno controlado (sandbox), observamos lo siguiente:

  • La muestra es un conocido troyano bancario escrito en Delphi, detectado por varios motores con diferentes nombres, como Casbaneiro, Ponteiro, Metamorfo y Zusy.
  • Incluye dos bibliotecas antiguas de OpenSSL (libeay32.dll y ssleay32.dll) del Proyecto Indy, una biblioteca de comunicaciones cliente/servidor de código abierto que se utiliza para establecer la comunicación con el C2 por HTTPS.
  • Incluye comandos SQL utilizados para extraer credenciales de los navegadores.

Una vez cargado en memoria, el troyano envía varias solicitudes HTTP a algunas URLs diferentes:

URL Descripción
https://cgf.facturastbs[.]shop/0725/a/home (GET) Página que contiene una configuración cifrada
https://cfg.brasilinst[.]site/a/br/logs/index.php?CHLG (POST) URL para enviar cierta información del host, pero en nuestras pruebas de laboratorio el valor estaba vacío.
Ejemplo de contenido de la solicitud:
Host: ‘ ‘
https://aufal.filevexcasv[.]buzz/on7/index15.php (POST)
https://aufal.filevexcasv[.]buzz/on7all/index15.php (POST)
URL utilizada para enviar información de la víctima
Ejemplo de contenido de la solicitud:
AT: ‘ Microsoft Windows 10 Pro FLARE-VM (64)bit REMFLARE-VM’
MD: 040825VS
https://cgf.facturastbs[.]shop/a/08/150822/au/at.html Página de señuelo HTML diseñada para engañar al usuario y hacerlo acceder a un enlace malicioso; su contenido también se utiliza como archivo adjunto PDF durante la fase de propagación por correo electrónico.
https://upstar.pics/a/08/150822/up/up (GET) El recurso ya no estaba disponible en el momento de realizar nuestras pruebas.
https://cgf.midasx.site/a/08/150822/au/au (GET) Página que contiene la primera etapa que conduce al propagador

Dado que esta familia de malware ha sido ampliamente documentada en investigaciones previas, no repetiremos su funcionalidad ya conocida. En su lugar, nos centraremos en las características menos documentadas y observadas recientemente, incluyendo la lógica de cifrado y manejo de protocolo del malware.

La muestra implementa un cifrado por XOR-sustracción con estado en la subrutina sub_00A86B64, que se utiliza para proteger cadenas y descifrar los datos HTTP recibidos del C2. A diferencia de un XOR simple, cada byte de salida aquí depende tanto de la clave como del byte anterior. En nuestra muestra, la clave es la cadena "0xFF0wx8066h".

Construcción de la clave (izquierda) y lógica de descifrado (derecha)

Construcción de la clave (izquierda) y lógica de descifrado (derecha)

Podemos reimplementar fácilmente la lógica de esta rutina en Python; para ello, podemos usar el siguiente fragmento e integrarlo en nuestro flujo de trabajo y automatizar así el descifrado de cadenas:

Python implementation of the decryption routine

Las cadenas cifradas se recuperan mediante tres métodos distintos: a través de búsquedas indexadas en una lista global cifrada de cadenas en Delphi (también observada por nuestros colegas de ESET), mediante referencias directas a cadenas cifradas en formato hexadecimal en la sección de datos, y por medio de referencias indirectas usando variables puntero, lo que añade cierta complejidad al automatizar el descifrado con scripts.

Puntero directo (izquierda), puntero indirecto (derecha)

Puntero directo (izquierda), puntero indirecto (derecha)

Cadenas indexadas mediante búsquedas en TStringList

Cadenas indexadas mediante búsquedas en TStringList

El malware obtiene su configuración realizando una solicitud HTTPS GET a su servidor C2, que está codificado y cifrado. El servidor responde con una configuración en forma de respuesta HTTP en bruto, que consta de varios valores, cada uno cifrado con el mismo algoritmo ya mencionado. La muestra extrae parámetros específicos según su posición en la lista.

Valores de configuración descifrados (contraseña de root oculta)

Valores de configuración descifrados (contraseña de root oculta)

Para mejorar la legibilidad, la captura de pantalla anterior se ha editado añadiendo los parámetros descifrados y separándolos con dobles saltos de línea.

La obtención y el análisis de la configuración se inician en la subrutina sub_00AD2C70, donde se extrae el primer valor de configuración: el ajuste de conexión del socket C2 (host;puerto).

Extracción de la dirección del socket C2

Extracción de la dirección del socket C2

Si el análisis falla, el malware recurre a una dirección de socket C2 secundaria predefinida, tras lo cual se establece la conexión por socket.

Repliegue a la dirección de socket predefinida (lifenews[.]pro:49569)

Repliegue a la dirección de socket predefinida (lifenews[.]pro:49569)

Los valores de configuración adicionales se analizan en sub_00AD2918 (y sus subrutinas). A modo de ejemplo, en la configuración C2 descifrada mostrada arriba, el parámetro 5 contiene la cadena “UPON” que desencadena la ejecución, y el parámetro 6 contiene los comandos de PowerShell que se ejecutarán cuando se use esta cadena. A continuación, se muestra la parte de la rutina que se encarga de analizar este comando:

Extracción de los valores 5 y 6 de la configuración

Extracción de los valores 5 y 6 de la configuración

Además de la comunicación HTTP, el malware también admite comunicación por socket sin formato mediante un protocolo personalizado que encapsula comandos en etiquetas como <|SIMPLE_TAG|> o <|TAG|>Arg1<|>Arg2<<|>.

El cliente inicia la conexión C2 en sub_00AD331C, donde establece un socket TCP con el servidor del operador y envía el comando “PRINCIPAL” para solicitar un canal de control. Al recibir una respuesta OK, continúa con un mensaje “Info” que contiene detalles del sistema. Una vez validado, el servidor responde con un mensaje “SocketMain” que incluye un ID de sesión, completando el handshake. Todo el manejo posterior de comandos ocurre en sub_00AD373C, una rutina orquestadora central que analiza los mensajes entrantes y ejecuta las acciones maliciosas.

La muestra, y por tanto el protocolo mismo, se hereda (como ya lo señalaron nuestros colegas de ESET) del proyecto de código abierto Delphi Remote Access PC. A continuación, se muestra una comparación visual:

Comparación de los comandos "PING" y "Close" (desensamblado de la muestra a la izquierda, código fuente de Delphi Remote Access a la derecha)

Comparación de los comandos “PING” y “Close” (desensamblado de la muestra a la izquierda, código fuente de Delphi Remote Access a la derecha)

Algunas funciones del proyecto de código abierto, como los comandos de chat y manipulación de archivos, se han eliminado, mientras que algunos comandos relacionados con el mouse se han renombrado de forma extraña con prefijos lúdicos como “LULUZ” (por ejemplo, LULUZLD, LULUZPos), posiblemente como una broma interna, ofuscación contra análisis, o simplemente para marcar variantes personalizadas. Más allá de la funcionalidad estándar, el protocolo ahora incluye una serie de comandos personalizados adicionales como LULUZSD para desplazar la rueda del ratón hacia abajo, ENTERMANDA (para simular la tecla Enter) y COLADIFKEYBOARD (para inyectar texto arbitrario como pulsaciones de teclas).

El conjunto completo de comandos es mucho mayor, y aunque no todos los comandos están implementados en la muestra analizada, la evidencia de su presencia (por ejemplo, en forma de cadenas) sugiere un desarrollo continuo.

Después de comprender el protocolo, centrémonos en el cifrado utilizado. En esta muestra, el tráfico intercambiado a través del canal de socket C2 se cifra mediante otro algoritmo XOR con estado que incluye claves de descifrado embebidas. Su lógica se implementa en las rutinas sub_00A9F2D0 (cifrado) y sub_00A9F5C0 (descifrado):

Rutina de cifrado sub_00A9F2D0

Rutina de cifrado sub_00A9F2D0

La rutina de cifrado genera tres claves enteras aleatorias de cuatro dígitos. La primera clave actúa como el estado inicial del cifrado, mientras que las otras dos sirven como multiplicador e incremento, que se aplican en cada etapa de cifrado tanto al estado como a los datos. Para cada carácter de la cadena de entrada, toma el byte más alto del estado actual, le aplica XOR con el carácter a cifrar y luego actualiza el estado del cifrado para el siguiente carácter. La salida se crea agregando las tres claves al texto cifrado y encapsulando todo dentro de los marcadores “##”. La salida final tendrá el siguiente aspecto:

Aquí hay un fragmento de código Python para decodificar dicho tráfico:

Esta capa de cifrado, que quizá pretendía evadir la inspección de red, irónicamente facilita la detección debido a su estructura altamente regular y repetitiva. Este patrón, que incluye los marcadores externos “##”, es poco común en el tráfico legítimo y puede utilizarse como una firma de red confiable para sistemas IDS/IPS. A continuación se muestra una regla de Suricata que coincide con la estructura descrita:

El malware contiene funcionalidad para mostrar ventanas emergentes falsas a las víctimas y solicitarles que ingresen credenciales bancarias, como también lo documentaron nuestros colegas de Fortinet. Las imágenes para estas ventanas emergentes se almacenan como recursos cifrados. A diferencia de las cadenas, los recursos se descifran utilizando el cifrado RC4 estándar y la clave, pega-avisao3234029284, se obtiene de la estructura TStringList anterior en el offset 3FEh.

Superposición de token falso utilizada para el robo de credenciales (derecha), con desensamblado (izquierda)

Superposición de token falso utilizada para el robo de credenciales (derecha), con desensamblado (izquierda)

El juego de palabras con “pega a visão”, una jerga brasileña que significa “capta la idea” en sentido figurado, revela una referencia cultural intencionada, lo que respalda los ya conocidos vínculos brasileños de los operadores, quienes poseen un conocimiento nativo del idioma.

A continuación se muestra un collage de imágenes donde se ven las superposiciones de los bancos objetivo.

Fragmento de superposiciones falsas descifradas

Fragmento de superposiciones falsas descifradas

Etapa 4: El propagador

En nuestras pruebas, notamos que tanto el script VBS (el “heavy lifter”) como la DLL de Delphi tienen funcionalidades superpuestas para descargar la siguiente etapa mediante PowerShell. Utilizan diferentes dominios, pero siguen el mismo patrón de URL.

Intentamos acceder a las URL destinadas a descargar el propagador. Una de las URL no devolvió nada, y en la otra observamos una secuencia de dos etapas  de PowerShell antes de llegar al propagador real.

En la segunda, encontramos varias URLs codificadas en base64, pero solo una de ellas estaba activa durante nuestro análisis. Basándonos en los comentarios encontrados en el código del propagador, sospechamos que, en versiones o campañas anteriores, el propagador se ensamblaba pieza por pieza a partir de estas otras URL. En nuestro caso, sin embargo, una sola URL contenía todo el código necesario.

Fragmento de superposiciones falsas descifradas

Fragmento de superposiciones falsas descifradas

Sí, también nos preguntábamos si PowerShell podía aceptar caracteres ASCII extraños como nombres de variables/funciones, y sí, lo hace. Tras limpiar esta caótica convención de nombres y revisar las rutinas bien comentadas (gracias, actor de amenaza), logramos identificar sus funciones principales:

  • Recolectar correos electrónicos a través del espacio de nombres MAPI
  • Exfiltrar direcciones de correo electrónico únicas al C2
  • Limpiar la Bandeja de salida
  • Usar una lista de palabras clave de bloqueo para filtrar las direcciones de correo electrónico exfiltradas.
  • Preparar un correo de phishing que contenga un PDF malicioso
  • Distribuirlo en masa a las direcciones filtradas

Un punto interesante es que el código y los comentarios del propagador nos permiten extraer información útil:

  • Todos los comentarios están redactados en portugués brasileño, lo que sugiere con claridad el origen del actor de amenaza.
  • Es bastante fácil distinguir los comentarios escritos por un humano de los que probablemente fueron generados por una IA/LLM: estos últimos son demasiado formales y están muy bien estructurados. Uno de los comentarios humanos fue, de hecho, la inspiración principal para el título de este artículo.
  • Uno de los comentarios en el código es “limpa a caixa de saida antes de sapecar”. Sapecar tiene un significado muy específico que solo los hablantes de portugués de Brasil comprenden sin explicación. El equivalente más cercano a este comentario en español sería algo como: Limpia la bandeja de salida antes de “darle con todo” o “darle duro”.

Dado que hemos estado rastreando la actividad de Horabot durante varios meses, nuestro equipo pudo recopilar una colección de ejemplos de archivos adjuntos maliciosos utilizados en esta campaña. Todos están escritos en español e instan al usuario a hacer clic en un gran botón dentro del documento para acceder a un “archivo confidencial” o una “factura”. Una vez que se hace clic, se activa la misma cadena de infección descrita en este artículo.

Detección de ingeniería y oportunidades de búsqueda de amenazas

Después de recorrer esta larga y compleja cadena de ataque, apostamos a que algunos de los más técnicos que lean esto, ya han comenzado a imaginar posibles oportunidades de detección.

Con eso en mente, esta sección reúne algunas reglas y consultas que pueden servir para detectar y buscar esta amenaza en su propio entorno.

Reglas Yara

Las reglas YARA se centran en dos componentes esenciales de la operación: el script de AutoIt que actúa como cargador y la DLL escrita en Delphi que funciona como troyano bancario.

Hunting queries

Se puede notar que algunos patrones en esta sección no aparecen en las URL descritas anteriormente en el artículo. Esto se debe a que los patrones adicionales se incluyeron porque hemos observado pequeñas variaciones introducidas por el actor de amenazas con el tiempo, como por ejemplo, el uso de códigos QR en las páginas señuelo.

VirusTotal Intelligence entity:url (url:”0DOWN1109″ or url:”0QR-CODE” or url:”0zip0408″ or url:”0out0408″ or url:”0capcha17″ or url:”/g1/ld1/” or url:”/g1/auxld1″ or url:”/au/gerapdf/blqs1″ or url:”/au/gerauto.php” or url:”g1/ctld” or url:”index25.php” or url:”07f07ffc-028d” or url:”0AT14″ or url:”0sen711″) or (url:”index15.php” and (url:”/on7″ or url:”/on7all” or url:”/inf”))
URLScan page.url.keyword:/.*\/([0-9]{6}|reserva)\/(au|up)\/.*/ OR page.url:(*0DOWN1109* OR *0QR-CODE* OR *0zip0408* OR *0out0408* OR *0capcha17* OR *\/g1\/ld1* OR *\/g1\/auxld1* OR *\/au\/gerapdf\/blqs1* OR *\/au\/gerauto.php* OR *\/g1\/ctld* OR *\/index25.php OR *\/index15.php)

IOCs

Indicador Descripción
hxxps://evs.grupotuis[.]buzz/0capcha17/ Página de Captcha falsa
hxxps://evs.grupotuis[.]buzz/0capcha17/DMEENLIGGB.hta Archivo HTA
hxxps://evs.grupotuis[.]buzz/0capcha17/DMEENLIGGB/GRXUOIWCEKVX JavaScript 01 loader
hxxps://pdj.gruposhac[.]lat/g1/ld1/ VBS Polimórfico 01
hxxps://pdj.gruposhac[.]lat/g1/auxld1 JavaScript 02 loader
hxxps://pdj.gruposhac[.]lat/g1/ VBS Polimórfico 02 (el “heavy lifter”)
hxxps://pdj.gruposhac[.]lat/g1/ctld/ Lista de víctimas
hxxps://pdj.gruposhac[.]lat/g1/gerador.php Enlace para descargar el script de AutoIT
hxxps://cgf.facturastbs[.]shop/0725/a/home (GET) Lista de direcciones C2 cifradas
hxxps://cfg.brasilinst[.]site/a/br/logs/index.php?CHLG (POST) Contactada por la DLL de Delphi
hxxps://aufal.filevexcasv[.]buzz/on7/index15.php (POST)
hxxps://aufal.filevexcasv[.]buzz/on7all/index15.php (POST)
Contactada por la DLL de Delphi
hxxps://cgf.facturastbs[.]shop/a/08/150822/au/at.html Contactada por la DLL de Delphi
hxxps://labodeguitaup[.]space/a/08/150822/au/au
hxxps://cgf.midasx[.]site/a/08/150822/au/au
Etapa de PowerShell 01
hxxps://cgf.facturastbs[.]shop/a/08/150822/au/gerauto.php Etapa de PowerShell 02
hxxps://cgf.facturastbs[.]shop/a/08/150822/au/app Enlace para descargar el propagador
hxxps://cgf.facturastbs[.]shop/a/08/150822/au/gerapdf/blqs1 Lista de palabras clave de la lista de bloqueados
hxxps://thea.gruposhac[.]space/0out0408 Enlace encontrado en el botón del primer archivo adjunto malicioso
6272EF6AC1DE8FB4BDD4A760BE7BA5ED Muestra de la DLL Delphi
lifenews[.]pro C2 (socket)
64.177.80[.]44 C2 (socket)

Archivos del SOC: Hora de “Sapecar”, análisis de una nueva campaña de Horabot en México

Su dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

 

Informes

BlindEagle vuela alto en LATAM

Kaspersky proporciona información sobre la actividad y los TTPs del APT BlindEagle. Grupo que apunta a organizaciones e individuos en Colombia, Ecuador, Chile, Panamá y otros países de América Latina.

MosaicRegressor: acechando en las sombras de UEFI

Encontramos una imagen de firmware de la UEFI infectada con un implante malicioso, es el objeto de esta investigación. Hasta donde sabemos, este es el segundo caso conocido en que se ha detectado un firmware malicioso de la UEFI usado por un actor de amenazas.