WMI Persistence: Subscriptions That Survive Reboots and Evade Almost Every Checklist

31 March 2026 | 5 min read | justruss.tech

WMI permanent event subscriptions are one of the most effective persistence mechanisms available to attackers because they tick every box a persistence mechanism needs: they survive reboots, they do not create files in standard startup locations, they are stored in the WMI repository (a binary database file, not a readable text file), they can be triggered by virtually any system event, and the majority of IR checklists simply do not check for them.

APT groups including APT29, APT32, and FIN7 have all used WMI persistence in documented campaigns. It is also available in every major post-exploitation framework.

How WMI permanent event subscriptions work

WMI event subscriptions have three components: an Event Filter (what to watch for), an Event Consumer (what to execute when the filter fires), and a Filter-to-Consumer Binding (connects them). All three are stored as objects in the WMI repository. When the triggering condition occurs, WMI executes the consumer with no user interaction and no obvious process creation chain that looks suspicious.

// WMI persistence installation (PowerShell - understanding for detection)
// This is the pattern to detect, not a guide to use

// Event Filter: trigger every time the system has been running for 60 seconds
$event_filter = Set-WmiInstance -Namespace "root\subscription" -Class __EventFilter -Arguments @{
 Name = "WindowsUpdate" // benign-looking name
 EventNameSpace = "root\cimv2"
 QueryLanguage = "WQL"
 Query = "SELECT * FROM __InstanceModificationEvent WITHIN 60 " +
 "WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' " +
 "AND TargetInstance.SystemUpTime >= 60 " +
 "AND TargetInstance.SystemUpTime < 120"
}

// Event Consumer: execute a command when the filter fires
$event_consumer = Set-WmiInstance -Namespace "root\subscription" -Class CommandLineEventConsumer -Arguments @{
 Name = "WindowsUpdateConsumer"
 CommandLineTemplate = "powershell.exe -NoP -sta -NonI -W Hidden -Enc [base64_payload]"
}

// Binding: connect filter to consumer
$binding = Set-WmiInstance -Namespace "root\subscription" -Class __FilterToConsumerBinding -Arguments @{
 Filter = $event_filter
 Consumer = $event_consumer
}

WMI persistence variants

// Variant 1: ActiveScript consumer (runs VBScript or JScript directly)
// More stealthy than CommandLine because no cmd.exe or powershell.exe spawned
$script_consumer = Set-WmiInstance -Namespace "root\subscription" -Class ActiveScriptEventConsumer -Arguments @{
 Name = "WindowsDefenderUpdate"
 ScriptingEngine = "VBScript"
 ScriptText = "Set WshShell = CreateObject(""WScript.Shell""): WshShell.Run ""cmd.exe /c ..."""
}

// This runs VBScript directly in the WMI provider process (WmiPrvSE.exe)
// Process creation events show WmiPrvSE.exe spawning the payload
// but the parent before WmiPrvSE is the WMI service, not anything suspicious

// Variant 2: Trigger on user logon
$logon_filter = Set-WmiInstance -Namespace "root\subscription" -Class __EventFilter -Arguments @{
 Name = "UserLogon"
 Query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_LogonSession' AND TargetInstance.LogonType = 2"
 // LogonType 2 = Interactive logon
}

// Variant 3: Trigger on specific process start
$proc_filter = Set-WmiInstance -Namespace "root\subscription" -Class __EventFilter -Arguments @{
 Name = "OnOutlookLaunch"
 Query = "SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.Name = 'OUTLOOK.EXE'"
 // Triggers only when Outlook opens - very targeted
}

Detection: querying the WMI repository directly

// This is the most reliable detection - directly query what is installed
// Run on every machine as part of regular hunting

// Check for all three components
Get-WMIObject -Namespace root\subscription -Class __EventFilter |
 Select-Object Name, Query, QueryLanguage |
 Format-List

Get-WMIObject -Namespace root\subscription -Class __EventConsumer |
 Select-Object Name, CommandLineTemplate, ScriptText, ScriptingEngine |
 Format-List

Get-WMIObject -Namespace root\subscription -Class __FilterToConsumerBinding |
 Select-Object Filter, Consumer |
 Format-List

// Any output from these three commands in your environment is suspicious
// unless you specifically created WMI subscriptions for legitimate monitoring purposes
// Most organisations have ZERO legitimate WMI subscriptions
// Velociraptor hunt across all endpoints
// Run this as a fleet hunt to find WMI persistence anywhere in your environment

SELECT * FROM Artifact.Windows.Persistence.PermanentWMIEvents()

// Or with custom VQL
SELECT
 Filter.Name AS filter_name,
 Filter.Query AS wmi_query,
 Consumer.Name AS consumer_name,
 Consumer.CommandLineTemplate AS command,
 Consumer.ScriptText AS script
FROM wmi(
 query="SELECT * FROM __FilterToConsumerBinding",
 namespace="root/subscription"
)

Detection via WMI activity event log

// Microsoft-Windows-WMI-Activity/Operational event log captures WMI activity
// Event ID 5860: registration of a new WMI permanent subscription
// Event ID 5861: subscription activation (payload executed)

Get-WinEvent -LogName "Microsoft-Windows-WMI-Activity/Operational" |
 Where-Object {$_.Id -in @(5860, 5861)} |
 Select-Object TimeCreated, Id, Message |
 Format-List

// Sigma rule for WMI subscription creation
title: WMI Permanent Event Subscription Created
logsource:
 product: windows
 service: wmi
detection:
 selection:
 EventID: 5860
 condition: selection
level: high
tags:
 - attack.persistence
 - attack.t1546.003

Detection via Sysmon process creation from WmiPrvSE

// When a WMI CommandLine consumer fires, WmiPrvSE.exe spawns the process
// This is visible in Sysmon Event ID 1

index=sysmon EventCode=1
 ParentImage="*\\WmiPrvSE.exe"
 NOT Image IN (
 "C:\\Windows\\System32\\wbem\\WmiPrvSE.exe",
 "C:\\Windows\\System32\\conhost.exe"
 )
| table _time, ComputerName, Account_Name, Image, CommandLine, ParentCommandLine

// The CommandLine field will show your WMI consumer's command
// This is the execution trace even if the subscription is later removed

WMI repository forensics

// The WMI repository is stored in binary files
// C:\Windows\System32\wbem\Repository\

// Tools for forensic analysis:
// PyWMIPersistenceFinder: https://github.com/davidpany/WMI_Forensics
// python-cim: https://github.com/fireeye/flare-wmi

// Basic analysis with python-cim
pip install python-cim
python3 -c "
import cim
repo = cim.CIM(cim.CIM_TYPE_WIN7, 'C:\\Windows\\System32\\wbem\\Repository')
namespace = repo.namespace_db().as_namespace('root\\subscription')

for filter_obj in namespace.class_instance_db().class_instances('__EventFilter'):
 print('FILTER:', filter_obj.string_value('Name'), '|', filter_obj.string_value('Query'))

for consumer in namespace.class_instance_db().class_instances('CommandLineEventConsumer'):
 print('CONSUMER:', consumer.string_value('Name'), '|', consumer.string_value('CommandLineTemplate'))
"