Microsoft Defender KQL Threat Hunting Guide
Nothing triggered an alert.
But the data already knew.
This guide brings together practical Microsoft Defender XDR hunting examples using KQL, EmailEvents, AuthenticationDetails, spoofed domain checks, UrlClickEvents and identity pivots.
It is designed for real-world investigation, not just theory.
At GEMXIT, we use KQL to move beyond alert chasing and into behaviour-based investigation across security operations, Microsoft Defender, identity and access, and broader Microsoft Security posture.
Guide summary
This page is a practical KQL threat hunting hub for Microsoft Defender XDR. It focuses on the exact investigation paths analysts use when something feels wrong but no obvious alert explains it.
Why this guide exists
How to read these KQL queries
Do not stop when a query returns results. Ask what the results mean, whether the behaviour matches the user, and what evidence should be checked next.
Start with failed email authentication
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
EmailEvents | where Timestamp > ago(30d) | where AuthenticationDetails has_any ("spf=fail", "dkim=fail", "dmarc=fail") | project Timestamp, SenderFromAddress, SenderFromDomain, SenderMailFromAddress, SenderMailFromDomain, RecipientEmailAddress, Subject, AuthenticationDetails, ThreatTypes, DeliveryAction | order by Timestamp desc
- Focus on AuthenticationDetails, especially SPF, DKIM or DMARC failures.
- Check whether DeliveryAction shows the message was delivered, blocked, junked or quarantined.
- Review the sender, recipient and subject together. One field rarely tells the full story.
π If authentication failed and the message was delivered, that is where the investigation should start.
Next step β Review DMARC failure hunting or deep dive into spoofing detection.
Hunt for spoofed domain signals
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
EmailEvents | where Timestamp > ago(30d) | where AuthenticationDetails has "spoof" or AuthenticationDetails has "dmarc=fail" | project Timestamp, SenderFromAddress, SenderFromDomain, SenderMailFromDomain, RecipientEmailAddress, Subject, AuthenticationDetails, DeliveryAction, NetworkMessageId | order by Timestamp desc
- The word spoof in AuthenticationDetails is useful, but context still matters.
- A blocked spoofed message is different from a delivered spoofed message.
- Multiple recipients or repeated subjects may indicate a campaign rather than a one-off message.
π Do not stop at the word spoof. Check who received it, whether it was delivered, and whether anyone clicked.
Continue investigation β Full spoofing case walkthrough.
Compare visible sender and envelope sender
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
EmailEvents | where Timestamp > ago(30d) | where SenderFromDomain != SenderMailFromDomain | project Timestamp, SenderFromAddress, SenderFromDomain, SenderMailFromAddress, SenderMailFromDomain, RecipientEmailAddress, Subject, AuthenticationDetails, DeliveryAction | order by Timestamp desc
- SenderFromDomain is what the user sees as the visible sender domain.
- SenderMailFromDomain helps show the underlying sending path.
- A mismatch may be normal for some third-party systems, but it should always be validated.
π The question is not βare these different?β The question is βdoes this difference make sense for this sender and this message?β
Find repeated spoofing or failed-authentication campaigns
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
EmailEvents | where Timestamp > ago(30d) | where AuthenticationDetails has_any ("spf=fail", "dkim=fail", "dmarc=fail", "spoof") | summarize MessageCount = count(), RecipientCount = dcount(RecipientEmailAddress) by SenderFromAddress, SenderFromDomain, Subject, DeliveryAction | where MessageCount >= 3 | order by MessageCount desc
- MessageCount shows how often the pattern appeared.
- RecipientCount helps identify whether the activity affected one user or many.
- Repeated subject lines can reveal phishing campaigns, payroll scams, fake document notifications or impersonation attempts.
π One suspicious email is a finding. Repeated suspicious emails across users can become an incident.
Pivot from suspicious email to user clicks
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
let SuspiciousMessages = EmailEvents | where Timestamp > ago(30d) | where AuthenticationDetails has_any ("spf=fail", "dkim=fail", "dmarc=fail", "spoof") | project NetworkMessageId, EmailTime = Timestamp, SenderFromAddress, RecipientEmailAddress, Subject; SuspiciousMessages | join kind=inner ( UrlClickEvents | where Timestamp > ago(30d) | project NetworkMessageId, ClickTime = Timestamp, AccountUpn, Url, ActionType ) on NetworkMessageId | order by ClickTime desc
- NetworkMessageId connects the suspicious email to URL click activity.
- ActionType helps show whether the click was allowed, blocked or scanned.
- The URL, user and click time are the starting point for identity and endpoint pivots.
π A suspicious email becomes more urgent when a user clicked the link.
Related scenario β The Missing Click.
Pivot from email click to sign-in activity
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
let ClickedUsers = UrlClickEvents | where Timestamp > ago(7d) | where ActionType has_any ("ClickAllowed", "UrlScanInProgress") | project AccountUpn, ClickTime = Timestamp, Url; ClickedUsers | join kind=inner ( IdentityLogonEvents | where Timestamp > ago(7d) | project AccountUpn, SignInTime = Timestamp, IPAddress, Location, Application, LogonType ) on AccountUpn | where SignInTime between ((ClickTime - 2h) .. (ClickTime + 6h)) | order by ClickTime desc
- Start with the clicked user, then look for sign-ins close to the click time.
- Review unfamiliar IP addresses, locations, applications and logon types.
- Watch for activity that looks technically valid but does not match the userβs normal pattern.
π This is where session hijacking, credential capture and suspicious post-click behaviour can start to appear.
Related investigation β MFA session hijacking.
Hunt for after-hours file activity
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
CloudAppEvents | where Timestamp > ago(14d) | where ActionType has_any ("FileDownloaded", "FileAccessed") | extend HourOfDay = datetime_part("hour", Timestamp) | where HourOfDay < 6 or HourOfDay > 20 | project Timestamp, AccountDisplayName, AccountId, IPAddress, Application, ActionType, ObjectName | order by Timestamp desc
- After-hours access is not automatically malicious, but it deserves context.
- Check whether the user normally accesses files at that time.
- Review the IP address, application, file name and sensitivity of the content accessed.
π A 2:14 AM file download may be harmless. It may also be the first visible sign of data leaving the environment.
Hunt for suspicious PowerShell behaviour
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
DeviceProcessEvents | where Timestamp > ago(14d) | where FileName in~ ("powershell.exe", "pwsh.exe") | where ProcessCommandLine has_any ( "-enc", "-encodedcommand", "iex", "downloadstring", "invoke-webrequest", "frombase64string", "hidden" ) | project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName | order by Timestamp desc
- Encoded commands, hidden execution and download strings are investigation signals.
- Review the initiating process to understand how PowerShell was launched.
- Pivot into device timeline, file events and network connections if the command line looks suspicious.
π PowerShell is not the problem. Suspicious PowerShell behaviour is the signal.
What good KQL threat hunting looks like
Continue your investigation
DMARC failure hunting
The Email Came From Me
EmailEvents investigation guide
The Session Token Never Expired
Impossible travel sign-ins
Identity and access security
When Nothing Looks Wrong
The PowerShell Never Triggered An Alert
The Alert Wasn't Understood
Microsoft Sentinel services
Security operations
GEMXIT Security Review
Related Agent Foskett investigations
Final thought
If you want help improving Microsoft Defender hunting, alert investigation and security visibility, π review Microsoft Defender services
Develop IT. Protect IT. GEMXIT PTY LTD | GEMXIT UK LTD