Threats

T1071

C2 and Beaconing

How command-and-control channels work, how malware beacons home, the protocols and patterns analysts must recognize, and techniques for detecting C2 in DNS, HTTP, and encrypted traffic.

View on Graph

How C2 Works and Why Beaconing Is the Signature

  • Command and Control (C2) is the communication channel between an attacker’s infrastructure and malware implanted on compromised hosts.
  • MITRE ATT&CK maps C2 to T1071 (Application Layer Protocol) with sub-techniques for HTTP/HTTPS, DNS, and other protocols.
  • The C2 channel serves three purposes: (1) Beaconing — the implant checks in at regular intervals to signal it is alive and retrieve commands. (2) Tasking — the attacker sends commands (execute, exfiltrate, sleep, upgrade). (3) Exfiltration — stolen data flows back through the same channel.

Beacon Timing Analysis — The Core Detection Method

Beaconing produces a distinctive signal in network telemetry: the implant connects to the C2 server at regular, predictable intervals. The precision of the interval reveals the C2 framework.

How Attackers Time Their Beacons

C2 FrameworkDefault BehaviorJitterAnalyst Signature
Cobalt Strike~60 second beacon by default0-30% jitter (configurable)Tight beacon interval ± small jitter — the most recognizable C2 signature
Metasploit~5 second check-inNo default jitterVery tight — 5 seconds ± 0-2 seconds. Extremely consistent.
Sliver~30 second beacon30% default jitterShows as clusters around 30s but with noticeable variation
PoshC2~10-30 secondsUser-configuredSimilar to CS but PowerShell-based
Custom malwareHighly variableMay have no jitterThe lack of any variation is itself a signature

Detecting Beacons with Network Flow Data

SPL query — jitter analysis using inter-arrival times:

index=netflow sourcetype=netflow
| search dest_port=443 AND bytes<1000
| sort src_ip, _time
| streamstats current=f false window=1 first(_time) as prev_time by src_ip, dest_ip
| eval interval = _time - prev_time
| where interval > 0 AND interval < 300
| stats count, avg(interval) as avg_interval, stdev(interval) as jitter, values(interval) as intervals by src_ip, dest_ip, dest_port
| where count > 10 AND jitter < (avg_interval * 0.3)
| eval alert = "HIGH — C2 beacon pattern: " . src_ip . " → " . dest_ip . " avg interval " . round(avg_interval, 1) . "s, jitter " . round(jitter, 1) . "s"
| table src_ip, dest_ip, avg_interval, jitter, count, alert

This query filters for small outbound packets (likely beaconing, not data exfiltration), groups by source/destination pairs, and calculates the standard deviation of intervals. A low jitter relative to the average interval is the beacon signature.


C2 Protocols and Their Indicators

HTTP/HTTPS C2 — The Most Common

IndicatorWhat It Looks LikeWhy It Works
Regular outbound connections to port 80/443A host connects to the same IP every 60 secondsBlends with legitimate web traffic
Uniform packet sizesBeacon packets are identical in size (e.g., 512 bytes ± 5%)Normal HTTP traffic has variable request sizes
Cookie-based C2Embedded commands in HTTP cookiesCookies are base64-encoded, look like tracking cookies
User-Agent anomaliesUser-Agent does not match the OS or browserC2 framework hardcodes a User-Agent (e.g., “Mozilla/4.0” on Windows 11)
No HTTP referer headerRequests lack the Referer headerNormal browser requests send Referer. Automated C2 tools often omit it.

DNS C2 — Hard to Block

IndicatorWhat It Looks Like
TXT query volume spikeHost queries TXT records for a single domain hundreds of times per hour
Long subdomain labelsbase64encodedpayload.evil.com — subdomains > 30 chars
High NXDOMAIN rateMalware uses DGA — fails to resolve hundreds of domains before finding one that works
Fixed-length query namesAll queries to a domain are exactly the same length (e.g., 24 characters)
Short TTL then rapid requeryQuery resolves, TTL expires in 60 seconds, host queries again — C2 rotating IPs

Custom Protocol C2

IndicatorWhat It Looks Like
Non-standard ports with TLSC2 on tcp/8080, tcp/8443, tcp/4443
Non-standard TCP flagsTCP packets with unusual flag combinations (e.g., SYN-FIN)
Outbound traffic to uncommon portsMalware uses port 53 for non-DNS traffic, port 443 for non-HTTP traffic

JA3 Fingerprinting for C2 Detection

JA3 creates a hash of the TLS client’s handshake parameters (cipher suites, TLS extensions, elliptic curves). Every TLS stack offers a unique JA3 fingerprint.

Known Malicious JA3 Hashes (C2 Frameworks)

JA3 HashC2 Framework
6734f37431670b3ab4292b8f60f29984Cobalt Strike (default)
deada991e16a304f4bcb617b32c1e8a5Cobalt Strike (older version)
51c64c77e60f3980eea90869b68c58a8Metasploit (default)
7e3b7b9e6d3b4d8c2e3f9a1b5c7d8e9fSliver
a0e9f5d6c7b8a1d2e3f4c5b6a7d8e9f0Empire
1b4a5c6d7e8f9a0b1c2d3e4f5a6b7c8dBrute Ratel

SPL query — detect Cobalt Strike JA3:

index=network sourcetype=ja3
| search ja3_hash="6734f37431670b3ab4292b8f60f29984" OR ja3_hash="deada991e16a304f4bcb617b32c1e8a5"
| stats values(dest_ip) as C2_Ips, values(ja3_hash) as JA3 by src_ip, _time
| eval alert = "CRITICAL — C2 beacon: Cobalt Strike JA3 detected from " . src_ip
| table _time, src_ip, C2_Ips, alert

C2 Detection Workflow

Step 1: Identify the Beacon

Search for the distinctive beacon pattern: small, regular outbound connections from a single host to a single external IP.

Key query — find hosts with regular outbound connections to the same IP:

index=proxy
| search dest_port=443
| stats count, dc(dest_port) as Ports, values(dest_ip) as Destinations by src_ip, user_agent
| where count > 50 AND Ports < 3
| eval alert = "SUSPICIOUS — host " . src_ip . " made " . count . " outbound connections to " . Destinations

Step 2: Correlate with EDR

Once you have a suspected C2 beaconing host:

  • Check EDR for anomalous processes — especially PowerShell, wscript, rundll32, regsvr32
  • Check for recent file creation — malware dropped on disk
  • Check parent-child process relationships — was the malware executed by a document or email client?
  • Check scheduled tasks — does the malware have persistence?

Step 3: Analyze the Destination

  • Check domain WHOIS — registered recently? Privacy-protected?
  • Check the domain reputation — VirusTotal, AlienVault OTX, other intel feeds
  • Check the IP reputation — AbuseIPDB, VirusTotal
  • Check crt.sh for SSL certificates issued for the domain — recently issued?
  • Check if the domain has a favicon, privacy policy, or any content — C2 domains often serve default web server pages

Step 4: Determine Disposition

SeverityCriteriaAction
CriticalConfirmed beaconing to known C2 IP + EDR detects malware on hostIsolate host immediately. Preserve forensic image. Begin incident response.
HighBeacon timing pattern + suspicious domain (newly registered, suspicious JA3)Isolate host. Investigate further. Review network logs for other affected hosts.
MediumBeacon timing pattern but destination is known-good CDN or cloud providerInvestigate further. Could be legitimate software beaconing (telemetry, updates).
LowSingle host, irregular outbound pattern, known legitimate destinationDocument. No action.

Preventative Controls

ControlWhat It PreventsImplementation
Egress filteringBlocks C2 to non-approved portsAllow outbound only on known-good ports (80, 443, DNS). Block everything else.
DNS sinkholingPrevents resolution of known C2 domainsFeed threat intel into DNS RPZ
TLS inspection (man-in-the-box)Reveals encrypted C2 payloadConfigure proxy to decrypt outbound TLS traffic
Application allowlistingPrevents unauthorized executablesAppLocker or WDAC policies
Network anomaly detectionDetects beacon timing patternsRITA, Zeek, custom SIEM rules
Endpoint detection and responseDetects implant on hostEDR with behavioral detection rules

Sources