Question Analysis
A suspicious BITS transfer was orchestrated via bitsadmin.exe on Windows, creating a job to download and then execute a payload. Investigate the process event logs to determine what custom job name was specified when the BITS job was created.
62a06ec5-5754-47d2-bcfc-123d8314c6ae
Question ID
9/23
Models Correct
1
Valid Answer
39%
Success Rate
Reference Answer
Human-validated correct answer for this question
AtomicBITS
Model Performance Comparison
See how different AI models performed on this question
Model | Answer | KQL Query | Status | Attempts | Time | Cost |
---|---|---|---|---|---|---|
gemini-2.5-flash-preview-04-17 | AtomicBITS | DeviceProcessEvents
| where FileName =~ "bitsadmin.exe"
| where ProcessCommandLine contains "/create" or ProcessCommandLine contains "/addfile"
| extend JobName_create = extract(@"/create\s+([^\s]+)", 1, ProcessCommandLine)
| extend JobName_addfile = extract(@"/addfile\s+([^\s]+)", 1, ProcessCommandLine)
| extend CustomJobName = coalesce(JobName_create, JobName_addfile)
| where isnotnull(CustomJobName)
| project Timestamp, DeviceName, ProcessCommandLine, CustomJobName | Correct | 1 | 10.24s | 0.0045 |
gpt-35-turbo | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0121 |
gpt-4-turbo-2024-04-09 | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.2233 |
gpt-4.1 | AtomicBITS | DeviceProcessEvents
| where FileName =~ "bitsadmin.exe"
| where ProcessCommandLine has "/create"
| extend JobName = extract(@"/create\s+([^\s]+)", 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine, JobName
| where isnotempty(JobName)
| sort by TimeGenerated desc | Correct | 1 | 4.30s | 0.0110 |
gpt-4.1-finetuned | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0406 |
gpt-4.1-mini | AtomicBITS | DeviceProcessEvents
| where FileName =~ "bitsadmin.exe"
| where ProcessCommandLine contains "create"
| extend JobName = extract(@"create\s+(\S+)", 1, ProcessCommandLine)
| project DeviceName, TimeGenerated, JobName, InitiatingProcessAccountName, ProcessCommandLine
| where isnotempty(JobName)
| sort by TimeGenerated desc | Correct | 1 | 25.77s | 0.0023 |
gpt-4.1-nano | None | DeviceProcessEvents
| where FileName endswith 'bitsadmin.exe'
| where ProcessCommandLine contains 'create'
| extend JobName = extract(@'\s/\s*(\S+)$', 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, JobName | Incorrect | 5 | 26.40s | 0.0015 |
gpt-4o | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0597 |
gpt-5-high | AtomicBITS | DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName =~ "bitsadmin.exe" or ProcessCommandLine has "bitsadmin"
// Extract job name from /create or /transfer (handles quoted and unquoted names, optional /download|/upload|/upload-reply)
| extend CreateQuoted = extract(@"(?i)(?:^|\s)(?:-|/)create\s+(?:(?:-|/)?(?:download|upload|upload-reply)\s+)?""([^""]+)""", 1, ProcessCommandLine)
| extend CreateUnquoted = iff(isempty(CreateQuoted), extract(@"(?i)(?:^|\s)(?:-|/)create\s+(?:(?:-|/)?(?:download|upload|upload-reply)\s+)?(\S+)", 1, ProcessCommandLine), "")
| extend TransferQuoted = iff(isempty(CreateQuoted) and isempty(CreateUnquoted), extract(@"(?i)(?:^|\s)(?:-|/)transfer\s+(?:(?:-|/)?(?:download|upload|upload-reply)\s+)?""([^""]+)""", 1, ProcessCommandLine), "")
| extend TransferUnquoted = iff(isempty(CreateQuoted) and isempty(CreateUnquoted) and isempty(TransferQuoted), extract(@"(?i)(?:^|\s)(?:-|/)transfer\s+(?:(?:-|/)?(?:download|upload|upload-reply)\s+)?(\S+)", 1, ProcessCommandLine), "")
| extend JobName = coalesce(CreateQuoted, CreateUnquoted, TransferQuoted, TransferUnquoted)
| where isnotempty(JobName)
| project TimeGenerated, DeviceId, DeviceName, AccountDomain, AccountName, ProcessCommandLine, JobName
| summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Examples=make_set(ProcessCommandLine, 3) by DeviceId, DeviceName, AccountDomain, AccountName, JobName
| order by LastSeen desc | Correct | 4 | 295.19s | 0.1891 |
gpt-5-mini-high | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0195 |
gpt-5-mini-low | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0088 |
gpt-5-mini-medium | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0252 |
gpt-5-nano-high | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0075 |
gpt-5-nano-medium | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0088 |
grok-3-beta | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0876 |
grok-3-mini-beta | AtomicBITS | DeviceProcessEvents
| where FileName =~ 'bitsadmin.exe'
| where ProcessCommandLine contains '/create'
| extend JobName = extract(@'/create\s+([^\s]+)', 1, ProcessCommandLine)
| project Timestamp, DeviceName, ProcessCommandLine, JobName
| summarize JobNames = makeset(JobName) by DeviceName | Correct | 1 | 13.77s | 0.0015 |
o1-high | AtomicBITS | DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName =~ "bitsadmin.exe"
| where ProcessCommandLine has "/create"
// Use a regex parse that captures either a quoted or unquoted job name
| parse kind=regex ProcessCommandLine with ".*bitsadmin\\.exe\\s+/create\\s+(\"[^\"]+\"|\\S+).*" JobName
// Clean up any surrounding double-quotes
| extend CustomJobName = trim('"', JobName)
| project TimeGenerated, DeviceName, InitiatingProcessAccountName, ProcessCommandLine, CustomJobName | Correct | 3 | 92.64s | 0.5674 |
o1-low | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.9217 |
o3-high | AtomicBITS | DeviceProcessEvents
// -- filter to bitsadmin executions that create a BITS job ------------------------------------
| where FileName =~ 'bitsadmin.exe' or ProcessCommandLine has_cs 'bitsadmin.exe'
| extend cmd = tostring(ProcessCommandLine)
// keep only invocations that attempt to *create* a job
| where tolower(cmd) has '/create'
// -- extract the argument that represents the custom job name ---------------------------------
| extend idx = indexof(tolower(cmd), '/create') // location of the verb
| extend afterCreate = substring(cmd, idx + 7) // text that follows "/create"
| extend afterCreate = trim_start(' ', afterCreate) // remove leading spaces
| extend tokens = split(afterCreate, ' ') // tokenise
| extend firstTok = tostring(tokens[0]) // first argument after the verb
// if the first argument is itself a switch (/download or /upload) take the next one instead
| extend jobTok = case(tolower(firstTok) == '/download' or tolower(firstTok) == '/upload',
tostring(tokens[1]),
firstTok)
| extend JobName = trim("'\"", jobTok) // strip any surrounding quotes
| where isnotempty(JobName)
// -- output ------------------------------------------------------------------------
| project TimeGenerated, DeviceName, DeviceId, AccountName, ProcessCommandLine, JobName
| summarize Executions = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated)
by DeviceName, DeviceId, AccountName, JobName
| order by LastSeen desc | Correct | 5 | 236.86s | 0.1186 |
o3-mini-high | AtomicBITS | DeviceProcessEvents
| where tolower(InitiatingProcessFileName) == "bitsadmin.exe" or tolower(FileName) == "bitsadmin.exe"
| where ProcessCommandLine has "/create"
| extend CustomJobName = extract(@"/create\s+(\S+)", 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, ProcessCommandLine, CustomJobName
| order by TimeGenerated desc | Correct | 1 | 11.13s | 0.0084 |
o3-mini-low | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0347 |
o4-mini-high | AtomicBITS | DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName has_cs "bitsadmin.exe"
| where ProcessCommandLine has_cs "/create"
| extend JobName = extract('(?i)/create\\s+"?([^"\\s]+)"?', 1, ProcessCommandLine)
| where isnotempty(JobName)
| project TimeGenerated, DeviceName, AccountName, ProcessId, JobName, ProcessCommandLine | Correct | 4 | 150.26s | 0.0429 |
o4-mini-low | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0445 |