Perform Threat Hunting · Topic 1 of 4
Hunting with KQL in Defender XDR
SC-200 advanced hunting: choosing the right table, KQL operators, example queries for PowerShell, logons and joins, the 30 day limit and detections.
- 6 min
- DeviceProcessEvents holds process creation. DeviceNetworkEvents holds connections. DeviceLogonEvents holds sign ins. DeviceInfo holds device details.
- Use
summarize,join,where,project,extend,let,arg_max,dcountandago. hasmatches whole terms.=~ignores case.
What it is
Advanced hunting in the Microsoft Defender portal lets you search raw security data from endpoints, email, identities and cloud apps with Kusto Query Language (KQL). Instead of waiting for an alert, you form a hypothesis, such as "an attacker is running encoded PowerShell", and test it with a query.
Two skills decide how well you hunt: knowing which table holds the data you need, and writing KQL that filters, summarises and joins it.
How it works
Choosing the right table
Each table describes one kind of event. Picking the right one is half the work.
| Data you need | Table |
|---|---|
| Process creation, with command lines | DeviceProcessEvents |
| Network connections made by processes | DeviceNetworkEvents |
| File creation, modification and deletion | DeviceFileEvents |
| Registry changes, such as Run keys | DeviceRegistryEvents |
| Sign ins to devices | DeviceLogonEvents |
| Device inventory and OS details | DeviceInfo |
| Network adapters and addresses | DeviceNetworkInfo |
| Miscellaneous events, such as antivirus detections, USB mounts and process access | DeviceEvents |
| Loaded libraries | DeviceImageLoadEvents |
| File certificates | DeviceFileCertificateInfo |
| Email messages and their verdicts | EmailEvents |
| Email attachments and URLs | EmailAttachmentInfo, EmailUrlInfo |
| Users clicking links | UrlClickEvents |
| Email actions after delivery, such as ZAP | EmailPostDeliveryEvents |
| Authentications against Active Directory | IdentityLogonEvents |
| Directory changes and queries | IdentityDirectoryEvents, IdentityQueryEvents |
| Activity in cloud apps and Microsoft 365 | CloudAppEvents |
| Alerts and their evidence | AlertInfo, AlertEvidence |
Remember the distinctions that exam questions test: DeviceProcessEvents records process creation, DeviceNetworkEvents records outbound and inbound connections of processes, DeviceNetworkInfo describes adapters and configuration, DeviceLogonEvents covers sign ins, and DeviceInfo holds per device details such as the operating system. In DeviceEvents, the ActionType column tells you the kind of event, for example AntivirusDetection, UsbDriveMounted, ExploitGuardNetworkProtectionBlocked or OpenProcessApiCall.
Core KQL operators
A query starts with a table, then pipes results through operators.
| Operator | Purpose |
|---|---|
where | Keeps rows that match a condition |
project | Chooses columns to show |
extend | Adds a calculated column |
summarize | Aggregates, for example count(), dcount(), arg_max() |
join | Combines rows from two tables on a column |
union | Stacks the rows of several tables |
order by and top | Sort and limit results |
let | Names a value or a sub query for reuse |
ago() and bin() | Time filters and time buckets |
has, contains, startswith, in | Text matching, where has matches whole terms and is faster |
mv-expand and parse_json | Expand arrays and read JSON fields |
=~ is a case insensitive equals, and == is case sensitive.
Example queries
Find devices that launched PowerShell with an encoded command:
DeviceProcessEvents
| where Timestamp > ago(7d)
| where FileName =~ "powershell.exe" and ProcessCommandLine has_any ("-enc", "-encodedcommand")
| project Timestamp, DeviceName, AccountName, ProcessCommandLine
| order by Timestamp desc
Find devices with many failed logons:
DeviceLogonEvents
| where Timestamp > ago(1d) and ActionType == "LogonFailed"
| summarize Failures = count() by DeviceName, AccountName
| where Failures > 20
Find devices that saw more than 100 distinct file hashes in a day. Here dcount(SHA256) counts distinct hashes for each device and the final where keeps only the busy ones:
DeviceFileEvents
| where Timestamp > ago(1d)
| summarize FileCount = dcount(SHA256) by DeviceName
| where FileCount > 100
Find devices that ran a process and then wrote to a Run registry key within ten minutes, by joining two tables on DeviceId and filtering the time gap:
DeviceProcessEvents
| where FileName =~ "powershell.exe"
| join kind=inner (
DeviceRegistryEvents
| where RegistryKey has @"CurrentVersion\Run" and ActionType == "RegistryValueSet"
| project DeviceId, RegistryTime = Timestamp
) on DeviceId
| where datetime_diff("minute", RegistryTime, Timestamp) between (0 .. 10)
Keep the latest record per device with arg_max, which returns one row for each device with its most recent record:
DeviceInfo
| where Timestamp > ago(7d)
| summarize arg_max(Timestamp, OSPlatform, DeviceName) by DeviceId
| where OSPlatform == "Windows10"
Because the filter comes after arg_max, it applies to each device's latest record only.
Hunting for beaconing
Malware that calls home often does so at regular intervals. A hunt for beaconing measures the time between consecutive connections for each source and destination pair, and ranks by low variance in those gaps. Counting ports finds scans, byte totals find heavy transfers, and busiest hosts find popular services, so none of them reveal periodic calls.
Limits and good practice
- Advanced hunting keeps 30 days of data. For older activity use Purview Audit or, with Sentinel, the longer retention tiers.
- Results are limited, so filter early with a time range and
wherebefore heavy operators. - Use
projectto keep only the columns you need. - Test on a short time range, then widen.
- Save useful queries to the shared queries, so the team can reuse them.
From a query to a detection
When a hunting query reliably finds something bad, select Create detection rule. The query must return Timestamp, ReportId and entity columns. The rule then runs on a schedule and raises alerts, as covered in the custom detections page. A query that joins two tables cannot run as continuous (NRT) frequency.
Choosing the table in a scenario
| The hunt | Table |
|---|---|
| Which devices launched an encoded PowerShell command? | DeviceProcessEvents |
| Which processes made outbound connections to a rare address? | DeviceNetworkEvents |
| Which users clicked a malicious link? | UrlClickEvents |
| Which mail with attachments reached the CFO? | EmailEvents and EmailAttachmentInfo |
| What did a user do in SharePoint? | CloudAppEvents |
| Who authenticated to the domain controller? | IdentityLogonEvents |
A worked scenario
A threat report describes an attacker who uses encoded PowerShell and writes a Run key for persistence. A hunter starts in DeviceProcessEvents, filters for powershell.exe with an encoded argument, and finds three devices. She joins DeviceProcessEvents to DeviceRegistryEvents on DeviceId, filters for a Run key write within ten minutes, and keeps two devices. After isolating them, she saves the query and creates a detection rule that runs every hour, because the join rules out continuous frequency.
What to remember for the exam
- DeviceProcessEvents holds process creation. DeviceNetworkEvents holds connections. DeviceLogonEvents holds sign ins. DeviceInfo holds device details.
- Use
summarize,join,where,project,extend,let,arg_max,dcountandago. hasmatches whole terms.=~ignores case.- Advanced hunting keeps 30 days.
- A detection rule from a query needs Timestamp, ReportId and entity columns.
To read an unfamiliar query, go line by line: which table, which filter, how it is summarised, and what the final where keeps.
How the exam asks about this
- "Which table records process creation on onboarded devices?" DeviceProcessEvents.
- "Which table records outbound connections made by processes?" DeviceNetworkEvents.
- "What does
summarize dcount(SHA256) by DeviceNamefollowed bywhere FileCount > 100return?" Devices that saw more than 100 distinct file hashes. - "Which analysis surfaces beaconing?" Measure gaps between connections per source and destination, ranked by low variance.
Common mistakes
Confusing DeviceNetworkEvents with DeviceNetworkInfo. Events are connections, info is adapter configuration.
Using union to relate two events. It only stacks rows. Use join.
Searching past 30 days in advanced hunting. The data is gone.
Forgetting a time filter. Queries become slow and cut off.
Check yourself
Which table records logon activity on devices?
DeviceLogonEvents.
What does
arg_max(Timestamp, ...) by DeviceIdreturn?One row per device holding its most recent record.
Why would a hunt rank connection gaps by low variance?
Beaconing calls home at regular intervals, so low variance in the gaps points to it.
Topic 1 of 4 in Perform Threat Hunting
Test yourself on Perform Threat Hunting
The full Microsoft SC-200 question bank has 650 questions, with timed practice exams and an explanation for every answer.
This study guide is independent and is not affiliated with, endorsed by, or sponsored by Microsoft. Vendor names, certification names and exam codes are trademarks of their respective owners and are used for identification only.