// question

A Windows host shows a process launching with install-driver switches, likely signaling malicious driver deployment. What is the name of the tool that was executed?

Reference KQL answer and model-by-model comparison.

5cb0b071-8a5a-412f-839d-116beb2ed9f7
question id
6/23
models correct
1
valid answer
26%
success rate
// reference answer

Human-validated correct answer for this question.

pnputil.exe
// model comparison
ModelAnswerKQL queryStatusTriesTimeCost
gemini-2.5-flash-preview-04-17
pnputil.exe
DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where (FileName =~ "pnputil.exe" and (ProcessCommandLine has "add-driver" or ProcessCommandLine has "install"))
      or (FileName =~ "devcon.exe" and ProcessCommandLine has "install")
      or (ProcessCommandLine has "install" and ProcessCommandLine has "driver")
| project Timestamp, DeviceName, FileName, ProcessCommandLine
pass326.55s0.0112
gpt-35-turbo
no answer
no query generatedfail50.00s0.0106
gpt-4-turbo-2024-04-09
install_helper
DeviceProcessEvents
| where ProcessCommandLine contains '/install' or ProcessCommandLine contains '/driver'
| where FileName has_any ('setup', 'install', 'update')
| project FileName, ProcessCommandLine
| distinct FileName
fail18.49s0.0497
gpt-4.1
pnputil.exe
DeviceProcessEvents
| where isnotempty(ProcessCommandLine) or isnotempty(InitiatingProcessCommandLine)
| where ProcessCommandLine has_any ('install', 'driver', 'install-driver', 'installdriver') or InitiatingProcessCommandLine has_any ('install', 'driver', 'install-driver', 'installdriver') or FileName has_any ('install', 'driver')
| summarize count() by FileName
| sort by count_ desc
pass414.30s0.0354
gpt-4.1-finetuned
no answer
no query generatedfail50.00s0.0301
gpt-4.1-mini
no answer
no query generatedfail50.00s0.0056
gpt-4.1-nano
pnputil.exe
DeviceProcessEvents
| where ProcessCommandLine contains 'install-driver' or ProcessCommandLine contains 'install drivers' or ProcessCommandLine contains 'driver'
| project InitiatingProcessFileName, ProcessCommandLine, InitiatingProcessCreationTime
| order by InitiatingProcessCreationTime desc
pass45.33s0.0010
gpt-4o
no answer
no query generatedfail50.00s0.0499
gpt-5-high
no answer
no query generatedfail50.00s0.2260
gpt-5-mini-high
pnputil.exe
let driverPattern = @"(?i)\b(install-?driver|install[_ ]driver|/install\b|-install\b|--install\b|createservice|sc\.exe|pnputil|devcon|drvinst|setupapi|add-?driver|adddriver)\b";
union
(
    DeviceProcessEvents
    | where isnotempty(ProcessCommandLine) and ProcessCommandLine matches regex driverPattern
    | project TimeGenerated, DeviceName, ToolFile = FileName, ProcessId, ProcessCreationTime, CommandLine = ProcessCommandLine, Initiator = coalesce(InitiatingProcessFileName, InitiatingProcessParentFileName), InitiatorCommandLine = InitiatingProcessCommandLine
),
(
    DeviceEvents
    | where isnotempty(ProcessCommandLine) and ProcessCommandLine matches regex driverPattern
    | project TimeGenerated, DeviceName, ToolFile = FileName, ProcessId, ProcessCreationTime, CommandLine = ProcessCommandLine, Initiator = coalesce(InitiatingProcessFileName, InitiatingProcessParentFileName), InitiatorCommandLine = InitiatingProcessCommandLine
),
(
    DeviceFileEvents
    | where isnotempty(InitiatingProcessCommandLine) and InitiatingProcessCommandLine matches regex driverPattern
    | project TimeGenerated, DeviceName, ToolFile = coalesce(InitiatingProcessFileName, InitiatingProcessParentFileName), ProcessId = InitiatingProcessId, ProcessCreationTime = InitiatingProcessCreationTime, CommandLine = InitiatingProcessCommandLine, Initiator = coalesce(InitiatingProcessFileName, InitiatingProcessParentFileName), InitiatorCommandLine = InitiatingProcessCommandLine
)
| extend MatchedToken = extract(driverPattern, 1, CommandLine)
| summarize Count = count(), LastSeen = max(TimeGenerated), ExampleCommandLine = any(CommandLine), Devices = make_set(DeviceName, 10), Initiators = make_set(Initiator, 10) by ToolFile
| where isnotempty(ToolFile)
| order by LastSeen desc
| take 50
pass253.95s0.0112
gpt-5-mini-low
pnputil.exe
// Look for processes that include driver-install related switches or known driver-install utilities
let suspicious_terms = dynamic(["install-driver","install driver","/install-driver","/install","-install","pnputil","devcon","sc.exe","sc ","driverinstall","install-driver.exe","/add-driver","/install-driver /file","-install-driver","/add"]); 

// Search DeviceProcessEvents and DeviceEvents for matching command lines
let procEvents =
    DeviceProcessEvents
    | where isnotempty(ProcessCommandLine)
    | where tolower(ProcessCommandLine) has_any (suspicious_terms)
    | extend ToolName = iff(isnotempty(FileName) and FileName != "", tostring(FileName), tostring(split(trim('"', ProcessCommandLine), ' ')[0]))
    | extend ToolName = extract(@"([^\\/]+\\.exe)$", 1, ToolName)
    | project TimeGenerated, SourceTable = "DeviceProcessEvents", DeviceName, AccountName, ProcessId, FileName, ToolName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessId = InitiatingProcessId, MD5, SHA1, SHA256;

let evEvents =
    DeviceEvents
    | where isnotempty(ProcessCommandLine)
    | where tolower(ProcessCommandLine) has_any (suspicious_terms)
    | extend ToolName = iff(isnotempty(FileName) and FileName != "", tostring(FileName), tostring(split(trim('"', ProcessCommandLine), ' ')[0]))
    | extend ToolName = extract(@"([^\\/]+\\.exe)$", 1, ToolName)
    | project TimeGenerated, SourceTable = "DeviceEvents", DeviceName, AccountName, ProcessId = ProcessId, FileName, ToolName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessId = InitiatingProcessId, MD5, SHA1, SHA256;

union isfuzzy=true procEvents, evEvents
| where isnotempty(ToolName) or isnotempty(FileName)
| extend ToolName = iff(isnotempty(ToolName) and ToolName != "", ToolName, tostring(FileName))
| extend ToolName = tostring(ToolName)
| summarize Hits = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by ToolName, DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessId, MD5, SHA1, SHA256
| order by LastSeen desc
| project ToolName, Hits, FirstSeen, LastSeen, DeviceName, AccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessId, MD5, SHA1, SHA256
pass329.30s0.0105
gpt-5-mini-medium
pnputil.exe
// Search for processes that include 'install-driver' or similar driver install switches in their command lines
let keywords = dynamic(["install-driver","install_driver","--install-driver","/install-driver","-install-driver","/i","-i","--install"]);
// DeviceProcessEvents has richer process fields; also include DeviceEvents to catch other records
union isfuzzy=true DeviceProcessEvents, DeviceEvents
| where TimeGenerated between (startofday(ago(14d)) .. now())
| where ProcessCommandLine has_any (keywords) or InitiatingProcessCommandLine has_any (keywords) or ProcessCommandLine has "installdriver" or InitiatingProcessCommandLine has "installdriver"
| extend ToolFile = coalesce(FileName, ProcessVersionInfoOriginalFileName, ProcessVersionInfoInternalFileName, InitiatingProcessFileName, InitiatingProcessVersionInfoOriginalFileName)
| extend CommandLine = tostring(coalesce(ProcessCommandLine, InitiatingProcessCommandLine, AdditionalFields.CommandLine, ""))
| project TimeGenerated, DeviceName, ToolFile, CommandLine, ProcessId, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessId, FolderPath, InitiatingProcessFolderPath, AccountName, InitiatingProcessAccountName, ReportId
| summarize count(), any(CommandLine), any(InitiatingProcessFileName), any(InitiatingProcessCommandLine), any(InitiatingProcessId), any(AccountName) by ToolFile, DeviceName
| sort by count_ desc
| top 50 by count_
pass112.58s0.0041
gpt-5-nano-high
no answer
no query generatedfail50.00s0.0080
gpt-5-nano-medium
no answer
no query generatedfail50.00s0.0071
grok-3-beta
no answer
no query generatedfail50.00s0.0835
grok-3-mini-beta
no answer
no query generatedfail50.00s0.0068
o1-high
no answer
no query generatedfail50.00s0.7220
o1-low
no answer
no query generatedfail50.00s0.7187
o3-high
no answer
no query generatedfail50.00s0.0682
o3-mini-high
no answer
no query generatedfail50.00s0.0407
o3-mini-low
no answer
no query generatedfail50.00s0.0376
o4-mini-high
no answer
no query generatedfail50.00s0.0427
o4-mini-low
no answer
no query generatedfail50.00s0.0371