T1518

Software Discovery

Discovery Last updated:

Adversaries may attempt to get a listing of software and software versions that are installed on a system or in a cloud environment. Adversaries use this information during automated discovery to shape follow-on behaviors — including whether to fully infect the target, which vulnerabilities to exploit for privilege escalation, or which security tools to evade. Common techniques include querying the Windows Registry uninstall keys, WMI Win32_Product class, PowerShell Get-Package cmdlet, and command-line tools such as wmic and reg. On Linux and macOS, adversaries use package managers (dpkg, rpm, brew) and filesystem enumeration of application directories.

What is T1518 Software Discovery?

Software Discovery (T1518) maps to the Discovery tactic — the adversary is trying to figure out your environment in MITRE ATT&CK.

This page provides production-ready detection logic for Software Discovery, covering the data sources and telemetry it touches: Process: Process Creation, Windows Registry: Windows Registry Key Access, Command: Command Execution, Microsoft Defender for Endpoint. The queries below are rated low severity at medium confidence, and ship for 7 SIEM platforms — KQL, SPL, Elastic, QRadar, Sumo, YARA-L, LogScale.

MITRE ATT&CK

Tactic
Discovery
Technique
T1518 Software Discovery
Canonical reference
https://attack.mitre.org/techniques/T1518/
Microsoft Sentinel / Defender
kusto
let SoftwareDiscoveryPatterns = dynamic([
  // Registry-based enumeration
  "\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
  "\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall",
  // WMI-based enumeration
  "Win32_Product",
  "Win32_InstalledWin32Program",
  "Win32_InstalledProgramFramework",
  // PowerShell cmdlets
  "Get-Package",
  "Get-WmiObject",
  "Get-CimInstance",
  // WMIC commands
  "product get",
  "product list"
]);
let SuspiciousParents = dynamic([
  "powershell.exe", "pwsh.exe", "cmd.exe", "wscript.exe",
  "cscript.exe", "mshta.exe", "rundll32.exe", "regsvr32.exe"
]);
// Branch 1: Registry queries targeting software inventory keys
let RegistryBranch = DeviceRegistryEvents
| where Timestamp > ago(24h)
| where RegistryKey has "CurrentVersion\\Uninstall"
| where ActionType in ("RegistryKeyValueQueried", "RegistryQueryKey")
| extend DetectionSource = "Registry"
| project Timestamp, DeviceName, AccountName, ActionType,
          RegistryKey, RegistryValueName,
          InitiatingProcessFileName, InitiatingProcessCommandLine,
          InitiatingProcessParentFileName, DetectionSource;
// Branch 2: Process-based software discovery (wmic, reg, PowerShell)
let ProcessBranch = DeviceProcessEvents
| where Timestamp > ago(24h)
| where (
    // wmic product enumeration
    (FileName =~ "wmic.exe" and ProcessCommandLine has_any ("product get", "product list", "product where", "Win32_Product"))
    // reg query against uninstall keys
    or (FileName =~ "reg.exe" and ProcessCommandLine has "Uninstall")
    // PowerShell software discovery cmdlets
    or (FileName in~ ("powershell.exe", "pwsh.exe") and ProcessCommandLine has_any (
        "Get-Package", "Win32_Product", "Win32_InstalledWin32Program",
        "Get-WmiObject", "Get-CimInstance", "CurrentVersion\\Uninstall",
        "InstalledProgramFramework"
    ))
    // rpm/dpkg/brew via bash (cross-platform endpoints)
    or (FileName in~ ("bash", "sh", "zsh") and ProcessCommandLine has_any (
        "dpkg -l", "dpkg --list", "rpm -qa", "rpm -q",
        "snap list", "flatpak list", "brew list",
        "apt list", "yum list installed", "dnf list installed"
    ))
)
| extend DetectionSource = "Process"
// Flag suspicious parent processes indicating post-exploitation context
| extend SuspiciousParent = InitiatingProcessFileName in~ (SuspiciousParents)
// Exclude obvious system management processes
| where not (
    InitiatingProcessFileName in~ ("msiexec.exe", "trustedinstaller.exe", "svchost.exe")
    and AccountName in~ ("SYSTEM", "NT AUTHORITY\\SYSTEM")
)
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
          InitiatingProcessFileName, InitiatingProcessCommandLine,
          InitiatingProcessParentFileName, SuspiciousParent, DetectionSource;
// Union and enrich
RegistryBranch
| union ProcessBranch
| extend RiskScore = case(
    DetectionSource == "Registry" and InitiatingProcessFileName in~ (SuspiciousParents), 3,
    DetectionSource == "Process" and SuspiciousParent == true, 3,
    DetectionSource == "Process" and FileName =~ "wmic.exe", 2,
    1
)
| sort by Timestamp desc

Detects software enumeration activity across two telemetry branches: (1) registry reads against HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall keys via DeviceRegistryEvents, and (2) process creation events in DeviceProcessEvents targeting wmic product enumeration, reg.exe Uninstall queries, PowerShell Get-Package/Get-WmiObject/Get-CimInstance Win32_Product calls, and Linux/macOS package manager invocations. A RiskScore field prioritizes events where discovery tools are launched from suspicious parent processes (PowerShell, cmd.exe, wscript.exe), indicating post-exploitation context rather than administrative activity.

low severity medium confidence

Data Sources

Process: Process Creation Windows Registry: Windows Registry Key Access Command: Command Execution Microsoft Defender for Endpoint

Required Tables

DeviceProcessEvents DeviceRegistryEvents

False Positives

  • Software inventory agents (SCCM, Tanium, Qualys, Tenable, ServiceNow Discovery) that regularly enumerate installed software for asset management and vulnerability scanning
  • System administrators running wmic product get or reg query manually during troubleshooting or software audits
  • PowerShell Desired State Configuration (DSC) and automation scripts (Ansible, Chef, Puppet) querying installed packages during compliance checks
  • Software installers and uninstallers that read Uninstall registry keys to check for existing versions before installation
  • Endpoint Detection & Response (EDR) agents that perform software inventory as part of their telemetry collection

Sigma rule & cross-platform mapping

The detection logic for Software Discovery (T1518) above is provided in a vendor-neutral form so you can deploy it on any SIEM. The same logic is shipped here as native KQL (Microsoft Sentinel / Defender), SPL (Splunk), Elastic (Elastic Security (EQL)), QRadar (IBM QRadar (AQL)), Sumo (Sumo Logic CSE), YARA-L (Google Chronicle / SecOps), LogScale (CrowdStrike LogScale (CQL)) queries. In Sigma terms, this detection targets the following logsource:

logsource:
  category: process_creation
  product: windows

Browse the community-maintained Sigma rules for this technique:


Testing Methodology

Validate this detection against 4 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.

  1. Test 1WMIC Product Enumeration

    Expected signal: Sysmon Event ID 1: Process Create with Image=wmic.exe, CommandLine containing 'product get'. WMI Activity Event IDs 5857/5858/5859 in Microsoft-Windows-WMI-Activity/Operational. File creation event (Sysmon Event ID 11) for %TEMP%\software_inv.csv. Security Event ID 4688 (if command line auditing enabled).

  2. Test 2Registry Query for Installed Software (reg.exe)

    Expected signal: Sysmon Event ID 1: Two Process Create events for reg.exe with CommandLine containing 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'. Registry access events (Sysmon Event ID 12/13) if registry monitoring is configured. Security Event ID 4688 for both reg.exe executions.

  3. Test 3PowerShell Software Discovery via Get-Package

    Expected signal: Sysmon Event ID 1: Process Create with Image=powershell.exe, CommandLine containing 'Get-Package' and 'Export-Csv'. PowerShell ScriptBlock Log Event ID 4104 in Microsoft-Windows-PowerShell/Operational with the full cmdlet. Sysmon Event ID 11 (File Create) for the CSV output in TEMP.

  4. Test 4Linux Package Enumeration via dpkg and rpm

    Expected signal: Auditd EXECVE records for dpkg, rpm, snap, awk, and cat process invocations. Syslog entries if process accounting is enabled. On endpoints with Sysmon for Linux (sysmonforlinux): Event ID 1 process creation events for each command in the pipeline. File creation event for /tmp/dpkg_inv.txt.


Response Playbook

Triage

  1. Identify the initiating process and parent chain — was software discovery invoked from a legitimate management tool (ccmexec.exe, qualys, tanium) or from an unexpected parent like powershell.exe launched by an Office document, wscript.exe, or mshta.exe?
  2. Check the user context — is this a service account associated with a known inventory system, a system administrator, or an interactive user who would not normally run software enumeration commands?
  3. Assess the breadth of enumeration — a single reg query may be incidental, but a sequence of registry reads, WMI queries, and PowerShell cmdlets within a short window suggests automated discovery reconnaissance
  4. Correlate with adjacent discovery events — check for T1033 (System Owner Discovery), T1007 (System Service Discovery), T1082 (System Information Discovery), T1016 (System Network Configuration Discovery) occurring within the same session timeframe on the same host
  5. For WMI-based discovery (Win32_Product), note that this provider triggers a Windows Installer repair check on all installed applications — unusual for non-admin users and generates substantial I/O activity that may be visible in performance logs
  6. Check if the discovered software list was exfiltrated — look for outbound network connections from the same process or follow-on processes writing to temp directories, network shares, or initiating HTTP/S connections shortly after enumeration

Containment

  1. If software discovery is confirmed as part of an active intrusion, isolate the affected endpoint using EDR network isolation to prevent follow-on exploitation based on discovered software versions
  2. If the enumeration was performed by a compromised service account, disable the account and revoke active sessions; reset the password and audit all systems the account accessed
  3. Capture a memory image and disk snapshot before containment actions if the host shows other indicators of compromise (e.g., T1059, T1105, T1055) — software discovery alone is insufficient grounds for immediate reimaging
  4. Block lateral movement paths: if discovered software includes remote management tools (RMM, VNC, SSH clients), monitor for those tools being abused for lateral movement to other systems
  5. If discovered software included vulnerable versions of applications (e.g., outdated browsers, unpatched Java), treat as high-risk and prioritize incident response — the adversary may be actively planning exploitation

Evidence Collection

  1. Process Creation Events — Sysmon Event ID 1 or Security Event ID 4688 (with command line auditing enabled via GPO: Audit Process Creation + Include command line in process creation events)
  2. Registry Access Events — Sysmon Event ID 12/13/14 for registry key access if key logging is enabled; note default Sysmon configs may not capture all registry reads
  3. PowerShell ScriptBlock Logging — Event ID 4104 in Microsoft-Windows-PowerShell/Operational, which captures the full script content including Get-Package and Get-WmiObject calls
  4. WMI Activity Logging — Event ID 5857/5858/5859/5860/5861 in Microsoft-Windows-WMI-Activity/Operational for WMI provider queries including Win32_Product
  5. Windows Registry: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ and HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\ — enumerate these to understand what software the adversary could have discovered
  6. Command History — PSReadLine history at $env:APPDATA\Microsoft\Windows\PowerShell\PSReadLine\ConsoleHost_history.txt for PowerShell commands; .bash_history for Linux systems
  7. Prefetch Files — C:\Windows\Prefetch\WMIC.EXE-*.pf and REG.EXE-*.pf for execution timestamps and frequency
  8. Network Connections — Sysmon Event ID 3 shortly after discovery events to determine if enumeration results were transmitted

Escalation Criteria

  • ! Software discovery immediately precedes or follows exploitation attempts — e.g., adversary queries installed Java or browser versions, then attempts T1068 (Exploitation for Privilege Escalation) targeting the discovered version
  • ! Discovery is performed against multiple systems in rapid succession, indicating automated lateral movement or a worm-like capability spreading through the network
  • ! The user or process performing software discovery has no legitimate business reason to inventory software, and the account has no history of this activity in baseline telemetry
  • ! Discovered software inventory is written to a staging directory or exfiltrated — look for output redirection (wmic product get > C:\Users\Public\inv.txt) or immediate upload attempts
  • ! Software discovery is one of multiple concurrent discovery techniques (T1007, T1033, T1082, T1016) being executed in the same session, indicating a systematic post-exploitation reconnaissance phase
  • ! Known threat actor tooling is identified in the parent process chain — e.g., Cobalt Strike beacon (beacon.exe, svchost.exe with unusual command lines) spawning wmic.exe for software enumeration

Investigation Guide

Forensic Artifacts

  • > Registry: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ — primary software inventory key; each subkey contains DisplayName, DisplayVersion, Publisher, InstallDate
  • > Registry: HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\ — 32-bit applications on 64-bit systems
  • > Registry: HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\ — per-user installed applications
  • > File System: C:\Windows\Prefetch\WMIC.EXE-*.pf — execution evidence for wmic with timestamps and run count
  • > File System: C:\Windows\Prefetch\REG.EXE-*.pf — execution evidence for reg.exe
  • > Event Log: Microsoft-Windows-WMI-Activity/Operational — Event IDs 5857-5861 for WMI provider activity including Win32_Product queries
  • > Event Log: Microsoft-Windows-PowerShell/Operational — Event ID 4104 ScriptBlock logs capturing Get-Package, Get-WmiObject, Get-CimInstance calls
  • > Event Log: Security — Event ID 4688 process creation (if command line auditing enabled via: Computer Configuration > Policies > Administrative Templates > System > Audit Process Creation > Include command line in process creation events)
  • > Linux: /var/log/auth.log or /var/log/secure — shell command history for dpkg/rpm/snap invocations
  • > Linux: /root/.bash_history and /home/*/.bash_history — command history files
  • > macOS: /private/var/log/system.log and unified log for system_profiler or ls /Applications invocations
  • > Memory: Running process list at time of incident — any processes with wmic, reg, or PowerShell holding open handles to registry hives

Tuning Guidance

Software discovery is a noisy technique with high false positive rates in environments with active software management tooling. Start by building an allowlist of known inventory service accounts and their parent processes: SCCM (ccmexec.exe), Tanium (TaniumClient.exe), Qualys (QualysAgent.exe), Rapid7 (ir_agent.exe), Tenable (nessus-service). Exclude these accounts and parent processes from alerting, but retain them in hunting datasets for anomaly detection. For WMIC-based discovery specifically, the Win32_Product provider triggers MSI repair checks — this is distinctive behavior that creates measurable I/O load and is rarely used by legitimate tools in favor of faster alternatives (Win32_InstalledWin32Program). Consider creating a higher-confidence alert specifically for Win32_Product queries from non-inventory-tool parents. On the registry side, most legitimate inventory tools use dedicated APIs rather than reg.exe directly; reg.exe querying Uninstall keys from interactive sessions is a stronger signal. For PowerShell, combine the software discovery cmdlet match with other discovery indicators in the same session (T1082, T1007, T1033) to raise confidence — an adversary doing full recon will chain these. Set minimum severity to Low initially, promote to Medium for hosts where software discovery precedes other post-exploitation techniques within 30 minutes.


Hunting Queries

Hunt for software discovery events followed by privilege escalation indicators within a 1-hour window on the same host and account. This sequence — enumerate software to identify vulnerable versions, then attempt exploitation — is characteristic of hands-on-keyboard adversary activity in post-exploitation phases.

Hunting — KQL
kql
// Hunt for software discovery preceding exploitation attempts within 1 hour
let SoftwareDiscovery = DeviceProcessEvents
| where Timestamp > ago(7d)
| where (
    (FileName =~ "wmic.exe" and ProcessCommandLine has_any ("product get", "Win32_Product"))
    or (FileName =~ "reg.exe" and ProcessCommandLine has "Uninstall")
    or (FileName in~ ("powershell.exe", "pwsh.exe") and ProcessCommandLine has_any ("Get-Package", "Win32_Product", "Win32_InstalledWin32Program"))
)
| project DiscoveryTime=Timestamp, DeviceName, AccountName, DiscoveryCmd=ProcessCommandLine;
let PrivEscAttempts = DeviceProcessEvents
| where Timestamp > ago(7d)
| where ProcessIntegrityLevel in ("High", "System")
| where InitiatingProcessIntegrityLevel in ("Medium", "Low")
| project EscalationTime=Timestamp, DeviceName, AccountName, EscalationCmd=ProcessCommandLine, EscalatingProcess=FileName;
SoftwareDiscovery
| join kind=inner PrivEscAttempts on DeviceName, AccountName
| where EscalationTime between (DiscoveryTime .. (DiscoveryTime + 1h))
| project DiscoveryTime, EscalationTime, DeviceName, AccountName, DiscoveryCmd, EscalatingProcess, EscalationCmd
| sort by DiscoveryTime desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
(
  (Image="*\\wmic.exe" CommandLine="*product get*")
  OR (Image="*\\reg.exe" CommandLine="*Uninstall*")
  OR ((Image="*\\powershell.exe" OR Image="*\\pwsh.exe") (CommandLine="*Get-Package*" OR CommandLine="*Win32_Product*"))
)
| eval DiscoveryTime=_time
| eval DiscoveryHost=host
| eval DiscoveryUser=User
| append [
    search index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
    (IntegrityLevel="High" OR IntegrityLevel="System")
    NOT (Image="*\\trustedinstaller.exe" OR Image="*\\msiexec.exe")
    | eval EscalationTime=_time
    | eval EscalationHost=host
    | eval EscalationUser=User
  ]
| stats values(Image) as Images values(CommandLine) as CmdLines min(_time) as earliest max(_time) as latest by host, User
| where mvcount(Images) > 1
| eval window_minutes=round((latest - earliest) / 60, 1)
| where window_minutes < 60
| sort - latest

Hunt for a single account performing software discovery across three or more distinct hosts within a 2-hour window. Legitimate software inventory tools run as dedicated service accounts on predictable schedules; an interactive user account or a service account touching multiple systems rapidly suggests lateral movement with reconnaissance activity.

Hunting — KQL
kql
// Hunt for bulk software discovery across multiple hosts from the same account (lateral spread indicator)
DeviceProcessEvents
| where Timestamp > ago(7d)
| where (
    (FileName =~ "wmic.exe" and ProcessCommandLine has_any ("product get", "Win32_Product", "product list"))
    or (FileName =~ "reg.exe" and ProcessCommandLine has "Uninstall")
    or (FileName in~ ("powershell.exe", "pwsh.exe") and ProcessCommandLine has_any ("Get-Package", "Win32_Product", "Win32_InstalledWin32Program", "Get-CimInstance"))
)
| summarize
    DiscoveryCount = count(),
    UniqueHosts = dcount(DeviceName),
    HostList = make_set(DeviceName, 20),
    CommandVariants = make_set(ProcessCommandLine, 5),
    FirstSeen = min(Timestamp),
    LastSeen = max(Timestamp)
  by AccountName, FileName
| where UniqueHosts >= 3
| extend SpreadRateMinutes = datetime_diff('minute', LastSeen, FirstSeen)
| where SpreadRateMinutes <= 120
| sort by UniqueHosts desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
(
  (Image="*\\wmic.exe" (CommandLine="*product get*" OR CommandLine="*Win32_Product*"))
  OR (Image="*\\reg.exe" CommandLine="*Uninstall*")
  OR ((Image="*\\powershell.exe" OR Image="*\\pwsh.exe") (CommandLine="*Get-Package*" OR CommandLine="*Win32_Product*" OR CommandLine="*Get-CimInstance*"))
)
| bucket _time span=2h
| stats count as DiscoveryCount, dc(host) as UniqueHosts, values(host) as HostList, values(CommandLine) as CmdVariants by User, Image, _time
| where UniqueHosts >= 3
| sort - UniqueHosts

Hunt for software discovery commands that include output redirection operators or cmdlets (>, >>, Out-File, Export-Csv) writing results to common staging locations (Public, Temp, ProgramData). This pattern indicates the adversary is saving enumeration results for later exfiltration rather than viewing them interactively.

Hunting — KQL
kql
// Hunt for software discovery output being written to disk (exfiltration staging)
let DiscoveryWithOutput = DeviceProcessEvents
| where Timestamp > ago(7d)
| where (
    ProcessCommandLine has_any ("product get", "Win32_Product", "Uninstall", "Get-Package", "Win32_InstalledWin32Program")
)
| where ProcessCommandLine has_any (">>", ">", "Out-File", "Set-Content", "Add-Content", "Tee-Object", "Export-Csv")
| project DiscoveryTime=Timestamp, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessFileName;
let StagingLocations = DeviceFileEvents
| where Timestamp > ago(7d)
| where FolderPath has_any ("\\Users\\Public\\", "\\Temp\\", "\\AppData\\Local\\Temp\\", "\\ProgramData\\", "\\Windows\\Temp\\")
| where FileName endswith ".txt" or FileName endswith ".csv" or FileName endswith ".log" or FileName endswith ".xml"
| project FileTime=Timestamp, DeviceName, FolderPath, FileName, InitiatingProcessFileName, InitiatingProcessAccountName;
DiscoveryWithOutput
| join kind=leftouter StagingLocations
    on DeviceName
    , $left.AccountName == $right.InitiatingProcessAccountName
| where FileTime between (DiscoveryTime .. (DiscoveryTime + 5m))
| project DiscoveryTime, DeviceName, AccountName, ProcessCommandLine, FileName, FolderPath
| sort by DiscoveryTime desc
Hunting — SPL
spl
index=wineventlog sourcetype="XmlWinEventLog:Microsoft-Windows-Sysmon/Operational" EventCode=1
(
  (Image="*\\wmic.exe" CommandLine="*product*")
  OR (Image="*\\reg.exe" CommandLine="*Uninstall*")
  OR ((Image="*\\powershell.exe" OR Image="*\\pwsh.exe") (CommandLine="*Get-Package*" OR CommandLine="*Win32_Product*"))
)
(CommandLine="*>*" OR CommandLine="*Out-File*" OR CommandLine="*Export-Csv*" OR CommandLine="*Set-Content*")
| eval staging_indicator=if(match(CommandLine, "(public|temp|appdata|programdata)"), 1, 0)
| table _time, host, User, Image, CommandLine, ParentImage, staging_indicator
| sort - _time

Atomic Red Team Tests

Test 1 WMIC Product Enumeration
windows

Uses Windows Management Instrumentation Command-line (wmic) to enumerate all installed software via the Win32_Product WMI class. This is a well-documented adversary technique used by Volt Typhoon, Dridex, and numerous post-exploitation frameworks to inventory installed applications. Note: Win32_Product triggers an MSI consistency check (repair) on all installed applications — this creates measurable I/O load and unusual MSI events.

Command

powershell
wmic product get Name,Version,Vendor /format:csv > %TEMP%\software_inv.csv

Cleanup

powershell
del %TEMP%\software_inv.csv

Expected Telemetry

Sysmon Event ID 1: Process Create with Image=wmic.exe, CommandLine containing 'product get'. WMI Activity Event IDs 5857/5858/5859 in Microsoft-Windows-WMI-Activity/Operational. File creation event (Sysmon Event ID 11) for %TEMP%\software_inv.csv. Security Event ID 4688 (if command line auditing enabled).

Expected Detection

KQL: ProcessBranch matches FileName=wmic.exe with 'product get' in ProcessCommandLine, RiskScore=2. SPL: DiscoveryType=WMI_Software_Enum, RiskScore=2. Hunting query 3 may additionally fire if output redirection to TEMP is detected.

Test 2 Registry Query for Installed Software (reg.exe)
windows

Uses the built-in reg.exe utility to query the Windows Uninstall registry keys directly, enumerating all 64-bit and 32-bit installed software. This technique is faster than Win32_Product and does not trigger MSI repair checks, making it preferred by adversaries who need to minimize noise. This matches the behavior documented for Volt Typhoon querying the Registry for installed software.

Command

powershell
reg query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall /s /v DisplayName && reg query HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall /s /v DisplayName

Expected Telemetry

Sysmon Event ID 1: Two Process Create events for reg.exe with CommandLine containing 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'. Registry access events (Sysmon Event ID 12/13) if registry monitoring is configured. Security Event ID 4688 for both reg.exe executions.

Expected Detection

KQL: ProcessBranch matches FileName=reg.exe with 'Uninstall' in ProcessCommandLine. SPL: DiscoveryType=Registry_Uninstall_Query. RegistryBranch in KQL may additionally fire if registry key access monitoring is active.

Test 3 PowerShell Software Discovery via Get-Package
windows

Uses the PowerShell Get-Package cmdlet to enumerate all installed software packages across all registered package providers (Programs, MSI, NuGet, etc.). This is a modern, script-friendly equivalent of WMIC product enumeration and is used by malware families like CharmPower and Dridex that rely on PowerShell for post-exploitation discovery.

Command

powershell
powershell.exe -NoProfile -Command "Get-Package | Select-Object Name,Version,ProviderName | Export-Csv -Path $env:TEMP\pkg_inv.csv -NoTypeInformation"

Cleanup

powershell
Remove-Item $env:TEMP\pkg_inv.csv -ErrorAction SilentlyContinue

Expected Telemetry

Sysmon Event ID 1: Process Create with Image=powershell.exe, CommandLine containing 'Get-Package' and 'Export-Csv'. PowerShell ScriptBlock Log Event ID 4104 in Microsoft-Windows-PowerShell/Operational with the full cmdlet. Sysmon Event ID 11 (File Create) for the CSV output in TEMP.

Expected Detection

KQL: ProcessBranch matches FileName=powershell.exe with 'Get-Package' in ProcessCommandLine. SPL: DiscoveryType=PS_GetPackage. Hunting query 3 additionally fires on output redirection to TEMP path.

Test 4 Linux Package Enumeration via dpkg and rpm
linux

Enumerates all installed packages on Linux systems using dpkg (Debian/Ubuntu) and rpm (RHEL/CentOS) package manager commands. This matches behavior observed in XCSSET and various Linux backdoors that enumerate installed software to identify security tools and target applications for injection or evasion.

Command

bash
dpkg -l 2>/dev/null | awk 'NR>5 {print $2, $3}' > /tmp/dpkg_inv.txt; rpm -qa --qf '%{NAME} %{VERSION}\n' 2>/dev/null >> /tmp/dpkg_inv.txt; snap list 2>/dev/null >> /tmp/dpkg_inv.txt; cat /tmp/dpkg_inv.txt

Cleanup

bash
rm -f /tmp/dpkg_inv.txt

Expected Telemetry

Auditd EXECVE records for dpkg, rpm, snap, awk, and cat process invocations. Syslog entries if process accounting is enabled. On endpoints with Sysmon for Linux (sysmonforlinux): Event ID 1 process creation events for each command in the pipeline. File creation event for /tmp/dpkg_inv.txt.

Expected Detection

KQL: ProcessBranch matches FileName in (bash, sh) with 'dpkg -l' or 'rpm -qa' in ProcessCommandLine, DetectionSource=Process. SPL: DiscoveryType=PackageManager_Enum.

Related Detections

Tactic Hub