Lesson 162 — One Query Found the Same Technique on Twelve Devices
Lesson 161 began with behaviour instead of a known indicator. The hunt found an unusual parent-child relationship: user-facing applications launching PowerShell. Then the analyst widened the query.
The result changed the investigation. The same technique appeared on twelve devices. That could mean a widespread attack — or it could be a legitimate management tool, deployment package or business application behaving exactly as designed. The next job is scoping.

Your hunting result
The same suspicious PowerShell technique appears on twelve endpoints. Determine whether the devices share the same command, user, parent process and timing — or whether the similarity disappears when you inspect the evidence.
Hunt briefing
Hunting objective
Use KQL to scope a behavioural hunting result across endpoints, determine how many devices and users are involved, identify repeated command lines and process ancestry, compare supporting behavioural signals and produce a device-level scope register for further investigation.
Hunter's rule
Scope before severity. Do not call twelve devices “twelve compromised devices” until the behaviour on those devices has actually been validated.
Stage 1 — count the devices that match the behaviour
Start by summarising the hunt result by device and parent process. This tells you whether the original technique is isolated or distributed and establishes first-seen and last-seen times for each endpoint.
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"
)
| summarize Executions=count(),
FirstSeen=min(Timestamp),
LastSeen=max(Timestamp),
Users=make_set(AccountName, 20)
by DeviceName,
InitiatingProcessFileName,
FileName
| order by Executions descDevice count changes the investigation
One endpoint invites deep inspection. Twelve endpoints require both deep inspection and environment-wide scoping so you understand whether you are looking at propagation, repeated delivery or legitimate enterprise activity.
Do not lose the users
If the same account appears across many devices, that may tell a different story from twelve unrelated users each triggering the same software package.
Stage 2 — find identical commands across multiple devices
Group by the initiating process and full PowerShell command line. Identical commands appearing across many endpoints can reveal a common deployment mechanism, script, attacker technique or shared artefact.
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"
)
| summarize Devices=dcount(DeviceName),
DeviceList=make_set(DeviceName, 100),
Users=dcount(AccountName),
FirstSeen=min(Timestamp),
LastSeen=max(Timestamp)
by InitiatingProcessFileName,
ProcessCommandLine
| order by Devices descIdentical can suggest coordination
A highly specific command repeated across devices is more informative than a generic powershell.exe launch. Preserve the complete command before normalising or shortening it.
But legitimate tooling repeats too
Software distribution systems are designed to execute the same command across many machines. Repetition is therefore evidence of commonality, not evidence of maliciousness.
Stage 3 — pivot from the repeated command back to raw events
Once a command appears on multiple devices, return to the underlying process events. This preserves individual timestamps, users, parent processes and hashes so the shared pattern can be tested rather than assumed.
let SuspiciousCommands =
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"
)
| summarize DeviceCount=dcount(DeviceName)
by ProcessCommandLine
| where DeviceCount >= 2;
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| join kind=inner SuspiciousCommands on ProcessCommandLine
| project Timestamp,
DeviceName,
AccountName,
InitiatingProcessFileName,
ProcessCommandLine,
DeviceCount,
SHA1
| order by ProcessCommandLine asc, Timestamp ascAggregation discovers; raw evidence explains
Summaries are excellent for finding patterns, but an incident conclusion should be supported by the underlying events. Always retain a path back from the aggregate to the source telemetry.
Look for divergence
If eleven devices have the same parent and user context but the twelfth is different, that outlier may be the most important result in the hunt.
Stage 4 — compare supporting behavioural signals
Measure how often the repeated activity also contains encoded commands or download behaviour. Supporting signals help distinguish a generic enterprise script from a more suspicious execution pattern.
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"
)
| extend EncodedCommand =
ProcessCommandLine has_any ("-enc", "-encodedcommand")
| extend DownloadBehaviour =
ProcessCommandLine has_any (
"Invoke-WebRequest", "iwr ",
"DownloadString", "WebClient",
"Start-BitsTransfer"
)
| summarize Executions=count(),
Devices=dcount(DeviceName),
Users=dcount(AccountName),
DeviceList=make_set(DeviceName, 50),
UserList=make_set(AccountName, 50),
EncodedExecutions=countif(EncodedCommand),
DownloadExecutions=countif(DownloadBehaviour)
by InitiatingProcessFileName,
ProcessCommandLine
| order by Devices desc, Executions descMultiple weak signals can become useful together
A browser launching PowerShell may be unusual. A browser launching encoded PowerShell that downloads content across multiple endpoints is a much stronger investigation candidate.
Still test the business explanation
Before escalation, check whether security tooling, endpoint management, software deployment or support processes can account for the pattern. Hunting works best when technical evidence is combined with environmental knowledge.
Stage 5 — build the device scope register
Finish by creating a concise record for every affected device. This gives the investigation team a reproducible list of endpoints, users, commands, parents, hashes and observation times.
let HuntResults =
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,
DeviceId,
DeviceName,
AccountName,
InitiatingProcessFileName,
ProcessCommandLine,
SHA1;
HuntResults
| summarize Executions=count(),
FirstSeen=min(Timestamp),
LastSeen=max(Timestamp),
Users=make_set(AccountName, 20),
Parents=make_set(InitiatingProcessFileName, 20),
Commands=make_set(ProcessCommandLine, 20),
Hashes=make_set(SHA1, 20)
by DeviceId, DeviceName
| order by FirstSeen ascScope registers support response
If the behaviour is later confirmed malicious, the device register immediately becomes useful for containment, forensic prioritisation and checking whether remediation covered the full observed scope.
Scope is allowed to change
A hunt may begin with twelve devices and later expand to twenty or contract to two genuinely suspicious endpoints. Record how the scope was derived and update it as evidence improves.
Agent Foskett's environment-wide scope
How to interpret environment-wide repetition
| Pattern | Possible explanation | Next question |
|---|---|---|
| Same command, same time, many devices | Central deployment or coordinated activity. | What system or actor initiated it? |
| Same command, scattered times | Recurring automation, user action or repeated attack technique. | What triggers each execution? |
| Same user across many devices | Administrator, service account or compromised identity. | Is the account expected on those endpoints? |
| Different users, identical parent and command | Common application or deployment mechanism. | Is the software approved and expected? |
| One device diverges from the other eleven | Potential outlier hidden inside a legitimate pattern. | Why is its ancestry, command or source different? |
Write the hunt finding like an analyst
Example: A behaviour-led PowerShell hunt identified matching execution patterns across twelve endpoints. The activity was scoped by device, user, initiating process, command line, hash and first/last observation time. Repeated command lines were then pivoted back to their underlying process events and compared for encoded execution and download-related behaviour. The presence of the technique across twelve devices does not establish twelve compromises; legitimate enterprise tooling can produce repeated execution at scale. The affected-device register should be validated against approved software deployment, management and support activity. Endpoints whose command line, ancestry, user context or supporting signals diverge from the established pattern should receive priority for deeper investigation.
Lesson 162 key takeaways
- Environment-wide scoping should follow a high-value behavioural hunting result.
- Count devices and users before describing the scale of an incident.
- Compare full command lines and parent processes across affected endpoints.
- Identical activity can indicate coordinated attack behaviour or legitimate centralised tooling.
- Pivot aggregate patterns back to raw telemetry before drawing conclusions.
- Outliers inside a repeated pattern can be more valuable than the common pattern itself.
- Use supporting behavioural signals to prioritise suspicious executions.
- Validate repeated activity against software deployment, support and security tooling.
- Build a device scope register that can support investigation and response.
- The number of matching devices is a scope measurement, not a compromise count.
Module 14 — from hunting result to reusable detection
Lesson 162 showed how a single behaviour-led query can expand into an environment-wide investigation. Next, we take a useful hunting query and ask the detection-engineering question: can this logic become a reliable, repeatable detection?
Continue your KQL investigation training
🔎 KQL Academy — Module 14: Advanced Detection Engineering & Proactive Threat Hunting
Scope KQL threat hunting results across multiple devices
Lesson 162 of the Agent Foskett KQL Academy shows how to expand a behavioural hunting result across Microsoft Defender endpoint telemetry and determine how many devices and users share the same suspicious technique.
Investigate repeated PowerShell behaviour across endpoints
Learn how to compare command lines, parent processes, users, hashes and supporting behavioural signals, pivot aggregate results back to raw events and build an environment-wide device scope register.
