Question Analysis
On Windows, review PowerShell process events to spot where a remote .ps1 was fetched and run to pull vault credentials. Determine the name of the script file that was downloaded.
c89becbe-1758-4e7d-a0f4-97d2188a23e3
Question ID
8/23
Models Correct
1
Valid Answer
35%
Success Rate
Reference Answer
Human-validated correct answer for this question
GetCredmanCreds.ps1
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 | GetCredmanCreds.ps1 | DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName =~ "powershell.exe"
// Look for common in-memory execution patterns involving remote sources
| where ProcessCommandLine has_any ("iex", "invoke-expression", "downloadstring", "invoke-webrequest")
and (ProcessCommandLine has "http://" or ProcessCommandLine has "https://")
// Extract potential remote source URL from the command line
| extend RemoteSourceUrl = extract(@'http[s]?://[^\s"]+', 0, ProcessCommandLine)
// Attempt to get the path/filename part from the URL
| extend PotentialScriptName = iif(isnotempty(RemoteSourceUrl), parse_url(RemoteSourceUrl).Path, "")
| project Timestamp, DeviceName, InitiatingProcessCommandLine, ProcessCommandLine, AccountName, RemoteSourceUrl, PotentialScriptName, ProcessId | Correct | 1 | 31.70s | 0.0162 |
gpt-35-turbo | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0110 |
gpt-4-turbo-2024-04-09 | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.2672 |
gpt-4.1 | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0601 |
gpt-4.1-finetuned | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0325 |
gpt-4.1-mini | GetCredmanCreds.ps1 | DeviceProcessEvents
| where FileName has "powershell" or FileName has "pwsh"
| where ProcessCommandLine has "http" or ProcessCommandLine has "https"
| extend ScriptUri = extract(@"(https?://[^\s']+\.ps1)", 1, ProcessCommandLine)
| where isnotempty(ScriptUri)
| extend ScriptName = extract(@"([^/]+\.ps1)", 1, ScriptUri)
| project TimeGenerated, DeviceName, AccountName, ProcessCreationTime, ProcessCommandLine, ScriptUri, ScriptName
| order by TimeGenerated desc | Correct | 1 | 4.50s | 0.0036 |
gpt-4.1-nano | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0015 |
gpt-4o | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0686 |
gpt-5-high | GetCredmanCreds.ps1 | let PwshBinaries = dynamic(["powershell.exe","pwsh.exe","powershell_ise.exe"]);
let VaultKeywords = dynamic(["vault","cyberark","hashicorp","secret","secrets","credential","credentials","creds"]);
let UrlPs1Regex = @"(?i)https?://[^\s'""`]+?\.ps1(?:[?#][^\s'""`]*)?";
let InMemoryExecRegex = @"(?i)(\|\s*iex\b|\binvoke-expression\b)";
let PSFetch =
DeviceProcessEvents
| where FileName in (PwshBinaries)
| where ProcessCommandLine has_any ("http","https",".ps1")
| where ProcessCommandLine matches regex @"(?i)(iwr|invoke-webrequest|irm|invoke-restmethod|start-bitstransfer|bitsadmin|downloadstring|downloadfile|System\.Net\.WebClient|Net\.WebClient|curl|wget)"
| extend RemotePs1Url = tostring(extract(UrlPs1Regex, 0, ProcessCommandLine))
| extend LocalOutFile = coalesce(
tostring(extract(@"(?i)-Out(File)?\s+(?:['""])?([^\s'""]+?\.ps1)", 2, ProcessCommandLine)),
tostring(extract(@"(?i)-Destination\s+(?:['""])?([^\s'""]+?\.ps1)", 1, ProcessCommandLine)),
tostring(extract(@"(?i)DownloadFile\([^,]+,\s*['""]([^'""]+?\.ps1)['""]", 1, ProcessCommandLine)),
tostring(extract(@"(?i)\s-o\s+(?:['""])?([^\s'""]+?\.ps1)", 1, ProcessCommandLine))
)
| extend RemoteScriptName = iif(isnotempty(RemotePs1Url), tostring(split(parse_url(RemotePs1Url).Path, "/")[-1]), "")
| extend LocalScriptName = iif(isnotempty(LocalOutFile), tostring(split(replace_string(LocalOutFile,'/','\\'), "\\")[-1]), "")
| extend DownloadedScriptName = coalesce(LocalScriptName, RemoteScriptName)
| extend ExecutedInMemory = iif(ProcessCommandLine matches regex InMemoryExecRegex, true, false)
| extend VaultRelated = iif(ProcessCommandLine has_any (VaultKeywords) or tostring(DownloadedScriptName) has_any (VaultKeywords) or tostring(RemotePs1Url) has_any (VaultKeywords), true, false)
| project FetchEventTime=TimeGenerated, DeviceId, DeviceName, AccountDomain, AccountName, ProcessId, ProcessCommandLine, RemotePs1Url, LocalOutFile, DownloadedScriptName, ExecutedInMemory, VaultRelated, SHA1
;
let PSExecLocal =
DeviceProcessEvents
| where FileName in (PwshBinaries)
| where ProcessCommandLine matches regex @"(?i)\s-File\s+['""]?([^\s'""]+\.ps1)"
| extend ExecutedLocalPath = tostring(extract(@"(?i)\s-File\s+['""]?([^\s'""]+\.ps1)", 1, ProcessCommandLine))
| extend ExecutedScriptName = tostring(split(replace_string(ExecutedLocalPath,'/','\\'), "\\")[-1])
| project ExecEventTime=TimeGenerated, DeviceId, ExecutedLocalPath, ExecutedScriptName
;
PSFetch
| join kind=leftouter (
PSExecLocal
) on DeviceId
| where isnull(ExecEventTime) or (ExecEventTime between (FetchEventTime .. FetchEventTime + 30m))
| extend CorrelatedExecution = iif(isnotempty(ExecutedLocalPath) and (tolower(ExecutedScriptName) == tolower(DownloadedScriptName) or (isnotempty(DownloadedScriptName) and tolower(ExecutedLocalPath) has tolower(DownloadedScriptName))), true, ExecutedInMemory)
| extend FinalScriptName = coalesce(DownloadedScriptName, ExecutedScriptName)
| where VaultRelated == true
| project Time=FetchEventTime, DeviceName, AccountName, ProcessId, RemotePs1Url, LocalOutFile, FinalScriptName, WasExecuted=CorrelatedExecution, InMemoryIEX=ExecutedInMemory, ProcessCommandLine
| order by Time desc | Correct | 1 | 144.05s | 0.0825 |
gpt-5-mini-high | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0235 |
gpt-5-mini-low | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0301 |
gpt-5-mini-medium | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0205 |
gpt-5-nano-high | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0084 |
gpt-5-nano-medium | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0112 |
grok-3-beta | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0987 |
grok-3-mini-beta | T1572-doh-beacon.ps1 | DeviceProcessEvents
| where FileName == 'powershell.exe'
| where ProcessCommandLine contains '.ps1' and (ProcessCommandLine contains 'http' or ProcessCommandLine contains 'Invoke-WebRequest')
| project ScriptFileName = extract(@"[^\\]+?\.ps1$", 0, ProcessCommandLine), Timestamp, DeviceName, ProcessCommandLine
| summarize arg_max(Timestamp, *) by ScriptFileName
| order by Timestamp desc
| limit 100 // Limit results for review; adjust as needed | Incorrect | 1 | 16.97s | 0.0016 |
o1-high | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.8259 |
o1-low | GetCredmanCreds.ps1 | DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName in~ ("powershell.exe", "pwsh.exe", "powershell_ise.exe")
| where ProcessCommandLine has_any ("http://", "https://") and ProcessCommandLine has ".ps1"
| project TimeGenerated,
DeviceName,
AccountName,
ProcessCommandLine,
DownloadedScript = extract("(https?://[^ ]+\\.ps1)", 0, ProcessCommandLine)
| order by TimeGenerated desc | Correct | 2 | 55.42s | 0.4529 |
o3-high | GetCredmanCreds.ps1 | // --- Remote PowerShell script download & execution ----------------------------
let PowerShellHosts = dynamic(["powershell.exe","pwsh.exe","powershell_ise.exe"]);
DeviceProcessEvents
// (The hunting portal will inject the overall time-range automatically)
| where FileName in~ (PowerShellHosts)
// High-level filter – keep only PowerShell that references the web
| where ProcessCommandLine has "http" or ProcessCommandLine has "https"
// -----------------------------------------------------------------------------
// If the command is Base-64 encoded (-enc/-encodedCommand) pull it out & decode
| extend EncodedCmd = extract(@"-(enc|encodedcommand)\s+([A-Za-z0-9+/=]+)", 2, ProcessCommandLine, typeof(string))
| extend DecodedCmd = iff(isnotempty(EncodedCmd), base64_decode_tostring(EncodedCmd), "")
| extend FullCommand = iff(isnotempty(DecodedCmd), strcat(ProcessCommandLine, " ", DecodedCmd), ProcessCommandLine)
// -----------------------------------------------------------------------------
// Locate the first HTTP/S URL that ends with .ps1 in the clear or decoded text
| extend RemoteScriptUrl = extract("https?://\\S+\\.ps1", 0, FullCommand, typeof(string))
| where isnotempty(RemoteScriptUrl)
// Derive the script file name (text after the final "/")
| extend ScriptName = tostring(split(RemoteScriptUrl, "/")[-1])
// -----------------------------------------------------------------------------
// Analyst-friendly view
| project TimeGenerated, DeviceName, AccountName, ScriptName, RemoteScriptUrl, FullCommand
| order by TimeGenerated desc
// Uncomment below if you need a quick unique list of scripts and how often/where
// | summarize FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated), Executions=count(), Devices=make_set(DeviceName) by ScriptName, RemoteScriptUrl
// | order by Executions desc | Correct | 3 | 133.48s | 0.0902 |
o3-mini-high | GetCredmanCreds.ps1 | DeviceProcessEvents
| where FileName =~ "powershell.exe"
| where ProcessCommandLine matches regex "https?://[^\\s]+\\.ps1"
| extend ScriptFullURL = extract("(https?://[^\\s]+\\.ps1)", 1, ProcessCommandLine)
| extend ScriptName = tostring(split(ScriptFullURL, "/")[-1])
| project TimeGenerated, DeviceName, ProcessCommandLine, ScriptName | Correct | 3 | 31.53s | 0.0281 |
o3-mini-low | GetCredmanCreds.ps1 | DeviceProcessEvents
| where FileName =~ "powershell.exe"
| where ProcessCommandLine contains ".ps1" and ProcessCommandLine contains "http"
| extend ScriptName = extract(@"(?:http[s]?://\S*/)?([\w\-.]+\.ps1)", 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, AccountName, ProcessId, ScriptName, ProcessCommandLine
| order by TimeGenerated desc | Correct | 2 | 101.05s | 0.0243 |
o4-mini-high | GetCredmanCreds.ps1 | DeviceProcessEvents
| where FileName in ("powershell.exe", "pwsh.exe")
| where ProcessCommandLine matches regex @"https?://\S+?\.ps1"
| extend ScriptUrl = extract(@"https?://\S+?\.ps1", 0, ProcessCommandLine)
| extend ScriptName = extract(@"([^/]+\.ps1)$", 1, ScriptUrl)
| project TimeGenerated, DeviceName, InitiatingProcessAccountName, ScriptUrl, ScriptName, ProcessCommandLine
| sort by TimeGenerated desc | Correct | 2 | 103.80s | 0.0260 |
o4-mini-low | No answer provided | No query generated | Incorrect | 5 | 0.00s | 0.0420 |