MDE - Scheduled Task Execution
MDE Schedulted Tasks
Query
let Lookback = 7d;
DeviceProcessEvents
| where Timestamp > ago(Lookback)
| where InitiatingProcessFileName =~ "svchost.exe"
| where InitiatingProcessCommandLine has "Schedule"
//
// Process started by Task Scheduler
//
| extend RunAsAccount = strcat(AccountDomain, @"\", AccountName)
| project
Timestamp,
DeviceName,
RunAsAccount,
AccountSid,
ExecutedFile = FileName,
CommandLine = ProcessCommandLine,
InitiatingProcessFileName,
InitiatingProcessCommandLine,
InitiatingProcessAccountName,
ProcessId,
InitiatingProcessId
//
// Calculate execution intervals
//
| sort by DeviceName asc, CommandLine asc, RunAsAccount asc, Timestamp asc
| serialize
| extend
PreviousTimestamp = prev(Timestamp),
PreviousDeviceName = prev(DeviceName),
PreviousCommandLine = prev(CommandLine),
PreviousRunAsAccount = prev(RunAsAccount)
| where DeviceName == PreviousDeviceName
and CommandLine == PreviousCommandLine
and RunAsAccount == PreviousRunAsAccount
| extend IntervalMinutes = datetime_diff("minute", Timestamp, PreviousTimestamp)
//
// Summarize schedule behavior
//
| summarize
FirstSeen = min(PreviousTimestamp),
LastSeen = max(Timestamp),
ExecutionCount = count() + 1,
MinIntervalMinutes = min(IntervalMinutes),
AvgIntervalMinutes = round(avg(IntervalMinutes),2),
MaxIntervalMinutes = max(IntervalMinutes),
ObservedIntervals = make_set(IntervalMinutes,20)
by
DeviceName,
RunAsAccount,
AccountSid,
ExecutedFile,
CommandLine
//
// Human readable schedule guess
//
| extend InferredSchedulePattern = case(
AvgIntervalMinutes between (0 .. 2), "Every few minutes",
AvgIntervalMinutes between (14 .. 16), "Every ~15 minutes",
AvgIntervalMinutes between (29 .. 31), "Every ~30 minutes",
AvgIntervalMinutes between (55 .. 65), "Every ~1 hour",
AvgIntervalMinutes between (115 .. 125), "Every ~2 hours",
AvgIntervalMinutes between (350 .. 370), "Every ~6 hours",
AvgIntervalMinutes between (710 .. 730), "Every ~12 hours",
AvgIntervalMinutes between (1430 .. 1450), "Daily",
AvgIntervalMinutes between (10000 .. 10120), "Weekly",
strcat("~Every ", tostring(AvgIntervalMinutes), " minutes")
)
| project
DeviceName,
RunAsAccount,
AccountSid,
ExecutedFile,
InferredSchedulePattern,
ExecutionCount,
FirstSeen,
LastSeen,
MinIntervalMinutes,
AvgIntervalMinutes,
MaxIntervalMinutes,
ObservedIntervals,
CommandLine
| order by ExecutionCount descAbout this query
Explanation
This KQL query is designed to provide an overview of scheduled tasks running on Windows Server devices in your environment. It consists of two main parts:
-
Scheduled Task Executions on Servers:
- The query first identifies devices that are onboarded and running Windows Server.
- It then looks for processes that were created by the Task Scheduler (
svchost.exewith "Schedule" in the command line). - It filters for processes that are specifically
cmd.exe,powershell.exe, orcscript.exe. - It excludes tasks run by system accounts like 'system', 'local service', and 'network service', focusing on custom accounts.
- The result is a list of scheduled tasks executed by custom accounts, showing details like the task's context, command line, and initiating process.
-
Scheduled Task Intervals:
- This part of the query analyzes task execution over the past 7 days.
- It calculates the intervals between task executions to infer the scheduling pattern.
- It summarizes the execution behavior, including the first and last seen times, execution count, and interval statistics (minimum, average, maximum).
- It attempts to guess a human-readable schedule pattern (e.g., "Every ~15 minutes", "Daily").
- The output includes details like the device name, account running the task, executed file, inferred schedule pattern, and command line.
Overall, this query helps you understand which scheduled tasks are running, who is running them, and how frequently they are executed on your Windows Server devices.