AvanzadoCobalt Strikethreat huntingJA3ZeekSuricataYARASigmaVolatilityMITRE ATT&CK

Detectar Cobalt Strike Beacon en Red: Guía de Threat Hunting

Guía completa de threat hunting para detectar Cobalt Strike beacons en red. Indicadores de red (JA3/JA3S, user-agent, URI, sleep/jitter), memoria, named pipes, malleable C2 profiles. Hunting con Zeek, Suricata, YARA, Sigma y Volatility.

MalwareIntel Research··15 min lectura
Serie: Casos de Uso — Parte 4

Cobalt Strike: la herramienta de doble filo

Cobalt Strike es un framework de post-explotación diseñado para pruebas de penetración. Desarrollado originalmente por Raphael Mudge y ahora mantenido por Fortra (antes HelpSystems), es la herramienta C2 más utilizada tanto por red teams legítimos como por actores de amenazas.

Según datos de Proofpoint, Cobalt Strike apareció en el 25% de los incidentes de ransomware analizados entre 2023 y 2025. Grupos como APT29, APT41, FIN7, y operadores de ransomware como LockBit, BlackCat y Conti lo usan como framework C2 principal.

Su popularidad entre atacantes se debe a tres factores: estabilidad probada en combate, capacidad de evasión mediante malleable C2 profiles, y la disponibilidad de versiones crackeadas que eliminan la barrera de coste. La versión 4.x sigue siendo la más utilizada, aunque existen variantes modificadas.

Para los defensores, esto significa que detectar Cobalt Strike es una habilidad fundamental. Este artículo cubre todos los vectores de detección: red, memoria, disco y logs.

Tipos de beacon

Cobalt Strike soporta varios tipos de beacon, cada uno con un canal de comunicación diferente:

TipoCanalPuerto típicoDificultad de detección
HTTPHTTP cleartext80, 8080Baja (inspección de contenido)
HTTPSTLS encriptado443, 8443Media (JA3, certificados, metadatos)
DNSConsultas DNS53Alta (requiere análisis de patrones DNS)
SMBNamed pipes445Alta (tráfico interno, sin salida a Internet)
TCPSocket rawVariableMedia (depende del puerto y contexto)

Los beacons HTTP/HTTPS son los más comunes porque se mezclan con el tráfico web legítimo. Los beacons SMB se usan para lateral movement interno: un beacon HTTPS en un servidor perimetral actúa como relay para beacons SMB en la red interna.

Indicadores de red

JA3 y JA3S fingerprints

JA3 es un fingerprint del TLS ClientHello que identifica la implementación TLS del cliente, independientemente del destino. JA3S hace lo mismo con el ServerHello.

Fingerprints conocidos de Cobalt Strike:

# JA3 de Cobalt Strike (versiones comunes)
72a589da586844d7f0818ce684948eea    # CS 4.x con Java 11
a0e9f5d64349fb13191bc781f81f42e1    # CS 4.x con Java 8
3f0f4a3b8c0e2d9c8a4e6b5f7d1c0e9a    # CS 4.x custom keystore

# JA3S del teamserver
ae4edc6faf64d08308082ad26be60767    # Respuesta default del teamserver
b742b407517bac9536a77a7b0fee28e9    # Variante con certificado custom

Limitaciones del JA3:

  • Los JA3 de Cobalt Strike pueden coincidir con aplicaciones Java legítimas.
  • Malleable profiles no pueden cambiar el JA3 directamente, pero el atacante puede modificar la versión de Java del teamserver.
  • Usar JA3 como indicador primario genera falsos positivos. Combinarlo con otros indicadores.

Detección por Zeek

Script de Zeek para detectar fingerprints JA3 sospechosos:

@load base/protocols/ssl

module CobaltStrikeDetect;

export {
    redef enum Notice::Type += {
        CS_JA3_Match,
        CS_Beacon_Pattern
    };
}

const cs_ja3_hashes: set[string] = {
    "72a589da586844d7f0818ce684948eea",
    "a0e9f5d64349fb13191bc781f81f42e1",
    "3f0f4a3b8c0e2d9c8a4e6b5f7d1c0e9a"
};

event ssl_client_hello(c: connection, version: count, record_version: count,
                       possible_ts: time, client_random: string,
                       session_id: string, ciphers: index_vec,
                       comp_methods: index_vec) {
    if (c$ssl?$ja3 && c$ssl$ja3 in cs_ja3_hashes) {
        NOTICE([
            $note=CS_JA3_Match,
            $msg=fmt("Cobalt Strike JA3 detected: %s -> %s:%d (JA3: %s)",
                     c$id$orig_h, c$id$resp_h, c$id$resp_p, c$ssl$ja3),
            $conn=c
        ]);
    }
}

User-Agent analysis

Los malleable C2 profiles permiten configurar cualquier User-Agent, pero la configuración por defecto y los profiles más populares usan patrones identificables:

# Defaults de Cobalt Strike (sin malleable profile)
Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)
Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; WOW64; Trident/4.0)

# Profiles populares (jQuery, Amazon, etc.)
Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36

La clave no es el User-Agent en sí, sino la inconsistencia:

  • Un sistema que genera tráfico con User-Agent de IE9 cuando tiene Chrome instalado.
  • Tráfico HTTPS con User-Agent moderno pero JA3 de Java (no de un navegador).
  • Mismo User-Agent en todas las peticiones sin variación (los navegadores reales varían).

URI patterns

Los beacons envían datos en los URIs. Sin malleable profile, los patrones por defecto son:

# GET (check-in / beacon)
GET /dpixel HTTP/1.1
GET /pixel.gif HTTP/1.1
GET /___utm.gif HTTP/1.1
GET /submit.php?id=XXXXXXXX HTTP/1.1
GET /activity HTTP/1.1

# POST (data exfiltration)
POST /submit.php?id=XXXXXXXX HTTP/1.1

Con malleable profiles, los URIs cambian completamente. El profile jQuery emula peticiones a CDN:

GET /jquery-3.3.1.min.js HTTP/1.1
POST /jquery-3.3.2.min.js HTTP/1.1

Detección: Buscar peticiones repetitivas a URIs estáticos que deberían ser cacheados por el navegador. Un navegador real no descarga jquery-3.3.1.min.js cada 60 segundos.

Sleep y jitter: el patrón temporal

El beacon contacta al C2 a intervalos regulares definidos por sleep (milisegundos) y jitter (porcentaje de variación):

Sleep: 60000 ms (60 segundos)
Jitter: 37%

Intervalo real: 60000 ± (60000 * 0.37)
Rango: 37,800 ms a 82,200 ms

La distribución de intervalos sigue un patrón uniforme dentro del rango. Esto es detectable estadísticamente:

# Pseudocódigo para detectar beaconing
import numpy as np

intervals = calculate_request_intervals(flow_data)

# Test: distribución uniforme con media constante
mean_interval = np.mean(intervals)
std_interval = np.std(intervals)
coefficient_of_variation = std_interval / mean_interval

# CV entre 0.15 y 0.40 con media entre 30s y 300s
# es altamente sospechoso de beaconing
if 0.15 < coefficient_of_variation < 0.40 and 30 < mean_interval < 300:
    alert("Possible C2 beaconing detected")

Certificados TLS

El teamserver de Cobalt Strike genera certificados TLS autofirmados con valores por defecto reconocibles:

# Valores por defecto del certificado CS
Subject: CN=Major Cobalt Strike
Issuer: CN=Major Cobalt Strike
Validity: 3 months

# Valores frecuentes en versiones crackeadas
Subject: CN=localhost
Subject: CN=*.local
Subject: O=Cobaltstrike, OU=AdvancedPenTesting

Los atacantes sofisticados usan certificados Let's Encrypt legítimos o certificados comprados, pero el serial number y la estructura del certificado pueden seguir revelando patrones.

Indicadores en memoria

Reflective DLL loading

Cobalt Strike carga su beacon en memoria usando reflective DLL injection: la DLL se carga sin tocar disco y sin usar la API estándar de carga de librerías de Windows.

Indicadores en memoria:

# Strings del beacon (no ofuscados en versiones antiguas)
"beacon.dll"
"beacon.x64.dll"
"ReflectiveLoader"

# MZ header en regiones de memoria no respaldadas por archivo
# (indica DLL cargada reflectively)

Análisis con Volatility

# Listar procesos sospechosos
$ vol3 -f memory.raw windows.pslist

# Buscar inyecciones de código (MZ headers en memoria no respaldada)
$ vol3 -f memory.raw windows.malfind

# Ejemplo de output sospechoso:
Process: rundll32.exe  PID: 4892
Protection: PAGE_EXECUTE_READWRITE
Address: 0x00000189A4C10000
  4d 5a 90 00 03 00 00 00  MZ......
  04 00 00 00 ff ff 00 00  ........

Un proceso legítimo como rundll32.exe con regiones de memoria PAGE_EXECUTE_READWRITE que contienen un MZ header es un indicador casi definitivo de inyección de código.

Detección de configuración en memoria

Herramientas especializadas pueden extraer la configuración del beacon directamente de la memoria:

# CobaltStrikeParser de Sentinel One
$ python3 parse_beacon_config.py --process 4892 memory.raw

# 1768.py de Didier Stevens
$ python3 1768.py -r memory.raw

La configuración extraída revela: C2 server, sleep time, jitter, watermark, named pipes, spawn processes, y todas las opciones del malleable profile.

Named pipes

Los beacons SMB usan named pipes para comunicación lateral. Los nombres por defecto son:

# Named pipes por defecto de Cobalt Strike
\\.\pipe\msagent_##
\\.\pipe\MSSE-####-server
\\.\pipe\status_##
\\.\pipe\postex_####
\\.\pipe\postex_ssh_####
\\.\pipe\mojo.####.####.####

(Donde # representa caracteres hexadecimales variables.)

Detección con Sysmon

Sysmon EventID 17 (PipeCreated) y EventID 18 (PipeConnected) registran actividad de named pipes:

<Event>
  <System>
    <EventID>17</EventID>
  </System>
  <EventData>
    <Data Name="PipeName">\msagent_f8</Data>
    <Data Name="Image">C:\Windows\System32\rundll32.exe</Data>
  </EventData>
</Event>

Regla Sigma para named pipes

title: Cobalt Strike Named Pipe Detected
id: f7a8b9c0-d1e2-4f3a-b4c5-d6e7f8a9b0c1
status: experimental
description: Detects named pipes commonly used by Cobalt Strike beacons
references:
    - https://malwareintel.es/blog/casos-de-uso/cobalt-strike-beacon-red-hunting
logsource:
    category: pipe_created
    product: windows
detection:
    selection:
        PipeName|re:
            - '\\msagent_[0-9a-f]{2}'
            - '\\MSSE-[0-9]{4}-server'
            - '\\postex_[0-9a-f]{4}'
            - '\\postex_ssh_[0-9a-f]{4}'
            - '\\status_[0-9a-f]{2}'
    condition: selection
level: critical
tags:
    - attack.command_and_control
    - attack.t1071
    - attack.lateral_movement
    - attack.t1021.002

Malleable C2 profiles: el reto para el defensor

Los malleable C2 profiles son archivos de configuración que permiten al atacante personalizar completamente el tráfico del beacon. Un profile bien configurado puede imitar cualquier aplicación legítima.

Ejemplo: profile jQuery

# Fragmento de jquery-c2.4.0.profile (público en GitHub)
set sleeptime "60000";
set jitter "37";
set useragent "Mozilla/5.0 (Windows NT 6.3; Trident/7.0; rv:11.0) like Gecko";

http-get {
    set uri "/jquery-3.3.1.min.js";
    client {
        header "Accept" "text/html,application/xhtml+xml";
        header "Referer" "http://code.jquery.com/";
        metadata {
            base64url;
            append "/__utm.gif?utmac=UA-2202604-2&utmcn=1&utmcs=ISO-8859-1&utmsr=1280x1024&utmsc=32-bit&utmul=en-US";
            header "Cookie";
        }
    }
    server {
        header "Content-Type" "application/javascript; charset=utf-8";
        header "Server" "NetDNA-cache/2.2";
        output {
            mask;
            base64url;
            prepend "!function(e,t){\"use strict\";\"object\"";
            append "\".(jQuery)\";})();";
            print;
        }
    }
}

Este profile hace que el tráfico parezca peticiones legítimas a jQuery CDN. La respuesta del C2 se oculta dentro de código JavaScript aparentemente legítimo.

Cómo detectar malleable profiles

  1. Análisis estadístico del tráfico: Aunque el contenido parezca legítimo, el patrón temporal (sleep + jitter) sigue siendo detectable. Un CDN real no recibe peticiones a intervalos regulares desde un solo host.

  2. Inspección de respuestas: Las respuestas del C2 tienen tamaños variables pero no cachean correctamente. Headers como Cache-Control: no-cache en recursos estáticos son sospechosos.

  3. Correlación de procesos: Si rundll32.exe genera tráfico HTTP a jQuery CDN, algo va mal. Correlacionar el proceso origen con el destino.

  4. Anomalías en certificados: Incluso con un certificado válido, el nombre del servidor TLS puede no coincidir con la IP de destino.

  5. Volume patterns: Los beacons enviando datos exfiltrados generan picos de tráfico POST que no corresponden con el uso normal del URI.

Hunting con Suricata

Reglas IDS para Cobalt Strike

# Detección de certificado autofirmado de Cobalt Strike
alert tls any any -> any any (msg:"Possible Cobalt Strike Default TLS Certificate";
  tls.cert_subject; content:"O=Cobaltstrike"; sid:2026001; rev:1;)

# Detección de URI por defecto (sin malleable profile)
alert http any any -> any any (msg:"Cobalt Strike Default Beacon URI";
  http.uri; content:"/dpixel"; sid:2026002; rev:1;)

alert http any any -> any any (msg:"Cobalt Strike Default Beacon URI";
  http.uri; content:"/pixel.gif"; sid:2026003; rev:1;)

alert http any any -> any any (msg:"Cobalt Strike Submit URI";
  http.uri; content:"/submit.php?id="; sid:2026004; rev:1;)

# Detección de beaconing por User-Agent obsoleto
alert http any any -> any any (msg:"Possible Cobalt Strike Default User-Agent";
  http.user_agent; content:"MSIE 9.0"; content:"Trident/5.0";
  sid:2026005; rev:1;)

# DNS beaconing: subdominios largos a un solo dominio
alert dns any any -> any any (msg:"Possible DNS C2 Beaconing - Long Subdomain";
  dns.query; pcre:"/^[a-z0-9]{20,}\./i"; threshold:type both,
  track by_src, count 10, seconds 60; sid:2026006; rev:1;)

Hunting con YARA

Regla para beacon en memoria

rule CobaltStrike_Beacon_Memory {
    meta:
        description = "Detects Cobalt Strike beacon in process memory"
        author = "MalwareIntel Research"
        date = "2026-06-06"
        
    strings:
        $reflective = "ReflectiveLoader" ascii
        $beacon1 = "beacon.dll" ascii
        $beacon2 = "beacon.x64.dll" ascii
        
        $cfg1 = { 00 01 00 01 00 02 ?? ?? 00 02 00 01 00 02 ?? ?? }
        $cfg2 = { 00 01 00 01 00 02 ?? ?? 00 02 00 02 00 04 ?? ?? ?? ?? }
        
        $sleep_mask = { 4C 8B 53 08 45 8B 0A 45 8B 5A 04 4D 8D 52 08 45 85 C9 }
        
        $pipe1 = "\\.\pipe\msagent_" ascii
        $pipe2 = "\\.\pipe\MSSE-" ascii
        $pipe3 = "\\.\pipe\postex_" ascii
        $pipe4 = "\\.\pipe\status_" ascii
        
    condition:
        ($reflective and ($beacon1 or $beacon2)) or
        any of ($cfg*) or
        $sleep_mask or
        2 of ($pipe*)
}

Regla para stager PowerShell

rule CobaltStrike_Stager_PowerShell {
    meta:
        description = "Detects Cobalt Strike PowerShell stager patterns"
        author = "MalwareIntel Research"
        date = "2026-06-06"
        
    strings:
        $iex1 = "IEX" ascii nocase
        $iex2 = "Invoke-Expression" ascii nocase
        $dl1 = "Net.WebClient" ascii
        $dl2 = "DownloadString" ascii
        $dl3 = "DownloadData" ascii
        $b64 = "FromBase64String" ascii
        $xor = "-bxor" ascii
        $hidden = "-w hidden" ascii
        $bypass = "-ep bypass" ascii
        $sc = "[System.Runtime.InteropServices.Marshal]" ascii
        
    condition:
        filesize < 50KB and
        ($iex1 or $iex2) and
        ($dl1 or $dl2 or $dl3) and
        ($b64 or $xor) and
        ($hidden or $bypass or $sc)
}

Hunting en SIEM con Sigma

Detección de beaconing por frecuencia

title: Periodic Outbound HTTP Beaconing Pattern
id: a8b9c0d1-e2f3-4a4b-c5d6-e7f8a9b0c1d2
status: experimental
description: Detects periodic HTTP/HTTPS connections from a single host
    to a single destination with consistent intervals (beaconing)
logsource:
    category: proxy
detection:
    selection:
        c-action: 'TCP_CONNECT'
    timeframe: 15m
    condition: selection | count(cs-uri) by src_ip, dst_ip > 12
level: medium
tags:
    - attack.command_and_control
    - attack.t1071.001

Detección de proceso sospechoso con conexión de red

title: Suspicious Process Making HTTP Connection
id: b9c0d1e2-f3a4-4b5c-d6e7-f8a9b0c1d2e3
status: experimental
description: Detects processes not typically making HTTP connections
logsource:
    category: network_connection
    product: windows
detection:
    selection:
        Image|endswith:
            - '\rundll32.exe'
            - '\regsvr32.exe'
            - '\mshta.exe'
            - '\certutil.exe'
        DestinationPort:
            - 80
            - 443
            - 8080
            - 8443
    condition: selection
level: high
tags:
    - attack.command_and_control
    - attack.t1071
    - attack.defense_evasion
    - attack.t1218

Detección de Mimikatz ejecutado desde beacon

title: LSASS Memory Access from Unusual Process
id: c0d1e2f3-a4b5-4c6d-e7f8-a9b0c1d2e3f4
status: experimental
description: Detects access to LSASS memory from non-security processes
logsource:
    category: process_access
    product: windows
detection:
    selection:
        TargetImage|endswith: '\lsass.exe'
        GrantedAccess|contains:
            - '0x1010'
            - '0x1410'
            - '0x1438'
    filter:
        SourceImage|endswith:
            - '\MsMpEng.exe'
            - '\csrss.exe'
            - '\svchost.exe'
    condition: selection and not filter
level: critical
tags:
    - attack.credential_access
    - attack.t1003.001

Hunting en memoria con Volatility

Workflow de análisis

# 1. Identificar procesos sospechosos
$ vol3 -f memory.raw windows.pslist | grep -E "rundll32|regsvr32|svchost"

# 2. Buscar inyecciones de código
$ vol3 -f memory.raw windows.malfind --pid 4892

# 3. Extraer DLLs cargadas reflectively
$ vol3 -f memory.raw windows.dlllist --pid 4892

# 4. Comparar DLLs en memoria vs disco
# Las DLLs cargadas reflectively NO aparecen en la lista de módulos del PEB
# pero SÍ aparecen con malfind como regiones PAGE_EXECUTE_READWRITE

# 5. Buscar strings del beacon en memoria del proceso
$ vol3 -f memory.raw windows.memmap --pid 4892 --dump
$ strings -a pid.4892.dmp | grep -iE "beacon|pipe|sleep|jitter"

# 6. Buscar named pipes activos
$ vol3 -f memory.raw windows.handles --pid 4892 | grep "\\Device\\NamedPipe"

Indicadores de inyección Cobalt Strike en Volatility

IndicadorComando VolatilityQué buscar
Proceso huérfanowindows.pstreerundll32.exe sin padre o con padre inesperado
Código inyectadowindows.malfindRegiones RWX con MZ header en procesos legítimos
DLL fantasmawindows.dlllist vs windows.ldrmodulesDLL en memoria pero no en lista del loader
Named pipeswindows.handlesPipes con nombres de patrón Cobalt Strike
Conexiones activaswindows.netscanConexiones desde procesos no-browser a puertos 443/8080

IOCs de referencia

Red

TipoValorContexto
JA372a589da586844d7f0818ce684948eeaCS 4.x Java 11
JA3a0e9f5d64349fb13191bc781f81f42e1CS 4.x Java 8
JA3Sae4edc6faf64d08308082ad26be60767Teamserver default
URI/dpixel, /pixel.gif, /__utm.gifURIs default (sin profile)
URI/submit.php?id=URI de exfiltración default
User-AgentMSIE 9.0; Windows NT 6.1; Trident/5.0UA default CS
Named Pipe\\.\pipe\msagent_##Pipe default para SMB beacon
Named Pipe\\.\pipe\MSSE-####-serverPipe default para post-exploitation
Named Pipe\\.\pipe\postex_####Pipe default para post-exploitation
Cert SubjectO=Cobaltstrike, OU=AdvancedPenTestingCertificado default

Host

TipoValorContexto
Processrundll32.exe sin argumentos legítimosSpawnTo default del beacon
RegistryHKCU\Software\Microsoft\Windows\CurrentVersion\RunPersistencia típica
SysmonEventID 17: PipeCreated con patrón CSCreación de named pipe
SysmonEventID 10: ProcessAccess a lsass.exeCredential dumping
MemoryPAGE_EXECUTE_READWRITE con MZ headerBeacon reflective-loaded

Mapeo MITRE ATT&CK

IDTécnicaRelevancia para hunting
T1071.001Web ProtocolsBeacons HTTP/HTTPS a C2
T1071.004DNSDNS beaconing para C2
T1573.002Asymmetric CryptographyTLS para cifrar C2 (JA3 detectable)
T1055.001DLL InjectionReflective DLL loading del beacon
T1055.012Process HollowingInyección en procesos legítimos
T1021.002SMB/Windows Admin SharesNamed pipes para lateral movement
T1059.001PowerShellStagers y post-exploitation
T1218.011Rundll32SpawnTo default del beacon
T1003.001LSASS MemoryCredential dumping via beacon
T1095Non-Application Layer ProtocolRaw TCP beacons

Checklist de hunting

Para una sesión de threat hunting enfocada en Cobalt Strike, seguir este orden:

1. SIEM: Buscar JA3 fingerprints conocidos en logs TLS/proxy
2. SIEM: Correlacionar procesos no-browser con conexiones HTTP salientes
3. Zeek: Analizar patrones temporales de conexiones (beaconing)
4. Suricata: Revisar alertas de certificados autofirmados sospechosos
5. EDR: Buscar creación de named pipes con patrones CS
6. EDR: Buscar rundll32.exe con conexiones de red
7. Sysmon: EventID 10 con acceso a lsass.exe desde procesos inusuales
8. Memoria: malfind en procesos con regiones RWX sospechosas
9. Memoria: Extraer configuración con CobaltStrikeParser/1768.py
10. Red: Analizar DNS queries con subdominios anormalmente largos

Si cualquier paso produce un hit, pasar inmediatamente a contención y análisis forense completo. Un beacon activo significa que el atacante tiene acceso y puede escalar en cualquier momento.


Los fingerprints, patrones y reglas de este artículo están basados en versiones conocidas de Cobalt Strike y profiles públicos. Los atacantes sofisticados modifican estos valores. La detección efectiva requiere correlación de múltiples indicadores, no dependencia de uno solo.

Preguntas frecuentes

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.