Help Ukraine, click for information

> Practical Threat Hunting: Finding Attackers Who Are Already Inside_

Threat hunting is the practice of proactively searching your environment for signs of compromise that automated detections missed. The assumption: you're already breached; you just don't know it yet.

The average dwell time before detection is around 200 days. Those 200 days are spent in your environment — hunting is how you reduce that number.


## The mindset shift

Reactive security waits for alerts. Threat hunting inverts this:

  • >Start with a hypothesis ("Are attackers using living-off-the-land binaries for persistence?")
  • >Query your data to confirm or deny the hypothesis
  • >Either find nothing (good, update your baselines) or find something (incident response)

The output of every hunt that finds nothing is still valuable: better baselines and detection logic.


## Data sources: what you need

A hunt is only as good as the data it can search.

Data SourceWhat it provides
Windows Event LogsProcess creation (4688), logon (4624/4625), service install (7045), scheduled tasks (4698)
SysmonEnhanced process creation with cmdline, network connections, file creation, registry changes
EDR telemetryProcess tree, memory regions, API calls — much richer than Event Logs
Network logsNetFlow, DNS queries, proxy logs — see what machines talk to
Authentication logsAD domain controller events, VPN logs, cloud identity
Cloud audit logsAWS CloudTrail, Azure Activity Log, GCP Audit Logs

Without Sysmon installed, install it now:

terminal
<!-- Sysmon config for threat hunting --> <Sysmon schemaversion="4.70"> <EventFiltering> <RuleGroup name="Processes" groupRelation="or"> <ProcessCreate onmatch="include"> <Image condition="end with">powershell.exe</Image> <Image condition="end with">cmd.exe</Image> <Image condition="end with">wscript.exe</Image> <Image condition="end with">cscript.exe</Image> <Image condition="end with">regsvr32.exe</Image> <Image condition="end with">mshta.exe</Image> <Image condition="end with">certutil.exe</Image> </ProcessCreate> </RuleGroup> </EventFiltering> </Sysmon>

## Hypothesis 1: Living-Off-The-Land (LOLBins) abuse

Why: Attackers avoid custom malware by using legitimate Windows binaries (certutil, mshta, regsvr32, wscript) for execution. These often bypass AV.

KQL (for Sentinel/Defender):

terminal
// Find certutil used for downloads (common malware dropper technique) DeviceProcessEvents | where FileName =~ "certutil.exe" | where ProcessCommandLine has_any ("-urlcache", "-decode", "-encode", "-split") | project Timestamp, DeviceName, InitiatingProcessFileName, ProcessCommandLine | order by Timestamp desc

Sigma rule:

terminal
title: Suspicious CertUtil Usage id: e011a729-98a3-4a2d-95a8-e987e1369c00 status: stable logsource: category: process_creation product: windows detection: selection: Image|endswith: '\certutil.exe' CommandLine|contains: - '-urlcache' - '-decode' - '-split' - 'http' condition: selection falsepositives: - Legitimate certificate operations by administrators level: high tags: - attack.defense_evasion - attack.t1140

What to look for:

terminal
// PowerShell with encoded commands (common evasion) DeviceProcessEvents | where FileName =~ "powershell.exe" | where ProcessCommandLine has_any ("-enc", "-EncodedCommand", "-ec") | extend DecodedCmd = base64_decode_tostring(extract(@"-[Ee][Nn][Cc][Oo][Dd][Ee][Dd]?[Cc][Oo][Mm][Mm][Aa][Nn][Dd]?\s+([A-Za-z0-9+/=]+)", 1, ProcessCommandLine)) | project Timestamp, DeviceName, ProcessCommandLine, DecodedCmd // MSHTA executing remote content DeviceProcessEvents | where FileName =~ "mshta.exe" | where ProcessCommandLine has_any ("http://", "https://", "vbscript:", "javascript:")

## Hypothesis 2: Scheduled task and service persistence

Why: Scheduled tasks are the most common persistence mechanism after malware gets execution. Most legitimate tasks are created at software install time, not at 3am.

terminal
// New scheduled tasks - look for recent creation from unusual parents DeviceEvents | where ActionType == "ScheduledTaskCreated" | extend TaskInfo = parse_json(AdditionalFields) | project Timestamp, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, TaskName = tostring(TaskInfo.TaskName), TaskContent = tostring(TaskInfo.TaskContent) | where not(InitiatingProcessFileName has_any ("svchost.exe", "taskschd.exe", "mmc.exe")) // Services created outside business hours or from cmd/powershell Event | where Source == "Service Control Manager" | where EventID == 7045 | where TimeGenerated between (ago(7d) .. now()) | extend ServiceName = tostring(EventData[0]), ServiceFile = tostring(EventData[3]) | where ServiceFile has_any ("temp", "appdata", "public", "users")

## Hypothesis 3: Lateral movement via SMB / WMI / PsExec

Why: After initial access, attackers move to other machines using stolen credentials. PsExec leaves service artifacts; WMI doesn't — so look for both.

terminal
// PsExec detection: service named "PSEXESVC" or similar Event | where Source == "Service Control Manager" and EventID == 7045 | where RenderedDescription has "PSEXESVC" | project TimeGenerated, Computer, RenderedDescription // WMI lateral movement: wmiprvse.exe spawning unusual children DeviceProcessEvents | where InitiatingProcessFileName =~ "WmiPrvSE.exe" | where FileName has_any ("cmd.exe", "powershell.exe", "net.exe", "whoami.exe") | project Timestamp, DeviceName, FileName, ProcessCommandLine, InitiatingProcessCommandLine // Authentication from unexpected sources (detect stolen cred use) SecurityEvent | where EventID == 4624 | where LogonType == 3 // Network logon | where AuthenticationPackageName == "NTLM" // NTLM when Kerberos expected | where not(SubjectUserName == "ANONYMOUS LOGON") | summarize LogonCount = count() by IpAddress, TargetUserName, Computer | where LogonCount > 10 | order by LogonCount desc

## Hypothesis 4: Credential access

Why: LSASS dumps, Kerberoasting, and DCSync are core attacker techniques. They all generate specific Event IDs.

terminal
// LSASS memory reads (Mimikatz signature) DeviceEvents | where ActionType == "OpenProcessApiCall" | where FileName =~ "lsass.exe" | where not(InitiatingProcessFileName has_any ("MsMpEng.exe", "svchost.exe", "csrss.exe", "werfault.exe")) | project Timestamp, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine // DCSync: replication rights used from non-DC source SecurityEvent | where EventID == 4662 | where Properties has "1131f6aa-9c07-11d1-f79f-00c04fc2dcd2" // DS-Replication-Get-Changes or Properties has "1131f6ad-9c07-11d1-f79f-00c04fc2dcd2" // DS-Replication-Get-Changes-All | where SubjectUserName !endswith "$" // Not a computer account (DCs authenticate as COMPUTER$) | project TimeGenerated, Computer, SubjectUserName, SubjectDomainName, ObjectName // Kerberoasting: large volume of TGS requests with RC4 SecurityEvent | where EventID == 4769 | where TicketEncryptionType == "0x17" // RC4 | where ServiceName !endswith "$" // Not a computer account | summarize RequestCount = count() by IpAddress, AccountName | where RequestCount > 5

## Hypothesis 5: Data exfiltration

Why: Before leaving or deploying ransomware, attackers compress and exfiltrate data.

terminal
// Large data transfers to external IPs DeviceNetworkEvents | where RemoteIPType == "Public" | where Protocol == "Tcp" | summarize TotalBytesSent = sum(SentBytes) by DeviceName, RemoteIP, RemotePort | where TotalBytesSent > 500000000 // 500MB | order by TotalBytesSent desc // Archive tools running from unusual locations DeviceProcessEvents | where FileName has_any ("7z.exe", "rar.exe", "zip.exe", "tar.exe", "compress.exe") | where FolderPath !has_any ("Program Files", "Windows") | project Timestamp, DeviceName, FolderPath, ProcessCommandLine // Cloud sync tools (rclone is commonly used by ransomware groups) DeviceProcessEvents | where FileName =~ "rclone.exe" or ProcessCommandLine has "rclone" | project Timestamp, DeviceName, ProcessCommandLine

## Hypothesis 6: DNS-based C2

Why: Many C2 frameworks use DNS to beacon home — it's allowed through almost every firewall and less monitored than HTTP.

terminal
// High-frequency DNS queries to same domain (beaconing) DnsEvents | where TimeGenerated > ago(24h) | summarize QueryCount = count() by DeviceName, Computer, Name | where QueryCount > 100 | join kind=leftouter ( DnsEvents | summarize RequestPerHour = count() by Name, bin(TimeGenerated, 1h) ) on Name | where Name !has_any ("windows.com", "microsoft.com", "google.com") | order by QueryCount desc // Long subdomain names (DNS tunneling) DnsEvents | extend SubLen = strlen(Name) | where SubLen > 50 | where Name !has_any ("amazonaws.com", "cloudfront.net", "akamai") | project TimeGenerated, DeviceName, Name, SubLen

## Building a hunt playbook

Each hunt should be documented for repeatability:

terminal
## Hunt: LOLBin Abuse via CertUtil **Hypothesis:** Attackers are using certutil.exe to download payloads from the internet **MITRE:** T1140 (Deobfuscate/Decode Files), T1105 (Ingress Tool Transfer) **Data required:** Windows process creation logs (Event 4688 with cmdline, or Sysmon Event 1) **Query:** [paste KQL/SPL/Sigma rule] **What's normal:** sysadmins using certutil for certificate management **What's suspicious:** -urlcache -split with HTTP URLs, downloading to Temp/AppData **Time to run:** 15 minutes **Last run:** 2025-11-30 **Result:** No findings — baseline updated

## Tools

ToolUse
ChainsawFast Windows Event Log analysis for incident response
HayabusaSigma rule-based threat hunting over Windows logs
VelociraptorDFIR and hunting at scale — agent-based collection
OSQuerySQL-like queries against live system state
CrowdStrike Falcon / Microsoft DefenderEDR with built-in hunting UI
MITRE ATT&CK NavigatorLayer coverage and planning
terminal
# Chainsaw: hunt for common attack patterns in EVTX files offline chainsaw hunt /path/to/evtx/ -s /sigma/rules/ --mapping /chainsaw/mappings/sigma-event-logs.yml

Threat hunting is a perishable skill — your value is knowing what normal looks like so anomalies stand out. Spend time in your environment's data on quiet days, not just incident days. The attacker who's been in for 90 days leaves subtle traces that only someone who knows the baseline will notice.

root@sovietghost:/blog/044-threat-hunting# ls -la ../

> Thanks for visiting. Stay curious and stay secure. _