T1571

Non-Standard Port

Command and Control Last updated:

This detection identifies adversary command and control (C2) activity using protocols on non-standard ports, a technique used to bypass network filtering rules and evade traffic analysis. Attackers may use HTTPS over ports like 8088, 2083, 2087, or 587, HTTP over 8080 or 8008, or arbitrary high ports like 4444, 1337, or 9001 to blend in with legitimate traffic or avoid port-based firewall rules. The detection correlates outbound connections to non-standard ports with high-risk processes (scripting interpreters, LOLBins, spawned shells) and flags known malicious port patterns observed in threat actor infrastructure including WIRTE, PingPull, and Contagious Interview campaigns. Both KQL and SPL queries score events by combining process risk and port suspicion to surface the highest-confidence alerts while suppressing common developer and admin tooling noise.

What is T1571 Non-Standard Port?

Non-Standard Port (T1571) 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 Non-Standard Port, 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
T1571 Non-Standard Port
Canonical reference
https://attack.mitre.org/techniques/T1571/
Microsoft Sentinel / Defender
kusto
let SuspiciousNonStandardPorts = dynamic([444, 587, 1224, 1337, 2083, 2087, 4443, 4444, 4445, 6666, 6667, 6668, 7777, 8008, 8088, 8888, 9001, 9090, 31337]);
let HighRiskProcesses = dynamic(["cmd.exe", "powershell.exe", "pwsh.exe", "wscript.exe", "cscript.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe", "certutil.exe", "bitsadmin.exe", "msiexec.exe", "svchost.exe"]);
let StandardWebPorts = dynamic([80, 443, 8080, 8443, 3000, 5000, 5001, 9000]);
DeviceNetworkEvents
| where TimeGenerated > ago(24h)
| where ActionType == "ConnectionSuccess"
| where RemoteIPType == "Public"
| extend ProcessLower = tolower(InitiatingProcessFileName)
| extend IsHighRiskProcess = ProcessLower in~ (HighRiskProcesses)
| extend IsKnownC2Port = RemotePort in (SuspiciousNonStandardPorts)
| extend IsNonStandardFromHighRisk = IsHighRiskProcess and RemotePort !in (StandardWebPorts) and RemotePort != 53 and RemotePort != 25
| where IsKnownC2Port or IsNonStandardFromHighRisk
| extend RiskScore = case(
    IsHighRiskProcess and IsKnownC2Port, 3,
    IsHighRiskProcess and IsNonStandardFromHighRisk, 2,
    IsKnownC2Port, 1,
    0
)
| summarize
    TotalConnections = count(),
    UniqueRemoteIPs = dcount(RemoteIP),
    PortsUsed = make_set(RemotePort, 20),
    RemoteIPs = make_set(RemoteIP, 10),
    MaxRiskScore = max(RiskScore),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated)
    by DeviceName, InitiatingProcessFileName, InitiatingProcessAccountName, InitiatingProcessParentFileName
| where MaxRiskScore >= 1
| extend AlertSeverity = case(
    MaxRiskScore >= 3, "High",
    MaxRiskScore == 2, "Medium",
    "Low"
)
| project-reorder DeviceName, InitiatingProcessFileName, InitiatingProcessAccountName, InitiatingProcessParentFileName, PortsUsed, UniqueRemoteIPs, TotalConnections, MaxRiskScore, AlertSeverity, FirstSeen, LastSeen
| order by MaxRiskScore desc, TotalConnections desc

Detects outbound network connections from high-risk processes (cmd.exe, PowerShell, LOLBins) to non-standard ports, and flags connections to known malicious C2 port patterns (4444, 1337, 2083, 2087, 8088, etc.) observed in real-world threat actor campaigns. Risk scoring combines process risk and port suspicion to surface highest-confidence alerts first.

high severity medium confidence

Data Sources

Microsoft Defender for Endpoint

Required Tables

DeviceNetworkEvents

False Positives

  • Developer tooling and local services running on non-standard ports (e.g., Node.js apps on 3001, Python Flask on 5000, webpack dev server on 8088)
  • Legitimate email relay over port 587 (SMTP STARTTLS) from mail client processes like outlook.exe or thunderbird.exe
  • cPanel/WHM web hosting control panel using ports 2083 and 2087 for legitimate SSL management
  • Security scanning tools (Nmap, Nessus, Metasploit listener) run by authorized red team or pentesters
  • VPN and proxy clients that tunnel legitimate traffic over non-standard ports

Sigma rule & cross-platform mapping

The detection logic for Non-Standard Port (T1571) 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 1Netcat C2 Listener on Non-Standard Port (Windows)

    Expected signal: Sysmon Event ID 3: DestinationPort=4444, Image=powershell.exe, Initiated=true. DeviceNetworkEvents: RemotePort=4444, InitiatingProcessFileName=powershell.exe.

  2. Test 2HTTPS Beacon Simulation Over Port 8088 (Linux/macOS)

    Expected signal: Sysmon/auditd network events: DestinationPort=8088, process=curl or python3. Linux netstat/ss shows ESTABLISHED connections on port 8088.

  3. Test 3RDP Port Change via Registry (Windows)

    Expected signal: Sysmon Event ID 13 (RegistryValueSet): TargetObject contains 'RDP-Tcp\PortNumber', Details=33890. DeviceRegistryEvents: RegistryKey contains 'RDP-Tcp', RegistryValueName=PortNumber, RegistryValueData=33890.

  4. Test 4Beaconing Simulation at Regular Intervals on Non-Standard Port

    Expected signal: Sysmon Event ID 3: 10 network connection events, DestinationPort=9001, Image=powershell.exe, at ~60-second intervals. DeviceNetworkEvents shows RegularInterval connections to port 9001.


Response Playbook

Triage

  1. Step 1: Identify the initiating process — note full image path (InitiatingProcessFolderPath in KQL, Image in SPL). Verify if the binary is signed and located in an expected directory (e.g., powershell.exe should be in C:\Windows\System32, not %TEMP% or user-writable locations).
  2. Step 2: Check parent process (InitiatingProcessParentFileName / ParentImage). A browser or Office document spawning cmd.exe or PowerShell that then connects on a non-standard port is a critical escalation indicator.
  3. Step 3: Resolve the destination IP. Check against threat intelligence feeds (VirusTotal, Shodan, AbuseIPDB). Look for ASN ownership — commodity cloud (DigitalOcean, Vultr, Linode) hosting on non-standard ports is a strong C2 indicator.
  4. Step 4: Inspect the destination port in context. Port 587 is legitimate SMTP STARTTLS — verify if the initiating process is a mail client. Ports 4444, 1337, 9001, 31337 have no legitimate standard use and should always be investigated.
  5. Step 5: Review the volume and frequency of connections. Use the summarized connection_count and time window (FirstSeen to LastSeen). Regular interval beaconing (e.g., every 60 seconds) with consistent byte sizes indicates C2 heartbeat behavior.
  6. Step 6: Check for associated DNS queries. Look in DeviceEvents or Sysmon Event ID 22 for DNS resolution of the destination IP's hostname immediately before the network connection — this can reveal the C2 domain name.
  7. Step 7: Correlate with process tree. Run a parent-child process tree query for the initiating process PID on the same device and timeframe. Determine whether this process was spawned by a suspicious loader, phishing document, or legitimate application.

Containment

  1. If high confidence of active C2 — isolate the endpoint using Microsoft Defender Live Response or EDR isolation to cut network access while preserving memory and disk artifacts for forensics.
  2. Block the destination IP and port at the perimeter firewall and proxy layer. Create a block rule specific to the IP:port pair, not blanket port blocking, to avoid disrupting legitimate services.
  3. If a specific non-standard port (e.g., 4444, 8088) is confirmed malicious, implement a temporary outbound block on that port for the affected subnet while investigation proceeds.
  4. Suspend or reset the credentials of the user account associated with the initiating process — the account may have been used for lateral movement after initial compromise.
  5. If the initiating process is a scheduled task or service binary, disable the task or service immediately to prevent C2 re-establishment after reboot.

Evidence Collection

  1. Capture full memory dump of the device (especially the malicious process) before isolation — use WinPmem, ProcDump, or Defender Live Response memory collection. Memory will contain in-flight C2 traffic, encryption keys, and injected shellcode.
  2. Collect Sysmon Event ID 3 logs for the full timeframe, filtered by the initiating process PID, to reconstruct all C2 connections made during the compromise window.
  3. Export the malicious process binary from disk and submit to sandbox analysis (Any.run, Hybrid Analysis). Compare file hash against VirusTotal. Check PE compilation timestamp and embedded strings for C2 domain/IP indicators.
  4. Collect prefetch files (C:\Windows\Prefetch) — presence of the process image in prefetch confirms execution and reveals timestamps of first and last run.
  5. Pull DNS cache (ipconfig /displaydns) and browser/OS DNS resolver logs to identify C2 domain names associated with the non-standard port destination.
  6. Collect Windows Security Event logs for 4624/4625/4648 logon events and 4688 process creation events for the affected user in the surrounding time window to identify lateral movement or privilege escalation.

Escalation Criteria

  • ! Escalate immediately if the non-standard port connection is from a system process (lsass.exe, svchost.exe, explorer.exe) — this indicates process injection or a compromised OS component.
  • ! Escalate if the destination IP has no DNS hostname and is hosted on a datacenter IP range (cloud VPS) — characteristic of adversary-controlled C2 infrastructure.
  • ! Escalate if the same non-standard port is observed on multiple endpoints within the environment in a short time window — indicates active lateral movement or a wormable payload.
  • ! Escalate if the connection precedes or follows a privilege escalation event (4672 Special Logon, new scheduled task creation, new service registration) on the same endpoint.
  • ! Escalate if the process making the non-standard port connection was spawned by a phishing delivery mechanism (winword.exe, excel.exe, outlook.exe, mshta.exe) — this is a full kill chain indicator from initial access through C2 establishment.

Investigation Guide

Forensic Artifacts

  • > Windows Filtering Platform (WFP) connection logs — shows port and protocol at kernel level, harder to spoof than application logs
  • > Sysmon Event ID 3 (Network Connection) logs — includes initiating process, source/destination IP and port, connection direction
  • > NetFlow/IPFIX records from network devices — provides flow duration, byte count, packet count for non-standard port connections
  • > Windows Firewall with Advanced Security logs (Microsoft-Windows-Windows Firewall With Advanced Security/Firewall) — outbound connection attempts including blocked ones
  • > Browser and application proxy logs — if traffic traverses a corporate proxy, non-standard ports may be blocked or logged
  • > Memory dump of initiating process — contains socket handles, connection state, and potentially decrypted C2 traffic in heap
  • > DNS resolver cache (ipconfig /displaydns) and DNS query logs for C2 domain resolution prior to non-standard port connection

Tuning Guidance

Start by building a baseline of expected non-standard port usage in your environment: inventory all approved applications that legitimately use non-standard ports (developer tools, monitoring agents, custom internal services). Add those process names and port combinations to an allowlist exclusion. For port 587, scope the alert to exclude known mail client processes (outlook.exe, thunderbird.exe) only when they connect to known email provider IPs. For ports 2083/2087, check whether any cPanel-managed web hosting exists in your environment. For the beaconing hunt, tune the StdDevInterval threshold based on your environment's background noise — start at 30 seconds and tighten as you baseline. Consider enriching alerts with Threat Intelligence table (ThreatIntelligenceIndicator) to auto-score destinations against known C2 IPs. For high-value targets (domain controllers, file servers), lower the detection threshold to flag any non-standard outbound port connection regardless of process name.


Hunting Queries

Identifies potential C2 beaconing on non-standard ports by calculating connection interval regularity. Low standard deviation in connection intervals combined with high connection count is a strong beaconing indicator.

Hunting — KQL
kql
// Hunt for beaconing behavior: regular interval connections on non-standard ports
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where ActionType == "ConnectionSuccess"
| where RemoteIPType == "Public"
| where RemotePort !in (80, 443, 22, 25, 53, 8080, 8443, 3389, 445, 139, 135)
| summarize
    ConnectionCount = count(),
    ConnectionTimes = make_list(TimeGenerated, 100)
    by DeviceName, InitiatingProcessFileName, RemoteIP, RemotePort
| where ConnectionCount > 5
| extend TimeDiffs = array_length(ConnectionTimes)
| mv-expand ConnectionTime = ConnectionTimes
| order by DeviceName, RemoteIP, RemotePort, ConnectionTime asc
| serialize
| extend PrevTime = prev(ConnectionTime, 1)
| where isnotnull(PrevTime)
| extend IntervalSeconds = datetime_diff('second', todatetime(ConnectionTime), todatetime(PrevTime))
| summarize
    AvgIntervalSec = avg(IntervalSeconds),
    StdDevInterval = stdev(IntervalSeconds),
    TotalConnections = count()
    by DeviceName, InitiatingProcessFileName, RemoteIP, RemotePort
| where StdDevInterval < 30 and TotalConnections >= 5
| extend BeaconingLikelihood = case(
    StdDevInterval < 5, "High",
    StdDevInterval < 15, "Medium",
    "Low"
)
| order by StdDevInterval asc
Hunting — SPL
spl
index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3 Initiated=true
| eval dest_port=tonumber(DestinationPort)
| where NOT dest_port IN (80, 443, 22, 25, 53, 8080, 8443, 3389, 445, 139, 135)
| bucket _time span=10m
| stats count as connections_per_bucket by host, Image, DestinationIp, dest_port, _time
| stats avg(connections_per_bucket) as avg_rate, stdev(connections_per_bucket) as stddev_rate, sum(connections_per_bucket) as total_conns, values(dest_port) as ports by host, Image, DestinationIp
| where stddev_rate < 1.5 AND total_conns > 10
| eval beaconing_score=round((total_conns / (stddev_rate + 0.1)), 2)
| sort -beaconing_score
| table host, Image, DestinationIp, ports, total_conns, avg_rate, stddev_rate, beaconing_score

Detects protocol-port mismatches where well-known processes (browsers, email clients) are communicating on ports outside their expected ranges, which may indicate process hollowing, DLL injection, or compromised legitimate applications being used as C2 proxies.

Hunting — KQL
kql
// Hunt for protocol-port mismatch: standard protocol processes using unexpected ports
let BrowserProcesses = dynamic(["chrome.exe", "msedge.exe", "firefox.exe", "iexplore.exe", "brave.exe", "opera.exe"]);
let EmailProcesses = dynamic(["outlook.exe", "thunderbird.exe", "msimn.exe"]);
DeviceNetworkEvents
| where TimeGenerated > ago(7d)
| where ActionType == "ConnectionSuccess"
| where RemoteIPType == "Public"
| extend ProcessCategory = case(
    InitiatingProcessFileName in~ (BrowserProcesses), "Browser",
    InitiatingProcessFileName in~ (EmailProcesses), "Email",
    "Other"
)
| where ProcessCategory in ("Browser", "Email")
| extend ExpectedPorts = case(
    ProcessCategory == "Browser", dynamic([80, 443, 8080, 8443]),
    ProcessCategory == "Email", dynamic([25, 143, 465, 587, 993, 995, 443]),
    dynamic([])
)
| extend IsUnexpectedPort = not(RemotePort in (ExpectedPorts))
| where IsUnexpectedPort
| summarize
    Count = count(),
    UnexpectedPorts = make_set(RemotePort, 20),
    RemoteIPs = make_set(RemoteIP, 10),
    FirstSeen = min(TimeGenerated),
    LastSeen = max(TimeGenerated)
    by DeviceName, InitiatingProcessFileName, ProcessCategory, InitiatingProcessAccountName
| order by Count desc
Hunting — SPL
spl
index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=3 Initiated=true
| eval dest_port=tonumber(DestinationPort)
| eval process_lower=lower(Image)
| eval process_category=case(
    match(process_lower, "(chrome|msedge|firefox|iexplore|brave|opera)\.exe"), "Browser",
    match(process_lower, "(outlook|thunderbird)\.exe"), "Email",
    true(), "Other")
| where process_category IN ("Browser", "Email")
| eval is_unexpected=case(
    process_category="Browser" AND NOT dest_port IN (80, 443, 8080, 8443), 1,
    process_category="Email" AND NOT dest_port IN (25, 143, 465, 587, 993, 995, 443), 1,
    true(), 0)
| where is_unexpected=1
| stats count as connection_count, values(DestinationPort) as unexpected_ports, values(DestinationIp) as remote_ips, min(_time) as first_seen, max(_time) as last_seen by host, Image, User, process_category
| sort -connection_count
| table host, Image, User, process_category, unexpected_ports, remote_ips, connection_count, first_seen, last_seen

Hunts for registry modifications that change default service ports for RDP, SMB, or WinRM to non-standard values — a technique documented in Conti ransomware playbooks (change_rdp_port_conti) to allow re-entry after perimeter blocks are applied.

Hunting — KQL
kql
// Hunt for RDP, SMB, or WinRM on non-standard ports — registry or config-based port changes
DeviceRegistryEvents
| where TimeGenerated > ago(30d)
| where ActionType in ("RegistryValueSet", "RegistryKeyCreated")
| where RegistryKey has_any (
    "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Control\\Terminal Server\\WinStations\\RDP-Tcp",
    "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet\\Services\\LanManServer\\Parameters",
    "HKLM\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\WSMAN"
)
| where RegistryValueName =~ "PortNumber" or RegistryValueName =~ "Port"
| extend NewPort = toint(RegistryValueData)
| where NewPort != 3389 and NewPort != 445 and NewPort != 5985 and NewPort != 5986
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessAccountName, RegistryKey, RegistryValueName, RegistryValueData, NewPort
| order by TimeGenerated desc
Hunting — SPL
spl
index=* sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" (EventCode=12 OR EventCode=13 OR EventCode=14)
| where match(TargetObject, "(Terminal Server\\WinStations\\RDP-Tcp|LanManServer\\Parameters|WSMAN)")
| where match(TargetObject, "(PortNumber|Port)")
| eval new_port=tonumber(Details)
| where new_port!=3389 AND new_port!=445 AND new_port!=5985 AND new_port!=5986 AND isnotnull(new_port)
| table _time, host, Image, User, TargetObject, Details, new_port
| sort -_time

Atomic Red Team Tests

Test 1 Netcat C2 Listener on Non-Standard Port (Windows)
windows

Simulates an adversary establishing C2 communication over a non-standard port by using netcat (ncat) to connect to a local listener on port 4444. Validates that DeviceNetworkEvents captures the outbound connection and that the alert fires for the known C2 port.

Command

powershell
Start-Process ncat.exe -ArgumentList '-l -p 4444' -NoNewWindow; Start-Sleep -Seconds 2; powershell.exe -Command "(New-Object System.Net.Sockets.TcpClient).Connect('127.0.0.1', 4444)"

Cleanup

powershell
Stop-Process -Name ncat -ErrorAction SilentlyContinue

Expected Telemetry

Sysmon Event ID 3: DestinationPort=4444, Image=powershell.exe, Initiated=true. DeviceNetworkEvents: RemotePort=4444, InitiatingProcessFileName=powershell.exe.

Expected Detection

Alert fires with RiskScore=3 (high-risk process + known C2 port). Alert severity: High.

Test 2 HTTPS Beacon Simulation Over Port 8088 (Linux/macOS)
linux

Simulates WIRTE and PingPull C2 patterns by sending HTTPS-like requests to a non-standard port (8088) using curl. Validates detection of protocol-port mismatch where HTTPS traffic appears on a port not typically associated with HTTPS.

Command

bash
python3 -m http.server 8088 &
sleep 2
curl -sk http://127.0.0.1:8088/beacon --max-time 5
curl -sk http://127.0.0.1:8088/beacon --max-time 5
curl -sk http://127.0.0.1:8088/beacon --max-time 5

Cleanup

bash
kill $(lsof -t -i:8088) 2>/dev/null; true

Expected Telemetry

Sysmon/auditd network events: DestinationPort=8088, process=curl or python3. Linux netstat/ss shows ESTABLISHED connections on port 8088.

Expected Detection

SPL query captures connections to port 8088 from curl process. KQL DeviceNetworkEvents logs RemotePort=8088 from curl.exe equivalent.

Test 3 RDP Port Change via Registry (Windows)
windows

Simulates the Conti ransomware technique of changing the RDP service port from standard 3389 to a non-standard port (e.g., 33890) to maintain persistence even when perimeter rules block default RDP. Tests whether the registry hunting query fires.

Command

powershell
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v PortNumber /t REG_DWORD /d 33890 /f
Write-Host 'RDP port changed to 33890 - restart required to take effect'

Cleanup

powershell
reg add "HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp" /v PortNumber /t REG_DWORD /d 3389 /f

Expected Telemetry

Sysmon Event ID 13 (RegistryValueSet): TargetObject contains 'RDP-Tcp\PortNumber', Details=33890. DeviceRegistryEvents: RegistryKey contains 'RDP-Tcp', RegistryValueName=PortNumber, RegistryValueData=33890.

Expected Detection

Registry hunting query fires: NewPort=33890 != 3389, alerting on non-standard RDP port configuration change.

Test 4 Beaconing Simulation at Regular Intervals on Non-Standard Port
windows

Simulates C2 beaconing behavior with regular-interval outbound connections to a non-standard port (9001, commonly associated with Tor and various C2 frameworks), validating the beaconing detection hunting query.

Command

powershell
for ($i=0; $i -lt 10; $i++) { try { $tcp = New-Object System.Net.Sockets.TcpClient; $tcp.ConnectAsync('8.8.8.8', 9001).Wait(500) } catch {}; finally { $tcp.Close() }; Start-Sleep -Seconds 60 }

Cleanup

powershell
# No persistent changes — loop exits after 10 iterations (~10 minutes)

Expected Telemetry

Sysmon Event ID 3: 10 network connection events, DestinationPort=9001, Image=powershell.exe, at ~60-second intervals. DeviceNetworkEvents shows RegularInterval connections to port 9001.

Expected Detection

Beaconing hunting query detects StdDevInterval < 5 seconds for powershell.exe connecting to port 9001 with 10 connections — BeaconingLikelihood=High.

Related Detections