// question

You notice rundll32.exe being used with desk.cpl,InstallScreenSaver on a Windows endpoint. Investigate your process creation logs to find which .scr file was loaded by this unusual invocation.

Reference KQL answer and model-by-model comparison.

83a95136-a496-423c-81d3-1c6750133917
question id
12/23
models correct
1
valid answer
52%
success rate
// reference answer

Human-validated correct answer for this question.

not_an_scr.scr
// model comparison
ModelAnswerKQL queryStatusTriesTimeCost
gemini-2.5-flash-preview-04-17
not_an_scr.scr
DeviceProcessEvents
| where FileName == "rundll32.exe"
| where ProcessCommandLine contains "desk.cpl,InstallScreenSaver"
| extend ScreenSaverFile = extract(@',InstallScreenSaver (.*\.scr)', 1, ProcessCommandLine)
| project Timestamp, DeviceName, ProcessCommandLine, ScreenSaverFile
pass18.49s0.0028
gpt-35-turbo
no answer
no query generatedfail50.00s0.0118
gpt-4-turbo-2024-04-09
no answer
no query generatedfail50.00s0.2488
gpt-4.1
not_an_scr.scr
DeviceProcessEvents
| where FileName =~ "rundll32.exe"
| where ProcessCommandLine has "desk.cpl,InstallScreenSaver" and ProcessCommandLine contains ".scr"
| extend ScreenSaverPath = extract(@"([A-Za-z]:\\[^ ]+?\.scr)", 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine, ScreenSaverPath
| order by TimeGenerated desc
pass13.93s0.0111
gpt-4.1-finetuned
not_an_scr.scr
// This query targets rundll32.exe invocations of desk.cpl for InstallScreenSaver
DeviceProcessEvents
| where InitiatingProcessCommandLine has "rundll32.exe" and InitiatingProcessCommandLine has ",InstallScreenSaver"
| where FileName =~ "rundll32.exe" and ProcessCommandLine has ",InstallScreenSaver"
| project TimeGenerated, DeviceName, ProcessCommandLine, InitiatingProcessCommandLine, FileName, ProcessCreationTime, AccountName, AccountDomain
pass16.79s0.0114
gpt-4.1-mini
not_an_scr.scr
DeviceProcessEvents
| where ProcessCommandLine has "desk.cpl,InstallScreenSaver" and FileName =~ "rundll32.exe"
| extend LoadedScrFile = extract(@"\b([\w\.-]+\.scr)\b", 1, ProcessCommandLine)
| project DeviceName, ProcessCreationTime, ProcessCommandLine, LoadedScrFile
| where isnotempty(LoadedScrFile)
| order by ProcessCreationTime desc
pass13.60s0.0023
gpt-4.1-nano
not_an_scr.scr
DeviceProcessEvents
| where FileName has "rundll32.exe"
| where ProcessCommandLine contains "desk.cpl,InstallScreenSaver"
| project ProcessId, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessFolderPath, InitiatingProcessCreationTime
| extend loadedScrFile = extract(@"(\w+\.scr)", 1, ProcessCommandLine)
| where isnotempty(loadedScrFile)
pass2174.80s0.0140
gpt-4o
not_an_scr.scr
DeviceProcessEvents
| where InitiatingProcessCommandLine contains "desk.cpl,InstallScreenSaver"
| where ProcessCommandLine contains ".scr"
| project FileName, FolderPath, ProcessCommandLine, InitiatingProcessCommandLine, TimeGenerated, DeviceName
pass330.91s0.0411
gpt-5-high
not_an_scr.scr
DeviceProcessEvents
| where ActionType == "ProcessCreated"
| where FileName =~ "rundll32.exe"
| where ProcessCommandLine has "InstallScreenSaver" and ProcessCommandLine has "desk.cpl"
// Try to capture a quoted .scr argument first, then fall back to unquoted
| extend ScreenSaverFile = coalesce(
    extract(@'(?i)"([^"]+\.scr)"', 1, ProcessCommandLine),
    extract(@'(?i)([^\s,]+\.scr)', 1, ProcessCommandLine)
  )
| where isnotempty(ScreenSaverFile)
| project TimeGenerated, DeviceName, AccountDomain, AccountName, FileName, FolderPath, ProcessCommandLine, ScreenSaverFile,
          InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessParentFileName, InitiatingProcessParentId
| order by TimeGenerated desc
pass3213.83s0.1247
gpt-5-mini-high
not_an_scr.scr
// Find rundll32.exe invocations that call desk.cpl,InstallScreenSaver and show which .scr was used or loaded
let rundll = DeviceProcessEvents
| where FileName =~ "rundll32.exe"
| where ProcessCommandLine has "desk.cpl" and ProcessCommandLine has "InstallScreenSaver"
// Try to extract a full-path .scr from the command line (case-insensitive)
| extend ScrFromCmd = extract(@"(?i)([a-zA-Z]:\\[^\"" ]+?\.scr)", 1, ProcessCommandLine)
// Fallback: extract any bare name.scr if full path wasn't present
| extend ScrFromCmd = iff(isempty(ScrFromCmd), extract(@"(?i)([^\\/\s]+?\.scr)", 1, ProcessCommandLine), ScrFromCmd)
| extend InitiatingProcessIdProc = ProcessId
| project TimeGenerated, DeviceName, ProcessId, InitiatingProcessIdProc, ProcessCreationTime, AccountName, ProcessCommandLine, ScrFromCmd;

let imageLoads = DeviceImageLoadEvents
| where FileName endswith ".scr"
| project TimeGeneratedImage = TimeGenerated, DeviceName, LoadedFileName = FileName, FolderPath, InitiatingProcessId, SHA256, MD5;

let fileEvents = DeviceFileEvents
| where FileName endswith ".scr"
| project TimeGeneratedFile = TimeGenerated, DeviceName, FileName, FolderPath, InitiatingProcessId, FileOriginUrl, FileOriginIP, SHA256;

rundll
// join image loads where the rundll process (ProcessId) is the initiator of the image load
| join kind=leftouter (imageLoads) on $left.DeviceName == $right.DeviceName and $left.InitiatingProcessIdProc == $right.InitiatingProcessId
// also join any file events for .scr files associated with the same rundll process
| join kind=leftouter (fileEvents) on $left.DeviceName == $right.DeviceName and $left.InitiatingProcessIdProc == $right.InitiatingProcessId
| project
    DetectionTime = TimeGenerated,
    DeviceName,
    ProcessId,
    ProcessCreationTime,
    AccountName,
    ProcessCommandLine,
    ScrFromCmd,
    LoadedFileName,
    FolderPath,
    FileName, // from DeviceFileEvents (may be null)
    SHA256 = coalesce(SHA256, SHA2561 = SHA256),
    MD5,
    TimeGeneratedImage,
    TimeGeneratedFile
| order by DetectionTime desc

// Notes: If your portal sets the time range externally, you don't need to add a TimeGenerated filter. Otherwise add e.g. | where TimeGenerated >= ago(7d) to limit the window.
pass135.89s0.0075
gpt-5-mini-low
no answer
no query generatedfail50.00s0.0229
gpt-5-mini-medium
no answer
no query generatedfail50.00s0.0151
gpt-5-nano-high
no answer
no query generatedfail50.00s0.0072
gpt-5-nano-medium
no answer
no query generatedfail50.00s0.0069
grok-3-beta
no answer
no query generatedfail50.00s0.0917
grok-3-mini-beta
not_an_scr.scr
DeviceProcessEvents
| where FileName == 'rundll32.exe'
| where ProcessCommandLine contains 'desk.cpl' and ProcessCommandLine contains 'InstallScreenSaver'
| extend ScrFile = extract(@'(?i)rundll32\.exe\s+desk\.cpl,InstallScreenSaver\s+([^\s]+\.scr)', 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, ProcessCommandLine, ScrFile
| order by TimeGenerated desc
pass112.77s0.0016
o1-high
not_an_scr.scr
DeviceProcessEvents
| where FileName =~ "rundll32.exe"
| where ProcessCommandLine has "desk.cpl,InstallScreenSaver"
| extend LoadedScr = extract(@"desk\.cpl,InstallScreenSaver\s+([^\s]+\.scr)", 1, ProcessCommandLine)
| where isnotempty(LoadedScr)
| project TimeGenerated, DeviceName, AccountName, InitiatingProcessAccountName, ProcessCommandLine, LoadedScr
| order by TimeGenerated desc
pass348.71s0.4229
o1-low
not_an_scr.scr
DeviceProcessEvents
| where FileName == "rundll32.exe"
| where ProcessCommandLine has_cs "desk.cpl,InstallScreenSaver"
| extend LoadedScrFile = extract(@"desk\.cpl,InstallScreenSaver\s+([^\s]+\.scr)", 1, ProcessCommandLine)
| project TimeGenerated, DeviceName, AccountDomain, AccountName, ProcessCommandLine, LoadedScrFile
| order by TimeGenerated desc
pass120.55s0.1716
o3-high
not_an_scr.scr
// -----------------------------------------------
// 1. Rundll32.exe processes that invoke InstallScreenSaver
// -----------------------------------------------
let RundllInstallSS = DeviceProcessEvents
| where FileName =~ "rundll32.exe"
| where ProcessCommandLine has_cs "desk.cpl,InstallScreenSaver"
| extend ScreenSaverPath = extract(@'[A-Za-z]:\\[^\s]+\.scr', 0, ProcessCommandLine)
| project TimeGenerated,
          DeviceId,
          DeviceName,
          AccountName,
          ScreenSaverPath,
          ProcessCommandLine,
          ProcessId,
          SHA256;

// -----------------------------------------------
// 2. .scr images actually loaded by those rundll32.exe instances
// -----------------------------------------------
let ImageLoadedSS = DeviceImageLoadEvents
| where InitiatingProcessFileName =~ "rundll32.exe"
| where InitiatingProcessCommandLine has_cs "desk.cpl,InstallScreenSaver"
| where FileName endswith_cs ".scr"
| extend ScreenSaverPath = iff(isnotempty(FolderPath), strcat(FolderPath, "\\", FileName), FileName)
| project TimeGenerated,
          DeviceId,
          DeviceName,
          AccountName = InitiatingProcessAccountName,
          ScreenSaverPath,
          ProcessCommandLine = InitiatingProcessCommandLine,
          InitiatingProcessId,
          SHA256;

// -----------------------------------------------
// 3. Combine, de-duplicate and summarise
// -----------------------------------------------
RundllInstallSS
| union ImageLoadedSS
| summarize FirstSeen = min(TimeGenerated),
            LastSeen  = max(TimeGenerated),
            Devices   = make_set(DeviceName),
            Accounts  = make_set(AccountName),
            ExampleCmdLines = make_set(ProcessCommandLine, 3)
            by ScreenSaverPath
| order by LastSeen desc
pass3119.92s0.0636
o3-mini-high
no answer
no query generatedfail50.00s0.0469
o3-mini-low
no answer
no query generatedfail50.00s0.0486
o4-mini-high
no answer
no query generatedfail50.00s0.0428
o4-mini-low
no answer
no query generatedfail50.00s0.0569