Hace un par de días, cubrimos cómo GlassWorm comprometía cientos de repositorios de GitHub y un popular paquete de números de teléfono de React en npm. Seguimos investigando la carga útil completa y encontramos un framework de múltiples etapas que instala un RAT persistente y, en lo profundo de la Etapa 3, fuerza la instalación de una extensión de Chrome que se hace pasar por Google Docs Offline. Registra las pulsaciones de teclas, descarga cookies y tokens de sesión, captura pantallas y recibe comandos de un servidor C2 oculto en un memo de la blockchain de Solana.

Etapa 1: La Infección Inicial
Proyectos Secuestrados
GlassWorm obtiene su punto de apoyo inicial a través de paquetes maliciosos publicados en npm, PyPI, GitHub y el marketplace de OpenVSX. El actor de la amenaza opera en dos frentes simultáneamente: (1) creando nuevos paquetes maliciosos desde cero, y (2) comprometiendo las cuentas de los mantenedores para subir versiones maliciosas de proyectos legítimos.
Dos Tipos de Cargadores
GlassWorm es quizás más conocido por su cargador Unicode invisible que hemos cubierto en publicaciones anteriores, pero no es el único mecanismo de entrega en uso. Una segunda variante, más directa, utiliza un script ofuscado convencional preinstall script, como se vio en el reciente compromiso de react-native-country-select en npm. Ambos logran en última instancia el mismo resultado y comparten la misma baliza C2 basada en blockchain, pero toman caminos muy diferentes para llegar a él.
Independientemente del cargador que llegue a la máquina víctima, la lógica de ejecución de la Etapa 1 es la misma. Tras un retardo de inicio de 10 segundos, el cargador realiza dos comprobaciones antes de continuar.
Geocercado. 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 resuelta de Intl) contra /ru_RU|ru-RU|Russian|russian/i, y comprueba la zona horaria del sistema y el desplazamiento UTC con una lista codificada de zonas horarias rusas que abarcan desde Europa/Moscú 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 fue escrito hace menos de dos horas, la ejecución se detiene. En caso contrario, la marca de tiempo se actualiza.
C2 de la Blockchain de Solana
Finalmente, el cargador consulta la blockchain de Solana para obtener su dirección C2. En lugar de codificar una URL que pueda ser eliminada, el actor de amenazas la almacena en el memo campo de una transacción de Solana. El cargador llama a getSignaturesForAddress contra una cartera codificada, alternando entre nueve puntos finales RPC públicos hasta que uno responde:
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 observado dos direcciones de cartera en las dos variantes del cargador:
BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC(cargador Unicode)6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ(Cargador de preinstalación ofuscado)
El cargador sondea en un bucle de 10 segundos hasta que encuentra una transacción con un campo de memo no nulo. La función de memo de Solana fue diseñada para añadir anotaciones a las transacciones, pero aquí funciona como un buzón muerto encubierto. Los memos son permanentes, visibles públicamente en la cadena y almacenados en una infraestructura que no puede ser eliminada por ninguna parte individual. 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 es necesario volver a desplegar ninguna infraestructura, y no hay nada que los defensores puedan bloquear en la capa de red.
El memo observado en la cartera 6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ es:
{"link":"aHR0cDovLzQ1LjMyLjE1MC4yNTEvM2U0VGc4ViUyRjhhQ21PSktpcEFTQURnJTNEJTNE"}El enlace El valor es una URL codificada en Base64. Decodificado:
http://45.32.150.251/3e4Tg8V%2F8aCmOJKipASADg%3D%3DEl cargador obtiene esta URL con un os encabezado establecido en la plataforma actual (darwin, linux, o win32), permitiendo que el C2 en 45.32.150[.]251 sirva payloads específicos de la plataforma. El cuerpo de la respuesta es el payload cifrado de la Etapa 2, que posteriormente se descifra y ejecuta. En el momento de escribir esto, el C2 seguía activo y devolvía un payload para win32.
Etapa 2: Exfiltración de secretos
El payload de la Etapa 2 es un framework completo de robo de datos con recolección de credenciales, exfiltración de carteras de criptomonedas, perfilado de hosts y su propia lógica de dropper para la Etapa 3 final y persistente. Todo lo recolectado se prepara bajo %TEMP%\hJxPxpHP\, comprimido y enviado mediante una solicitud POST a http://217.69.3[.]152/wall.
Robo de carteras de criptomonedas
El payload busca recursivamente en %APPDATA% y %LOCALAPPDATA% perfiles de extensiones de navegador y datos de aplicaciones de cartera independientes. Se dirige a 71 IDs de carteras de extensiones de navegador, cubriendo prácticamente todas las carteras principales 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 coinciden con palabras clave asociadas a frases semilla o tenencias de criptomonedas.
Robo de credenciales de desarrolladores
La fase 2 se dirige a los almacenes de credenciales que un desarrollador de software probablemente tenga en su máquina. La carga útil lee ~/.npmrc y process.env.NPM_TOKEN. Cualquier token encontrado se valida en tiempo real contra https://registry.npmjs.org/-/whoami antes de la exfiltración. También extrae tokens a través del git credential comando y del almacenamiento interno de VS Code.
Exfiltración de secretos de cloud
La fase 2 también copia archivos de credenciales para AWS, GCP, Azure, Docker, Kubernetes, claves SSH, los de Heroku, .netrc, los de DigitalOcean doctl, y Terraform.
Perfilado de host
Finalmente, genera un system_info.txt con un perfil de hardware detallado, variables de entorno, aplicaciones instaladas, procesos en ejecución, distribución del disco y detalles del SO.
Preparación para la fase 3
Después de la exfiltración, la fase 3 se prepara descargando dos componentes:
- 3a) Binario de phishing para monederos de criptomonedas físicos (Ledger y Trezor).
- 3b) Un RAT inmortal basado en Websocket, guardado como
%APPDATA%\QtCvyfVWKH\index.js, que se distribuye con varios binarios:c_x64.node/f_ex86.node— extractores de credenciales de navegadordatos— Omisión de cifrado ligado a la aplicación de Chromeindex_ia32.node/index_x64.node— Módulos HVNCw.node(Windows) /m(macOS) — Instala una extensión de navegador maliciosa
El payload del RAT no está simplemente codificado con una URL. En su lugar, obtiene 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 un slug de URL a http://45.32.150[.]251. Utilizar Google Calendar como capa de indirección para la entrega del payload es un patrón que hemos estado rastreando desde marzo de 2025, y sigue apareciendo de forma consistente en las herramientas de este actor de amenazas.

Etapa 3a: Phishing de cartera de hardware
En las máquinas donde %APPDATA%\Ledger Live existe, la Etapa 3 obtiene un 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 para persistencia. El nombre interno del archivo es Assaac.exe, atribuido a una empresa que se autodenomina "LLC LogicSub" (SHA-256: 06fab21dc276e3ab9b5d0a1532398979fd377b080c86d74f2c53a04603a43b1d). El binario no es un RAT. Su única función es robar criptocarteras suplantando a Ledger Live y Trezor.

Al inicio, consulta https://ipapi.co/xml y compara el país devuelto con 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 refleja la lógica de geofencing 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 numerados para introducir la frase de recuperación. La interfaz de usuario de Trezor muestra un mensaje falso de "Fallo 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".
Un bucle en segundo plano que se ejecuta a intervalos de un segundo llama a Process.GetProcessesByName para eliminar cualquier proceso real de Ledger Live y vuelve a mostrar la ventana de phishing si la víctima la cierra. El Window_Closing controlador intercepta los intentos de cierre con un cuadro de diálogo que advierte que el cierre podría resultar en la pérdida de criptoactivos.
Cuando se envía una frase válida, las 24 palabras se transmiten a través de System.Net.Http.HttpClient con 45.150.34[.]158.
Etapa 3b: RAT basado en Websocket
El RAT se guarda como %APPDATA%\QtCvyfVWKH\index.js y viene con dos mecanismos de persistencia para sobrevivir a los reinicios. Una tarea programada llamada UpdateApp se ejecuta al inicio con los privilegios más altos, y una HKCU\Software\Microsoft\Windows\CurrentVersion\Run clave ejecuta un lanzador de PowerShell en %LOCALAPPDATA%\QtCvyfVWKH\AghzgY.ps1.
La inmortalidad está integrada. El script se engancha a SIGINT, SIGTERM, SIGQUIT, SIGHUP, SIGUSR2, uncaughtException, y unhandledRejection. Ante cualquiera de esas señales, programa la redescarga y el reinicio del payload. Si el proceso es eliminado, simplemente se reconstruye más tarde.
C2 basado en DHT
El RAT no codifica su dirección C2 principal. Realiza una búsqueda DHT para la clave pública fijada 3c90fa0e84dd76c94b1468f38ed640945d72bc12, arrancando a través de dht.libtorrent.org, router.bittorrent.com, y router.utorrent.com.
El operador almacena la configuración en vivo en el valor DHT de esa clave. Si dht.get falla directamente, el script reintenta después de cinco minutos. Si no devuelve ningún valor, el script recurre al dead-drop de memo de Solana: sondea getSignaturesForAddress para la cartera BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC, decodifica la IP del campo de enlace del memo y vuelve a ejecutar la búsqueda. El memo de Solana puede actualizarse con una nueva IP en cualquier momento para restablecer la accesibilidad DHT sin tocar el cargador.
La configuración recuperada de la infraestructura del atacante:
217.69.0[.]159:10000- Nodo de arranque DHT45.32.150[.]251- C2 basado en WebSocket217.69.3[.]152:80- Servidor de exfiltración
Los Comandos C2
Una vez resuelta la configuración DHT, el script abre una conexión Socket.IO a 45.32.150[.]251:4787 y procesa cinco categorías de comandos C2:
- start_hvnc / stop_hvnc: Despliega el módulo nativo HVNC para acceso remoto oculto al escritorio.
- start_socks / stop_socks: 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 la máquina víctima en un nodo proxy, sirviendo como infraestructura para que el actor de amenazas 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 del SO, CPU, memoria, nombre de host, tiempo de actividad, nombre de usuario y directorio de inicio.
- command: Ejecuta JavaScript arbitrario proporcionado por el atacante a través de eval(), otorgando al operador ejecución remota completa de código.
Robo de Credenciales del Navegador
El script se dirige a Chrome, Edge, Brave, Opera, Opera GX, Vivaldi y Firefox. Enumera los directorios de perfil, verifica las cookies para identificar perfiles activos, luego invoca a c_x64.node para extraer credenciales directamente de las bases de datos SQLite del navegador (Login Data, Cookies, Web Data). Chrome v127+ cifra su clave maestra utilizando App-Bound Encryption, lo que normalmente impide que un proceso externo a Chrome la lea. El binario de datos intenta eludir esta característica de seguridad. Los resultados se organizan como archivos JSON en %TEMP%\EUXFUxzOVe\, cubriendo cookies, inicios de sesión guardados, entradas de autocompletar, historial de navegación, marcadores y tarjetas de pago. El directorio se comprime, cifra y se envía mediante POST a 217.69.3[.]152:80/log.
RAT de Extensión Maliciosa de Chrome
El script también instala forzosamente una extensión que se hace pasar por Google Docs Offline (versión 1.95.1). Resuelve su C2 a partir de un memo de Solana independiente, realizando sondeos getSignaturesForAddress para la cartera DSRUBTziADDHSik7WQvSMjvwCHFsbsThrbbjWMoJPUiW. El memo de esa cartera contiene los campos c2server y checkIp que apuntan al servidor API de la extensión y al asistente de geo-IP. Después de analizar el memo, la extensión se registra como un agente a través de POST /api/register, almacena el agent_id devuelto en chrome.storage.local y comienza a sondear GET /api/commands?agent_id=<id> en un intervalo aleatorio de 5 a 30 segundos.

El operador puede emitir los siguientes comandos:
- domsnapshot: exfiltra el contenido completo de
document.documentElement.outerHTMLde la pestaña activa - getcookies: recopila cookies, opcionalmente filtradas por dominio
- localstoragedump: vuelca todos los
localStoragepares clave/valor - take_screenshot: captura una captura de pantalla de la pestaña codificada en base64
- capture_clipboard: lee el portapapeles a través de
navigator.clipboard.readText() - history: extrae hasta 5.000 entradas del historial del navegador (ventana predeterminada: 7 días)
- bookmarks: exporta el árbol completo de marcadores
- enumeration: toma la huella digital del navegador, el hardware, los detalles de WebGL/GPU y sondea las extensiones instaladas a través de
chrome-extension://<id>/manifest.json - startkeylogger / stopkeylogger / getkeyloggerdata: intercepta los eventos keydown, keyup, keypress, input, change, focus y blur en todas las páginas; captura los valores introducidos, los metadatos del formulario y el contexto del elemento objetivo; los envía a
POST /api/exfilcada cinco segundos
Todos los datos recopilados se envían a POST /api/exfil como { agent_id, action, payload }.
La extensión también realiza vigilancia de sesión dirigida. Obtiene las reglas de los sitios monitorizados de /api/get-url-for-watch y se distribuye con Bybit (.bybit.com) preconfigurado como objetivo, monitorizando las cookies secure-token y deviceid. Al detectarlas, dispara un webhook auth-detected a /api/webhook/auth-detected que contiene el material de las cookies y los metadatos de la página. El C2 también puede proporcionar reglas de redirección que fuerzan las pestañas activas a URLs 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 o en el linting estándar para detectar lo que no se ve. En Aikido, hemos integrado la detección de Glassworm y otros actores de amenazas directamente en nuestra pipeline de escaneo 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).
Finalmente, una herramienta que puede detener el malware de la cadena de suministro en tiempo real a medida que aparece puede prevenir una infección grave. Esta es la idea detrás de Aikido Safe Chain, una herramienta gratuita y de código abierto que envuelve npm, npx, yarn, pnpm y pnpx, y utiliza tanto AI como investigadores de malware humanos para detectar y bloquear los últimos riesgos de la cadena de suministro antes de que entren en su entorno.
Indicadores de Compromiso
Red — Direcciones IP
45.32.150[.]251— Entrega de payload de Etapa 2, RAT WebSocket de Etapa 3 (:4787)217.69.3[.]152— Servidor de exfiltración: Etapa 2 (/wall), Etapa 3 (/log)217.69.0[.]159— Nodo de arranque DHT (:10000)45.150.34[.]158— Exfiltración de frase semilla de Ledger/Trezor
Red — URLs C2
http://45.32.150[.]251/3e4Tg8V%2F8aCmOJKipASADg%3D%3D— Payload cifrado de Etapa 2http://45.32.150[.]251/led-win32— Descarga de binario de phishing de Ledger/Trezorhttp://45.32.150[.]251/get_arhive_npm/nt70c2J3PG%2BfPBSFHJKoWQ%3D%3D— Archivo de módulo nativohttp://45.32.150[.]251/get_encrypt_file_exe/E/E%2BT9tEjmURMwNnCCY2CA%3D%3D— Payload operativo HVNChttp://45.32.150[.]251/module/wrtc— Módulo WebRTC de proxy SOCKShttp://45.32.150[.]251:4787— Canal RAT WebSocket (Socket.IO)http://217.69.3[.]152/wall— Punto final de exfiltración de Etapa 2http://217.69.3[.]152:80/log— Punto final de exfiltración de credenciales de navegador de Etapa 3https://calendar.app[.]google/2NkrcKKj4T6Dn4uK6— Indirección de URL de Etapa 3 a través de invitación de Google Calendar
Carteras Solana
BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC— Punto de entrega inactivo C2 de cargador Unicode de Etapa 1; retroceso DHT de Etapa 36YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ— Punto de entrega inactivo C2 de cargador preinstalado ofuscado de Etapa 1DSRUBTziADDHSik7WQvSMjvwCHFsbsThrbbjWMoJPUiW— Punto de entrega inactivo C2 de extensión de navegador
Hashes de Archivos (SHA-256)
06fab21dc276e3ab9b5d0a1532398979fd377b080c86d74f2c53a04603a43b1d— Assaac.exe / SKuyzYcDD.exe (binario de phishing de Ledger/Trezor)f171c383e21243ac85b5ee69821d16f10e8d718089a5c090c41efeaa42e81fca— c_x64.node (extractor de credenciales de navegador, Windows x64)9df62cefd87784c7ee1ca8b4e6fc49737a90492fa6c23901e3b7981b18c6c988— f_ex86.node (extractor de credenciales de navegador, Windows x86)43253a888417dfab034f781527e08fb58e929096cb4ef69456c3e13550cb4e9e— data (bypass de cifrado ligado a 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 extensión de Chrome, Windows x64)ee3e4dd5c1e073b8805f4107ccc7bc7e6e3c209fe13ea04ff3f2173c8dbe74a6— m (instalador forzado de extensión de Chrome, binario universal de macOS)
Nombres de Archivos
~/init.json/%USERPROFILE%\init.json— Marca de tiempo de limitación de velocidad; contiene uuid, version, date%TEMP%\hJxPxpHP\— Directorio de preparación de credenciales de la Etapa 2%TEMP%\EUXFUxzOVe\— Directorio de preparación de credenciales del navegador de la Etapa 3%TEMP%\SKuyzYcDD.exe— Binario de phishing de Ledger/Trezor desplegado%APPDATA%\QtCvyfVWKH\index.js— Script RAT principal de la Etapa 3%LOCALAPPDATA%\QtCvyfVWKH\AghzgY.ps1— Lanzador de persistencia de PowerShell de la Etapa 3%APPDATA%\_node_x86\node\node.exe— Runtime de Node.js v22.9.0 x86 descargado silenciosamente%APPDATA%\_node_x64\node\node.exe— Runtime de Node.js v22.9.0 x64 descargado silenciosamente%APPDATA%\_node_x64\webrtc\wrtc-win32-x64\index.js— Módulo de proxy SOCKS%LOCALAPPDATA%\Google\Chrome\jucku\— Directorio de extensión maliciosa de Chrome (Windows)/Library/Application Support/Google/Chrome/myextension/— Directorio de extensión maliciosa de Chrome (macOS)
Registro
HKCU\Software\Microsoft\Windows\CurrentVersion\Run\UpdateApp— Persistencia RAT de la Etapa 3HKCU\Software\Microsoft\Windows\CurrentVersion\Run\UpdateLedger→%TEMP%\SKuyzYcDD.exe— Persistencia del binario de phishing de Ledger
Tareas programadas
UpdateApp— EjecutaAghzgY.ps1(Etapa 3) al inicio con los máximos privilegios
WMI
SELECT * FROM __InstanceCreationEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_PnPEntity'— Activador de detección de monedero de hardware USB (binario de phishing de Ledger)
Extensión del navegador
- Nombre para mostrar: Google Docs Offline (versión 1.95.1)
- Nombre del directorio de la extensión (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

