Hace un par de días, informamos sobre GlassWorm, que había comprometido cientos de repositorios de GitHub y un popular paquete de React para números de teléfono en npm. Seguimos investigando la carga útil completa y encontramos un marco de trabajo de varias etapas que instala un RAT persistente y, en lo más profundo de la etapa 3, instala a la fuerza una extensión de Chrome que se hace pasar por Google Docs Offline. Registra las pulsaciones de teclas, extrae cookies y tokens de sesión, captura capturas de pantalla y recibe comandos de un servidor C2 oculto en un memo de la cadena de bloques de Solana.

Fase 1: La infección inicial
Proyectos secuestrados
GlassWorm se abre paso inicialmente a través de paquetes maliciosos publicados en npm, PyPI, GitHub y el mercado de OpenVSX. El autor de la amenaza actúa en dos frentes simultáneamente: (1) creando nuevos paquetes maliciosos desde cero, y (2) comprometiendo las cuentas de los mantenedores para publicar versiones maliciosas de proyectos legítimos.
Dos tipos de cargadores
GlassWorm es quizás más conocido por su cargador Unicode invisible Ya lo hemos tratado en entradas anteriores, pero no es el único mecanismo de distribución que se utiliza. Una segunda variante, más directa, utiliza un código ofuscado convencional preinstall guion, tal y como se ha visto en el reciente Vulnerabilidad de react-native-country-select en npm. Ambas opciones ofrecen, en última instancia, el mismo resultado y comparten la misma baliza C2 basada en blockchain, pero siguen caminos muy diferentes para llegar a él.
Independientemente del cargador que llegue al equipo de la víctima, la lógica de ejecución de la fase 1 es la misma. Tras un retraso de 10 segundos en el inicio, el cargador realiza dos comprobaciones antes de continuar.
Geovallas. El cargador comprueba cinco señales de configuración regional (os.userInfo().username, process.env.LANG, process.env.LANGUAGE, process.env.LC_ALL, y la configuración regional «Intl» resuelta) frente a /ru_RU|ru-RU|Ruso|ruso/i, y compara la zona horaria del sistema y la diferencia con respecto al UTC con una lista predefinida de zonas horarias rusas que abarca desde Europe/Moscow hasta Asia/Anadyr. Si se detecta una configuración regional rusa, la ejecución se detiene.
limitación de velocidad. El cargador lee ~/init.json (o %USERPROFILE%\init.json (en Windows) y comprueba una marca de tiempo almacenada. Si el archivo se ha guardado hace menos de dos horas, se detiene la ejecución. De lo contrario, se actualiza la marca de tiempo.
C2 de la cadena de bloques Solana
Por último, el cargador consulta la cadena de bloques de Solana para obtener su dirección C2. En lugar de codificar de forma fija una URL que podría ser eliminada, el autor de la amenaza la almacena en el nota campo de una transacción de Solana. El cargador llama a getSignaturesForAddress frente a un monedero preconfigurado, probando sucesivamente nueve puntos de conexión RPC públicos hasta que uno de ellos responda:
https://api.mainnet-beta.solana.comhttps://solana-mainnet.gateway.tatum.iohttps://go.getblock.us/86aac42ad4484f3c813079afc201451chttps://solana-rpc.publicnode.comhttps://api.blockeden.xyz/solana/KeCh6p22EX5AeRHxMSmchttps://solana.drpc.orghttps://solana.leorpc.com/?api_key=FREEhttps://solana.api.onfinality.io/publichttps://solana.api.pocket.network/
Se han detectado dos direcciones de monedero en las dos variantes del cargador:
BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC(Cargador Unicode)6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ(Cargador de preinstalación ofuscado)
El cargador realiza consultas en un bucle de 10 segundos hasta que encuentra una transacción con el campo «memo» no nulo. La función «memo» de Solana se diseñó para añadir anotaciones a las transacciones, pero en este caso funciona como un punto de entrega secreto. Los memos son permanentes, visibles públicamente en la cadena y se almacenan en una infraestructura que ninguna parte puede desactivar. El operador puede actualizar la URL de la Etapa 2 en cualquier momento enviando una nueva transacción de Solana con un nuevo memo. No es necesario modificar ningún paquete, no hay que volver a implementar ninguna infraestructura y no hay nada que los defensores puedan bloquear en la capa de red.
La nota que se encontró en la cartera 6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ es:
{"link":"aHR0cDovLzQ1LjMyLjE1MC4yNTEvM2U0VGc4ViUyRjhhQ21PSktpcEFTQURnJTNEJTNE"}El enlace El valor es una URL codificada en Base64. Una vez descodificada:
http://45.32.150.251/3e4Tg8V%2F8aCmOJKipASADg%3D%3DEl cargador recupera esta URL mediante un os encabezado configurado para la plataforma actual (Darwin, Linux, o Win32), lo que permite que el C2 en 45.32.150[.]251 para servir cargas útiles específicas para cada plataforma. El cuerpo de la respuesta es la carga útil cifrada de la fase 2, que posteriormente se descifra y se ejecuta. En el momento de redactar este informe, el servidor C2 seguía activo y devolvía una carga útil para Win32.
Fase 2: Exfiltración secreta
La carga útil de la Etapa 2 es un marco completo para el robo de datos que incluye la recopilación de credenciales, la sustracción de carteras de criptomonedas, la elaboración de perfiles del host y su propia lógica de dropper para la Etapa 3, que es la fase final y persistente. Toda la información recopilada se almacina en %TEMP%\hJxPxpHP\, comprimido y enviado mediante una solicitud POST a http://217.69.3[.]152/wall.
Robo de carteras de criptomonedas
La carga útil realiza una búsqueda recursiva %APPDATA% y %LOCALAPPDATA% para perfiles de extensiones de navegador y datos de aplicaciones de monedero independientes. Se centra en 71 identificadores de monederos de extensiones de navegador, lo que abarca prácticamente todos los principales monederos en uso: MetaMask, Phantom, Coinbase, Exodus, Binance, Ronin, Keplr, etc. También recopila .txt archivos de las carpetas «Documentos» y «Escritorio» de la víctima, y copia imágenes cuyos nombres de archivo coincidan con palabras clave relacionadas con frases de recuperación o activos criptográficos.
Robo de credenciales de desarrolladores
La fase 2 se centra en los almacenes de credenciales que un desarrollador de software suele tener en su equipo. La carga útil dice lo siguiente: ~/.npmrc y process.env.NPM_TOKEN. Cada token encontrado se valida en tiempo real con respecto a https://registry.npmjs.org/-/whoami antes de la exfiltración. También extrae tokens a través del credenciales de Git el comando y desde el almacenamiento interno de VS Code.
Exfiltración de secretos en la nube
La etapa 2 también copia los archivos de credenciales de AWS, GCP, Azure, Docker, Kubernetes, claves SSH y Heroku .netrc, de DigitalOcean doctl, y Terraform.
Perfil del anfitrión
Por último, genera un system_info.txt con un perfil detallado del hardware, las variables de entorno, las aplicaciones instaladas, los procesos en ejecución, la estructura del disco y los detalles del sistema operativo.
Preparación para la fase 3
Tras la exfiltración, se prepara la fase 3 descargando dos componentes:
- 3a) Archivo binario de phishing para carteras físicas de criptomonedas (Ledger y Trezor).
- 3b) Un RAT inmortal basado en WebSocket, guardado como
%APPDATA%\QtCvyfVWKH\index.js, que incluye varios archivos binarios:c_x64.node/f_ex86.node— programas que roban credenciales del navegadordatos— Elusión del cifrado integrado en las aplicaciones de Chromeindex_ia32.node/index_x64.node— Módulos HVNCw.node(Windows) /m(macOS) — Instala una extensión maliciosa para el navegador
La carga útil del RAT no viene simplemente codificada con una URL. En su lugar, recupera la página pública de Google Calendar en https://calendar.app.google/2NkrcKKj4T6Dn4uK6 y extrae el título de la invitación. Ese valor se decodifica en Base64 y se añade como slug de URL a http://45.32.150[.]251. Uso de Google Calendar como capa de redireccionamiento para la entrega de datos es una tendencia que llevamos observando desde marzo de 2025, y sigue apareciendo de forma constante en las herramientas de este actor malicioso.

Fase 3a: Suplantación de identidad en carteras de hardware
En equipos en los que %APPDATA%\Ledger Live si existe, la etapa 3 recupera un archivo binario .NET WPF de http://45.32.150[.]251/led-win32, lo deja en %TEMP%\SKuyzYcDD.exe, y añade HKCU\Software\Microsoft\Windows\CurrentVersion\Run\UpdateLedger por su persistencia. El nombre interno del archivo es Assaac.exe, atribuido a una empresa que se hace llamar «LLC LogicSub» (SHA-256: 06fab21dc276e3ab9b5d0a1532398979fd377b080c86d74f2c53a04603a43b1d). El archivo binario no es un RAT. Su única función es robar carteras de criptomonedas haciéndose pasar por Ledger Live y Trezor.

Al iniciarse, consulta https://ipapi.co/xml y comprueba si el país indicado coincide con alguna de las nueve exclusiones de la región de la CEI: Rusia, Kazajistán, Kirguistán, Azerbaiyán, Tayikistán, Uzbekistán, Bielorrusia, Moldavia y Armenia. Si la víctima se encuentra en alguno de esos países, la ejecución se detiene. Esto reproduce la lógica de geolocalización de la Etapa 1.
El binario registra una suscripción a eventos WMI para detectar conexiones de dispositivos USB:
SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_PnPEntity'Cuando se conecta un dispositivo Ledger o Trezor, se abre la ventana de phishing correspondiente. La interfaz de usuario de Ledger muestra un error de configuración falso y presenta 24 campos de entrada numerados para la frase de recuperación. La interfaz de usuario de Trezor muestra un mensaje falso que dice «Error en la validación del firmware, iniciando reinicio de emergencia», con el mismo diseño de entrada de 24 palabras. Ambas ventanas incluyen un botón «RESTORE WALLET» (Restaurar monedero).
Un bucle en segundo plano que se ejecuta cada segundo llama a Process.GetProcessesByName para cerrar cualquier proceso real de Ledger Live y volver a mostrar la ventana de phishing si la víctima la cierra. El Ventana_Cerrando El controlador intercepta los intentos de cierre y muestra un cuadro de diálogo en el que se advierte de que el cierre podría provocar la pérdida de activos criptográficos.
Cuando se introduce una frase válida, las 24 palabras se transmiten a través de System.Net.Http.HttpClient con 45.150.34[.]158.
Fase 3b: RAT basado en WebSocket
El RAT se guarda como %APPDATA%\QtCvyfVWKH\index.js y cuenta con dos mecanismos de persistencia para sobrevivir a los reinicios. Una tarea programada denominada Actualizar aplicación se ejecuta al iniciar el sistema con los privilegios más altos, y un HKCU\Software\Microsoft\Windows\CurrentVersion\Run La tecla ejecuta un lanzador de PowerShell en %LOCALAPPDATA%\QtCvyfVWKH\AghzgY.ps1.
La inmortalidad está integrada. Los ganchos del script SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGUSR2, excepción no capturada, y Rechazo no gestionado. Ante cualquiera de esas señales, programa la descarga y el reinicio de la carga útil. Si se interrumpe el proceso, simplemente se vuelve a iniciar más tarde.
C2 basado en DHT
El RAT no codifica de forma fija su dirección C2 principal. Realiza una consulta en el DHT para obtener la clave pública fijada. 3c90fa0e84dd76c94b1468f38ed640945d72bc12, iniciando el sistema mediante dht.libtorrent.org, router.bittorrent.com, y router.utorrent.com.
El operador almacena la configuración en tiempo real en el valor DHT asociado a esa clave. Si dht.get falla directamente, el script vuelve a intentarlo tras cinco minutos. Si no devuelve ningún valor, el script recurre al «dead-drop» de Solana: realiza una consulta getSignaturesForAddress para el monedero BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC, descodifica la dirección IP del campo de enlace del memo y vuelve a ejecutar la búsqueda. El memo de Solana se puede actualizar con una nueva dirección IP en cualquier momento para restablecer la accesibilidad de la DHT sin necesidad de modificar el cargador.
La configuración recuperada de la infraestructura del atacante:
217.69.0[.]159:10000- Nodo de arranque de DHT45.32.150[.]251- C2 basado en WebSocket217.69.3[.]152:80- Servidor de exfiltración
Los comandos de C2
Una vez resuelta la configuración de DHT, el script abre una conexión Socket.IO con 45.32.150[.]251:4787 y procesa cinco categorías de órdenes C2:
- start_hvnc / stop_hvnc: Implementa el módulo nativo HVNC para el acceso remoto oculto al escritorio.
- start_socks / calcetines antideslizantes: Obtiene un módulo WebRTC de
http://45.32.150[.]251/module/wrtc, lo instala en%APPDATA%\_node_x64\webrtc\wrtc-win32-x64\index.js, y lo ejecuta como un proxy SOCKS, convirtiendo el equipo de la víctima en un nodo proxy que sirve de infraestructura para que el autor de la amenaza lleve a cabo otros ataques desde la IP de la víctima. - reget_log: Ejecuta el proceso completo de robo y exfiltración de credenciales del navegador.
- get_system_info: Envía información sobre el sistema operativo, la CPU, la memoria, el nombre del host, el tiempo de actividad, el nombre de usuario y el directorio de inicio.
- comando: Ejecuta código JavaScript arbitrario proporcionado por el atacante mediante eval(), lo que permite al operador ejecutar código de forma remota sin restricciones.
Robo de credenciales del navegador
El script está diseñado para Chrome, Edge, Brave, Opera, Opera GX, Vivaldi y Firefox. Enumera los directorios de perfiles, comprueba las cookies para identificar los perfiles activos y, a continuación, llama a c_x64.node para extraer credenciales directamente de las bases de datos SQLite del navegador (datos de inicio de sesión, cookies, datos web). Chrome v127+ cifra su clave maestra mediante el cifrado vinculado a la aplicación, lo que normalmente impide que un proceso ajeno a Chrome pueda leerla. El binario de datos intenta eludir esta función de seguridad. Los resultados se almacenan como archivos JSON en %TEMP%\EUXFUxzOVe\, incluyendo cookies, datos de inicio de sesión guardados, entradas de autocompletado, historial de navegación, marcadores y tarjetas de pago. El directorio se comprime en formato ZIP, se cifra y se envía mediante un método POST a 217.69.3[.]152:80/registro.
Extensión maliciosa de Chrome RAT
El script también instala a la fuerza una extensión que se hace pasar por Google Docs sin conexión (versión 1.95.1). Obtiene su C2 a partir de un memo de Solana independiente, consultando getSignaturesForAddress para el monedero DSRUBTziADDHSik7WQvSMjvwCHFsbsThrbbjWMoJPUiW. El mensaje de esa cartera contiene los campos «c2server» y «checkIp», que apuntan al servidor de la API de la extensión y al asistente de geo-IP. Tras analizar el mensaje, la extensión se registra como agente a través de POST /api/register, almacena el agent_id devuelto en chrome.storage.local y comienza a realizar consultas GET /api/commands?agent_id=<id> a intervalos aleatorios de entre 5 y 30 segundos.

El operador puede introducir los siguientes comandos:
- domsnapshot: extrae el contenido completo
document.documentElement.outerHTMLde la pestaña activa - getcookies: recopila cookies, que se pueden filtrar opcionalmente por dominio
- volcado de la memoria local: vacía todo
localStoragepares clave-valor - take_screenshot: captura una imagen de la pestaña codificada en Base64
- capturar_portapapeles: lee el portapapeles a través de
navigator.clipboard.readText() - historial: extrae hasta 5.000 entradas del historial del navegador (ventana predeterminada: 7 días)
- Marcadores: exporta el árbol completo de marcadores
- enumeración: identifica el navegador, el hardware y los detalles de WebGL/GPU, y comprueba las extensiones instaladas a través de
chrome-extension://<id>/manifest.json - iniciar keylogger / detener keylogger / obtener datos del keylogger: detecta los eventos keydown, keyup, keypress, input, change, focus y blur en todas las páginas; captura los valores introducidos, los metadatos de los formularios y el contexto del elemento de destino; actualiza
POST /api/exfilcada cinco segundos
Todos los datos recopilados se envían a POST /api/exfil como { id_agente, acción, carga útil }.
La extensión también lleva a cabo una vigilancia específica de las sesiones. Obtiene las reglas de los sitios supervisados de /api/obtener-url-para-ver y se entrega con Bybit (.bybit.com) preconfigurado como destino, a la espera de las cookies «secure-token» y «deviceid». Cuando las detecta, activa un webhook de «auth-detected» para /api/webhook/autenticación-detectada que contiene la información de las cookies y los metadatos de la página. El servidor C2 también puede proporcionar reglas de redireccionamiento que obliguen a las pestañas activas a redirigirse a direcciones URL controladas por el atacante.
Detección y Protección
Las amenazas invisibles requieren defensas activas. No se puede confiar en la revisión visual del código ni en los análisis sintácticos estándar para detectar lo que no se ve. En Aikido, hemos integrado la detección de Glassworm y otros actores maliciosos directamente en nuestro proceso de análisis de malware.
Si ya utiliza Aikido, estos paquetes serían marcados en su feed como un hallazgo crítico de 100/100.

¿Todavía no está en Aikido? Cree una cuenta gratuita y vincule sus repositorios. El plan gratuito incluye nuestra cobertura de detección de malware (no se requiere tarjeta de crédito).
Por fin, una herramienta capaz de detener el malware de la cadena de suministro en tiempo real, en cuanto aparece, puede evitar una infección grave. Esta es la idea en la que se basa Aikido Safe Chain, una herramienta gratuita y de código abierto que se integra con npm, npx, yarn, pnpm y pnpx, y que utiliza tanto inteligencia artificial como investigadores humanos especializados en malware para detectar y bloquear los riesgos más recientes de la cadena de suministro antes de que entren en tu entorno.
Indicadores de Compromiso
Red — Direcciones IP
45.32.150[.]251— Entrega de la carga útil de la fase 2, RAT WebSocket de la fase 3 (:4787)217.69.3[.]152— Servidor de exfiltración: Etapa 2 (/wall), Etapa 3 (/log)217.69.0[.]159— Nodo de arranque de DHT (:10000)45.150.34[.]158— Sustracción de la frase de semillas de Ledger/Trezor
Red — URL de C2
http://45.32.150[.]251/3e4Tg8V%2F8aCmOJKipASADg%3D%3D— Carga útil cifrada de la fase 2http://45.32.150[.]251/led-win32— Descarga del archivo binario de phishing de Ledger/Trezorhttp://45.32.150[.]251/get_arhive_npm/nt70c2J3PG%2BfPBSFHJKoWQ%3D%3D— Archivo de módulos nativoshttp://45.32.150[.]251/get_encrypt_file_exe/E/E%2BT9tEjmURMwNnCCY2CA%3D%3D— Carga útil operativa del HVNChttp://45.32.150[.]251/module/wrtc— Módulo WebRTC de proxy SOCKShttp://45.32.150[.]251:4787— Canal RAT de WebSocket (Socket.IO)http://217.69.3[.]152/wall— Punto final de exfiltración de la fase 2http://217.69.3[.]152:80/log— Punto final de exfiltración de credenciales del navegador (Fase 3)https://calendar.app[.]google/2NkrcKKj4T6Dn4uK6— Indirección de URL de la etapa 3 a través de una invitación de Google Calendar
Carteras Solana
BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC— Cargador Unicode de la fase 1 con «dead-drop» C2; alternativa DHT en la fase 36YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ— Cargador de preinstalación ofuscado de la fase 1 con punto de entrega C2DSRUBTziADDHSik7WQvSMjvwCHFsbsThrbbjWMoJPUiW— Extensión de navegador C2 dead-drop
Hash de archivos (SHA-256)
06fab21dc276e3ab9b5d0a1532398979fd377b080c86d74f2c53a04603a43b1d— Assaac.exe / SKuyzYcDD.exe (archivo binario de phishing para Ledger/Trezor)f171c383e21243ac85b5ee69821d16f10e8d718089a5c090c41efeaa42e81fca— c_x64.node (programa para robar credenciales del navegador, Windows x64)9df62cefd87784c7ee1ca8b4e6fc49737a90492fa6c23901e3b7981b18c6c988— f_ex86.node (programa para robar credenciales del navegador, Windows x86)43253a888417dfab034f781527e08fb58e929096cb4ef69456c3e13550cb4e9e— datos (elusión del cifrado vinculado a la aplicación de Chrome)4a60afa085fe5a847aef164578537bc33b9b58954143381e0c65c6354e4501e3— index_ia32.node (módulo HVNC, Windows x86)de81eacd045a88598f16680ce01bf99837b1d8170c7fc38a18747ef10e930776— index_x64.node (módulo HVNC, Windows x64)fdba5be3da2467e642bd8710f971e6b266b30ac15f5f413982fd719d7e0bffd9— w.node (instalador forzado de la extensión de Chrome, Windows x64)ee3e4dd5c1e073b8805f4107ccc7bc7e6e3c209fe13ea04ff3f2173c8dbe74a6— m (Instalador forzado de la extensión de Chrome, binario universal para macOS)
Nombres de archivos
~/init.json/%USERPROFILE%\init.json— Marca de tiempo de limitación de velocidad; contiene un UUID, la versión y la fecha%TEMP%\hJxPxpHP\— Directorio de almacenamiento de credenciales de la fase 2%TEMP%\EUXFUxzOVe\— Directorio de almacenamiento temporal de credenciales del navegador de la etapa 3%TEMP%\SKuyzYcDD.exe— Archivo binario de phishing de Ledger/Trezor%APPDATA%\QtCvyfVWKH\index.js— Script principal de RAT de la fase 3%LOCALAPPDATA%\QtCvyfVWKH\AghzgY.ps1— Lanzador de persistencia de PowerShell de la fase 3%APPDATA%\_node_x86\node\node.exe— Se ha descargado automáticamente el entorno de ejecución de Node.js v22.9.0 x86%APPDATA%\_node_x64\node\node.exe— Se ha descargado automáticamente el entorno de ejecución de Node.js v22.9.0 x64%APPDATA%\_node_x64\webrtc\wrtc-win32-x64\index.js— Módulo proxy SOCKS%LOCALAPPDATA%\Google\Chrome\jucku\— Directorio de extensiones maliciosas de Chrome (Windows)/Biblioteca/Application Support/Google/Chrome/myextension/— Directorio de extensiones maliciosas de Chrome (macOS)
Registro
HKCU\Software\Microsoft\Windows\CurrentVersion\Run\UpdateApp— Persistencia del RAT en la fase 3HKCU\Software\Microsoft\Windows\CurrentVersion\Run\UpdateLedger→%TEMP%\SKuyzYcDD.exe— Persistencia de binarios en el phishing de Ledger
Tareas programadas
Actualizar aplicación— CarrerasAghzgY.ps1(Fase 3) al iniciar el sistema con los privilegios más altos
WMI
SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_PnPEntity'— Desencadenante de detección de monederos físicos USB (archivo binario de phishing de Ledger)
Extensión para el navegador
- Nombre para mostrar: Google Docs sin conexión (versión 1.95.1)
- Nombre del directorio de extensiones (Windows): jucku
- Nombre del directorio de la extensión (macOS): myextension
Nombres de procesos
Assaac— Nombre del proceso interno del binario de phishing de Ledger/Trezor

