What it does. Identify command-and-control beaconing patterns in network traffic by Part of mukul975/Anthropic-Cybersecurity-Skills (817 security skills) (mukul975/Anthropic-Cybersecurity-Skills).
Install
npx skills add mukul975/Anthropic-Cybersecurity-Skills --skill hunting-for-beaconing-with-frequency-analysis, or copy the skill folder into ~/.claude/skills/hunting-for-beaconing-with-frequency-analysis/.
- Raw file:
curl -sL https://raw.githubusercontent.com/mukul975/Anthropic-Cybersecurity-Skills/HEAD/skills/hunting-for-beaconing-with-frequency-analysis/SKILL.md
SKILL.md (verbatim)
name: hunting-for-beaconing-with-frequency-analysis
description: Identify command-and-control beaconing patterns in network traffic by
applying statistical frequency analysis, jitter calculation, and coefficient of
variation scoring to detect periodic callbacks from compromised endpoints.
domain: cybersecurity
subdomain: threat-hunting
tags:
- threat-hunting
- beaconing
- c2-detection
- frequency-analysis
- network-traffic
- RITA
- jitter-detection
- mitre-t1071
version: '1.0'
author: mahipal
license: Apache-2.0
d3fend_techniques:
- File Metadata Consistency Validation
- Certificate Analysis
- Application Protocol Command Analysis
- Content Format Conversion
- File Content Analysis
nist_csf:
- DE.CM-01
- DE.AE-02
- DE.AE-07
- ID.RA-05
mitre_attack:
- T1046
- T1057
- T1082
- T1083
- T1071
Hunting for Beaconing with Frequency Analysis
When to Use
- When proactively searching for compromised endpoints calling back to C2 infrastructure
- After threat intelligence reports indicate active C2 frameworks targeting your sector
- When network logs show periodic outbound connections to unfamiliar destinations
- During purple team exercises validating C2 detection capabilities
- When investigating a potential breach and need to identify active C2 channels
Prerequisites
- Network proxy/firewall logs with timestamps and destination data (minimum 24 hours)
- Zeek conn.log, dns.log, and ssl.log or equivalent NetFlow/IPFIX data
- SIEM platform with statistical analysis capability (Splunk, Elastic, Microsoft Sentinel)
- RITA (Real Intelligence Threat Analytics) or AC-Hunter for automated beacon analysis
- Threat intelligence feeds for domain/IP reputation enrichment
Workflow
- Define Beacon Parameters: Establish detection thresholds -- coefficient of variation (CV) below 0.20 indicates strong periodicity, minimum 50 connections over 24 hours, average interval between 30 seconds and 24 hours.
- Collect Network Telemetry: Aggregate proxy logs, DNS queries, firewall connection logs, and Zeek metadata into the analysis platform.
- Calculate Connection Intervals: For each source-destination pair, compute the time delta between consecutive connections and derive mean interval, standard deviation, and CV.
- Apply Jitter Analysis: Sophisticated C2 frameworks like Cobalt Strike add jitter (randomness) to beacon intervals. The Sunburst backdoor beaconed every 15 minutes plus/minus 90 seconds. Analyze jitter patterns to detect even randomized beaconing.
- Filter Legitimate Periodic Traffic: Exclude known-good beaconing sources including Windows Update, antivirus definition updates, NTP synchronization, SaaS heartbeat services, and CDN health checks.
- Analyze Data Size Consistency: C2 heartbeat packets typically have consistent payload sizes. Calculate the CV of bytes transferred per connection -- low variance suggests automated communication.
- Enrich with Threat Intelligence: Check identified beaconing destinations against VirusTotal, WHOIS registration data (flag domains under 30 days old), certificate transparency logs, and passive DNS history.
- Correlate with Endpoint Telemetry: Map beaconing source IPs to endpoint hostnames via DHCP logs, then correlate with process creation events (Sysmon Event ID 1, 3) to identify the responsible process.
- Score and Prioritize: Assign risk scores based on CV value, domain age, TI matches, data size consistency, and suspicious port usage. Escalate high-confidence findings.
Key Concepts
| Concept |
Description |
| T1071.001 |
Application Layer Protocol: Web Protocols -- HTTP/HTTPS beaconing |
| T1071.004 |
Application Layer Protocol: DNS -- DNS-based C2 tunneling |
| T1573 |
Encrypted Channel -- TLS/SSL encrypted C2 communication |
| T1568.002 |
Dynamic Resolution: Domain Generation Algorithms |
| Coefficient of Variation |
Standard deviation divided by mean; values below 0.20 indicate periodicity |
| Jitter |
Random variation added to beacon interval to evade detection |
| RITA Beacon Score |
Composite score from connection regularity, data size consistency, and connection count |
| JA3/JA4 Fingerprinting |
TLS client fingerprinting to identify C2 framework signatures |
| Fast-Flux DNS |
Rapidly changing DNS resolution used to protect C2 infrastructure |
| Tool |
Purpose |
| RITA (Real Intelligence Threat Analytics) |
Automated beacon scoring from Zeek logs |
| AC-Hunter |
Commercial threat hunting platform with beacon detection |
| Splunk |
SPL-based statistical beacon analysis with streamstats |
| Elastic Security |
ML anomaly detection for periodic network behavior |
| Zeek |
Network metadata collection (conn.log, dns.log, ssl.log) |
| Suricata |
Network IDS with JA3/JA4 TLS fingerprint extraction |
| FLARE |
C2 profile and beacon pattern detection |
| VirusTotal |
Domain and IP reputation enrichment |
Detection Queries
Splunk -- HTTP/S Beacon Frequency Analysis
index=proxy OR index=firewall
| where NOT match(dest, "(?i)(microsoft|google|amazonaws|cloudflare|akamai)")
| bin _time span=1s
| stats count by src_ip dest _time
| streamstats current=f last(_time) as prev_time by src_ip dest
| eval interval=_time-prev_time
| stats count avg(interval) as avg_interval stdev(interval) as stdev_interval
min(interval) as min_interval max(interval) as max_interval by src_ip dest
| where count > 50
| eval cv=stdev_interval/avg_interval
| where cv < 0.20 AND avg_interval > 30 AND avg_interval < 86400
| sort cv
| table src_ip dest count avg_interval stdev_interval cv
KQL -- Microsoft Sentinel Beacon Detection
DeviceNetworkEvents
| where Timestamp > ago(24h)
| where RemoteIPType == "Public"
| summarize ConnectionTimes=make_list(Timestamp), Count=count() by DeviceName, RemoteIP, RemoteUrl
| where Count > 50
| extend Intervals = array_sort_asc(ConnectionTimes)
| mv-apply Intervals on (
extend NextTime = next(Intervals)
| where isnotempty(NextTime)
| extend IntervalSec = datetime_diff('second', NextTime, Intervals)
| summarize AvgInterval=avg(IntervalSec), StdDev=stdev(IntervalSec)
)
| extend CV = StdDev / AvgInterval
| where CV < 0.2 and AvgInterval > 30
| sort by CV asc
Sigma Rule -- Beaconing Pattern Detection
title: Potential C2 Beaconing Pattern Detected
status: experimental
logsource:
category: proxy
detection:
selection:
dst_ip|cidr: '!10.0.0.0/8'
timeframe: 24h
condition: selection | count(dst) by src_ip > 50
level: medium
tags:
- attack.command_and_control
- attack.t1071.001
Common Scenarios
- Cobalt Strike Beacon: Default 60-second interval with configurable 0-50% jitter over HTTPS. Malleable C2 profiles can mimic legitimate traffic patterns.
- Sunburst/SUNSPOT: 12-14 day dormancy period, then beaconing every 12-14 minutes with randomized jitter, designed to evade frequency analysis.
- DNS Tunneling C2: Encoded data exfiltration via DNS TXT/CNAME queries to attacker-controlled domains, detectable via high subdomain entropy and query volume.
- Sliver C2: Modern C2 framework with HTTPS, mTLS, and WireGuard protocols, configurable beacon intervals with built-in jitter support.
- Legitimate Service Abuse: C2 communication over Slack, Discord, Telegram, or cloud storage APIs, making destination-based filtering ineffective.
Hunt ID: TH-BEACON-[DATE]-[SEQ]
Source IP: [Internal IP]
Source Host: [Hostname from DHCP/DNS]
Destination: [Domain/IP]
Protocol: [HTTP/HTTPS/DNS]
Beacon Interval: [Average seconds]
Jitter Estimate: [Percentage]
Coefficient of Variation: [CV value]
Connection Count: [Total connections in window]
Data Size CV: [Payload consistency metric]
Domain Age: [Days since registration]
TI Match: [Yes/No -- source]
Risk Score: [0-100]
Risk Level: [Critical/High/Medium/Low]
Indicators: [List of triggered risk factors]
Other files in this skill
assets/template.md (verbatim)
Beaconing Frequency Analysis Hunt Template
| Field |
Value |
| Hunt ID |
TH-BEACON-YYYY-MM-DD-NNN |
| Analyst |
|
| Date |
|
| Data Window |
[Start] to [End] |
| Status |
[ ] In Progress / [ ] Complete |
Hypothesis
Compromised endpoints are beaconing to adversary C2 infrastructure using periodic HTTP/HTTPS/DNS connections with detectable frequency patterns.
Data Sources
Beaconing Findings
| # |
Source IP |
Source Host |
Destination |
Protocol |
Avg Interval |
CV |
Jitter % |
Connections |
Risk |
| 1 |
|
|
|
|
|
|
|
|
|
Domain Intelligence
| Domain/IP |
WHOIS Age |
VirusTotal Score |
PassiveDNS |
JA3 Match |
Assessment |
|
|
|
|
|
|
Endpoint Correlation
| Host |
Process |
PID |
User |
Parent Process |
File Path |
Suspicious |
|
|
|
|
|
|
|
IOC List
| Type |
Value |
Confidence |
Source |
| Domain |
|
|
|
| IP |
|
|
|
| JA3 |
|
|
|
| User-Agent |
|
|
|
Recommendations
- Block: [Domains/IPs to block at firewall and proxy]
- Isolate: [Endpoints to contain via EDR]
- Detect: [New detection rules to deploy]
- Hunt: [Additional IOCs to sweep for across the environment]
references/api-reference.md (verbatim)
API Reference: Beaconing Detection via Frequency Analysis
Beaconing Characteristics
| Characteristic |
Description |
| Regular intervals |
Connections at fixed time periods |
| Low jitter |
Small variance in intervals |
| Persistent |
Continues over hours/days |
| Consistent size |
Similar packet sizes |
Jitter Calculation
Standard Deviation of Intervals
import math
intervals = [t[i+1] - t[i] for i in range(len(t)-1)]
mean = sum(intervals) / len(intervals)
variance = sum((x - mean)**2 for x in intervals) / len(intervals)
jitter = math.sqrt(variance)
jitter_percent = (jitter / mean) * 100
Jitter Thresholds
| Jitter % |
Confidence |
Likely Cause |
| < 5% |
HIGH |
Automated C2 beacon |
| 5-15% |
MEDIUM |
Possible C2 with sleep jitter |
| 15-30% |
LOW |
May be legitimate polling |
| > 30% |
NONE |
Likely human/random |
Fields
| Index |
Name |
Description |
| 0 |
ts |
Unix timestamp |
| 2 |
id.orig_h |
Source IP |
| 3 |
id.orig_p |
Source port |
| 4 |
id.resp_h |
Destination IP |
| 5 |
id.resp_p |
Destination port |
| 6 |
proto |
Protocol |
| 9 |
orig_bytes |
Sent bytes |
| 10 |
resp_bytes |
Received bytes |
RITA (Real Intelligence Threat Analytics)
Analyze Zeek Logs
rita import /path/to/zeek/logs dataset_name
rita show-beacons dataset_name
Output Columns
| Column |
Description |
| Score |
Beacon probability (0-1) |
| Source |
Source IP |
| Destination |
Destination IP |
| Connections |
Total connections |
| Avg Bytes |
Average data transfer |
Splunk SPL — Beacon Detection
index=network sourcetype=zeek:conn
| bin _time span=60s
| stats count by src_ip, dest_ip, dest_port, _time
| streamstats window=100 stdev(count) as jitter avg(count) as avg_count by src_ip, dest_ip
| where jitter/avg_count < 0.15
| stats count as beacon_count by src_ip, dest_ip, dest_port
| where beacon_count > 100
Elastic SIEM — Beacon Detection
{
"query": {
"bool": {
"must": [
{"range": {"@timestamp": {"gte": "now-24h"}}},
{"exists": {"field": "destination.ip"}}
]
}
},
"aggs": {
"by_flow": {
"composite": {
"sources": [
{"src": {"terms": {"field": "source.ip"}}},
{"dst": {"terms": {"field": "destination.ip"}}}
]
}
}
}
}
Common C2 Beacon Intervals
| Framework |
Default Interval |
| Cobalt Strike |
60 seconds |
| Metasploit |
5 seconds |
| Empire |
5 seconds |
| Covenant |
10 seconds |
| Sliver |
60 seconds |
references/standards.md (verbatim)
Standards and References - Beaconing Frequency Analysis
MITRE ATT&CK Command and Control (TA0011)
| Technique |
Name |
Beacon Indicators |
| T1071.001 |
Web Protocols |
HTTP/HTTPS periodic connections with regular intervals |
| T1071.004 |
DNS |
DNS query patterns, tunneling with high entropy subdomains |
| T1573.001 |
Symmetric Cryptography |
Encrypted C2 channels with consistent packet sizes |
| T1573.002 |
Asymmetric Cryptography |
TLS C2 with custom or self-signed certificates |
| T1572 |
Protocol Tunneling |
DNS-over-HTTPS, ICMP tunneling with periodic patterns |
| T1568.002 |
Domain Generation Algorithms |
Algorithmically generated domains with high entropy |
| T1568.001 |
Fast Flux DNS |
Rapidly rotating IP addresses for C2 infrastructure |
| T1132.001 |
Standard Encoding |
Base64/hex encoded data in C2 traffic |
| T1095 |
Non-Application Layer Protocol |
ICMP, raw TCP/UDP for covert C2 |
| T1090 |
Proxy |
Multi-hop C2 infrastructure obscuring origin |
| T1102 |
Web Service |
C2 over legitimate cloud services |
Beaconing Detection Thresholds
| Metric |
Threshold |
Rationale |
| Coefficient of Variation (CV) |
< 0.20 |
Strong indicator of periodic automated communication |
| Minimum Beacon Interval |
> 30 seconds |
Below this may be streaming or polling traffic |
| Maximum Beacon Interval |
< 86400 seconds |
Beyond 24 hours reduces statistical significance |
| Minimum Connection Count |
> 50 per 24 hours |
Needed for reliable statistical analysis |
| Data Size CV |
< 0.30 |
Consistent payloads suggest automated heartbeats |
| Domain Age |
< 30 days |
Newly registered domains associated with C2 infrastructure |
Known C2 Framework Default Beacon Profiles
| Framework |
Default Interval |
Default Jitter |
Protocols |
Detection Notes |
| Cobalt Strike |
60s |
0-50% |
HTTPS, DNS |
Malleable C2 profiles can change all defaults |
| Sliver |
60s |
0-30% |
HTTPS, mTLS, WireGuard, DNS |
Supports domain fronting |
| Brute Ratel C4 |
60s |
10-30% |
HTTPS, DNS, SMB |
Designed to evade EDR detection |
| Metasploit Meterpreter |
5s |
0% |
TCP, HTTP/S |
Highly configurable via handlers |
| Havoc |
5s |
0-20% |
HTTPS |
Demon agent with sleep obfuscation |
| Mythic |
Configurable |
Configurable |
HTTP/S, TCP, WebSocket |
Agent-dependent behavior |
| Covenant |
10s |
10% |
HTTP/S |
.NET-based C2 framework |
| Empire/Starkiller |
5s |
0-20% |
HTTP/S |
Python-based listeners |
Statistical Methods for Beacon Detection
| Method |
Description |
Best For |
| Coefficient of Variation |
stdev/mean of intervals |
Regular beacons with low jitter |
| Fast Fourier Transform (FFT) |
Frequency domain analysis |
Detecting periodic signals in noisy data |
| Autocorrelation |
Self-correlation at various lags |
Identifying repeating patterns |
| Median Absolute Deviation |
Robust measure of variability |
Beacon detection resistant to outliers |
| Kullback-Leibler Divergence |
Distribution comparison |
Comparing observed intervals to uniform distribution |
RITA Beacon Scoring Algorithm
RITA scores beacons on a 0-1 scale using:
- Timestamp score: Regularity of connection intervals
- Data size score: Consistency of bytes transferred
- Connection count: Volume of connections in analysis window
- Duration: How long the beaconing pattern has persisted
Composite score above 0.70 is considered high-confidence beaconing.
references/workflows.md (verbatim)
Detailed Hunting Workflow - Beaconing Frequency Analysis
Phase 1: Data Collection and Preparation
Step 1.1 - Gather Network Connection Logs
Collect at minimum 24 hours (ideally 7 days) of:
- Proxy/firewall logs with timestamps, source/destination, bytes
- Zeek conn.log for connection metadata
- Zeek dns.log for DNS query analysis
- Zeek ssl.log for TLS certificate and JA3 fingerprinting
- NetFlow/IPFIX for high-level flow data
Step 1.2 - Normalize Timestamps
Ensure all timestamps are in a consistent format (epoch or ISO 8601) and timezone (UTC). Misaligned timestamps will corrupt interval calculations.
Phase 2: Statistical Frequency Analysis
Step 2.1 - Splunk Interval Calculation
index=proxy OR index=firewall
| where NOT match(dest, "(?i)(microsoft|google|amazonaws|cloudflare|akamai|apple|adobe)")
| bin _time span=1s
| stats count by src_ip dest _time
| streamstats current=f last(_time) as prev_time by src_ip dest
| eval interval=_time-prev_time
| stats count avg(interval) as avg_interval stdev(interval) as stdev_interval
min(interval) as min_interval max(interval) as max_interval
dc(interval) as unique_intervals by src_ip dest
| where count > 50
| eval cv=stdev_interval/avg_interval
| eval jitter_pct=round((stdev_interval/avg_interval)*100, 1)
| where cv < 0.25 AND avg_interval > 30 AND avg_interval < 86400
| sort cv
| table src_ip dest count avg_interval stdev_interval cv jitter_pct
Step 2.2 - Elastic Query for Beacon Detection
{
"aggs": {
"by_pair": {
"composite": {
"sources": [
{"src": {"terms": {"field": "source.ip"}}},
{"dst": {"terms": {"field": "destination.domain"}}}
]
},
"aggs": {
"timestamps": {
"date_histogram": {"field": "@timestamp", "fixed_interval": "1s"}
},
"stats": {
"extended_stats": {"field": "event.duration"}
}
}
}
}
}
Step 2.3 - RITA Automated Analysis
# Import Zeek logs into RITA
rita import /path/to/zeek/logs mydataset
# Analyze beacons
rita show-beacons mydataset
# Export results as CSV
rita show-beacons mydataset --csv > beacon_results.csv
# Show long connections
rita show-long-connections mydataset
Phase 3: Jitter-Aware Detection
Step 3.1 - Detect Beacons with Jitter
Cobalt Strike adds configurable jitter (0-50%) to its sleep timer. A 60-second beacon with 30% jitter produces intervals between 42-78 seconds.
index=proxy
| stats count by src_ip dest _time
| streamstats current=f last(_time) as prev_time by src_ip dest
| eval interval=_time-prev_time
| stats count avg(interval) as avg stdev(interval) as sd
percentile25(interval) as p25 percentile75(interval) as p75 by src_ip dest
| where count > 50
| eval iqr=p75-p25
| eval jitter_ratio=iqr/avg
| where jitter_ratio < 0.50 AND avg > 30
| sort jitter_ratio
Phase 4: Data Size Consistency Analysis
Step 4.1 - Payload Size Regularity
index=proxy
| stats count avg(bytes_out) as avg_bytes stdev(bytes_out) as sd_bytes
by src_ip dest
| where count > 50
| eval data_cv=sd_bytes/avg_bytes
| where data_cv < 0.30
| sort data_cv
Phase 5: Domain Intelligence Enrichment
Step 5.1 - Check Domain Age via WHOIS
Flag any beaconing destination with domain registration under 30 days. Newly registered domains correlate strongly with C2 infrastructure.
Step 5.2 - JA3/JA4 TLS Fingerprinting
index=zeek sourcetype=bro_ssl
| stats count dc(id.resp_h) as unique_dests values(server_name) as domains by ja3
| lookup ja3_known_c2 ja3 OUTPUT framework
| where isnotnull(framework)
| table ja3 framework count unique_dests domains
Phase 6: Endpoint Correlation
Step 6.1 - Map Network to Process
index=sysmon EventCode=3
| where NOT cidrmatch("10.0.0.0/8", DestinationIp)
AND NOT cidrmatch("172.16.0.0/12", DestinationIp)
AND NOT cidrmatch("192.168.0.0/16", DestinationIp)
| stats count values(DestinationPort) as ports dc(DestinationIp) as unique_ips
by Image Computer DestinationIp
| where count > 50 AND unique_ips < 3
| sort -count
Phase 7: Verification and Response
Step 7.1 - Confirm C2 Activity
- Capture packet sample of suspected C2 traffic
- Analyze TLS certificate (self-signed, unusual issuer, short validity)
- Cross-reference domain/IP against multiple TI sources
- Review process tree on source endpoint
- Check for associated lateral movement or tool transfers
Step 7.2 - Containment Actions
- Block C2 domain/IP at firewall, proxy, and DNS sinkhole
- Isolate compromised endpoint via EDR network containment
- Preserve memory dump and disk image for forensics
- Reset credentials used on affected systems
- Sweep environment for additional infections using discovered IOCs
Back to mukul975/Anthropic-Cybersecurity-Skills (817 security skills) or Agent skills.