// question

You suspect malicious persistence via scheduled tasks on a Windows endpoint. Review the process execution logs to identify the built-in utility used to register tasks at logon or startup. What is the name of this utility?

Reference KQL answer and model-by-model comparison.

fec27f65-db86-4c2d-b66c-61945aee87c2
question id
21/23
models correct
1
valid answer
91%
success rate
// reference answer

Human-validated correct answer for this question.

schtasks
// model comparison
ModelAnswerKQL queryStatusTriesTimeCost
gemini-2.5-flash-preview-04-17
schtasks.exe
DeviceProcessEvents | where FileName =~ "schtasks.exe" | distinct FileName
pass18.14s0.0033
gpt-35-turbo
schtasks
DeviceProcessEvents
| where ProcessCommandLine has 'schtasks'
| project ProcessCommandLine, InitiatingProcessCommandLine
pass24.17s0.0056
gpt-4-turbo-2024-04-09
schtasks
DeviceProcessEvents
| where FileName == 'schtasks.exe' and (ProcessCommandLine contains 'create' or ProcessCommandLine contains '/CREATE' or ProcessCommandLine contains '/create')
| project DeviceName, AccountName, AccountDomain, InitiatingProcessParentFileName, ProcessCommandLine, Timestamp
| distinct DeviceName, AccountName, AccountDomain, InitiatingProcessParentFileName, ProcessCommandLine, Timestamp
pass435.75s0.2089
gpt-4.1
schtasks.exe
DeviceProcessEvents
| where FileName =~ "schtasks.exe"
| summarize count() by FileName
pass13.90s0.0106
gpt-4.1-finetuned
no answer
no query generatedfail50.00s0.0328
gpt-4.1-mini
schtasks.exe
DeviceProcessEvents
| where ProcessCommandLine has "schtasks" or FileName =~ "schtasks.exe"
| summarize count() by FileName
| project FileName, Count=count_
pass13.30s0.0022
gpt-4.1-nano
PowerShell
DeviceProcessEvents
| where FileName in ('schtasks.exe', 'powershell.exe', 'wmic.exe', 'schtasks')
| where ProcessCommandLine contains ('register') and (ProcessCommandLine contains ('logon') or ProcessCommandLine contains ('startup') or ProcessCommandLine contains ('boot'))
| project TimeGenerated, FileName, ProcessCommandLine, InitiatingProcessFileName, DeviceName, ProcessId, InitiatingProcessId
| order by TimeGenerated desc
fail12.61s0.0006
gpt-4o
schtasks.exe
DeviceProcessEvents
| where FileName in ('schtasks.exe', 'taskeng.exe')
| where InitiatingProcessCommandLine contains 'create' or InitiatingProcessCommandLine contains 'logon' or InitiatingProcessCommandLine contains 'startup'
| project DeviceName, AccountName, FileName, ProcessCommandLine, ProcessCreationTime
pass12.77s0.0161
gpt-5-high
schtasks.exe
DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName =~ "schtasks.exe"
| where ProcessCommandLine contains "/create"
| where ProcessCommandLine matches regex @"(?i)/sc\s+(onlogon|onstart)"
| summarize by UtilityName = FileName
pass150.70s0.0353
gpt-5-mini-high
schtasks.exe
// Search for executions that indicate scheduled-task creation/registration
DeviceProcessEvents
| where isnotempty(ProcessCommandLine) or isnotempty(FileName)
// Look for known scheduling utilities / patterns and PowerShell cmdlets/flags used to create tasks
| where ProcessCommandLine has_any ("schtasks","/create","/Create","Register-ScheduledTask","New-ScheduledTask","-AtLogon","-AtStartup","schtasks.exe","at ")
      or FileName has_any ("schtasks","at","powershell","pwsh")
| extend exe = tolower(tostring(FileName)), cmd = tostring(ProcessCommandLine)
| summarize Count = count(), SampleCommands = make_list(cmd, 10), SampleDevices = make_list(DeviceName, 10) by exe
| order by Count desc

// (Optional) If you want raw events for deeper triage, uncomment the block below:
// DeviceProcessEvents
// | where isnotempty(ProcessCommandLine) or isnotempty(FileName)
// | where ProcessCommandLine has_any ("schtasks","/create","/Create","Register-ScheduledTask","New-ScheduledTask","-AtLogon","-AtStartup","schtasks.exe","at ")
//       or FileName has_any ("schtasks","at","powershell","pwsh")
// | project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine
// | order by TimeGenerated desc
pass125.73s0.0076
gpt-5-mini-low
schtasks.exe
union DeviceProcessEvents, DeviceEvents, DeviceFileEvents
| where isnotempty(ProcessCommandLine) or isnotempty(FileName)
| where (
    tolower(FileName) contains "schtasks" 
    or tolower(ProcessCommandLine) contains "schtasks"
    or tolower(FileName) contains "at.exe"
    or tolower(ProcessCommandLine) contains "\bat "
    or tolower(ProcessCommandLine) contains "register-scheduledtask"
    or tolower(ProcessCommandLine) contains "new-scheduledtask"
    or tolower(ProcessCommandLine) contains "register-scheduledtask"
    or tolower(ProcessCommandLine) contains "/sc onlogon"
    or tolower(ProcessCommandLine) contains "/sc onstart"
)
| project TimeGenerated, DeviceName, Account = coalesce(AccountName, InitiatingProcessAccountName), FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine
| extend matched = case(
    tolower(FileName) contains "schtasks" or tolower(ProcessCommandLine) contains "schtasks", "schtasks.exe",
    tolower(FileName) contains "at.exe" or tolower(ProcessCommandLine) contains " at ", "at.exe",
    tolower(ProcessCommandLine) contains "register-scheduledtask" or tolower(ProcessCommandLine) contains "new-scheduledtask", "PowerShell ScheduledTask cmdlets",
    "other"
)
| summarize Count = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by matched, DeviceName, Account, FileName, ProcessCommandLine
| order by Count desc
| take 100
pass130.00s0.0072
gpt-5-mini-medium
schtasks.exe
DeviceProcessEvents
| where FileName has_cs "schtasks" or ProcessCommandLine has_cs "schtasks" or FileName has_cs "at.exe" or ProcessCommandLine has_cs "at.exe"
| where ProcessCommandLine has_cs "/create" or ProcessCommandLine has_cs "ONLOGON" or ProcessCommandLine has_cs "ONSTART" or ProcessCommandLine has_cs "\bat \b"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessId, InitiatingProcessId
| extend Utility = case(
    FileName has_cs "schtasks" or ProcessCommandLine has_cs "schtasks","schtasks.exe",
    FileName has_cs "at.exe" or ProcessCommandLine has_cs "at.exe","at.exe",
    "unknown")
| where Utility != "unknown"
| order by Timestamp desc
| take 100
pass118.30s0.0055
gpt-5-nano-high
schtasks
DeviceProcessEvents
| where (ProcessCommandLine contains "schtasks" or InitiatingProcessCommandLine contains "schtasks" or FileName contains "schtasks.exe" or InitiatingProcessFileName contains "schtasks.exe")
| project TimeGenerated, DeviceName, DeviceId, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessCommandLine, FileName
| summarize Count = count() by InitiatingProcessFileName, ProcessCommandLine, InitiatingProcessCommandLine
| where Count > 0
| order by Count desc
pass129.40s0.0021
gpt-5-nano-medium
schtasks
DeviceProcessEvents
| where InitiatingProcessFileName has_any ("schtasks.exe", "schtasks") or ProcessCommandLine has_any ("schtasks.exe", "schtasks")
| where (InitiatingProcessCommandLine contains "/Create" or ProcessCommandLine contains "/Create")
| where (InitiatingProcessCommandLine contains "/SC ONLOGON" or InitiatingProcessCommandLine contains "/SC ONSTART" or ProcessCommandLine contains "/SC ONLOGON" or ProcessCommandLine contains "/SC ONSTART")
| project TimeGenerated, DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessCommandLine
| sort by TimeGenerated desc
| take 100
pass4104.57s0.0057
grok-3-beta
schtasks.exe
DeviceProcessEvents
| where FileName contains "schtasks.exe"
| where ProcessCommandLine contains "logon" or ProcessCommandLine contains "startup"
| summarize count() by FileName, ProcessCommandLine, DeviceName, AccountName, ProcessCreationTime
| order by ProcessCreationTime desc
pass118.02s0.0217
grok-3-mini-beta
schtasks.exe
DeviceProcessEvents
| where FileName has "schtasks.exe"
| where ProcessCommandLine has_any ("create", "at logon", "at startup")
| summarize count() by FileName, ProcessCommandLine
| project FileName, ProcessCommandLine, count_
pass110.30s0.0016
o1-high
schtasks.exe
DeviceProcessEvents
| where ActionType =~ "ProcessCreated" or ActionType =~ "CreateProcess"
| where FileName in~ ("schtasks.exe", "at.exe")
| where ProcessCommandLine has_any ("/create", "/Create", "AtLogon", "OnStart")
| project TimeGenerated, DeviceName, InitiatingProcessAccountName, FileName, ProcessCommandLine
pass132.71s0.2031
o1-low
schtasks.exe
DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName in~ ("schtasks.exe", "at.exe")
| where ProcessCommandLine has_any ("create", "onstart", "onlogon", "onboot")
| project TimeGenerated, DeviceName, AccountDomain, AccountName, FileName, ProcessCommandLine
| order by TimeGenerated desc
pass123.45s0.1917
o3-high
schtasks
// Scheduled task creation or modification that runs at logon or start-up
DeviceProcessEvents
| where TimeGenerated >= ago(7d)  // <-- time filter will be overridden by the function call
| where FileName =~ "schtasks.exe"
// Look for switches that indicate a new or modified task and that the schedule is logon/start-up
| where ProcessCommandLine has_any ("/create", "/change")
| where ProcessCommandLine contains "/sc" and (
        ProcessCommandLine contains "onlogon" or
        ProcessCommandLine contains "onstart"  or
        ProcessCommandLine contains "onstartup")
| project TimeGenerated,
          DeviceName,
          Account = strcat(AccountDomain, "\\", AccountName),
          FileName,
          ProcessCommandLine,
          ParentProcess = InitiatingProcessFileName,
          ParentCmd = InitiatingProcessCommandLine,
          FolderPath,
          MD5,
          SHA256
| order by TimeGenerated desc
pass130.11s0.0193
o3-mini-high
schtasks.exe
DeviceProcessEvents
| where FileName =~ "schtasks.exe"
| where ProcessCommandLine has "create"
| project TimeGenerated, DeviceName, FileName, ProcessCommandLine, InitiatingProcessFileName
| order by TimeGenerated desc
pass19.14s0.0077
o3-mini-low
schtasks.exe
DeviceProcessEvents
| where FileName =~ "schtasks.exe"
| summarize EventCount = count() by FileName
| project FileName, EventCount
pass113.23s0.0064
o4-mini-high
schtasks
DeviceProcessEvents
| where TimeGenerated between (startofday(ago(30d)) .. now())  // replace with desired timerange
| where FileName =~ "schtasks.exe"
| project TimeGenerated, DeviceName, InitiatingProcessFileName, ProcessCommandLine, InitiatingProcessAccountName
| summarize count() by DeviceName, InitiatingProcessAccountName, ProcessCommandLine
| order by count_ desc
pass128.14s0.0084
o4-mini-low
schtasks.exe
DeviceProcessEvents
| where FileName in ("schtasks.exe", "at.exe")
| where ProcessCommandLine has "/create"
| project Timestamp, DeviceName, FileName, ProcessCommandLine
| distinct FileName
pass118.66s0.0090