Lesson 161 — The Hunt Started With a Behaviour, Not an IOC
Module 14 changes the question. Until now, many investigations began because something had already happened: an alert fired, a user behaved strangely or telemetry exposed a suspicious event. Proactive threat hunting starts earlier.
There may be no malicious IP address, no known hash and no domain on a blocklist. Instead, the analyst begins with a behaviour that should be uncommon — for example, a browser or Office application launching PowerShell — and asks whether that behaviour exists anywhere in the environment.

Your hunting hypothesis
An attacker may use a trusted user-facing application to launch PowerShell and execute follow-on activity. You do not have a hash, IP address or domain. You have a behaviour to hunt.
Hunt briefing
Hunting objective
Use Microsoft Defender endpoint telemetry and KQL to turn a behavioural hypothesis into a structured hunt, establish what normal PowerShell execution looks like, isolate unusual parent-child relationships and combine multiple behavioural signals to produce high-value investigation candidates.
Hunter's rule
Do not start by trying to prove your hypothesis. Start by testing it. A good hunt can end with “this behaviour is normal here” and still improve your understanding of the environment.
Stage 1 — begin broad enough to understand the behaviour
Start with PowerShell executions across the environment. Preserve the initiating process and command line so you can see how PowerShell is normally launched.
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| project Timestamp,
DeviceName,
AccountName,
FileName,
ProcessCommandLine,
InitiatingProcessFileName,
InitiatingProcessCommandLine
| order by Timestamp descDo not filter too aggressively yet
If the first query contains every suspicious keyword you already expect, you risk building a hunt that can only find the attack you imagined. Begin broad enough to learn from the telemetry.
Parent-child relationships matter
powershell.exe is not automatically suspicious. The process that launched it and the command it received can make the same executable either routine administration or a high-value lead.
Stage 2 — establish the environmental baseline
Measure which processes normally launch PowerShell and how widely those relationships occur. This gives the hunt environmental context before you label anything abnormal.
DeviceProcessEvents
| where Timestamp > ago(30d)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| summarize Executions=count(),
Devices=dcount(DeviceName),
Users=dcount(AccountName)
by InitiatingProcessFileName
| order by Executions descCommon is not automatically safe
An attacker can abuse common administrative behaviour. Baseline helps prioritise rarity and deviation; it does not create an allow list of trusted activity.
Rare is not automatically malicious
A legitimate software deployment, support script or administrator may create a parent-child relationship seen only once. Rarity creates a question, not a verdict.
Stage 3 — test the behavioural hypothesis
Now narrow the hunt to user-facing and script-host processes launching PowerShell. These relationships deserve attention because they can appear in phishing, drive-by execution and script-based attack chains.
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| where InitiatingProcessFileName in~ (
"winword.exe", "excel.exe", "outlook.exe",
"chrome.exe", "msedge.exe", "firefox.exe",
"wscript.exe", "cscript.exe", "mshta.exe"
)
| project Timestamp,
DeviceName,
AccountName,
InitiatingProcessFileName,
FileName,
ProcessCommandLine,
SHA1
| order by Timestamp descThe behaviour is the pivot
Notice that the query does not depend on a known malicious IP or hash. If the attacker changes infrastructure tomorrow, the behavioural relationship may still be visible.
Preserve the hash anyway
Behaviour-led hunting does not mean ignoring IOCs. Once a suspicious process is found, hashes, IP addresses, URLs and domains become valuable pivots for scoping the incident.
Stage 4 — find first-seen relationships
Compare recent parent-child relationships with historical telemetry. A process relationship appearing on a device for the first time can be a useful hunting signal.
let Lookback = 30d;
let Recent = 24h;
let Baseline =
DeviceProcessEvents
| where Timestamp between (ago(Lookback) .. ago(Recent))
| where FileName in~ ("powershell.exe", "pwsh.exe")
| summarize HistoricalCount=count()
by DeviceName, InitiatingProcessFileName;
let Current =
DeviceProcessEvents
| where Timestamp > ago(Recent)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| summarize CurrentCount=count(),
Commands=make_set(ProcessCommandLine, 20)
by DeviceName, InitiatingProcessFileName;
Current
| join kind=leftouter Baseline
on DeviceName, InitiatingProcessFileName
| extend HistoricalCount=coalesce(HistoricalCount, 0)
| where HistoricalCount == 0
| order by CurrentCount descFirst seen needs sufficient history
A relationship may look new because the device was recently onboarded, telemetry was unavailable or retention is limited. Always understand the observation window behind “first seen”.
Environment-wide and device-specific rarity differ
A relationship may be common across the enterprise but completely new for one workstation. Both perspectives can reveal useful anomalies.
Stage 5 — combine weak signals into stronger candidates
One behavioural signal may generate too much noise. Combine suspicious parent processes with encoded commands, download behaviour and hidden execution to rank the events that deserve investigation first.
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| extend SuspiciousParent =
InitiatingProcessFileName in~ (
"winword.exe", "excel.exe", "outlook.exe",
"chrome.exe", "msedge.exe", "firefox.exe",
"wscript.exe", "cscript.exe", "mshta.exe"
)
| extend EncodedCommand =
ProcessCommandLine has_any ("-enc", "-encodedcommand")
| extend DownloadBehaviour =
ProcessCommandLine has_any (
"Invoke-WebRequest", "iwr ",
"DownloadString", "WebClient",
"Start-BitsTransfer"
)
| extend HiddenExecution =
ProcessCommandLine has_any (
"-w hidden", "-windowstyle hidden",
"-nop", "-noprofile"
)
| extend BehaviourScore =
toint(SuspiciousParent) +
toint(EncodedCommand) +
toint(DownloadBehaviour) +
toint(HiddenExecution)
| where BehaviourScore >= 2
| project Timestamp,
DeviceName,
AccountName,
BehaviourScore,
InitiatingProcessFileName,
ProcessCommandLine,
SHA1
| order by BehaviourScore desc, Timestamp descA score is prioritisation, not proof
The behavioural score helps order results. It is not a mathematical probability that an event is malicious and should never replace analyst validation.
Good hunts create new questions
A high-value result should trigger pivots into network, file, user and device telemetry. Threat hunting is an iterative investigation process, not a single query.
Agent Foskett's behaviour-led hunt
IOC hunting versus behaviour hunting
| Approach | Strength | Limitation |
|---|---|---|
| Known malicious hash | Precise and fast to search. | Fails when the payload changes. |
| Known malicious IP or domain | Excellent for scoping known infrastructure. | Infrastructure can be rotated quickly. |
| Behavioural relationship | Can survive changes to infrastructure and payload. | Often requires baseline and analyst interpretation. |
| Multiple behavioural signals | Can reduce noise and expose attack patterns. | Must be tested to avoid overfitting. |
| Behaviour + IOC correlation | Combines resilient hunting with precise pivots. | Still requires validation and context. |
Write the hunt finding like an analyst
Example: A proactive behavioural hunt was conducted across Microsoft Defender endpoint process telemetry to identify unusual PowerShell execution without relying on a known malicious indicator. PowerShell parent-process relationships were baselined across the environment before focusing on execution initiated by browsers, Office applications and script hosts. Candidate events were further prioritised using first-seen relationships and supporting command-line behaviours including encoded commands, download functionality and hidden execution. The resulting events represent investigation candidates rather than confirmed compromise. Each candidate should be validated against expected administrative and application behaviour and correlated with file, network, user and device telemetry before escalation.
Lesson 161 key takeaways
- Proactive hunting can begin with a behaviour rather than a known IOC.
- Write a hunting hypothesis that can be tested rather than a conclusion you intend to prove.
- Start broad enough to understand how the behaviour normally appears.
- Baseline parent-child process relationships before labelling them unusual.
- Common behaviour is not automatically benign and rare behaviour is not automatically malicious.
- Behavioural hunts can remain useful when attackers change hashes or infrastructure.
- First-seen relationships can provide valuable anomaly context.
- Observation windows and telemetry coverage affect rarity conclusions.
- Combine multiple weak signals to prioritise investigation candidates.
- A hunting score ranks evidence; it does not prove compromise.
Module 14 has begun
Lesson 161 introduced the behaviour-led hunting mindset. Next we take a useful behavioural query and discover that the same technique appears on multiple devices — forcing us to move from a single hunting result into environment-wide scoping.
Continue your KQL investigation training
🔎 KQL Academy — Module 14: Advanced Detection Engineering & Proactive Threat Hunting
Learn behaviour-led threat hunting with KQL
Lesson 161 of the Agent Foskett KQL Academy begins Module 14 by showing how to hunt proactively across Microsoft Defender endpoint telemetry without relying on a known malicious hash, IP address or domain.
Build proactive KQL hunts from attacker behaviour
Learn how to define a hunting hypothesis, baseline PowerShell execution, identify unusual process relationships, find first-seen behaviour and combine multiple weak signals into high-value investigation candidates.
