// question

Analyze Windows process events for any schtasks.exe commands that created a new task invoking PowerShell. What is the name of the .ps1 script specified to run?

Reference KQL answer and model-by-model comparison.

f9f2fe59-96f7-4a7d-ba9f-a9783200d4c9
question id
13/23
models correct
1
valid answer
57%
success rate
// reference answer

Human-validated correct answer for this question.

T1036.004_NonExistingScript.ps1
// model comparison
ModelAnswerKQL queryStatusTriesTimeCost
gemini-2.5-flash-preview-04-17
T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where FileName == "schtasks.exe"
| where ProcessCommandLine has "/create" and ProcessCommandLine has_any ("powershell", "pwsh")
| extend ScriptFileName = extract(@'\b([a-zA-Z0-9_.-]+\.ps1)\b', 1, ProcessCommandLine)
| where isnotempty(ScriptFileName)
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessCommandLine, ScriptFileName
pass114.39s0.0066
gpt-35-turbo
no answer
no query generatedfail50.00s0.0120
gpt-4-turbo-2024-04-09
no answer
no query generatedfail50.00s0.2367
gpt-4.1
no answer
no query generatedfail50.00s0.0582
gpt-4.1-finetuned
no answer
no query generatedfail50.00s0.0553
gpt-4.1-mini
no answer
no query generatedfail50.00s0.0067
gpt-4.1-nano
no answer
no query generatedfail50.00s0.0013
gpt-4o
T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where FileName == "schtasks.exe" and ProcessCommandLine contains "powershell"
| extend PSFileName = extract(@"([\w\/\:\-]+\.ps1)", 1, ProcessCommandLine)
| where isnotempty(PSFileName)
| project DeviceId, DeviceName, ProcessCommandLine, PSFileName, TimeGenerated
pass25.73s0.0277
gpt-5-high
T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName =~ "schtasks.exe"
| where ProcessCommandLine contains "/create"
| where ProcessCommandLine has_any ("powershell", "pwsh")
| where ProcessCommandLine contains ".ps1"
// Extract task name from /TN (quoted or unquoted)
| extend TaskName = coalesce(
    extract("(?i)(?:^|\\s)/tn(?::)?\\s*\"([^\"]+)\"", 1, ProcessCommandLine),
    extract("(?i)(?:^|\\s)/tn(?::)?\\s*([^\\s\\\"]+)", 1, ProcessCommandLine)
)
// Extract .ps1 path (prefer -File, then & invocation, then any .ps1)
| extend ScriptPath = coalesce(
    extract("(?i)-file\\s+\"([^\"]+?\\.ps1)\"", 1, ProcessCommandLine),
    extract("(?i)-file\\s+([^\\s\\\"]+?\\.ps1)", 1, ProcessCommandLine),
    extract("(?i)\\&\\s*\"([^\"]+?\\.ps1)\"", 1, ProcessCommandLine),
    extract("(?i)\\&\\s*([^\\s\\\"]+?\\.ps1)", 1, ProcessCommandLine),
    extract("(?i)\"([^\"]+?\\.ps1)\"", 1, ProcessCommandLine),
    extract("(?i)([^\\s\\\"]+?\\.ps1)", 1, ProcessCommandLine)
)
| extend ScriptName = extract("(?i)([^\\\\/]+\\.ps1)$", 1, tostring(ScriptPath))
| where isnotempty(ScriptName)
| project TimeGenerated, DeviceName, AccountDomain, AccountName, TaskName, ScriptPath, ScriptName, ProcessCommandLine
| order by TimeGenerated desc
pass4220.48s0.1700
gpt-5-mini-high
t1036.004_nonexistingscript.ps1
let events = union isfuzzy=true DeviceProcessEvents, DeviceEvents;
events
| extend cmd_raw = coalesce(ProcessCommandLine, InitiatingProcessCommandLine)
| where isnotempty(cmd_raw)
| extend cmd = tolower(tostring(cmd_raw)), file = tolower(tostring(FileName)), ipfile = tolower(tostring(InitiatingProcessFileName))
// look for schtasks as the creator (file name or in the commandline) and signs of a PowerShell task being created
| where file contains "schtasks" or ipfile contains "schtasks" or cmd contains "schtasks"
| where cmd contains "powershell" or cmd contains ".ps1" or cmd contains "/tr" or cmd contains "/create"
// extract the first non-space token that ends with .ps1 (may include surrounding quotes)
| extend ps1_raw = extract(@"(?i)(\S+\.ps1)", 1, cmd)
| where isnotempty(ps1_raw)
// remove surrounding single or double quotes if present
| extend ps1 = trim("'\"", tostring(ps1_raw))
// summarize distinct scripts and provide examples for triage
| summarize Devices = make_set(DeviceName), Count = count(), SampleCommand = any(cmd_raw), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by ps1
| order by Count desc
pass380.62s0.0213
gpt-5-mini-low
no answer
no query generatedfail50.00s0.0138
gpt-5-mini-medium
T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where isnotempty(ProcessCommandLine)
| where tolower(FileName) == "schtasks.exe" or tolower(ProcessCommandLine) contains "schtasks"
// Focus on task creation that references PowerShell (create + powershell/enc/command/file)
| where tolower(ProcessCommandLine) contains "/create" and (
    tolower(ProcessCommandLine) contains "powershell" or
    tolower(ProcessCommandLine) contains "-enc" or
    tolower(ProcessCommandLine) contains "-command" or
    tolower(ProcessCommandLine) contains "-file"
)
| extend Cmd = tostring(ProcessCommandLine), InitiatorCmd = tostring(InitiatingProcessCommandLine), Additional = tostring(AdditionalFields)
// Extract any .ps1-looking token from the different possible locations
| extend Ps1_in_cmd = extract(@"([A-Za-z0-9_:\/\.\-]+\.ps1)", 1, Cmd)
| extend Ps1_in_initiator = extract(@"([A-Za-z0-9_:\/\.\-]+\.ps1)", 1, InitiatorCmd)
| extend Ps1_in_additional = extract(@"([A-Za-z0-9_:\/\.\-]+\.ps1)", 1, Additional)
| extend Ps1 = coalesce(Ps1_in_cmd, Ps1_in_initiator, Ps1_in_additional)
| where isnotempty(Ps1)
| project TimeGenerated, DeviceName, DeviceId, AccountName, FileName, ProcessId, ProcessCreationTime, Cmd, InitiatorCmd, Additional, Ps1
| summarize occurrences = count(), firstSeen = min(TimeGenerated), lastSeen = max(TimeGenerated) by Ps1, DeviceName, DeviceId, AccountName
| order by occurrences desc
pass4114.81s0.0252
gpt-5-nano-high
no answer
no query generatedfail50.00s0.0121
gpt-5-nano-medium
no answer
no query generatedfail50.00s0.0095
grok-3-beta
T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where FileName contains 'schtasks.exe'
| where ProcessCommandLine has_any ('/create', '-create')
| where ProcessCommandLine has 'powershell'
| extend ScriptName = extract('[^a-zA-Z0-9]([a-zA-Z0-9\\-_.]+\\.ps1)[^a-zA-Z0-9]', 1, ProcessCommandLine)
| where isnotempty(ScriptName)
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, ScriptName
| order by Timestamp desc
pass19.77s0.0218
grok-3-mini-beta
no answer
no query generatedfail50.00s0.0077
o1-high
c:\T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where FileName == "schtasks.exe"
| where ProcessCommandLine has " /create " and ProcessCommandLine has "powershell"
| extend ScriptName = extract(@"([A-Za-z0-9\\/\-_.:]+\.ps1)", 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine, ScriptName
| order by TimeGenerated desc
pass140.90s0.1748
o1-low
c:\T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where FileName == "schtasks.exe"
| where ProcessCommandLine has_any ("/create", "create")
| where ProcessCommandLine has_any ("powershell", "powershell.exe")
| extend Ps1Script = extract(@"(\S+\.ps1)", 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, ProcessCommandLine, Ps1Script
pass131.28s0.2128
o3-high
c:\T1036.004_NonExistingScript.ps1
// Scheduled Task creations that launch PowerShell scripts
DeviceProcessEvents
| where FileName =~ "schtasks.exe"
// only creation of new tasks
| where ProcessCommandLine contains "/create"
// …that invoke PowerShell (Windows PowerShell or PowerShell Core)
| where ProcessCommandLine has_any ("powershell", "pwsh")
// pull out the script that will be executed (first token ending with .ps1)
| extend PsScript = extract(@"(\S+\.ps1)", 1, ProcessCommandLine)
| where isnotempty(PsScript)
| project TimeGenerated, DeviceName, DeviceId, AccountDomain, AccountName, PsScript, ProcessCommandLine
| summarize Events = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
          by PsScript, DeviceName, DeviceId, AccountDomain, AccountName
| order by LastSeen desc
pass4169.19s0.0724
o3-mini-high
T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where tolower(FileName) == "schtasks.exe"
| where ProcessCommandLine has "powershell" and ProcessCommandLine has ".ps1"
| extend ScriptName = extract(@"(\S+\.ps1)", 1, ProcessCommandLine)
| where isnotempty(ScriptName)
| project TimeGenerated, DeviceName, ScriptName, ProcessCommandLine
pass112.02s0.0089
o3-mini-low
c:\T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where FileName =~ "schtasks.exe"
| where ProcessCommandLine contains "/create" 
| where ProcessCommandLine contains "PowerShell"
| where ProcessCommandLine contains ".ps1"
| extend ScriptName = extract(@"(?i)(\S+\.ps1)", 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, ProcessCommandLine, ScriptName
| distinct ScriptName, DeviceName, TimeGenerated
pass139.69s0.0089
o4-mini-high
T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where FileName == "schtasks.exe"
  and ProcessCommandLine has "/create"
  and ProcessCommandLine contains "-file"
  and ProcessCommandLine contains ".ps1"
| extend ScriptName = extract(@"(?i)-file\s+""?([^""\s]+\.ps1)", 1, ProcessCommandLine)
| where isnotempty(ScriptName)
| project TimeGenerated, DeviceName, InitiatingProcessAccountName, ProcessCommandLine, ScriptName
| sort by TimeGenerated desc
pass4156.42s0.0424
o4-mini-low
T1036.004_NonExistingScript.ps1
DeviceProcessEvents
| where FileName =~ "schtasks.exe"
| where ProcessCommandLine has "/create"
| where ProcessCommandLine has "powershell"
| parse ProcessCommandLine with * "-File " ScriptNameRaw:string ".ps1" *
| extend Ps1Script = strcat(trim('"', ScriptNameRaw), ".ps1")
| where isnotempty(Ps1Script)
| project TimeGenerated, DeviceName, AccountName, Ps1Script, ProcessCommandLine
| sort by TimeGenerated desc
pass3335.93s0.0702