Playbooks

TA0043

Threat Hunting

What threat hunting is, how it differs from alert triage, the hypothesis-driven hunting loop that analysts follow, specific KQL/SPL hunting queries, and how to turn hunting findings into automated detections.

View on Graph

What Threat Hunting Is and How It Differs From Alert Triage

  • Threat hunting is the proactive, analyst-driven search for threats that have evaded existing security controls and detection rules.
  • Alert triage is reactive: an alert fires, an analyst investigates, the alert dictates the starting point.
  • Threat hunting is proactive - the hunter forms a hypothesis about what an adversary might be doing in the network and searches for supporting evidence across logs, endpoints, and network telemetry without any alert to guide them.
  • The hunting loop: Hypothesis → Research → Query → Analyze → Document → Automate

The Hunting Loop

Step 1: Form a Hypothesis

A hypothesis should be specific, testable, and based on real threat intelligence or observed gaps.

Good HypothesesBad Hypotheses
”Attackers might be using PowerShell encoded commands to bypass AppLocker""Let me check if we are compromised"
"Ransomware groups targeting our sector use Cobalt Strike over HTTPS to port 443""Let me look at all the logs"
"We have no detection for service binary hijacking - let me search for services pointing to user-writable paths""I’m going to find the bad stuff”

Step 2: Gather Data

For each hypothesis, identify the data sources needed:

HypothesisData Sources NeededKey Events
PowerShell encoded commandsWindows Event 4103/4104 (PowerShell), Sysmon Event 1-EncodedCommand, -ExecutionPolicy Bypass, $env:APPDATA
Cobalt Strike beaconingNetwork logs (proxy, firewall), DNS logs, Sysmon Event 22HTTPS to unknown IPs, JA3 signature patterns, DNS queries at regular intervals — correlate with KQL hunting queries
Service binary hijackingSysmon Event 1, Windows Event 4697/7045Service binary from %TEMP%, %APPDATA%, user-writable paths
LSASS credential dumpingSysmon Event 10 (Process Access), Event 4663Non-LSASS process with PROCESS_ALL_ACCESS to lsass.exe

Step 3: Execute the Hunt

Now run specific queries. Below are production-ready hunting queries for common hypotheses.


Hunting Hypothesis 1: PowerShell Encoded Command Execution

Hypothesis: Attackers are using PowerShell with -EncodedCommand to execute payloads without writing files to disk.

SPL query:

index=windows sourcetype=WinEventLog:Sysmon EventCode=1
| search Image="*powershell.exe" CommandLine="*-EncodedCommand*"
| eval decoded_cmd_len = len(split(CommandLine, "-EncodedCommand")[1])
| where decoded_cmd_len > 50
| stats count, values(Computer) as Systems, values(User) as Users by CommandLine, ParentImage
| eval alert = "POWERSHELL ENCODED COMMAND - base64 payload of " . decoded_cmd_len . " chars from " . mvjoin(Users, ", ") . " on " . mvjoin(Systems, ", ")
| table _time, Systems, Users, CommandLine, ParentImage, decoded_cmd_len, alert
| sort - count

SPL query - hunt for PowerShell downloading payloads:

index=windows sourcetype=WinEventLog:Sysmon EventCode=3
| search Image="*powershell.exe" DestinationPort IN (80, 443)
| stats count by Image, CommandLine, DestinationIp, DestinationPort
| eval alert = "PowerShell making outbound connections - possible download cradle"
| table _time, Image, CommandLine, DestinationIp, DestinationPort, count, alert

KQL query - PowerShell hunting:

DeviceProcessEvents
| where FileName startswith "powershell"
| where ProcessCommandLine contains "-EncodedCommand" or ProcessCommandLine contains "IEX" or ProcessCommandLine contains "DownloadString"
| where ProcessCommandLine contains "http"
| project Timestamp, DeviceName, AccountName, ProcessCommandLine

Hunting Hypothesis 2: Lateral Movement via WMI or PSExec

Hypothesis: Attackers are moving laterally using WMI (wmic.exe, Invoke-WmiMethod) or PSExec (psexec.exe), which does not write files to disk on the target.

SPL query - WMI process creation from remote:

index=windows sourcetype=WinEventLog:Sysmon EventCode=1
| search Image="*wmiprvse.exe"
| stats count, values(CommandLine) as Commands, values(ParentImage) as Parents by Computer
| where count > 1 AND mvcount(Commands) > 1
| eval alert = "LATERAL MOVEMENT - WMI process creation (wmiPrvSE.exe) spawning shell commands from " . Computer
| table _time, Computer, Commands, Parents, count, alert

SPL query - detect PSExec service installation:

index=windows sourcetype=WinEventLog:Security EventCode=4697
| search ServiceName="*PSEXESVC*"
| eval alert = "LATERAL MOVEMENT - PSExec service installed - remote command execution"
| table _time, Computer, SubjectUserName, ServiceName, ServiceFileName, alert

Hunting Hypothesis 3: Unusual Scheduled Task Patterns

Hypothesis: Attackers are creating scheduled tasks for persistence or lateral movement.

SPL query - scheduled task creation from non-admin tools:

index=windows sourcetype=WinEventLog:Security EventCode=4698
| search SubjectUserName!="*$" AND TaskContent="*cmd*" OR TaskContent="*powershell*" OR TaskContent="*wscript*"
| stats count by Computer, SubjectUserName, TaskName, TaskContent
| eval alert = "Scheduled task with shell command created by " . SubjectUserName . " on " . Computer
| table _time, Computer, SubjectUserName, TaskName, TaskContent, alert

SPL query - high-frequency scheduled tasks (potential C2 beacon disguised as task):

index=windows sourcetype=WinEventLog:Security EventCode=106 (Task Trigger Registered)
| search TaskName="*\\*" TaskTrigger="*Repetition*"
| eval alert = "Repetitive scheduled task - possible persistence mechanism"
| table _time, Computer, TaskName, TaskTrigger, alert

Hunting Hypothesis 4: Unusual Service Binary Paths

Hypothesis: Attackers have installed services pointing to user-writable directories for persistence or privilege escalation.

SPL query - hunt for services from user-writable paths:

index=windows sourcetype=WinEventLog:Security EventCode=4697
| search ServiceFileName="*\\Users\\*" OR ServiceFileName="*\\Temp\\*" OR ServiceFileName="*\\AppData\\*" OR ServiceFileName="*\\Desktop\\*"
| eval alert = "SERVICE HIJACK - service binary in user-writable path: " . ServiceFileName
| table _time, Computer, SubjectUserName, ServiceName, ServiceFileName, alert

Hunting Hypothesis 5: DNS Tunneling Indicators

Hypothesis: Data is being exfiltrated via DNS tunneling (TX T record queries with long subdomains).

SPL query - hunt for DNS tunneling:

index=dns sourcetype=dns_logs
| eval subdomain_len = len(split(query, ".")[0])
| where subdomain_len > 30
| stats count, values(query_type) as QueryTypes by src_ip, query
| where mvcount(QueryTypes) > 2 OR count > 50
| eval alert = "DNS TUNNELING - host " . src_ip . " made " . count . " queries with subdomains > 30 chars"
| table _time, src_ip, query, QueryTypes, count, alert
| sort - count

Hunting Hypothesis 6: Unusual Outbound Traffic Patterns

Hypothesis: Compromised hosts are beaconing to C2 infrastructure with consistent intervals and payload sizes.

SPL query - hunt for beaconing patterns:

index=proxy sourcetype=access_combined
| search dest_port=443
| stats earliest(_time) as first_seen, latest(_time) as last_seen, count by src_ip, dest_ip
| eval duration = last_seen - first_seen
| eval connections_per_hour = if(duration > 0, (count / (duration / 3600)), 0)
| where connections_per_hour > 10 AND connections_per_hour < 100  (beaconing: 10+ per hour but not constant streaming)
| eval alert = "BEACONING - host " . src_ip . " made " . count . " connections to " . dest_ip . " in " . tostring(duration/3600, "0.0") . " hours (" . tostring(connections_per_hour, "0.0") . "/hour)"
| table _time, src_ip, dest_ip, count, connections_per_hour, alert

Hunting Hypothesis 7: Unusual Logon Patterns

Hypothesis: An attacker is using compromised credentials to log in at unusual times or from unusual workstations.

SPL query - hunt for after-hours logins:

index=windows sourcetype=WinEventLog:Security EventCode=4624 LogonType=2
| eval login_hour = strftime(_time, "%H")
| where login_hour < 6 OR login_hour > 18 (after 6 PM or before 6 AM)
| stats count by AccountName, Computer, login_hour
| where count > 3
| eval alert = "After-hours logon by " . AccountName . " - " . count . " logins between hour " . login_hour
| table _time, AccountName, Computer, login_hour, count, alert

SPL query - hunt for workstation-to-workstation logins (lateral movement):

index=windows sourcetype=WinEventLog:Security EventCode=4624 LogonType=3
| search WorkstationName=Computer (same machine)
| stats count by AccountName, Computer, WorkstationName, SourceNetworkAddress
| where count > 1 AND SourceNetworkAddress != "-" AND SourceNetworkAddress != Computer
| eval alert = "LATERAL MOVEMENT - " . AccountName . " logged into " . Computer . " from " . SourceNetworkAddress
| table _time, AccountName, Computer, SourceNetworkAddress, count, alert

Automating Hunting Findings

When you find a pattern during hunting, the final step is turning it into an automated detection:

Hunting FindingMissing DetectionNew Rule Type
Found PowerShell encoded commands executing from Office macrosNo rule for PowerShell from winword.exe or excel.exe parentSysmon rule: Parent=Office + Child=powershell.exe + CommandLine=-EncodedCommand
Found scheduled tasks created by standard usersNo alert on Task Creation Event 4698 from non-admin usersSIEM correlation: Event 4698 with user not in Admin group
Found service binary hijack on three serversNo baseline for expected service binariesSIEM correlation: Event 4697 with ServiceFile in user-writable path
Found DNS queries to .xyz TLD from development machinesNo block/alert for anomalous TLD queriesDNS sinkhole + SIEM alert for .xyz TLD from non-browser processes

Sources