Hunting Playbook: Persistence Mechanisms in Microsoft Defender XDR.
The password was reset. The malicious process was stopped. The obvious alert was closed.
But the attacker had already prepared a way back in.
A scheduled task. A service. A registry run key. A startup folder entry. A WMI subscription.
Agent Foskett knew the investigation was not finished when the first threat was removed.
The real question was simple: what did the attacker leave behind?
Lesson overview
Learn how to hunt for attacker persistence by analysing scheduled tasks, services, registry run keys, startup folder changes, WMI activity and suspicious post-compromise behaviour inside Microsoft Defender XDR.
Why persistence mechanisms matter
The persistence hunting workflow
Step 1 — Start with suspicious task creation
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
let TimeFrame = 14d;
DeviceProcessEvents
| where Timestamp > ago(TimeFrame)
| where FileName in~ ("schtasks.exe", "powershell.exe", "cmd.exe")
| where ProcessCommandLine has_any ("/create", "Register-ScheduledTask", "New-ScheduledTask")
| project Timestamp,
DeviceName,
AccountName,
FileName,
ProcessCommandLine,
InitiatingProcessFileName
| order by Timestamp descStep 2 — Hunt suspicious service creation
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
let TimeFrame = 14d;
DeviceProcessEvents
| where Timestamp > ago(TimeFrame)
| where FileName in~ ("sc.exe", "powershell.exe", "cmd.exe")
| where ProcessCommandLine has_any (" create ", "New-Service", "binPath", "start= auto")
| project Timestamp,
DeviceName,
AccountName,
FileName,
ProcessCommandLine,
InitiatingProcessFileName
| order by Timestamp descStep 3 — Review registry run key changes
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
let TimeFrame = 14d;
DeviceRegistryEvents
| where Timestamp > ago(TimeFrame)
| where RegistryKey has_any ("\Run", "\RunOnce", "\Winlogon", "\Policies\Explorer\Run")
| project Timestamp,
DeviceName,
InitiatingProcessAccountName,
InitiatingProcessFileName,
RegistryKey,
RegistryValueName,
RegistryValueData,
ActionType
| order by Timestamp descStep 4 — Look for startup folder file creation
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
let TimeFrame = 14d;
DeviceFileEvents
| where Timestamp > ago(TimeFrame)
| where FolderPath has_any ("\Startup\", "Start Menu\Programs\Startup")
| project Timestamp,
DeviceName,
InitiatingProcessAccountName,
InitiatingProcessFileName,
FileName,
FolderPath,
SHA256,
ActionType
| order by Timestamp descStep 5 — Hunt WMI persistence indicators
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
let TimeFrame = 14d;
DeviceProcessEvents
| where Timestamp > ago(TimeFrame)
| where ProcessCommandLine has_any ("__EventFilter", "CommandLineEventConsumer", "ActiveScriptEventConsumer", "wmic", "Set-WmiInstance")
| project Timestamp,
DeviceName,
AccountName,
FileName,
ProcessCommandLine,
InitiatingProcessFileName
| order by Timestamp descStep 6 — Build the persistence timeline
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
let TimeFrame = 14d;
let SuspiciousDevice = "DEVICE-01";
union isfuzzy=true
(
DeviceProcessEvents
| where Timestamp > ago(TimeFrame)
| where DeviceName =~ SuspiciousDevice
| where ProcessCommandLine has_any ("schtasks", "sc.exe", "New-Service", "Register-ScheduledTask", "wmic")
| project Timestamp, DeviceName, EvidenceType="Process", AccountName, FileName, Evidence=ProcessCommandLine
),
(
DeviceRegistryEvents
| where Timestamp > ago(TimeFrame)
| where DeviceName =~ SuspiciousDevice
| where RegistryKey has_any ("\Run", "\RunOnce", "\Winlogon")
| project Timestamp, DeviceName, EvidenceType="Registry", AccountName=InitiatingProcessAccountName, FileName=InitiatingProcessFileName, Evidence=strcat(RegistryKey, " ", RegistryValueData)
),
(
DeviceFileEvents
| where Timestamp > ago(TimeFrame)
| where DeviceName =~ SuspiciousDevice
| where FolderPath has "Startup"
| project Timestamp, DeviceName, EvidenceType="File", AccountName=InitiatingProcessAccountName, FileName, Evidence=FolderPath
)
| order by Timestamp ascCommon persistence investigation clues
False positives to consider
Investigation checklist
Related Agent Foskett Academy lessons
Coming next
Final thought
Hunting Playbook Persistence Mechanisms in Microsoft Defender XDR
Agent Foskett Academy Lesson 107 teaches defenders how to hunt for attacker persistence mechanisms using Microsoft Defender XDR telemetry, KQL, scheduled tasks, services, registry run keys, startup folders and WMI evidence.
Learn persistence hunting with KQL and Microsoft Defender XDR
Persistence hunting helps defenders identify scheduled tasks, service creation, registry autoruns, startup folder files and WMI activity that attackers use to maintain access after compromise.
Microsoft Defender XDR persistence investigation tutorial
This lesson explains how to use DeviceProcessEvents, DeviceRegistryEvents, DeviceFileEvents and KQL timelines to investigate attacker persistence across Microsoft Defender XDR telemetry.
