// question

On the Windows device, a security check was run to detect debugger processes via PowerShell. Which tool (process) carried out this check?

Reference KQL answer and model-by-model comparison.

58bd8c8d-3a1a-4467-a69c-439c75469b07
question id
11/23
models correct
1
valid answer
48%
success rate
// reference answer

Human-validated correct answer for this question.

powershell
// model comparison
ModelAnswerKQL queryStatusTriesTimeCost
gemini-2.5-flash-preview-04-17
powershell.exe
DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName =~ "powershell.exe"
| where ProcessCommandLine has_any ("Get-Process", "debugger", "windbg", "ollydbg", "x64dbg", "ida", "process") // Added "process" as a more general term
| distinct InitiatingProcessFileName, InitiatingProcessCommandLine
| project InitiatingProcessFileName, InitiatingProcessCommandLine
pass111.29s0.0054
gpt-35-turbo
no answer
no query generatedfail50.00s0.0109
gpt-4-turbo-2024-04-09
no answer
no query generatedfail50.00s0.2275
gpt-4.1
no answer
no query generatedfail50.00s0.0374
gpt-4.1-finetuned
no answer
no query generatedfail50.00s0.0408
gpt-4.1-mini
powershell.exe
DeviceProcessEvents
| where FileName has "powershell"
| where ProcessCommandLine has_any ("debugger", "debug", "attach")
| project DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessCommandLine, TimeGenerated
| sort by TimeGenerated desc
pass13.29s0.0022
gpt-4.1-nano
no answer
no query generatedfail50.00s0.0012
gpt-4o
no answer
no query generatedfail50.00s0.0646
gpt-5-high
no answer
no query generatedfail50.00s0.2841
gpt-5-mini-high
senseir.exe
let pattern = @"(?i)(isdebuggerpresent|isdebuggerpresent\(\)|debugger(attached)?|checkdebugger|ntqueryinformationprocess|debugactiveprocess|enumeratedebuggers|get-process|get-module|get-childitem|get-wmiobject|get-ciminstance|\-executionpolicy\s*bypass|\-noprofile)";

// Search DeviceProcessEvents and DeviceEvents for PowerShell commands that mention debugger-related keywords
(
    DeviceProcessEvents
    | where TimeGenerated between (startofday(ago(7d))..now())
    | extend CmdLine = coalesce(ProcessCommandLine, InitiatingProcessCommandLine, "")
    | where tolower(CmdLine) has_any ("powershell","pwsh","powershell.exe","powershell_ise")
    | where CmdLine matches regex pattern
    | project TimeGenerated, DeviceName, Table = "DeviceProcessEvents", ProcessId, ProcessFileName = FileName, ProcessCommandLine = CmdLine, InitiatingProcessFileName, InitiatingProcessId
)
| union (
    DeviceEvents
    | where TimeGenerated between (startofday(ago(7d))..now())
    | extend CmdLine = coalesce(ProcessCommandLine, InitiatingProcessCommandLine, "")
    | where tolower(CmdLine) has_any ("powershell","pwsh","powershell.exe","powershell_ise")
    | where CmdLine matches regex pattern
    | project TimeGenerated, DeviceName, Table = "DeviceEvents", ProcessId, ProcessFileName = FileName, ProcessCommandLine = CmdLine, InitiatingProcessFileName, InitiatingProcessId
)
| summarize Hits = count(), AnyProcessCommandLine = any(ProcessCommandLine), AnyInitiatingProcessCommandLine = any(InitiatingProcessFileName) by DeviceName, InitiatingProcessFileName, InitiatingProcessId, ProcessFileName, ProcessId
| order by Hits desc
| take 50
fail236.17s0.0102
gpt-5-mini-low
powershell.exe
let indicators = dynamic(["isdebuggerpresent","checkremotedebuggerpresent","get-process","get-module","windbg","x64dbg","olly","ida","ida64","cheatengine","frida","dbg","debugger"]);
union DeviceProcessEvents, DeviceEvents
| where isnotempty(ProcessCommandLine) or isnotempty(InitiatingProcessCommandLine)
| where (tolower(ProcessCommandLine) contains "powershell" or tolower(InitiatingProcessCommandLine) contains "powershell")
| where ( (isnotempty(ProcessCommandLine) and tolower(ProcessCommandLine) has_any (indicators)) or (isnotempty(InitiatingProcessCommandLine) and tolower(InitiatingProcessCommandLine) has_any (indicators)) )
| project TimeGenerated, DeviceName, ProcessFileName = FileName, ProcessCommandLine, ProcessId, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessId, InitiatingProcessAccountName, InitiatingProcessAccountDomain
| summarize Count = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated) by DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessAccountName, InitiatingProcessAccountDomain, ProcessFileName, ProcessCommandLine
| order by Count desc
| top 50 by Count
pass250.24s0.0118
gpt-5-mini-medium
powershell.exe
// Find PowerShell executions that check for debugger/processes and show which tool/process initiated them
let suspiciousPS = DeviceProcessEvents
| where FileName has_cs "powershell" or ProcessCommandLine has_cs "powershell"
// look for common debugger-check keywords in the command line
| where ProcessCommandLine has_any ("Get-Process", "-Name Debug", "Debugger", "Get-WmiObject", "Get-CimInstance", "IsDebuggerPresent", "-match 'debug'", "Where-Object", "Get-ItemProperty" , "-and $_.Debugger", "Wow64" )
| project TimeGenerated, DeviceId, DeviceName, ProcessId, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessId, InitiatingProcessCommandLine, InitiatingProcessAccountName, InitiatingProcessAccountDomain
;

// Also search DeviceEvents for PowerShell actions with suspicious command lines (fallback)
let ev = DeviceEvents
| where FileName has_cs "powershell" or ProcessCommandLine has_cs "powershell" or InitiatingProcessFileName has_cs "powershell" or InitiatingProcessCommandLine has_cs "powershell"
| where ProcessCommandLine has_any ("Get-Process", "Debugger", "Get-WmiObject", "Get-CimInstance", "IsDebuggerPresent", "Where-Object", "-match 'debug'", "-Name Debug")
| project TimeGenerated, DeviceId, DeviceName, FileName, ProcessId, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessId, InitiatingProcessCommandLine, InitiatingProcessAccountName, InitiatingProcessAccountDomain
;

// Union and show initiating process details (tool that carried out the check)
union suspiciousPS, ev
| where isnotempty(InitiatingProcessFileName) or isnotempty(InitiatingProcessCommandLine)
| extend Initiator = coalesce(InitiatingProcessFileName, tostring(split(InitiatingProcessCommandLine, ' ')[0]))
| summarize count() , any(InitiatingProcessAccountName), any(InitiatingProcessAccountDomain), any(InitiatingProcessId), any(InitiatingProcessCommandLine) by Initiator, DeviceName, DeviceId
| order by count_ desc
| take 50
pass116.07s0.0034
gpt-5-nano-high
no answer
no query generatedfail50.00s0.0074
gpt-5-nano-medium
powershell.exe
DeviceProcessEvents
| where FileName in ("powershell.exe","pwsh.exe")
| where isnotempty(InitiatingProcessFileName)
| project TimeGenerated, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessCommandLine
| summarize by InitiatingProcessFileName, InitiatingProcessCommandLine, DeviceName
| order by DeviceName asc
| take 50
pass141.60s0.0021
grok-3-beta
powershell.exe
DeviceProcessEvents
| where TimeGenerated > ago(7d)
| where InitiatingProcessFileName contains 'powershell'
| where ProcessCommandLine contains 'debugger'
| project Timestamp, DeviceName, InitiatingProcessFileName, ProcessCommandLine, AccountName
| order by Timestamp desc
pass17.93s0.0209
grok-3-mini-beta
powershell.exe
DeviceProcessEvents
| where InitiatingProcessFileName =~ "powershell.exe"
| project Timestamp, DeviceName, InitiatingProcessCommandLine, InitiatingProcessFileName
| order by Timestamp desc
| take 10
pass115.21s0.0020
o1-high
powershell.exe
DeviceProcessEvents
| where FileName =~ "powershell.exe"
| where ProcessCommandLine has_any ("debugger", "Get-Process", "windbg", "debug")
| project TimeGenerated, DeviceName, DeviceId, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessFolderPath, InitiatingProcessVersionInfoCompanyName
| order by TimeGenerated desc
pass131.49s0.2572
o1-low
CreateProcessWithPipe.exe
DeviceProcessEvents
| where FileName in~ ("powershell.exe", "powershell_ise.exe", "pwsh.exe")
| where ProcessCommandLine has_any ("debug", "debugger")
| project TimeGenerated, DeviceName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by TimeGenerated desc
fail136.85s0.2815
o3-high
powershell.exe
let debugger_keywords = dynamic(["dbg","debug","windbg","x32dbg","x64dbg","ollydbg","ida","dnSpy","devenv","vsjitdebugger","gflags"]);
DeviceProcessEvents
| where FileName in~ ("powershell.exe","pwsh.exe","powershell_ise.exe")
// PowerShell commands that try to find debugger processes
| where ProcessCommandLine has_any (debugger_keywords)
       or ProcessCommandLine matches regex @"(?i)Get-Process.*dbg"
       or ProcessCommandLine matches regex @"(?i)tasklist.*dbg"
| project TimeGenerated,
          DeviceName,
          PowerShellCommand = ProcessCommandLine,
          InitiatingTool      = InitiatingProcessFileName,
          InitiatingToolPath  = InitiatingProcessFolderPath,
          InitiatingToolCmd   = InitiatingProcessCommandLine
| summarize FirstSeen=min(TimeGenerated),
            LastSeen = max(TimeGenerated),
            Executions=count() 
            by DeviceName, InitiatingTool, InitiatingToolPath, InitiatingToolCmd
| order by Executions desc
pass133.85s0.0224
o3-mini-high
no answer
no query generatedfail50.00s0.0479
o3-mini-low
powershell.exe
union withsource=EventSource DeviceProcessEvents, DeviceEvents
| where FileName =~ "powershell.exe"
| extend PS_CmdLine = tolower(tostring(ProcessCommandLine)), Init_CmdLine = tolower(tostring(InitiatingProcessCommandLine))
// Look for mentions of debug in either the PowerShell process or its initiator's command line
| where PS_CmdLine contains "debug" or Init_CmdLine contains "debug"
// Summarize by the initiating process name, which is the tool that launched PowerShell
| summarize EventCount = count() by InitiatingProcessFileName, EventSource
| order by EventCount desc
pass453.57s0.0408
o4-mini-high
powershell.exe
// 1) Find PowerShell instances invoking debugger checks
let psDebugChecks = DeviceProcessEvents
| where FileName == "powershell.exe"
// look for debugger‐related keywords in the PS command line
| where ProcessCommandLine has_any ("Debugger", "-Debug", "Test-ProcessDebugger")
| project TimeGenerated, DeviceName, PsProcessId = ProcessId, ParentProcessId = InitiatingProcessParentId, PsCommandLine = ProcessCommandLine;

// 2) Lookup parent process details
let parentInfo = DeviceProcessEvents
| project ParentProcessId = ProcessId, ParentFileName = FileName, ParentCommandLine = ProcessCommandLine;

// 3) Join and summarize unique parent tools
psDebugChecks
| join kind=leftouter parentInfo on ParentProcessId
| project TimeGenerated, DeviceName, ParentFileName, ParentCommandLine, PsCommandLine
| distinct ParentFileName, ParentCommandLine
| order by ParentFileName
pass152.49s0.0161
o4-mini-low
no answer
no query generatedfail50.00s0.0445