Encrypted Channel
This detection identifies adversaries using custom or non-standard encryption to conceal command and control (C2) traffic. Unlike legitimate TLS/HTTPS, malware implementing encrypted channels often exhibits behavioral anomalies: unusual processes making encrypted connections, connections to raw IP addresses without SNI, self-signed or short-lived certificates, high-frequency beaconing intervals, non-browser processes using port 443/8443 with atypical TLS fingerprints (JA3), and data volumes inconsistent with the application type. This detection correlates process lineage, network destinations, certificate characteristics, and traffic timing to surface encrypted C2 channels used by threat actors such as Tropic Trooper, Lazarus Group, and malware families including RCSession, Cryptoistic, Gomir, and Chaes.
What is T1573 Encrypted Channel?
Encrypted Channel (T1573) 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 Encrypted Channel, covering the data sources and telemetry it touches: 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
- Command and Control
- Technique
- T1573 Encrypted Channel
- Canonical reference
- https://attack.mitre.org/techniques/T1573/
let SuspiciousParentProcesses = dynamic(["cmd.exe", "powershell.exe", "wscript.exe", "cscript.exe", "mshta.exe", "regsvr32.exe", "rundll32.exe", "svchost.exe", "explorer.exe"]);
let LegitimateEncryptedApps = dynamic(["chrome.exe", "firefox.exe", "msedge.exe", "iexplore.exe", "outlook.exe", "teams.exe", "onedrive.exe", "slack.exe", "zoom.exe", "msiexec.exe", "wuauclt.exe", "svchost.exe"]);
let EncryptedPorts = dynamic([443, 8443, 8080, 4443, 9443, 3443, 7443]);
// Step 1: Identify network connections from suspicious or non-browser processes on encrypted ports
let SuspiciousEncryptedConnections = DeviceNetworkEvents
| where TimeGenerated >= ago(24h)
| where ActionType == "ConnectionSuccess"
| where RemotePort in (EncryptedPorts)
| where not(InitiatingProcessFileName has_any (LegitimateEncryptedApps))
| where isnotempty(RemoteIP)
// Exclude private/loopback IP ranges
| where not(RemoteIP matches regex @"^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.|::1|fc00:|fe80:)")
| extend IsIPOnlyConnection = (isempty(RemoteUrl) or RemoteUrl == RemoteIP or RemoteUrl matches regex @"^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$")
| extend SuspiciousParent = (InitiatingProcessParentFileName has_any (SuspiciousParentProcesses))
| project
TimeGenerated,
DeviceName,
DeviceId,
InitiatingProcessFileName,
InitiatingProcessCommandLine,
InitiatingProcessParentFileName,
InitiatingProcessAccountName,
InitiatingProcessId,
RemoteIP,
RemotePort,
RemoteUrl,
IsIPOnlyConnection,
SuspiciousParent,
BytesSent,
BytesReceived;
// Step 2: Detect beaconing behavior — repeated encrypted connections at regular intervals
let BeaconingDetection = DeviceNetworkEvents
| where TimeGenerated >= ago(24h)
| where ActionType == "ConnectionSuccess"
| where RemotePort in (EncryptedPorts)
| where not(InitiatingProcessFileName has_any (LegitimateEncryptedApps))
| where not(RemoteIP matches regex @"^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.)")
| summarize
ConnectionCount = count(),
UniqueRemoteIPs = dcount(RemoteIP),
FirstSeen = min(TimeGenerated),
LastSeen = max(TimeGenerated),
AvgBytesSent = avg(BytesSent),
AvgBytesReceived = avg(BytesReceived),
ConnectionTimes = make_list(TimeGenerated, 50)
by DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteIP, RemotePort
| where ConnectionCount >= 5
| where UniqueRemoteIPs == 1
| extend DurationMinutes = datetime_diff('minute', LastSeen, FirstSeen)
| extend AvgIntervalMinutes = iff(ConnectionCount > 1, toreal(DurationMinutes) / toreal(ConnectionCount - 1), 0.0)
// Flag regular beaconing: 5+ connections with consistent intervals (1-60 min)
| where AvgIntervalMinutes between (1.0 .. 60.0)
| extend BeaconScore = case(
AvgIntervalMinutes < 5, "High - Sub-5min beaconing",
AvgIntervalMinutes < 15, "Medium - Regular beaconing",
"Low - Periodic connection"
);
// Combine results
SuspiciousEncryptedConnections
| join kind=leftouter (
BeaconingDetection
| project DeviceName, InitiatingProcessFileName, RemoteIP, RemotePort, ConnectionCount, AvgIntervalMinutes, BeaconScore
) on DeviceName, InitiatingProcessFileName, RemoteIP, RemotePort
| extend RiskScore = case(
IsIPOnlyConnection == true and SuspiciousParent == true, "Critical",
IsIPOnlyConnection == true or (isnotempty(BeaconScore) and BeaconScore startswith "High"), "High",
SuspiciousParent == true or isnotempty(BeaconScore), "Medium",
"Low"
)
| where RiskScore in ("Critical", "High", "Medium")
| project
TimeGenerated,
DeviceName,
RiskScore,
InitiatingProcessFileName,
InitiatingProcessCommandLine,
InitiatingProcessParentFileName,
InitiatingProcessAccountName,
RemoteIP,
RemotePort,
RemoteUrl,
IsIPOnlyConnection,
BeaconScore,
ConnectionCount,
AvgIntervalMinutes,
BytesSent,
BytesReceived
| sort by RiskScore asc, TimeGenerated desc Detects encrypted C2 channels by identifying non-browser processes making encrypted connections (ports 443, 8443, etc.) to external IPs, particularly connections to raw IP addresses without hostname resolution (SNI omission), and beaconing behavior with regular connection intervals. Assigns risk scores based on parent process suspicion, IP-only destinations, and regularity of connections.
Data Sources
Required Tables
False Positives
- Custom internal applications or agents that connect to known infrastructure over HTTPS but are not in the allowlist (add to LegitimateEncryptedApps)
- IT monitoring and management tools (SCCM, Ansible, Puppet) that make frequent scheduled encrypted connections to management infrastructure
- Security products (EDR agents, vulnerability scanners, DLP solutions) that beacon home over encrypted channels on non-standard ports
- Cloud sync clients or backup agents connecting to cloud storage endpoints on port 443 at regular intervals
- VPN clients and network tunneling software that establish persistent encrypted connections as part of normal operation
Sigma rule & cross-platform mapping
The detection logic for Encrypted Channel (T1573) 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:
Platform-specific guides for T1573
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 1Simulate Custom Encrypted C2 Beacon Using PowerShell SSL
Expected signal: Sysmon Event ID 3 (NetworkConnect) with Image=powershell.exe, DestinationPort=443, DestinationHostname=ifconfig.me; Sysmon Event ID 1 showing PowerShell execution with -ExecutionPolicy Bypass flag; DeviceNetworkEvents showing 5 connections at ~30 second intervals (low jitter beaconing pattern)
- Test 2Simulate C2 Connection to Raw IP Address Over HTTPS
Expected signal: Sysmon Event ID 3 with Image=powershell.exe, DestinationIp=1.1.1.1, DestinationPort=443, DestinationHostname empty or equal to the IP address; DeviceNetworkEvents showing IsIPOnlyConnection=true with RemoteUrl matching RemoteIP
- Test 3Simulate Encrypted C2 Beacon from LOLBin (mshta.exe)
Expected signal: Sysmon Event ID 1 showing mshta.exe execution with HTA file path argument; Sysmon Event ID 3 with Image=mshta.exe, DestinationPort=443, DestinationHostname=httpbin.org; DeviceProcessEvents and DeviceNetworkEvents correlation showing mshta.exe as initiating process
- Test 4Linux Custom Encrypted Beacon Simulation Using OpenSSL
Expected signal: Auditd SYSCALL records for connect() calls from openssl process; syslog entries showing openssl process network activity; on hosts with Sysmon for Linux, Event ID 3 showing openssl making TLS connections to external IP on port 443 at ~30 second intervals
Response Playbook
Triage
- Step 1: Identify the initiating process — retrieve the full process tree (parent → child → grandchild) for the alerting process using DeviceProcessEvents or Sysmon Event ID 1. Determine if the process is a known legitimate application or exhibits LOLBin behavior.
- Step 2: Examine the destination — query the remote IP against threat intelligence sources (VirusTotal, Shodan, AbuseIPDB). Check if the IP is a known cloud provider, CDN, or malicious infrastructure. Look up WHOIS/ASN data to determine hosting provider and registration age.
- Step 3: Analyze the connection pattern — retrieve all connections from this process/host to the same destination over the past 7 days. Calculate average interval between connections. Intervals of 30s, 60s, 5m, 15m, or 30m are strong beaconing indicators.
- Step 4: Examine TLS certificate details — if available in network logs or proxy logs, extract the certificate CN, issuer, validity period, and SANs. Self-signed certs, certificates valid for <30 days or >5 years, or certificates with generic CNs (e.g., 'localhost', IP addresses) are red flags.
- Step 5: Review data transfer volumes — compare BytesSent vs BytesReceived ratios. C2 channels often show small outbound (heartbeat/check-in) with occasional larger inbound (command/payload). Consistent near-equal bidirectional traffic may indicate tunneled sessions.
- Step 6: Check process command line and loaded modules — examine the initiating process command line for encoded arguments, suspicious flags, or unusual paths. Query DeviceImageLoadEvents for DLLs loaded by the process, particularly custom crypto libraries.
- Step 7: Correlate with other suspicious activity on the host — search for related indicators: recent file drops (DeviceFileEvents), registry modifications (DeviceRegistryEvents), privilege escalation (SecurityEvent 4672), or lateral movement events within 24h of the encrypted channel activity.
Containment
- If confirmed malicious: Isolate the endpoint using EDR/MDM isolation to prevent further C2 communication while preserving the system for forensic analysis.
- Block the remote IP and any associated domains at the perimeter firewall, web proxy, and DNS sinkholes. Apply the block to all network segments, not just the affected host.
- Terminate the suspicious process and any child processes. Document all PIDs before termination for evidence collection.
- If a user account was used to execute the suspicious process, disable or reset the account credentials immediately. Check for OAuth tokens or API keys associated with the account that may need rotation.
- Search for the same process binary or network destination across the entire environment using EDR fleet queries to identify additional compromised hosts.
- If the process was running as a service or scheduled task, disable the persistence mechanism to prevent re-establishment after containment.
Evidence Collection
- Export the complete process tree and command line arguments from EDR for the alerting process and all ancestors.
- Capture a full memory dump of the suspicious process before termination if forensics team requires it — memory often contains decrypted C2 traffic, keys, and configuration.
- Collect the suspicious binary from disk: calculate SHA256 hash, extract PE metadata, and submit to sandboxes (Any.run, Cuckoo) for behavioral analysis and key extraction.
- Export all network connection logs (DeviceNetworkEvents, proxy logs, firewall logs, DNS query logs) for the affected host for the past 7-30 days to establish C2 timeline.
- Collect Sysmon operational logs (Event ID 1, 3, 7, 8, 10, 11, 12, 13) from the endpoint for the period of compromise.
- Capture packet captures (PCAP) from network monitoring infrastructure if available — even encrypted traffic metadata (timing, size, directionality) aids in identifying the C2 protocol and infrastructure.
- Export Windows Prefetch files (C:\Windows\Prefetch\) to establish execution history and frequency of the suspicious binary.
- Collect scheduled tasks (schtasks /query /fo LIST /v), services (sc query), and autorun registry keys to identify persistence mechanisms.
Escalation Criteria
- ! Escalate immediately if the suspicious process has established connections to more than one external IP, indicating active C2 infrastructure rotation or multi-stage payload delivery.
- ! Escalate if the encrypted channel is running under a SYSTEM, service account, or privileged user context — this indicates post-exploitation activity with elevated access.
- ! Escalate if lateral movement indicators are present (successful remote logins, PsExec/WMI activity, SMB connections) within the same timeframe as the encrypted channel activity.
- ! Escalate if the beaconing host is a server (domain controller, file server, build system, database server) rather than a workstation — server compromise has higher blast radius.
- ! Escalate if memory analysis or sandbox detonation reveals the binary performs decryption of embedded payloads, suggesting staged malware with encrypted secondary C2.
- ! Escalate if multiple hosts in the same subnet show the same pattern within a short window — this may indicate a worm or automated lateral movement component.
- ! Escalate if the investigation reveals exfiltration indicators: large outbound transfers (BytesSent > 10MB) to the C2 IP, or connections timing after access to sensitive data repositories.
Investigation Guide
Forensic Artifacts
- >
Process memory dump: decrypted C2 traffic buffers, encryption keys, hardcoded C2 IP/domains, and configuration data - >
Network PCAP: TLS handshake metadata (JA3/JA3S fingerprints, cipher suites, SNI values, certificate chain) - >
Windows Prefetch: C:\Windows\Prefetch\<processname>-*.pf — confirms execution frequency and loaded DLLs - >
DNS cache: ipconfig /displaydns — may show resolved domains associated with C2 even after process termination - >
Windows Event Log: Security (4688 process creation if audit enabled), Sysmon operational log - >
Scheduled tasks and services: C:\Windows\System32\Tasks\, HKLM\SYSTEM\CurrentControlSet\Services\ - >
Browser history and extensions: malware may abuse browser processes for encrypted channel cover - >
Binary on disk: PE headers, embedded resources, import table (CryptEncrypt, WSAStartup, SSL APIs), packed sections - >
Linux: /proc/<pid>/net/tcp6 for active encrypted connections, /proc/<pid>/maps for loaded libraries, auditd logs
Tuning Guidance
Start by building an allowlist of legitimate processes in your environment that routinely make encrypted connections (update agents, monitoring tools, backup clients). Add these to the LegitimateEncryptedApps list in both KQL and SPL queries. For beaconing detection, adjust the minimum ConnectionCount threshold (default: 5) and interval window based on observed false positives — backup tools and monitoring agents may check in every 5-15 minutes legitimately. For the IP-only connection check, some CDNs and cloud services return connections to IP addresses without SNI — maintain a known-safe IP allowlist. Consider deploying SSL/TLS inspection at your perimeter to enable JA3 fingerprint analysis, which dramatically improves detection accuracy for custom crypto implementations. In environments with Defender for Endpoint P2, leverage the built-in network inspection capabilities which provide additional certificate metadata not available in standard DeviceNetworkEvents. The low-jitter beaconing hunt (StdDev < 10%) is highly specific — most legitimate software has much more variance in connection timing.
Hunting Queries
Hunts for low-prevalence processes (seen on 5 or fewer endpoints globally) making encrypted connections — indicative of custom malware or implants vs. widely deployed legitimate software.
// Hunt for JA3 fingerprint anomalies — processes with rare TLS fingerprints
// Requires network proxy/SSL inspection data in CommonSecurityLog or custom table
DeviceNetworkEvents
| where TimeGenerated >= ago(7d)
| where ActionType == "ConnectionSuccess"
| where RemotePort in (443, 8443, 4443)
| where not(RemoteIP matches regex @"^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.)")
| summarize
TotalConnections = count(),
UniqueDestinations = dcount(RemoteIP),
Hosts = make_set(DeviceName, 20),
SampleCommandLines = make_set(InitiatingProcessCommandLine, 5)
by InitiatingProcessFileName, InitiatingProcessSHA256
| where TotalConnections < 10 and UniqueDestinations <= 3
// Low-prevalence encrypted channels — rare processes making few encrypted connections
| join kind=leftouter (
DeviceNetworkEvents
| where TimeGenerated >= ago(7d)
| summarize GlobalPrevalence = dcount(DeviceId) by InitiatingProcessSHA256
) on InitiatingProcessSHA256
| where GlobalPrevalence <= 5
| project InitiatingProcessFileName, InitiatingProcessSHA256, TotalConnections, UniqueDestinations, GlobalPrevalence, Hosts, SampleCommandLines
| sort by GlobalPrevalence asc index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3
| where RemotePort IN ("443", "8443", "4443", "8080")
| where NOT match(DestinationIp, "^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\.168\\.|127\\.)")
| eval ProcessName=lower(mvindex(split(Image, "\\"), -1))
| stats
dc(host) AS HostCount,
dc(DestinationIp) AS UniqueIPs,
count AS TotalConns,
values(host) AS AffectedHosts
by ProcessName, Hashes
| where HostCount <= 3 AND TotalConns >= 5
| sort HostCount Hunts for high-regularity beaconing with low jitter (standard deviation < 10% of average interval). Legitimate software typically has variable connection intervals; malware beacons often use simple sleep timers with very consistent timing.
// Hunt for encrypted beaconing with high regularity (low jitter)
// Adversaries often implement timers with little randomness
DeviceNetworkEvents
| where TimeGenerated >= ago(3d)
| where ActionType == "ConnectionSuccess"
| where RemotePort in (443, 8443, 4443, 8080, 9443)
| where not(RemoteIP matches regex @"^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.)")
| where not(InitiatingProcessFileName has_any ("chrome.exe", "firefox.exe", "msedge.exe", "outlook.exe", "teams.exe", "onedrive.exe"))
| sort by DeviceName, InitiatingProcessFileName, RemoteIP, TimeGenerated asc
| serialize
| extend PrevTime = prev(TimeGenerated, 1)
| extend PrevProcess = prev(InitiatingProcessFileName, 1)
| extend PrevHost = prev(DeviceName, 1)
| extend PrevIP = prev(RemoteIP, 1)
| where DeviceName == PrevHost and InitiatingProcessFileName == PrevProcess and RemoteIP == PrevIP
| extend IntervalSeconds = datetime_diff('second', TimeGenerated, PrevTime)
| where IntervalSeconds > 0
| summarize
ConnectionCount = count(),
AvgInterval = avg(IntervalSeconds),
StdDevInterval = stdev(IntervalSeconds),
MinInterval = min(IntervalSeconds),
MaxInterval = max(IntervalSeconds)
by DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteIP, RemotePort
| where ConnectionCount >= 8
// Low jitter: standard deviation less than 10% of average interval
| where StdDevInterval < (AvgInterval * 0.10)
| extend JitterPercent = round(StdDevInterval / AvgInterval * 100, 1)
| sort by JitterPercent asc index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3
| where RemotePort IN ("443", "8443", "4443", "8080")
| where NOT match(DestinationIp, "^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\.168\\.|127\\.)")
| eval ProcessName=lower(mvindex(split(Image, "\\"), -1))
| where NOT ProcessName IN ("chrome.exe", "firefox.exe", "msedge.exe", "outlook.exe", "teams.exe")
| sort host, ProcessName, DestinationIp, _time
| streamstats current=f last(_time) AS prev_time by host, ProcessName, DestinationIp
| eval interval_seconds=_time - prev_time
| where interval_seconds > 0
| stats count AS conn_count, avg(interval_seconds) AS avg_interval, stdev(interval_seconds) AS std_interval by host, ProcessName, CommandLine, DestinationIp, DestinationPort
| where conn_count >= 8
| eval jitter_pct=round(std_interval / avg_interval * 100, 1)
| where jitter_pct < 10
| sort jitter_pct Hunts for processes that load cryptographic libraries (bcrypt, openssl, etc.) immediately before making outbound encrypted connections. This pattern identifies custom encryption implementations used by malware families like Gomir and RCSession that load crypto APIs at runtime just before C2 beaconing.
// Hunt for processes loading crypto libraries immediately before making network connections
// Custom encryption implementations often load CNG/crypto DLLs right before C2 activity
let CryptoDLLs = dynamic(["bcrypt.dll", "ncrypt.dll", "crypt32.dll", "cryptsp.dll", "rsaenh.dll", "dpapi.dll", "libssl", "openssl", "boringssl"]);
DeviceImageLoadEvents
| where TimeGenerated >= ago(24h)
| where FileName has_any (CryptoDLLs)
| where not(InitiatingProcessFileName has_any ("chrome.exe", "firefox.exe", "msedge.exe", "outlook.exe", "teams.exe", "lsass.exe", "svchost.exe", "services.exe"))
| project
CryptoLoadTime = TimeGenerated,
DeviceName,
DeviceId,
InitiatingProcessFileName,
InitiatingProcessCommandLine,
InitiatingProcessId,
InitiatingProcessAccountName,
CryptoDLL = FileName,
CryptoSHA256 = SHA256
| join kind=inner (
DeviceNetworkEvents
| where TimeGenerated >= ago(24h)
| where ActionType == "ConnectionSuccess"
| where RemotePort in (443, 8443, 4443, 8080)
| where not(RemoteIP matches regex @"^(10\.|172\.(1[6-9]|2[0-9]|3[01])\.|192\.168\.|127\.)")
| project NetworkTime = TimeGenerated, DeviceName, InitiatingProcessId, RemoteIP, RemotePort, BytesSent, BytesReceived
) on DeviceName, InitiatingProcessId
| where NetworkTime > CryptoLoadTime and NetworkTime < datetime_add('minute', 5, CryptoLoadTime)
| project CryptoLoadTime, NetworkTime, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessAccountName, CryptoDLL, RemoteIP, RemotePort, BytesSent, BytesReceived
| sort by CryptoLoadTime desc index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=7
| eval ImageLoaded=lower(ImageLoaded)
| where match(ImageLoaded, "bcrypt\.dll|ncrypt\.dll|crypt32\.dll|cryptsp\.dll|rsaenh\.dll|libssl|openssl")
| eval ProcessName=lower(mvindex(split(Image, "\\"), -1))
| where NOT ProcessName IN ("chrome.exe", "firefox.exe", "msedge.exe", "outlook.exe", "lsass.exe", "svchost.exe")
| eval crypto_time=_time
| join type=inner ProcessId [
search index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3
| where RemotePort IN ("443", "8443", "4443", "8080")
| where NOT match(DestinationIp, "^(10\\.|172\\.(1[6-9]|2[0-9]|3[01])\\.|192\.168\\.|127\\.)")
| eval net_time=_time
| table ProcessId, net_time, DestinationIp, DestinationPort, host
]
| eval time_diff=net_time - crypto_time
| where time_diff >= 0 AND time_diff <= 300
| table host, ProcessName, CommandLine, ImageLoaded, DestinationIp, DestinationPort, time_diff
| sort time_diff Atomic Red Team Tests
Simulates a custom encrypted C2 channel by establishing a TLS connection from PowerShell to an external endpoint. This validates that non-browser processes making encrypted connections are detected, particularly from scripting engines that are common malware carriers.
Command
powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "$url = 'https://ifconfig.me/all.json'; for ($i=0; $i -lt 5; $i++) { try { $r = Invoke-RestMethod -Uri $url -UseBasicParsing; Write-Host 'Beacon $($i+1): Connected' } catch { Write-Host 'Failed: $_' }; Start-Sleep -Seconds 30 }" Cleanup
# No cleanup required — connections are outbound only. Kill PowerShell process if still running.
Get-Process powershell | Where-Object {$_.MainWindowTitle -eq ''} | Stop-Process -Force Expected Telemetry
Sysmon Event ID 3 (NetworkConnect) with Image=powershell.exe, DestinationPort=443, DestinationHostname=ifconfig.me; Sysmon Event ID 1 showing PowerShell execution with -ExecutionPolicy Bypass flag; DeviceNetworkEvents showing 5 connections at ~30 second intervals (low jitter beaconing pattern)
Expected Detection
Alert fires on PowerShell making repeated encrypted connections at regular intervals; beaconing hunt query flags low-jitter pattern (5 connections, ~30s average interval, StdDev < 3s)
Tests detection of encrypted connections to raw IP addresses without hostname (SNI omission), which is a common indicator of custom C2 implementations that embed IP addresses directly to avoid DNS-based detection.
Command
powershell.exe -NoProfile -Command "Add-Type @'
using System.Net;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
public class TrustAll {
public static bool Validate(object s, X509Certificate c, X509Chain ch, SslPolicyErrors e) { return true; }
}
'@
[System.Net.ServicePointManager]::ServerCertificateValidationCallback = [TrustAll]::Validate
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
try { $r = (New-Object System.Net.WebClient).DownloadString('https://1.1.1.1/') } catch { }
Write-Host 'Connection attempt to raw IP complete'" Cleanup
# No cleanup required — single connection attempt only Expected Telemetry
Sysmon Event ID 3 with Image=powershell.exe, DestinationIp=1.1.1.1, DestinationPort=443, DestinationHostname empty or equal to the IP address; DeviceNetworkEvents showing IsIPOnlyConnection=true with RemoteUrl matching RemoteIP
Expected Detection
Alert fires with RiskScore=High or Critical due to IP-only encrypted connection from PowerShell; the IsIPOnlyConnection flag is set to true triggering elevated risk scoring
Tests detection of encrypted channel established via mshta.exe (Microsoft HTML Application Host), a Living Off the Land Binary commonly abused by threat actors including Tropic Trooper to proxy C2 traffic through trusted Windows processes.
Command
# Create temporary HTA file that makes HTTPS connections
$htaContent = @'
<script language="VBScript">
Function MakeRequest()
Dim http
Set http = CreateObject("MSXML2.XMLHTTP")
http.Open "GET", "https://httpbin.org/get", False
http.Send
MsgBox "Response: " & http.Status
End Function
MakeRequest
</script>
'@
$htaPath = "$env:TEMP\test_beacon.hta"
$htaContent | Out-File -FilePath $htaPath -Encoding ASCII
mshta.exe $htaPath Cleanup
Remove-Item -Path "$env:TEMP\test_beacon.hta" -Force -ErrorAction SilentlyContinue Expected Telemetry
Sysmon Event ID 1 showing mshta.exe execution with HTA file path argument; Sysmon Event ID 3 with Image=mshta.exe, DestinationPort=443, DestinationHostname=httpbin.org; DeviceProcessEvents and DeviceNetworkEvents correlation showing mshta.exe as initiating process
Expected Detection
Alert fires with RiskScore=Medium or High since mshta.exe is in the SuspiciousParentProcesses list — the process itself is the initiator; detection identifies non-browser process (mshta.exe) making encrypted connection on port 443
Simulates a custom encrypted C2 channel on Linux using OpenSSL's s_client, which bypasses certificate validation similar to how malware implements custom TLS without proper verification. Tests detection of unusual processes establishing encrypted connections.
Command
# Simulate beaconing — 5 connections at 30-second intervals using openssl s_client
for i in $(seq 1 5); do
echo 'GET / HTTP/1.0\r\n\r\n' | timeout 5 openssl s_client -connect httpbin.org:443 -quiet 2>/dev/null | head -1
echo "Beacon $i sent at $(date)"
sleep 30
done Cleanup
# No cleanup required — outbound connections only. Kill the loop if still running:
# kill %1 Expected Telemetry
Auditd SYSCALL records for connect() calls from openssl process; syslog entries showing openssl process network activity; on hosts with Sysmon for Linux, Event ID 3 showing openssl making TLS connections to external IP on port 443 at ~30 second intervals
Expected Detection
Beaconing hunt query flags regular interval connections from openssl s_client process; low-jitter pattern detection triggers on 5 connections with StdDev/AvgInterval ratio < 10%
Related Detections
Tactic Hub
Detection Variants (1)
Different telemetry and tradecraft for the same technique — pick the one that matches the data you collect.