// question

Investigate Windows process events for PowerShell activity that leverages WMI to register a scheduled task via XML import. What was the name of the XML file supplied to the RegisterByXml method?

Reference KQL answer and model-by-model comparison.

e16b3b75-dc9e-4cde-a23d-dfa2d0507b3b
question id
6/23
models correct
1
valid answer
26%
success rate
// reference answer

Human-validated correct answer for this question.

T1053_005_WMI.xml
// model comparison
ModelAnswerKQL queryStatusTriesTimeCost
gemini-2.5-flash-preview-04-17
no answer
no query generatedfail50.00s0.0717
gpt-35-turbo
T1053_005_WMI.xml
DeviceProcessEvents
| where ProcessCommandLine has "PowerShell" and ProcessCommandLine has "RegisterByXml"
| extend XmlFileName = tostring(AdditionalFields.XmlFileName)
| project TimeGenerated, ProcessId, ProcessCommandLine, XmlFileName
pass13.32s0.0027
gpt-4-turbo-2024-04-09
no answer
no query generatedfail50.00s0.2373
gpt-4.1
C:\AtomicRedTeam\atomics\T1053.005\src\T1053_005_WMI.xml
DeviceProcessEvents
| where FileName =~ "powershell.exe"
| where ProcessCommandLine has "RegisterByXml" or ProcessCommandLine has "RegisterTaskDefinition" or ProcessCommandLine has "RegisterTask"
| where ProcessCommandLine has ".xml"
| extend XMLFileName = extract(@"([\w\d:\\/_\-\.]+\.xml)", 1, ProcessCommandLine)
| where isnotempty(XMLFileName)
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, XMLFileName
pass17.22s0.0129
gpt-4.1-finetuned
no answer
no query generatedfail50.00s0.0452
gpt-4.1-mini
no answer
no query generatedfail50.00s0.0085
gpt-4.1-nano
no answer
no query generatedfail50.00s0.0015
gpt-4o
no answer
no query generatedfail50.00s0.0623
gpt-5-high
T1053_005_WMI.xml
let pwsh_bins = dynamic(["powershell.exe","pwsh.exe","powershell_ise.exe"]);
let task_ns1 = @"root\microsoft\windows\taskscheduler";
let ps_wmi_calls =
    DeviceEvents
    | where (ActionType in~ ("WmiMethodInvoked","WmiMethodCall","WmiMethodExecuted")) or (tolower(ActionType) has "wmi" and tolower(ActionType) has "method")
    | where InitiatingProcessFileName in~ (pwsh_bins)
    | extend MethodName = tolower(coalesce(tostring(AdditionalFields.MethodName), tostring(AdditionalFields.Method), tostring(AdditionalFields["methodName"])))
    | extend WmiNamespace = tolower(coalesce(tostring(AdditionalFields.Namespace), tostring(AdditionalFields["NameSpace"]), tostring(AdditionalFields["WmiNamespace"])))
    | where MethodName == "registerbyxml" and (isempty(WmiNamespace) or WmiNamespace has task_ns1)
    | project TimeGenerated, DeviceId, DeviceName, InitiatingProcessFileName, InitiatingProcessId, InitiatingProcessCommandLine;
let ps_cmd_matches =
    DeviceProcessEvents
    | where FileName in~ (pwsh_bins)
    | where (ProcessCommandLine has_cs "RegisterByXml" or InitiatingProcessCommandLine has_cs "RegisterByXml")
    | project TimeGenerated, DeviceId, DeviceName, InitiatingProcessFileName=FileName, InitiatingProcessId=ProcessId, InitiatingProcessCommandLine=coalesce(ProcessCommandLine, InitiatingProcessCommandLine);
union ps_wmi_calls, ps_cmd_matches
| extend Cmd = InitiatingProcessCommandLine
// Extract XML path or bare filename from the PowerShell command line
| extend xml_candidates = extract_all(@"(?i)(?:['""])?((?:[A-Z]:\\|\\\\)[^'""\s]+\.xml)", Cmd)
| extend xml_names      = extract_all(@"(?i)([^\\/:'""\s]+\.xml)", Cmd)
| extend xml_token = case(array_length(xml_candidates) > 0, tostring(xml_candidates[0]), array_length(xml_names) > 0, tostring(xml_names[0]), "")
| extend XmlFileName = tostring(extract(@"([^\\/:]+\.xml)", 1, xml_token))
| where isnotempty(XmlFileName)
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Events=count(), Devices=make_set(DeviceName, 10) by XmlFileName
| order by Events desc, LastSeen desc
pass2331.72s0.1476
gpt-5-mini-high
no answer
no query generatedfail50.00s0.0340
gpt-5-mini-low
no answer
no query generatedfail50.00s0.0118
gpt-5-mini-medium
T1053_005_WMI.xml
// Find PowerShell processes that reference RegisterByXml or mention .xml, extract XML names and correlate with .xml file events
let process_candidates = DeviceProcessEvents
| where tolower(ProcessCommandLine) contains "powershell" or tolower(FileName) contains "powershell" or tolower(ProcessCommandLine) contains "pwsh"
| where ProcessCommandLine contains "RegisterByXml" or ProcessCommandLine contains ".xml" or tostring(AdditionalFields) contains "RegisterByXml" or tostring(AdditionalFields) contains ".xml"
| extend XmlMatches = extract_all(@"([^\s]+\.xml)", ProcessCommandLine)
| mv-expand XmlFile = XmlMatches to typeof(string)
| project ProcTime=Timestamp, DeviceName, DeviceId, ProcessId, InitiatingProcessId, Account=AccountName, ProcessCommandLine, XmlFile;

let file_events = DeviceFileEvents
| where tolower(FileName) endswith ".xml"
| where tolower(InitiatingProcessFileName) contains "powershell" or tolower(InitiatingProcessCommandLine) contains "powershell" or tolower(InitiatingProcessCommandLine) contains "pwsh"
| project FileTime=Timestamp, DeviceName, DeviceId, FileName, FolderPath, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessId;

let device_events_xml = DeviceEvents
| where tostring(AdditionalFields) contains "RegisterByXml" or tostring(AdditionalFields) contains ".xml"
| extend XmlMatches = extract_all(@"([^\s]+\.xml)", tostring(AdditionalFields))
| mv-expand XmlFile = XmlMatches to typeof(string)
| project EvTime=Timestamp, DeviceName, DeviceId, ProcessCommandLine, XmlFile, Account=AccountName;

process_candidates
| join kind=leftouter (file_events) on DeviceId
| where isnotempty(XmlFile) or (isnotnull(FileTime) and abs(datetime_diff('second', ProcTime, FileTime)) <= 120)
| extend ObservedXml = iff(isnotempty(XmlFile), XmlFile, FileName)
| project DeviceName, Account, ProcessId, InitiatingProcessId, ProcTime, FileTime, ObservedXml, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, FolderPath
| union (device_events_xml | project DeviceName, Account, ProcessId=long(null), InitiatingProcessId=long(null), ProcTime=EvTime, FileTime=EvTime, ObservedXml=XmlFile, ProcessCommandLine, InitiatingProcessFileName="", InitiatingProcessCommandLine="", FolderPath="")
| where isnotempty(ObservedXml)
| summarize FirstSeen=min(ProcTime), LastSeen=max(ProcTime), AnyCommands = make_set(ProcessCommandLine,5), FileEvents = make_set(pack('File',ObservedXml,'Folder',FolderPath,'InitiatingCmd',InitiatingProcessCommandLine),20) by DeviceName, Account, ObservedXml
| order by FirstSeen desc
| take 200
pass468.59s0.0180
gpt-5-nano-high
no answer
no query generatedfail50.00s0.0097
gpt-5-nano-medium
no answer
no query generatedfail50.00s0.0088
grok-3-beta
no answer
no query generatedfail50.00s0.0893
grok-3-mini-beta
no answer
no query generatedfail50.00s0.0077
o1-high
C:\AtomicRedTeam\atomics\T1053.005\src\T1053_005_WMI.xml
// Investigate PowerShell activity leveraging WMI to register a scheduled task via XML import
DeviceProcessEvents
| where FileName in~ ("powershell.exe", "pwsh.exe")
| where ProcessCommandLine has "RegisterByXml"
| extend XmlFileName = extract(@"(?i)([A-Z]:\\[\w\\.\-]+\.xml)", 1, ProcessCommandLine)
| project TimeGenerated, DeviceId, DeviceName, AccountName, ProcessCommandLine, XmlFileName
| order by TimeGenerated desc
pass138.08s0.2797
o1-low
no answer
no query generatedfail50.00s0.8630
o3-high
T1053_005_WMI.xml
// -------------  PowerShell using WMI RegisterByXml (scheduled-task import) -------------
// Time range is controlled by the hunting UI – no explicit time filter is added here.
DeviceProcessEvents
// 1. Limit to the various PowerShell interpreters
| where FileName in~ ("powershell.exe", "pwsh.exe", "powershell_ise.exe")
// 2. Command line must show the WMI method plus an XML reference
| where ProcessCommandLine has "RegisterByXml" and ProcessCommandLine has ".xml"
// 3. Try to extract the XML path
//    3a. 1st attempt – a normal absolute path (e.g. C:\Temp\task.xml)
| extend xmlPath = extract(@'([A-Za-z]:\\[^\s''"<>]+?\.xml)', 1, ProcessCommandLine)
//    3b. Fallback – grab the first token that simply ends with .xml (covers relative paths, URLs, vars, etc.)
| extend xmlPath = iff(isnull(xmlPath) or xmlPath == "", extract(@'(\S+?\.xml)', 1, ProcessCommandLine), xmlPath)
// 4. Pull out just the file name so we can answer the analyst’s question
| extend xmlFile = tostring(split(xmlPath, "\\")[-1])
// 5. Return concise context around each occurrence
| summarize FirstSeen = min(TimeGenerated),
            LastSeen  = max(TimeGenerated),
            ExecCount = count()
          by DeviceName, AccountName, xmlFile, xmlPath, ProcessCommandLine
| order by LastSeen desc
pass4148.36s0.0814
o3-mini-high
no answer
no query generatedfail50.00s0.0424
o3-mini-low
no answer
no query generatedfail50.00s0.0470
o4-mini-high
no answer
no query generatedfail50.00s0.0586
o4-mini-low
no answer
no query generatedfail50.00s0.0403