// question

An analyst suspects a user or script ran a service enumeration command on a Linux system. Review process events to find the service-listing invocation and specify the full command that was executed.

Reference KQL answer and model-by-model comparison.

f4b26bce-4c2c-46c0-bcc5-fce062d38bef
question id
7/23
models correct
1
valid answer
30%
success rate
// reference answer

Human-validated correct answer for this question.

systemctl --type=service
// model comparison
ModelAnswerKQL queryStatusTriesTimeCost
gemini-2.5-flash-preview-04-17
no answer
no query generatedfail50.00s0.0369
gpt-35-turbo
no answer
no query generatedfail50.00s0.0111
gpt-4-turbo-2024-04-09
no answer
no query generatedfail50.00s0.2307
gpt-4.1
bash -c 'if [ "$(uname)" = 'FreeBSD' ]; then service -e; else systemctl --type=service; fi;'
DeviceProcessEvents
| where ActionType == 'ProcessCreated'
| where ProcessCommandLine has_any ('systemctl list-units', 'systemctl --type=service', 'service --status-all', 'initctl list', 'rc-status', 'chkconfig --list')
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine, FileName, InitiatingProcessAccountName
| order by TimeGenerated desc
pass17.14s0.0133
gpt-4.1-finetuned
no answer
no query generatedfail50.00s0.0457
gpt-4.1-mini
systemctl status himdsd
DeviceProcessEvents
| where ProcessCommandLine has_any ("systemctl", "service", "ps", "netstat", "ss", "chkconfig", "systemd")
| where Timestamp between (startofday(ago(30d)) .. endofday(now()))
| project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, ProcessCreationTime
| order by TimeGenerated desc
| take 50
fail328.98s0.0082
gpt-4.1-nano
ps aux or ps -ef
DeviceProcessEvents
| where ProcessCommandLine has_any ('systemctl list-units', 'service --status-all', 'ps aux', 'ps -ef')
| project TimeGenerated, DeviceName, InitiatingProcessFileName, ProcessCommandLine
| order by TimeGenerated desc
fail12.68s0.0008
gpt-4o
no answer
no query generatedfail50.00s0.0598
gpt-5-high
systemctl --type=service
let linux_devices = DeviceInfo
| where OSPlatform =~ "Linux"
| project DeviceId, DeviceName, OSPlatform, MachineGroup;
DeviceProcessEvents
| where ActionType == "ProcessCreated"
| join kind=inner (linux_devices) on DeviceId
| where
  (
    // systemctl variants that list services
    (tolower(FileName) == "systemctl" and (
        ProcessCommandLine has "list-units"
        or ProcessCommandLine has "list-unit-files"
        or ProcessCommandLine has "--type=service"
        or ProcessCommandLine has "-t service"
        or ProcessCommandLine has "--type service"
        or ProcessCommandLine has " -a"    // default action (list-units) with all
        or ProcessCommandLine has " --all"
    ))
    or
    // SysV service enumeration
    (tolower(FileName) == "service" and ProcessCommandLine has "--status-all")
    or
    // chkconfig list
    (tolower(FileName) == "chkconfig" and ProcessCommandLine has "--list")
    or
    // Upstart list
    (tolower(FileName) == "initctl" and ProcessCommandLine has "list")
    or
    // OpenRC
    (tolower(FileName) == "rc-update" and ProcessCommandLine has "show")
    or
    (tolower(FileName) == "rc-service" and (ProcessCommandLine has " -l" or ProcessCommandLine has " --list"))
    or
    (tolower(FileName) == "rc-status")
    or
    // runit
    (tolower(FileName) == "sv" and ProcessCommandLine has "status")
  )
| extend MatchHint = case(
    tolower(FileName) == "systemctl" and ProcessCommandLine has "list-units", "systemctl list-units",
    tolower(FileName) == "systemctl" and ProcessCommandLine has "list-unit-files", "systemctl list-unit-files",
    tolower(FileName) == "systemctl" and (ProcessCommandLine has "--type=service" or ProcessCommandLine has "-t service" or ProcessCommandLine has "--type service"), "systemctl --type=service",
    tolower(FileName) == "systemctl" and (ProcessCommandLine has " -a" or ProcessCommandLine has " --all"), "systemctl -a/--all",
    tolower(FileName) == "service" and ProcessCommandLine has "--status-all", "service --status-all",
    tolower(FileName) == "chkconfig" and ProcessCommandLine has "--list", "chkconfig --list",
    tolower(FileName) == "initctl" and ProcessCommandLine has "list", "initctl list",
    tolower(FileName) == "rc-update" and ProcessCommandLine has "show", "rc-update show",
    tolower(FileName) == "rc-service" and (ProcessCommandLine has " -l" or ProcessCommandLine has " --list"), "rc-service -l/--list",
    tolower(FileName) == "rc-status", "rc-status",
    tolower(FileName) == "sv" and ProcessCommandLine has "status", "sv status",
    "other")
| project Timestamp, DeviceName, AccountName, AccountUpn, FileName, ProcessCommandLine, MatchHint, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessId, InitiatingProcessId, MachineGroup
| order by Timestamp desc
pass1136.61s0.0722
gpt-5-mini-high
systemctl --type=service
// Search for common Linux service enumeration commands across process events and device events
let service_patterns = dynamic([
  "systemctl list-units",
  "systemctl --type=service",
  "systemctl status",
  "service --status-all",
  "ls /etc/init.d",
  "chkconfig --list",
  "svcs -a",
  "rcsvcs -a",
  "systemctl list-units --type=service",
  "service --status-all 2>&1",
  "systemctl --all",
  "systemctl --type=service --all",
  "systemctl list-unit-files",
  "systemctl --failed"
]);

// DeviceProcessEvents (recommended for process command lines)
let dpe = DeviceProcessEvents
| where TimeGenerated >= ago(30d)
| where isnotempty(ProcessCommandLine)
| where FileName has_any ("systemctl","service","chkconfig","svcs","rcsvcs","ls","systemctl")
| where array_length(service_patterns) == array_length(service_patterns) or true
| where (
    ProcessCommandLine has "systemctl" or
    ProcessCommandLine has "service --status-all" or
    ProcessCommandLine has "/etc/init.d" or
    ProcessCommandLine has "chkconfig" or
    ProcessCommandLine has "svcs -a" or
    ProcessCommandLine has "rcsvcs -a"
  )
| extend Command = ProcessCommandLine, Account = tostring(AccountName)
| project TimeGenerated, DeviceName, FileName, ProcessId, Command, Account, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessCreationTime, ReportId, TenantId
;

// DeviceEvents may also contain process command lines
let de = DeviceEvents
| where TimeGenerated >= ago(30d)
| where isnotempty(ProcessCommandLine)
| where ProcessCommandLine has_any ("systemctl","service","chkconfig","svcs","rcsvcs","/etc/init.d","ls /etc/init.d")
| extend Command = ProcessCommandLine, Account = tostring(AccountName)
| project TimeGenerated, DeviceName, FileName, ProcessId, Command, Account, InitiatingProcessFileName, InitiatingProcessCommandLine, ProcessCreationTime, ReportId, TenantId
;

// Union results and deduplicate by Command + Device + ProcessId
union dpe, de
| sort by TimeGenerated desc
| extend match = case(
    Command has "systemctl", "systemctl",
    Command has "service --status-all", "service",
    Command has "/etc/init.d", "init.d",
    Command has "chkconfig", "chkconfig",
    Command has "svcs", "svcs",
    Command has "rcsvcs", "rcsvcs",
    Command has "launchctl", "launchctl",
    "other")
| summarize FirstSeenUtc = min(TimeGenerated), LastSeenUtc = max(TimeGenerated), count() by Command, DeviceName, FileName, ProcessId, Account, InitiatingProcessFileName, InitiatingProcessCommandLine
| sort by LastSeenUtc desc
| project LastSeenUtc, FirstSeenUtc, DeviceName, FileName, ProcessId, Account, Command, InitiatingProcessFileName, InitiatingProcessCommandLine, count_
| take 200
pass120.90s0.0076
gpt-5-mini-low
systemctl --type=service
let linuxDevices = DeviceInfo
| where isnotempty(DeviceId)
| where tolower(tostring(OSPlatform)) contains "linux"
    or tolower(tostring(OSDistribution)) contains "linux"
    or tolower(tostring(OSVersionInfo)) contains "linux"
| distinct DeviceId;

let procEvents = union
(
    DeviceProcessEvents
    | project TimeGenerated, DeviceId, DeviceName, AccountName, AccountDomain=AccountDomain, FileName, ProcessId, ProcessCreationTime, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessId, InitiatingProcessCommandLine, InitiatingProcessAccountName, InitiatingProcessAccountDomain, ReportId
),
(
    DeviceEvents
    | project TimeGenerated, DeviceId, DeviceName, AccountName, AccountDomain=AccountDomain, FileName, ProcessId=ProcessId, ProcessCreationTime=ProcessCreationTime, ProcessCommandLine=ProcessCommandLine, InitiatingProcessFileName=InitiatingProcessFileName, InitiatingProcessId=InitiatingProcessId, InitiatingProcessCommandLine=InitiatingProcessCommandLine, InitiatingProcessAccountName=InitiatingProcessAccountName, InitiatingProcessAccountDomain=InitiatingProcessAccountDomain, ReportId
);

procEvents
| where DeviceId in (linuxDevices)
| where isnotempty(ProcessCommandLine)
| extend CommandLine = trim(" '\"`", tostring(ProcessCommandLine))
| extend lcmd = tolower(CommandLine)
| where lcmd contains "systemctl"
    or lcmd contains "service --status-all"
    or lcmd contains "/etc/init.d"
    or lcmd contains "chkconfig"
    or lcmd contains "initctl"
    or lcmd contains "list-units"
    or lcmd contains "list-unit-files"
    or lcmd contains "--type=service"
    or (lcmd contains "ps aux" and lcmd contains "grep")
    or (lcmd contains "ps -ef" and lcmd contains "grep")
    or lcmd contains "rc-service"
    or lcmd contains "rc-status"
    or lcmd contains "svcadm"
    or lcmd contains "ss -ltnp"
    or lcmd contains "ss -tulpn"
    or lcmd contains "netstat -tuln"
    or lcmd contains "/sbin/service"
| summarize Count = count(), FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), Devices = make_set(DeviceName, 20), DeviceIds = make_set(DeviceId, 20), Accounts = make_set(AccountName, 20), AnyProcessId = any(ProcessId), AnyFile = any(FileName), AnyInitiatingProcess = any(InitiatingProcessFileName) by CommandLine
| sort by LastSeen desc
| limit 500
pass597.28s0.0252
gpt-5-mini-medium
no answer
no query generatedfail50.00s0.0196
gpt-5-nano-high
sh -c "systemctl status himdsd 1>/dev/null 2>&1"
DeviceProcessEvents
| where (
    InitiatingProcessCommandLine contains_cs "systemctl" or InitiatingProcessCommandLine contains_cs "service" or
    ProcessCommandLine contains_cs "systemctl" or ProcessCommandLine contains_cs "service" or
    InitiatingProcessFileName contains_cs "systemctl" or InitiatingProcessFileName contains_cs "service" or
    FileName contains_cs "systemctl" or FileName contains_cs "service"
)
| where (
    InitiatingProcessCommandLine contains_cs "list-units" or InitiatingProcessCommandLine contains_cs "list-unit-files" or InitiatingProcessCommandLine contains_cs "--status-all" or
    ProcessCommandLine contains_cs "list-units" or ProcessCommandLine contains_cs "list-unit-files" or ProcessCommandLine contains_cs "--status-all" or
    InitiatingProcessFileName contains_cs "systemctl" or FileName contains_cs "systemctl"
)
| extend FullCommand = coalesce(InitiatingProcessCommandLine, ProcessCommandLine, InitiatingProcessFileName, FileName)
| project TimeGenerated, DeviceName, DeviceId, InitiatingProcessId, InitiatingProcessCommandLine, ProcessCommandLine, InitiatingProcessFileName, FileName, FullCommand
| sort by TimeGenerated desc
| take 100
fail257.02s0.0039
gpt-5-nano-medium
sh -c "systemctl status himdsd 1>/dev/null 2>&1"
DeviceProcessEvents
| where isnotempty(InitiatingProcessCommandLine) or isnotempty(ProcessCommandLine)
| extend CmdLine = tostring(coalesce(InitiatingProcessCommandLine, ProcessCommandLine))
| where CmdLine contains "systemctl" or CmdLine contains "service"
| where CmdLine contains "systemctl list-units" or CmdLine contains "systemctl list-unit-files" or CmdLine contains "systemctl list-units --type=service" or CmdLine contains "systemctl list-units -t service" or CmdLine contains "systemctl status" or CmdLine contains "systemctl list-unit-files" or CmdLine contains "service --status-all"
| project TimeGenerated, DeviceName, ProcessId, InitiatingProcessId, InitiatingProcessFileName, CmdLine, InitiatingProcessAccountDomain, InitiatingProcessAccountName, ProcessCommandLine, InitiatingProcessCreationTime, InitiatingProcessCommandLine
| sort by TimeGenerated desc
fail286.75s0.0049
grok-3-beta
no answer
no query generatedfail50.00s0.0879
grok-3-mini-beta
systemctl --type=service
DeviceProcessEvents
| where ProcessCommandLine has_any('service', 'systemctl', 'list-units')
| join kind=inner (DeviceInfo | where OSPlatform == 'Linux' | project DeviceId) on DeviceId
| summarize arg_max(TimeGenerated, *) by ProcessCommandLine
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine
| order by TimeGenerated desc
| take 100
pass435.98s0.0079
o1-high
no answer
no query generatedfail50.00s0.7628
o1-low
systemctl --type=service
DeviceProcessEvents
| where DeviceId in (DeviceInfo
    | where OSPlatform == "Linux"
    | distinct DeviceId)
| where FileName in~ ("service", "systemctl", "initctl", "chkconfig", "rc-update")
  or ProcessCommandLine has_any ("systemctl list", "list-units", "--status-all", "initctl list", "chkconfig", "rc-update")
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine, FolderPath, SHA256, InitiatingProcessCommandLine
| order by TimeGenerated desc
pass258.03s0.6394
o3-high
systemctl --type=service
// --------------- Service enumeration investigation (Linux) ---------------
// 1) Identify Linux endpoints so we do not pick up Windows service-related utilities
let LinuxDevices = DeviceInfo
    | where OSPlatform == "Linux"
    | project DeviceId;

// 2) Known utilities used to enumerate services on *nix systems
let svc_enum_utilities = dynamic(["systemctl","service","chkconfig","initctl","rc-service"]);

// 3) Common command-line phrases that indicate the intent is *listing* services
let svc_enum_phrases = dynamic([
        "systemctl list",          // systemd service listing
        "systemctl --type=service",
        "systemctl --all",
        "service --status-all",    // SysV-style listing
        "service -e",              // BusyBox variant
        "chkconfig --list",        // RHEL/CentOS
        "initctl list",            // Upstart
        "rc-service -l",           // OpenRC
        "rc-service list"          // OpenRC alternate
]);

DeviceProcessEvents
| where DeviceId in (LinuxDevices)                       // keep only Linux hosts
| where ActionType == "ProcessCreated"                  // process start events
| where FileName in~ (svc_enum_utilities)                // executable of interest (case-insensitive)
       or ProcessCommandLine has_any (svc_enum_phrases)  // or explicit enumeration flags
// 4) Return the details the analyst cares about
| project TimeGenerated,
          DeviceName,
          AccountName,
          FileName,
          ProcessCommandLine,       // <— full command that was run
          InitiatingProcessAccountName,
          InitiatingProcessCommandLine,
          FolderPath,
          ProcessId,
          InitiatingProcessFileName,
          InitiatingProcessId,
          SHA256,
          ReportId
| order by TimeGenerated desc
pass268.63s0.0662
o3-mini-high
no answer
no query generatedfail50.00s0.0490
o3-mini-low
bash
DeviceProcessEvents
| where isnotempty(ProcessCommandLine)
| where ProcessCommandLine matches regex @'.*(systemctl\s+list-units|service\s+--status-all|chkconfig).*'
| project TimeGenerated, DeviceName, AccountName, ProcessCommandLine
| order by TimeGenerated desc
| limit 100
fail159.18s0.0283
o4-mini-high
no answer
no query generatedfail50.00s0.0344
o4-mini-low
systemctl status himdsd
let LinuxDevices = DeviceInfo
    | where OSPlatform =~ "Linux"
    | summarize by DeviceId;
DeviceProcessEvents
| where DeviceId in (LinuxDevices)
| where ProcessCommandLine matches regex @"\b(systemctl|chkconfig|service|update-rc\.d)\b"
    and ProcessCommandLine has_any ("list","status","--status-all")
| project TimeGenerated, DeviceName, InitiatingProcessAccountName, InitiatingProcessAccountDomain, FileName, ProcessId, ProcessCommandLine
| order by TimeGenerated desc
fail142.56s0.0144