En enero respondimos a una nueva campaña de ataques del grupo Lazarus contra Corea del Sur, que continuó la Operation SyncHole del año pasado. En esta nueva operación, el grupo empleó una cadena de malware que combina malware antiguo y nuevo, la cual descubrimos por completo, y usó otro software de seguridad obligatorio en Corea del Sur como parte de la cadena de infección junto con una estrategia de watering hole. Cabe destacar que el grupo eligió a sus víctimas de forma más selectiva en esta campaña: envió correos de spear phishing con enlaces a sitios falsos específicos, como páginas de portafolio y currículum adaptadas a cada objetivo. Bautizamos esta actividad como Operation FlashHole.
Nuestro análisis revela que la evidencia más antigua de esta nueva operación se remonta a julio del año pasado, lo que sugiere que el grupo comenzó a preparar la campaña poco después de que terminara Operation SyncHole, que había durado al menos cuatro meses. Identificamos al menos tres organizaciones afectadas por la campaña en los sectores surcoreanos de software, construcción y fabricación de equipos de comunicación por cable, industrias distintas de las observadas en Operation SyncHole. Esto evidencia que el grupo amplía su alcance de objetivos con el tiempo.
Antecedentes
Más de un año después de la primera observación de Operation SyncHole, detectamos una cadena de ejecución sospechosa que se originó en un software legítimo surcoreano. Esta cadena replica la de la operación anterior, pero esta vez el atacante explotó CrossWeb EX en lugar de Cross EX, que se abusó en Operation SyncHole. Ambas aplicaciones reciben mantenimiento del mismo desarrollador, y ambas tienen vínculos con la seguridad financiera. CrossWeb EX es una solución de seguridad financiera necesaria para acceder a los sitios web bancarios y gubernamentales popelares, que cifra las comunicaciones entre el navegador del usuario y el servidor web mediante PKI (infraestructura de clave pública). Esta no es la primera vez que Lazarus abusa de este software. También se utilizó en 2021 para desplegar el downloader Racket, así como en 2022 y 2023. Aunque no pudimos obtener el código del exploit, identificamos que la cadena de ataque conduce a la ejecución del malware en memoria.
Observamos que el proceso generado se ejecutaba con un nivel de integridad alto. El proceso padre INISAFECrossWebEXSvc.exe proviene del paquete de instalación de INISAFE CrossWeb EX V3, versión 3.4.1.2, publicada en 2023, tras el aviso público de KrCERT.
Como ya mencionamos en nuestro blog sobre SyncHole, el patrón replica la estrategia de cascada que el grupo Lazarus emplea desde hace muchos años contra Corea del Sur. Dado que CrossWeb EX y software similar son obligatorios para los usuarios surcoreanos y suelen ejecutarse en segundo plano para interactuar con el navegador, el grupo los ha aprovechado como un vector de ataque crítico. En 2025 se presentó un artículo en el USENIX Security Symposium que investiga las vulnerabilidades del software de seguridad obligatorio en Corea del Sur y demuestra cómo se puede crear una superficie de ataque masiva sin tener la intención de hacerlo.
En julio de 2026, el gobierno surcoreano y varios proveedores de seguridad locales también publicaron un aviso de seguridad conjunto que abarca las técnicas de ataque típicas de Lazarus, incluida la explotación de software de seguridad financiera. Si bien el aviso coincide con nuestros hallazgos tanto de Operation FlashHole como de Operation SyncHole, y el informe de análisis detallado de AhnLab titulado Operation Double Barrel también abarca un amplio espectro de actividades recientes del grupo Lazarus, nosotros realizamos una clasificación más granular basada en sus TTP (Tácticas, Técnicas y Procedimientos). Analizaremos esto con más detalle en la sección Atribución.
Vector de infección inicial
Aunque el método exacto por el cual se abusó de CrossWeb EX sigue sin estar claro, nuestro análisis descubrió un sitio web sospechoso alojado en GitHub Pages, asociado con la cuenta de GitHub utilizada como canal de C2. La cuenta de GitHub se creó en septiembre del año pasado y la versión inicial del sitio se diseñó para mostrar el currículum de un desarrollador sénior de dispositivos de red. Sin embargo, en enero, este sitio se reemplazó por otro con una fachada de diseño de interiores. Es probable que el primer sitio haya sido visitado por un empleado de una empresa fabricante de equipos de comunicación por cable, mientras que el segundo haya afectado a un objetivo del sector de la construcción.
El primer sitio, con el currículum, incluía la fotografía de alguien que se suponía que era un candidato a empleo, pero la ausencia de metadatos EXIF y la textura poco natural de la imagen sugieren que pudo haberse generado con IA. Esto indica que el grupo Lazarus incorporó la IA a su estrategia de cascada, de forma similar a otros actores de amenaza de habla coreana (1, 2). Lo más probable es que el grupo también haya aprovechado la IA para generar el sitio señuelo: el nombre del candidato se parece a “John Doe” adaptado al estilo coreano, y el portafolio se rellenó con detalles y empresas aleatorias. Después, se hizo una adaptación manual del sitio generado para que cumpla los objetivos.
Los sitios web contenían enlaces incrustados que cargaban un archivo JavaScript externo mediante una etiqueta script.
- Enlace malicioso incrustado en el sitio del currículum:
hxxps://javadevhouse.co[.]kr/ajax/libs/jquery/1.7.3/jquery.min.js - Enlace malicioso incrustado en el sitio de diseño de interiores:
hxxps://pythonapischool[.]com/api/detach
Con base en el análisis, evaluamos con confianza media-alta que los objetivos recibieron correos de phishing con enlaces al sitio malicioso, alojado en GitHub Pages (con el dominio <username>.github.io).Los resultados de la investigación mostraron una alta posibilidad de que visitar el sitio malicioso iniciara un proceso de infección que involucrara el software CrossWeb EX. Esta evaluación coincide con el enfoque reciente de Lazarus, según reveló el aviso conjunto del gobierno surcoreano y las empresas de seguridad.
Cadena de infección completa
Tras el compromiso inicial, se ejecutó el binario legítimo de Windows fsquirt.exe dentro del proceso de CrossWeb EX, al que luego se le inyectó un shellcode que incluye una DLL maliciosa, el malware TechHub. Tras un examen extenso y exhaustivo, identificamos varios payloads maliciosos y reconstruimos la cadena de infección completa. Esta cadena de infección es bastante compleja y revela las técnicas operativas avanzadas del grupo Lazarus en los hosts objetivo, que ocultan tanto sus payloads maliciosos como su intención, además de su sofisticado framework de entrega de malware. Este último se actualizó de forma significativa respecto de la campaña anterior, aunque la nueva comenzó menos de un año después. Cabe destacar que la cadena de infección que se muestra a continuación existe solo en memoria durante la infiltración inicial, lo que evidencia el considerable esfuerzo de los atacantes por ocultar el compromiso inicial.
Tras el compromiso inicial, el grupo buscó mantener la persistencia en la red mediante la instalación de un par de familias de malware, TouchHub y TouchShift, que aprovechan la técnica DLL side-loading para la carga de una DLL con el nombre mscoree.dll. TouchHub fue desplegado por la primera instancia de TechHub. Luego utilizó la misma técnica para la carga de la DLL que inicia TouchShift, lo que al final condujo a la ejecución en memoria de otra instancia de TechHub. Tras iniciarse por segunda vez, TechHub desplegó otro par de familias de malware, ClientHub y LPEClient, en lugar de ejecutar Cubridge de forma directa. Solo se encontraron rastros mínimos de estos archivos en el disco; el resto del código malicioso persistió solo en memoria.
Dado que Cubridge sigue residiendo solo en memoria en la etapa del compromiso inicial, sospechamos que el grupo diseñó esta cadena indirecta y de varias etapas para volver a desplegar Cubridge de forma deliberada después de obtener persistencia, ya que funciona como el orquestador más sofisticado del ataque.
Conjunto de malware
La cadena completa comprende las variantes avanzadas de las familias de malware conocidas de Lazarus, como TechHub, Cubridge, TouchShift y LPEClient, así como las recién identificadas TouchHub y ClientHub.
TechHub, el inicio de la cadena
TechHub, un downloader que desempeña un papel central en este ataque, se comunica con GitHub mediante un token de acceso personal (PAT). Funciona como el payload inicial y constituye el punto de partida de la cadena, con funcionalidad suficiente para perfilar los hosts comprometidos y facilitar los payloads posteriores.
Esta variante es una versión más avanzada del malware denominado CLOUDBURST por Mandiant y NickelLoader por ESET. Según los informes, la versión anterior se comunicaba con un servidor C2 mediante HTTP(S) para obtener payloads adicionales. Sin embargo, la iteración más reciente que encontramos se comunica con GitHub y cuenta con cadenas de comandos actualizadas.
Identificamos tres variantes de TechHub en la cadena: una versión en memoria, una versión simple utilizada en DLL side-loading y otra versión usada en DLL side-loading que utiliza un servicio de Windows registrado. Según la etapa que cargue el malware, este contacta un repositorio privado de GitHub mediante la API de GitHub, con credenciales embebidas o recuperadas de su archivo de configuración.
Cuando TechHub se carga, crea un identificador (ID) hexadecimal de 4 bytes en el rango 0x1000–0xFFFF, o lo lee del archivo de configuración, para que los atacantes puedan distinguir entre los hosts comprometidos. Verifica un issue de GitHub enviando la solicitud GET /issues?state=[open/closed] para determinar si alguna comunicación previa sigue activa, elimina los rastros de esa comunicación previa, si los encuentra, y luego continúa con el proceso de handshake.
- Crea un nuevo issue con el título
1[ID]y el cuerpo “hel” mediante una solicitud POST /issues, y establece su estado como abierto. - Luego recupera del repositorio un archivo que contiene el valor
2[ID]en su nombre. Este archivo contiene la clave pública RSA. - Genera una clave XOR aleatoria de 16 bytes, la cifra con la clave pública RSA proporcionada y luego sube el resultado al repositorio con el prefijo
1[ID]. - El vector de inicialización (IV) hardcodeado se combina mediante XOR con la clave de 16 bytes generada y luego se utiliza después del handshake.
Durante el intercambio de archivos, los nombres siguen el patrón [1|2][ID][random-16-byte-key]. A lo largo de toda su comunicación. El prefijo “2” indica una entrega del repositorio a TechHub, mientras que “1” indica una entrega de TechHub al repositorio. La clave aleatoria de 16 bytes en el nombre del archivo se utiliza para el cifrado o descifrado AES del contenido de cada archivo, con un IV embebido o uno actualizado.
Una vez concluido el intercambio de claves, TechHub lee de nuevo un archivo con el prefijo “2” y verifica que los datos entregados sean iguales a “hel”. Si la verificación es exitosa, recopila información extensa del host infectado. Luego, estos datos se cifran y se envían al repositorio. Tras transmitir la información del dispositivo, el proceso finaliza actualizando el cuerpo del issue creado de “hel” a “hey” mediante PATCH /issues/[issue number]. En este punto, el malware ya está preparado para recibir comandos del repositorio.
TechHub admite cuatro comandos. El comando laeca activa el despliegue del payload, que está empaquetado en un shellcode que carga de forma reflexiva el payload incrustado directo en memoria.
| Comando | Descripción |
mqdrz |
Recopila información sobre el dispositivo y sus procesos en ejecución |
laeca |
Invoca directo en memoria el shellcode recibido |
aqvxp |
Finaliza el proceso actual |
rtcya |
Beaconing tras finalizar el proceso de handshake |
Cubridge, el orquestador del framework
Cubridge, desplegado mediante TechHub en el host comprometido, puede recuperar diversos payloads por múltiples métodos. Funciona como el orquestador central de todo el framework de malware y admite una variedad de plugins, módulos y herramientas. Una versión anterior de Cubridge también se divulgó en los informes que abarcaron la versión previa de TechHub. En esos informes, Mandiant la identificó como SIDESHOW y ESET identificó uno de sus módulos como LightlessCan.
Para establecer la comunicación con el servidor C2, Cubridge selecciona al azar uno de los servidores C2 predefinidos y construye una URL de C2 dedicada para cada solicitud con el patrón [C2_URL]/[page1]/[page2]/[page3]. Esto se logra concatenando términos de listas de palabras predefinidas. Nuestro análisis identificó un único servidor C2 embebido (hxxps://cubedesign[.]co[.]kr/news/AABBCC) asociado con la instancia examinada, que está configurada con la versión 5.1. Durante la generación de la URL, AABBCC se sustituye por un valor nulo. El segmento page3 recibe un entero generado al azar entre 10 000 000 y 99 999 999. En consecuencia, cada URL generada está diseñada para parecer auténtica y ser única para cada solicitud.
La lista predefinida para page1 se muestra a continuación; TechHub selecciona al azar un elemento de ella.
|
1 |
economy, opinion, politics, national, international, medical, investment, sports, lifestyle, shopping, culture |
La lista de palabras predefinida para page2 se muestra a continuación:
|
1 |
article, list, story |
Así, siguiendo los pasos descritos, la URL embebida puede transformarse, por ejemplo, en hxxps://cubedesign[.]co[.]kr/news/economy/article/12345678.
La autenticación mediante la solicitud POST con el servidor C2 requiere tres parámetros en forma de pares clave-valor. Cada clave se genera al azar a partir de otros diccionarios de palabras predefinidos, y los valores asociados consisten en un ID de bot hexadecimal de 8 bytes generado al azar, un token de autenticación fijo (KW4Ofw982CNJjxd51AVqkGAop) y un ID de sesión hexadecimal de 16 bytes generado al azar.
Cubridge emplea un proceso de handshake más robusto que TechHub, que combina los algoritmos RSA y RC6. A diferencia de TechHub, omite el paso de perfilado y pasa directo al comando y control después del handshake. Durante la comunicación, el malware imita solicitudes de navegador: usa los encabezados X‑CSRF‑Token<code> y X‑Requested‑With para la autenticación y el encabezado Upgrade‑Insecure‑Requests para solicitar datos adicionales.
Cubridge tiene una funcionalidad extensa, centrada en cargar payloads de etapas posteriores. Los comandos emplean diversas técnicas, como inyección de DLL, carga reflexiva e inyección por mapeo de secciones. Los payloads pueden entregarse de diversas formas:
- Plugins: extensiones reutilizables que agregan funcionalidad según sea necesario y pueden invocarse en cualquier momento (en forma de shellcode y DLL)
- Herramientas (en forma de DLL): artefactos independientes que realizan tareas puntuales
- Módulos: componentes que se cargan una sola vez, permanecen activos, y ofrecen un conjunto amplio de funcionalidades
Se prevé que los comandos para plugins y shellcode carguen tipos idénticos de plugins, ya que ambos admiten una función exportada de formato similar para la actividad posterior. El shellcode puede generarse con la herramienta de código abierto sRDI para empaquetar un plugin de tipo DLL. Es probable que las capacidades de una sola DLL se utilicen para cargar una herramienta que funciona de manera independiente, ya que, cuando se carga una sola DLL, solo son accesibles su punto de entrada DllMain y sus parámetros; no se expone ninguna otra función exportada.
| Comando | Tipo de payload | Descripción |
| 0 | – | Recopila información del dispositivo, incluidos el nombre del equipo, la zona horaria, el PID y otros detalles similares |
| 1 | Almacena el archivo o directorio especificado con el algoritmo heredado ZipCrypto y la contraseña embebida: xdkiTajAAxc3i/w[<881fnC!G*cb1Dit2sh.gAk/ |
|
| 2 | Crea un archivo en la ruta especificada | |
| 3 | Posible plugin | Inyecta el payload de DLL proporcionado en el proceso objetivo y lo carga de forma reflexiva mediante inyección reflexiva de DLL |
| 4 | Plugin | Carga de forma reflexiva un plugin en formato DLL |
| 5 | Recupera la dirección de la función exportada especificada del plugin objetivo y la ejecuta con los parámetros proporcionados | |
| 6 | Recupera toda la información sobre los plugins cargados | |
| 7 | Descarga de memoria el plugin especificado | |
| 8 | Shellcode | Inyecta el shellcode proporcionado en el proceso objetivo y lo carga mediante inyección por mapeo de secciones |
| 9 | Carga el shellcode proporcionado directo en memoria | |
| 10 | Recupera la dirección de la función exportada especificada del shellcode objetivo (que podría ser un plugin en forma de shellcode) y la ejecuta con el parámetro proporcionado | |
| 11 | Recupera toda la información sobre el shellcode cargado | |
| 12 | Descarga de memoria el shellcode especificado | |
| 13 | – | Establece el tiempo de ejecución programado de Cubridge (en minutos) mediante la actualización de una variable global |
| 14 | Establece el tiempo de ejecución programado de Cubridge (en minutos) mediante la actualización de una variable global y, al mismo tiempo, deshabilita el monitoreo mediante la actualización de otra variable global | |
| 15 | Se finaliza a sí mismo de forma controlada | |
| 16 | Obtiene la configuración de Cubridge: recupera los flags globales, la cantidad de servidores C2, las direcciones C2, entre otros | |
| 17 | Actualiza los flags globales, la cantidad de servidores C2, las direcciones C2, entre otros | |
| 18 | Herramienta | Carga de forma reflexiva una DLL con el parámetro especificado |
| 19 | Configura los parámetros para cargar una sola DLL | |
| 20 | Descarga de memoria la DLL individual | |
| 21 | Módulo | Carga de forma reflexiva el “módulo de acción” (ActionModule.dll) e invoca su función exportada AppinfoView |
| 22 | Carga de forma reflexiva el “módulo de función” (FunctionModule.dll) e invoca su función exportada PresentationFontConfig |
Los comandos 21 y 22 tratan un módulo diferente cada uno. Según sus nombres internos, el módulo de acción gestiona operaciones básicas de archivos y procesos, mientras que el módulo de función implementa los comandos predeterminados de Windows. El módulo de acción abarca los comandos 23–41, y el módulo de función maneja los comandos 42–79.
El módulo de acción maneja comandos de operaciones del sistema, interacciones con el sistema de archivos y el comportamiento de procesos. Se invoca pasando el comando y los parámetros adecuados a su función exportada AppinfoView. El módulo admite 19 comandos, numerados del 23 al 41. Los resultados de la ejecución se envían primero a Cubridge, que luego los reenvía al servidor C2.
| Comando | Rol |
| 23 | Obtiene el espacio en disco local de cada unidad |
| 24 | Obtiene información sobre el archivo o directorio especificado |
| 25 | Ejecuta el comando proporcionado |
| 26 | Obtiene información sobre el archivo o directorio especificado (similar al comando 24) |
| 27 | Ejecuta el comando proporcionado bajo el proceso objetivo (PPID spoofing) |
| 28 | Ejecuta el comando proporcionado bajo el proceso objetivo dentro de la sesión proporcionada (PPID spoofing + suplantación de sesión) |
| 29 | Obtiene información detallada sobre los procesos |
| 30 | Finaliza el proceso proporcionado |
| 31 | Suspende todos los hilos que pertenecen al proceso especificado |
| 32 | Reanuda todos los hilos que pertenecen al proceso especificado |
| 33 | Elimina el archivo de forma permanente sobrescribiendo todo su contenido con la secuencia: 0 → 1 → bytes aleatorios → 1 → 0 |
| 34 | Cambia el nombre del archivo proporcionado a :EFS (el área de flujo de datos alternativo) y lo elimina mediante la API nativa SetFileInformationByHandle |
| 35 | Establece el directorio de trabajo actual |
| 36 | Copia el archivo especificado en la ruta proporcionada |
| 37 | Elimina el directorio especificado |
| 38 | Mueve el archivo especificado a la ruta proporcionada |
| 39 | Crea el directorio proporcionado |
| 40 | Inicia un intento de conexión no bloqueante a la dirección IP y el puerto especificados (que podría ser para escaneo de puertos) |
| 41 | Lee el archivo especificado |
El módulo de función implementa comandos que emulan los comandos integrados de Windows. Al igual que el módulo de acción, su rutina DllMain inicializa todas las funciones de comandos admitidas, a las que luego se accede mediante la exportación PresentationFontConfig. En total, ofrece 38 comandos, numerados del 42 al 79. Creemos que este módulo se basa en el anterior LightlessCan, pero es la primera vez que lo vemos en forma de módulo independiente.
| Comando | Rol |
| 42 | Captura todas las pantallas y las archiva con el algoritmo heredado ZipCrypto y la contraseña embebida: xdkiTajAAxc3i/w[<881fnC!G*cb1Dit2sh.gAk/ |
| 43 | Sincroniza las marcas de tiempo MAC (modificación, acceso y creación) del archivo proporcionado en el segundo argumento para que coincidan con las del archivo proporcionado como primer argumento |
| 44 | Obtiene información sobre el directorio especificado |
| 45 | Obtiene información sobre la unidad especificada |
| 46 | Inyecta el payload de DLL proporcionado en el proceso objetivo |
| 47 | Descarga de memoria la DLL especificada del proceso especificado |
| 48 | Implementación del comando ipconfig |
| 49 | Implementación del comando net |
| 50 | Implementación del comando netsh advfirewall firewall |
| 51 | Implementación del comando netstat |
| 52 | Implementación del comando ping -6 |
| 53 | Implementación del comando reg |
| 54 | Implementación del comando sc |
| 55 | Implementación del comando ping |
| 56 | Implementación del comando whoami |
| 57 | Implementación del comando nslookup |
| 58 | Implementación del comando schtasks |
| 59 | Implementación del comando systeminfo |
| 60 | Implementación del comando arp |
| 61 | Llama a la función CryptUnprotectData para recuperar la clave AES que protege DPAPI. Extrae la clave mediante la palabra clave encrypted_key del archivo Local State de Chromium, ubicado en: %LOCALAPPDATA%\Google\Chrome\User Data\Local State |
| 62 | No implementado |
| 63 | No implementado |
| 64 | Lee el archivo especificado y lo descifra mediante una operación XOR con la clave 0x59. Luego extrae las rutas del búfer descifrado y almacena los archivos y directorios de esas rutas con el algoritmo heredado ZipCrypto, usando la contraseña embebida: xdkiTajAAxc3i/w[<881fnC!G*cb1Dit2sh.gAk/ |
| 65 ~ 79 | No implementado |
Además de los módulos, observamos que el actor desplegó diversos plugins y herramientas.
| Tipo de payload | Nombre | Descripción |
| Plugin | ADFinder (AdFinder.dll) |
Lanza consultas LDAP en un entorno de Active Directory y toma seis argumentos, como la ruta del archivo de registro, ADsPath, el filtro de búsqueda y los nombres de atributos. |
| Plugin | FileCollector (Dll.dll) |
Escanea de forma recursiva cada subdirectorio y archivo del directorio proporcionado y recopila información detallada de cada uno. |
| Herramienta | Stealer de navegadores | Puede inyectarse en navegadores basados en Chromium, como Google Chrome, Microsoft Edge y Brave. Una vez inyectado, extrae archivos y credenciales de los navegadores de la víctima, incluidos contraseñas almacenadas, marcadores, historial, preferencias y cookies. |
| Herramienta | Recolector de procesos | Itera sobre todos los procesos en ejecución y recopila el ID, la ruta y la línea de comandos de cada proceso. |
TouchHub instala un servicio para TouchShift
Durante nuestro análisis, obtuvimos una muestra de malware que hasta entonces desconocíamos, proveniente del repositorio privado de GitHub de TechHub, que sirvió como instalador principal de TouchShift. Llamamos a este malware TouchHub. Al ejecutarse, copia el archivo legítimo printfilterpipelinesvc.exe en C:\Windows\System32\RasConv\ImeBroker.exe, lo registra como servicio y coloca un payload de TouchShift incrustado, llamado mscoree.dll, en el mismo directorio. Tras la creación, el malware sincroniza las marcas de tiempo MAC (modificación, acceso y creación) de C:\Windows\System32\drivers\monitor.sys con las del archivo recién escrito para dificultar el análisis forense.
Luego pasa por el proceso de registro del servicio: recopila hasta 100 nombres de servicios legítimos registrados en el grupo netsvcs de svchost en HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost. Elige uno de estos nombres al azar, le agrega dos caracteres alfabéticos aleatorios para formar un nuevo nombre de servicio y usa este nombre para crear un servicio que ejecuta la línea de comandos embebida C:\Windows\System32\RasConv\ImeBroker.exe -TimeBroker con la descripción Microsoft Service. El servicio recién creado se inicia de inmediato.
En total, TouchHub crea tres archivos en el directorio designado para iniciar TouchShift con privilegios de SYSTEM.
| Ruta | Tipo | Descripción |
C:\Windows\System32\RasConv\ImeBroker.exe |
Archivo ejecutable registrado como servicio | Copiado de C:\Windows\System32\printfilterpipelinesvc.exe |
C:\Windows\System32\RasConv\mscoree.dll |
Payload de TouchShift cargado lateralmente | Colocado por TouchHub, contiene payloads cifrados e incluye partes del contenido de una DLL legítima, lo que infla de manera significativa su tamaño. |
C:\Windows\System32\RasConv\ActivationStore.dat |
Archivo de configuración de TechHub | Colocado por TouchHub tras extraer los valores de configuración |
TouchShift, un loader muy extendido y empleado en múltiples cadenas de infección
El TouchShift entregado por TouchHub es casi idéntico a la versión descrita en el blog de Mandiant, e incluso comparte la misma función de exportación maliciosa, LockClrVersion. Toma el argumento suministrado por TouchHub y le aplica XOR con una clave embebida. Al valor resultante se le aplica XOR una vez más con el nombre de archivo del ejecutable, y este resultado se usa como clave AES. Todas las cadenas que participan en este proceso (el argumento, la clave XOR y el nombre de archivo) deben tener 16 bytes con exactitud; si una cadena es más corta, se rellena con bytes NULL (\x00), y si es más larga, se trunca a 16 caracteres. Por ejemplo, la siguiente fue una de las combinaciones de cadenas en la muestra obtenida:
- Argumento:
-TimeBroker\x00\x00\x00\x00\x00(rellenado con NULL) - Clave XOR embebida:
x809G736iC3f8Wp8 - Nombre de archivo del ejecutable:
ImeBroker.exe\x00\x00\x00(rellenado con NULL)
Tras obtener la clave, el malware descifra el payload incrustado mediante AES-CBC-128 sin padding. Los datos descifrados son un shellcode que comienza con una instrucción call, que envuelve el payload de la siguiente etapa, identificado como la tercera versión de TechHub (DLL side-loading con un servicio registrado), que lee el archivo ActivationStore.dat como configuración externa.
ClientHub
También identificamos un nuevo malware almacenado en el repositorio privado de TechHub, al que llamamos ClientHub. Admite diversos comandos, que se forman mediante una máscara de bits. Existen al menos dos versiones de ClientHub: una se comunica con sitios web mediante HTTP(S), mientras que la otra interactúa con la API de Dropbox mediante credenciales.
Según su versión, su configuración proviene de recursos internos o de un archivo de configuración externo, C:\Program Files\Common Files\System\msadc\msadc.inc. La configuración comprende claves y vectores de inicialización (IV) para el algoritmo SNOW 1.0, tiempos de ejecución programados y direcciones de servidores C2 cifradas con el algoritmo SNOW. El cifrado SNOW es una familia de cifrados de flujo de alta velocidad que se utilizan para el cifrado seguro de datos en telecomunicaciones y redes inalámbricas. Es la primera vez que se observa en el malware del grupo Lazarus.
Para establecer la comunicación con el C2, el malware genera un arreglo aleatorio de 32 bytes para iniciar. Luego sobrescribe partes de este arreglo con datos recopilados del dispositivo comprometido. Así, el arreglo de 32 bytes tiene una mezcla de bytes aleatorios e información relevante. Más adelante, el arreglo se usa como clave del algoritmo SNOW para descifrar los datos recibidos del servidor C2. Por último, el arreglo de la clave se cifra con una llave pública RSA embebida y se codifica en Base64.
| Desplazamiento | Tamaño | Valor del campo |
| 0 | 4 | ID del proceso actual |
| 4 | 4 | Primeros cuatro bytes de la información descifrada del servidor C2. |
| 8 | 7 | Bytes generados de forma aleatoria |
| 15 | 1 | Valor de flag calculado que indica una máquina de estados. |
| 16 | 8 | Hora actual del sistema, representada como una estructura FILETIME. |
| 24 | 8 | Bytes generados de forma aleatoria |
El texto cifrado se entrega al servidor C2 mediante solicitudes GET. Cada solicitud contiene encabezados atípicos en el malware: Sec-CH-UA, Sec-CH-UA-Platform, Sec-CH-UA-Mobile, Sec-Fetch-Mode y Sec-Fetch-Dest. Los navegadores legítimos basados en Chromium suelen utilizar estos encabezados, y permiten que el malware imite el tráfico legítimo y evada la detección. El servidor C2 responde con comandos, que entrega en un encabezado personalizado y en un cuerpo de mensaje.
|
1 2 3 4 5 6 7 8 9 |
struct header { int has_more_data // whether more body data remains int body_checksum;// ROR13 checksum for the body data int body_type; // specifies the body type int unknown; int body_length; // Length of the body data int IV[2]; // Random IV used to encrypt the body data }; |
El campo body_type del encabezado determina cómo se procesa el payload siguiente. Este valor funciona como una máscara de bits, en la que cada bit representa un flag distinto (por ejemplo, 0x1, 0x2, 0x4, etc.). Por ende, el comportamiento también depende de si el bit menos significativo (bit 0) está activado: cuando el valor es impar, el malware interpreta el cuerpo del mensaje entrante como un payload adicional, que luego se carga en memoria. Por el contrario, cuando el valor es par, el malware invoca el payload que se ha cargado antes.
El valor impar admite cuatro métodos de carga distintos según el cuerpo del mensaje recibido y garantiza que cada método se ejecute solo una vez.
| Máscara de bits | Valor en decimal | Descripción | Resultado enviado al C2 |
0x00000001 |
1 | Carga de DLL: carga de forma reflexiva el cuerpo recibido junto con el parámetro proporcionado | La base de imagen del payload |
0x00000011 |
3 | Plugin: carga de forma reflexiva el cuerpo recibido, obtiene la dirección de una función en el payload y luego invoca esa función junto con el parámetro proporcionado | La base de imagen del payload, la dirección de la función invocada y el resultado de la ejecución |
0x00000101 |
5 | Plugin: carga de forma reflexiva el cuerpo recibido, obtiene la dirección de una función en el payload, pero evita invocarla de inmediato | La base de imagen del payload y la dirección de la función |
0x00001011 |
11 | Plugin: ejecuta el comportamiento asociado con el valor 3 y lo descarga de memoria después de invocar el plugin | – |
0x00010001 |
17 | Carga de DLL: carga de forma reflexiva el cuerpo recibido con el parámetro proporcionado y mantiene una comunicación con estado mediante una sesión interactiva persistente que usa un búfer compartido | La base de imagen del payload, la dirección del búfer compartido interactivo y el resultado de la ejecución |
El valor par ofrece dos métodos de invocación distintos para las DLL y los plugins ya cargados, asociados con la máscara de bits de valor impar. El flag 2 (0x10) permite reutilizar e invocar de forma directa el payload que se cargó antes con la máscara de bits 1, 3 o 5. El valor 16 (0x10000) corresponde al flag 17 (0x10001) en el modo de carga y utiliza el búfer compartido interactivo establecido para intercambiar datos. Se garantiza que todos los valores tengan un comportamiento independiente.
| Máscara de bits | Valor en decimal | Descripción | Resultado enviado al C2 |
0x00000010 |
2 | Invoca las DLL y los plugins que habían sido cargados, junto con el parámetro proporcionado | El resultado de la ejecución |
0x00000100 |
4 | No implementado | – |
0x00001000 |
8 | Descarga de memoria las DLL y los plugins que habían sido cargados | El resultado de la ejecución |
0x00010000 |
16 | Envía el parámetro actualizado al payload cargado por el comando con el valor 17 e intercambia datos mediante la sesión interactiva. Este comando también determina si se recupera el resultado de la ejecución o se descarga el payload. | El resultado de la ejecución |
Considerando el mecanismo de carga, identificamos cuatro plugins desplegados en el objetivo, que funcionan a la perfección con ClientHub.
| Plugin | Descripción |
| Archivador de archivos | Archiva el archivo proporcionado con el algoritmo heredado ZipCrypto (sin protección con contraseña) y devuelve los datos comprimidos. |
| Recolector de archivos | Busca todos los archivos que coinciden con el patrón de búsqueda proporcionado y recopila metadatos, incluidos el nombre de archivo, las marcas de tiempo MAC (modificación, acceso y creación), el tamaño del archivo y los valores de atributos. |
| Limpiador de archivos | Sobrescribe el archivo proporcionado con bytes NULL, lo renombra con un nombre de archivo aleatorio de la misma longitud y luego lo elimina. Si se proporciona un directorio con un patrón de búsqueda, localiza todos los archivos que coinciden, renombra cada uno con un nombre aleatorio de la misma longitud que su nombre original y los elimina. |
| Monitor de unidades y sesiones | Monitorea los cambios de sesiones remotas y de unidades locales durante la duración proporcionada (en intervalos de 10 minutos) y devuelve la información de estado recopilada. |
Además de los plugins, ClientHub admite la carga del malware LPEClient y la comunicación con él. Descubrimos que los valores 16 y 17 de body_type en ClientHub corresponden al mecanismo de comunicación con el C2 de LPEClient.
LPEClient
LPEClient es el único malware observado también en Operation SyncHole, lo que indica que el actor depende en gran medida de él para perfilar a las víctimas con sofisticación y entregar payloads en múltiples operaciones. LPEClient apareció por primera vez en 2019 y se descubrió en 2020. Desde entonces, la herramienta se ha observado con frecuencia en las campañas Dream Job y Cascade Hole, dirigidas a Corea del Sur. Una investigación reciente de Check Point reveló que se utilizó para desplegar el malware FudModule mediante un zero-day.
Con el tiempo, LPEClient ha evolucionado de manera continua, pero descubrimos que hace poco sufrió una importante renovación operativa. Ya no contiene la dirección del servidor C2, sino que interactúa con ClientHub mediante un búfer compartido. Creemos que este cambio busca mejorar la ocultación de la comunicación.
La versión anterior recopilaba el nombre del equipo, el estado de la memoria, las especificaciones del CPU, los detalles del sistema operativo, la versión del archivo ntoskrnl.exe, la tabla de firmware, el nombre del antivirus, el nombre de dominio, el nombre de usuario, el nivel de integridad del proceso actual y una secuencia aleatoria de 1568 bytes. La variante de LPEClient recién actualizada recopila en su mayoría la misma información, aunque también introduce varios cambios.
- No recopila la versión del archivo ntoskrnl.exe consultando el valor
FileVersion. En su lugar, lee la clave del registroHKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\UBRo la estructuraSYSTEM_BUILD_VERSION_INFORMATIONpara recuperar la parte de revisión del número de compilación de Windows, según la compilación específica. Estos valores pueden usarse para inferir el nivel de actualización acumulativa o de parches del sistema. - Para recopilar información sobre los productos antivirus instalados, pasó de consultar mediante un comando WQL a leer directo el archivo del repositorio de WMI. Ahora lee
C:\Windows\System32\wbem\Repository\OBJECTS.DATAy busca palabras clave como AntiVirusProduct, companyName y displayName para identificar los productos instalados. - También recopila el estado de las mitigaciones de seguridad de Windows de bajo nivel. Para lograrlo, consulta la estructura
SYSTEM_KERNEL_VA_SHADOW_INFORMATIONpara obtener el estado de la mitigación Kernel VA Shadow y la estructuraSYSTEM_SHADOW_STACK_INFORMATIONpara obtener el estado de la protección Shadow Stack (CET).
Además, genera un identificador único aleatorio de 32 bytes aplicando el algoritmo HighwayHash con una operación XOR con la hora actual del sistema. La información recopilada, incluido el identificador generado, se comprime con el algoritmo XPRESS Huffman con la configuración de compresión máxima. Luego, los datos comprimidos se concatenan con el ID de mensaje 0xF07D6B34 y se cifran mediante GOST (también conocido como Magma), el estándar criptográfico nacional de Rusia, que emplea una estructura similar a DES, antes de enviarse a ClientHub mediante un búfer compartido. En un inicio, KrCERT describió el algoritmo como un esquema personalizado similar a DES. Sin embargo, un análisis posterior realizado por nosotros y por Check Point confirmó que en realidad se trata del algoritmo GOST. La clave se genera al azar mediante un algoritmo propietario de generación de claves y se antepone al mensaje cifrado.
La siguiente solicitud gestiona el intercambio de claves enviando el ID de mensaje 0xA39CF278 junto con el identificador único generado. La respuesta se descifra con el algoritmo AES-CBC-256. Para este descifrado, la clave es el hash SHA-256 del valor aleatorio de 1568 bytes generado antes, que se envió al servidor C2 durante la fase de recopilación.
Mediante este proceso, LPEClient obtiene de la respuesta del C2 un arreglo de bytes que comprende cuatro bloques, cada uno de 1568 bytes de tamaño. Cada bloque contiene una clave pública ML-KEM-1024, donde ML-KEM es un mecanismo de criptografía poscuántica estandarizado por el NIST y derivado de CRYSTALS-Kyber. LPEClient genera cuatro pares distintos de claves compartidas y textos cifrados a partir de estos bloques, cifra los textos cifrados con el algoritmo GOST y los transmite al servidor C2 mediante ClientHub, junto con el identificador de mensaje 0xEF8C0D51 y el identificador asociado. Con la fase de preparación para recibir payloads ya completada, el malware está listo para recibir los payloads que ClientHub reenvía desde el servidor C2, junto con los parámetros necesarios. El uso de criptografía poscuántica evidencia que el grupo intenta ocultar los payloads posteriores.
La respuesta al mensaje 0xEF8C0D51 se descifra con el algoritmo Threefish mediante una clave de 256 bytes compuesta por las cuatro claves compartidas distintas. Threefish es un cifrado por bloques ajustable (tweakable) que acepta un valor “tweak” junto con la clave y el mensaje. El concepto de tweak es similar al de nonce o vector de inicialización, que se utilizan en distintos tipos de cifrados. En la comunicación de LPEClient, el tweak para el descifrado se deriva aplicando XOR al identificador único con 165 (0xA5). Los primeros cuatro bytes del mensaje descifrado deben especificar la longitud del parámetro, seguida del parámetro en sí y luego del payload. El payload debe ser mayor que 4 KB y comenzar con los caracteres “MZ”, lo que indica que el payload descifrado es un archivo ejecutable. Luego, el payload se carga de forma reflexiva en memoria. Tras la carga exitosa, LPEClient envía el ID de mensaje 0xCB790A25 al servidor C2.
Antes de cargar el payload adquirido, LPEClient toma medidas para evadir los productos de seguridad. En lugar de invocar VirtualProtect de forma directa, el malware usa la función identificada HeapPageAllocator::ProtectPages en jscript9.dll para modificar la protección de la página de memoria de la función MD4Update. Luego, el inicio de la función se sobrescribe con una secuencia de opcodes embebida que funciona como un stub de syscall con los argumentos requeridos. Mediante el stub de syscall, LPEClient deshabilita un hook de instrumentación de syscalls en modo usuario.
El proceso de comunicación general es el siguiente. Identificamos el payload final cargado en última instancia como Cubridge.
Comparación de plugins y módulos
A lo largo de la investigación, identificamos una variedad de payloads desplegados por TechHub, Cubridge y ClientHub. Estos payloads se clasificaron en herramientas, plugins y módulos que conforman el framework de malware modular del grupo. Aunque aún no hemos determinado qué payloads se despliegan bajo condiciones específicas, la evidencia sugiere que el conjunto de herramientas del grupo Lazarus es cada vez más sofisticado y está segmentado en componentes especializados, en lugar de un único backdoor integral. También creemos que TechHub y Cubridge podrían compartir herramientas similares.
| Desplegado mediante | Tipo de payload | Familia |
| TechHub/Cubridge | Herramienta | Recolector de procesos, Stealer de navegadores |
| Cubridge | Módulo | Módulo de acción, Módulo de función |
| Cubridge | Plugin | ADFinder, FileCollector |
| ClientHub | Plugin | Almacenamiento de archivos, Recolector de archivos, Limpiador de archivos, Monitor de unidades/sesiones |
Estas modularizaciones no se limitan a las instancias de esta campaña. Como ya se ha indicado, se han identificado patrones similares en CookiePlus, MISTPEN, SIGNBT e IMETHOD. Cabe señalar que reclasificamos la variante de ThreatNeedle utilizada en Operation SyncHole como la versión más reciente de IMETHOD, el predecesor de ThreatNeedle que estaba en uso desde al menos 2016.
Infraestructura
Con base en la información que obtuvimos del malware TechHub, identificamos al menos tres repositorios principales utilizados como servidor C2 y un repositorio de respaldo. La evidencia más antigua muestra que el grupo ha aprovechado GitHub como servidor C2 desde al menos julio del año pasado. Sospechamos que todos los perfiles de GitHub se crearon con cuentas de correo electrónico secuestradas y se disfrazaron de repositorios normales mediante la copia o creación de proyectos comunes para evitar sospechas.
Para los servidores C2 de Cubridge y ClientHub, el grupo Lazarus empleó solo un número mínimo de sitios web surcoreanos legítimos, pero comprometidos, de medios de comunicación y diseño de interiores. Más tarde observamos que también se explotó una gama más amplia de sitios legítimos comprometidos de diversas industrias. Además, una muestra de ClientHub que detectamos utilizó Dropbox como canal de C2.
Víctimas
Identificamos al menos tres empresas de software, construcción y fabricación de equipos de comunicación por cable en Corea del Sur que fueron objetivo de Operation FlashHole. No obstante, al igual que con la operación anterior, seguimos convencidos de que un número mucho mayor de organizaciones de un espectro más amplio de industrias se ha visto afectado.
El software es el único sector atacado en ambas campañas, SyncHole y FlashHole. Esto sugiere que el actor tiene interés en comprometer el sector, robar código fuente, encontrar vulnerabilidades y utilizarlas en ataques posteriores.
Atribución y vínculos con otras campañas
FlashHole es la última oleada de la campaña Cascade Hole, de mayor alcance. Emplea software de origen surcoreano como vector de entrada para desplegar malware dirigido a dicho país. Aunque la cadena de malware ha avanzado de manera significativa respecto del año pasado, evaluamos con confianza media-alta que el mismo actor es responsable de las operaciones SyncHole y FlashHole, con base en el vector inicial de infección, los objetivos, la cadena de infección que involucra varias etapas y las mejoras técnicas y operativas. En particular, el uso de LPEClient es un fuerte indicador que respalda esta evaluación.
Las familias de malware utilizadas en el ataque tienen un vínculo histórico con los conjuntos de herramientas observados en la notoria campaña Dream Job del grupo Lazarus. Las versiones anteriores de TechHub (también conocido como CLOUDBURST y NickelLoader), Cubridge (también conocido como SIDESHOW y LightlessCan) y TouchShift se han observado en esa campaña, en especial entre 2022 y 2023.
También descubrimos que CookiePlus y ClientHub comparten coincidencias significativas: nombre de clase, ruta de configuración y plugins. Con base en esto, evaluamos con un nivel de confianza medio-alto que ClientHub es una versión avanzada de CookiePlus.
Al menos desde julio del año pasado, cuando Operation SyncHole comenzaba a llegar a su fin, también observamos varios ataques notables contra Corea del Sur que emplearon el backdoor COPPERHEDGE y para atacar organizaciones surcoreanas. Lo curioso es que las fechas de inicio de estas actividades coinciden con la evidencia más antigua que hemos identificado de Operation FlashHole. Aunque el backdoor formó parte de la segunda fase de Operation SyncHole, opera de forma independiente con su loader personalizado desde entonces. Estos incidentes presentaron cadenas de malware y herramientas distintas de las utilizadas en Operation SyncHole y FlashHole.
Como señaló AhnLab en su informe, lo más probable es que el mismo backdoor se haya observado en una actividad atípica, en específico la infección por el ransomware Gunra. Además, nuestra investigación reveló una infección originada por el backdoor que derivó en la extracción de información a un sitio de filtración de datos en la dark web, que tiene diferencias claras con el de Gunra. El sitio parece haberse creado solo para esta actividad. En resumen, a diferencia de otros ataques, el backdoor también se ha utilizado junto con ransomware y extracción de datos.
Otro punto que vale la pena mencionar es que la campaña reciente de Dream Job emplea una cadena de malware actualizada que, desde más o menos 2024, ha involucrado a MISTPEN y ForestTiger en sus ataques en lugar de su arsenal anterior, que incluía herramientas como TechHub y Cubridge. Sin embargo, las versiones actualizadas de este malware más antiguo han reaparecido ahora como parte de Operation FlashHole. Considerando estos cambios y todos los aspectos de las TTP de cada ataque, organizamos una clasificación para cada uno.
Conclusión
Nuestro análisis indica que el grupo Lazarus inicia los preparativos para las operaciones posteriores poco después de concluir las campañas anteriores, y despliega una cadena de malware mejorada mediante el perfeccionamiento de las herramientas existentes. El grupo sigue utilizando la versión avanzada de LPEClient para el las fases de perfilado y la entrega de payloads, lo que indica que la herramienta se gestiona de forma meticulosa y recibe un buen mantenimiento. Lo irónico es que el grupo parece haber adoptado la criptografía poscuántica —una opción más segura— con mayor rapidez que muchos productos de seguridad legítimos. Estas observaciones sugieren la participación de un desarrollador dedicado, mientras que otros orquestan un escenario de ataque integral contra software recién seleccionado como objetivo.
Anticipábamos que los ataques especializados dirigidos a Corea del Sur persistirían. Sin embargo, no previmos que se ejecutaran varias campañas de ataque de forma simultánea, cada una con distintos tipos de malware y herramientas. Cabe destacar que el clúster COPPERHEDGE parece estar involucrado en la monetización del ataque, mientras que Operation FlashHole se centra en el espionaje. Estamos monitoreando de cerca estos cambios para comprender sus motivaciones y objetivos.
En octubre del año pasado, el gobierno surcoreano presentó un plan de ciberseguridad integral que eliminará de forma gradual la instalación obligatoria de software de seguridad para los usuarios a partir de 2026. Estimamos que las operaciones que explotan este software seguirán muy activas durante un tiempo, para maximizar su eficiencia, antes de que este software se elimine o se mitigue por completo.
Los productos de Kaspersky detectan los exploits y el malware utilizados en este ataque con los siguientes veredictos: MEM:Trojan.Win64.Shellcode.gen, Trojan.Win64.DLLhijack.*, Trojan.Win64.Lazarus.*.
Indicadores de compromiso
Hashes de archivos
TouchShift
ec84d6cb2ae7974767aedac246b50a3e mscoree.dll
a28cba214058fcae2883d8cffc883abd mscoree.dll
c105d6b16f544582772de0159f24c00a mscoree.dll
2f8475a90a25624ed02f1d18d4e6d65d mscoree.dll
676fabe30a28b53925fba98e34b35986 mscoree.dll
b4a7eff35f048f06fb0a2d7631f23a7d mscoree.dll
Loader de ClientHub
ff07641dc56914dd90ee0bd7404d7ad7 liblzma.dll
Rutas de archivos
C:\ProgramData\Dell\Dell1.tmp
C:\ProgramData\Dell\Dell3.tmp
C:\ProgramData\Package.txt
C:\ProgramData\RasConv\mscoree.dll
C:\ProgramData\Apple\mscoree.dll
C:\ProgramData\ssh\mscoree.dll
C:\ProgramData\qorestor\mscoree.dll
C:\ProgramData\Dell\mscoree.dll
C:\ProgramData\Dell\Dell1.tmp
C:\ProgramData\Dell\Dell3.tmp
C:\Windows\System32\RasConv\mscoree.dll
C:\Windows\System32\RasConv\ActivationStore.dat
C:\Windows\System32\DrvConh\mscoree.dll
C:\Windows\System32\DrvConh\ActivationStore.dat
C:\Program Files\Common Files\System\msadc\msadc.inc
C:\ProgramData\desktops.ini
Servidores C2
javadevhouse.co[.]kr
pythonapischool[.]com
hxxps://cubedesign[.]co[.]kr/news C2 de Cubridge
hxxps://cubedesign[.]co[.]kr/mobile/fashion C2 de Cubridge
hxxps://fp-news[.]co[.]kr/shop/cart C2 de Cubridge
hxxps://k-wbc[.]co[.]kr/skin/social/social_view.php C2 de ClientHub
hxxps://rcsh[.]co[.]kr/modules/bbs/tiles/bbs_div/inputForm.php C2 de ClientHub
hxxps://www[.]ksog[.]org/insert_file/handle.php C2 de ClientHub














Operation FlashHole: Lazarus vulnera la seguridad y desafía las defensas