Hunting for Cobalt Strike and C2 Periodic Beaconing Using DeviceNetworkEvents
Command and Control implants periodically phone home to their listener to retrieve pending instructions (sleep/jitter cycles). While attackers introduce sleep jitter (e.g., 20% randomization) to evade static interval checks, mathematical delta analysis still reveals high regularity over extended observation windows.
Here is how to calculate interval standard deviations to unmask stealth C2 beacons.
Log Source
- Microsoft Defender for Endpoint:
DeviceNetworkEvents
C2 Beaconing KQL Hunting Script
// Detect Low-Variance Periodic Outbound Connections (C2 Heartbeat)
let timeWindow = 12h;
let minConnections = 30;
DeviceNetworkEvents
| where TimeGenerated >= ago(timeWindow)
| where ActionType == "ConnectionSuccess"
| where RemotePort in (80, 443, 8080, 8443)
// Filter out local and broadcast traffic
| where not(ipv4_is_private(RemoteIP))
| sort by DeviceName asc, RemoteIP asc, TimeGenerated asc
| serialize
| extend PrevTime = prev(TimeGenerated, 1),
PrevDevice = prev(DeviceName, 1),
PrevRemoteIP = prev(RemoteIP, 1)
| where DeviceName == PrevDevice and RemoteIP == PrevRemoteIP
| extend IntervalSeconds = datetime_diff('second', TimeGenerated, PrevTime)
| where IntervalSeconds between (10 .. 600) // Focus on regular beacon windows
| summarize
ConnectionCount = count(),
AvgInterval = round(avg(IntervalSeconds), 1),
StdDevInterval = round(stdev(IntervalSeconds), 1),
MinInterval = min(IntervalSeconds),
MaxInterval = max(IntervalSeconds)
by DeviceName, InitiatingProcessFileName, RemoteIP, RemoteUrl
| where ConnectionCount >= minConnections
// Jitter ratio: a very low StdDev relative to AvgInterval indicates automated beaconing
| extend JitterRatio = round(StdDevInterval / AvgInterval, 2)
| where JitterRatio < 0.25 // Highly periodic signal
| project DeviceName, InitiatingProcessFileName, RemoteIP, RemoteUrl, ConnectionCount, AvgInterval, StdDevInterval, JitterRatio
| order by JitterRatio asc
Understanding the Math
- Delta Serialization:
datetime_diff('second', TimeGenerated, PrevTime)computes the exact seconds elapsed between consecutive packets sent to the destination. - Standard Deviation (
stdev()): Human browsing exhibits random delays (stddev > 50s). A beacon configured with a 60s sleep and 10% jitter will stay tightly grouped around 54s to 66s, yielding a lowJitterRatio.
MITRE ATT&CK Mapping
- Tactic: Command and Control (TA0011)
- Technique: Application Layer Protocol: Web Protocols (T1071.001)
Responses (0)
Join the technical conversation or share implementation thoughts.
What are your thoughts?
Sign in to join the technical discussion or share feedback.
There are currently no responses for this story. Be the first to respond.