T1573

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.

Microsoft Sentinel / Defender
kusto
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
high severity medium confidence

Data Sources

Microsoft Defender for Endpoint

Required Tables

DeviceNetworkEvents

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

Unlock Pro Content

Get the full detection package for T1573 including response playbook, investigation guide, and atomic red team tests.

Response PlaybookInvestigation GuideHunting QueriesAtomic Red Team TestsTuning Guidance

Related Detections