Security is an ever-escalating arms race. The good guys have gotten better about monitoring the file system for artifacts of advanced threat actors. They in turn are avoiding the file system and burrowing deeper into Windows to find places to store their malware code and dependably trigger its execution in order to gain persistence between reboots.
For decades the Run and RunOnce keys in the registry have been favorite bad guy locations for persistence but we know to monitor them using Windows auditing for sysmon. So, attackers in the know have moved on to WMI.
WMI is such a powerful area of Windows for good or evil. Indeed, the bad guys have found effective ways to hide and persist malware in WMI. In this article I’ll show you a particularly sophisticated way to persist malware with WMI Event Filters and Consumers.
WMI allows you to link these 2 objects in order to execute a custom action whenever specified things happen in Windows. WMI events are related to but more general than the events we all know and love in the event log. WMI events include system startup, time intervals, program execution and many, many other things. You can define a __EventFilter which is basically a WQL query that specifies what events you want to catch in WMI. This is a permanent object saved in the WMI repository. It’s passive until you create a consumer and link them with a binding. The WMI event consumer defines what the system should do with any events caught by the filter. There are different kinds of event consumers for action like running a script, executing a command line, sending an email or writing to a log file. Finally, you link the filter and consumer with a __FilterToConsumerBinding. After saving the binding, everything is now active and whenever events matching the filter occur, they are fed to the consumer.
So how would an attacker cause his malware to start up each time Windows reboots? Just create a filter that catches some event that happens shortly after startup. Here’s what PowerSploit uses for that purpose:
SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 200 AND TargetInstance.SystemUpTime < 320
Then you create a WMI Event Consumer which is another permanent object stored in the WMI Repository. Here’s some VB code adapted from mgeeky’s WMIPersistence.vbs script on Github. It’s incomplete, but edited for clarity. If you want to play with this functionality refer to https://gist.github.com/mgeeky/d00ba855d2af73fd8d7446df0f64c25a:
Set objInstances2 = objService1.Get("CommandLineEventConsumer")
Set consumer = objInstances2.Spawninstance_
consumer.name = “MyConsumer”
consumer.CommandLineTemplate = “c:\bad\malware.exe”
consumer.Put_
So now you have a filter that looks for when the system has recently started up and a consumer which runs c:\bad\malware.exe but nothing’s going to happen until they are linked like this:
Set objInstances3 = objService1.Get("__FilterToConsumerBinding")
Set binding = objInstances3.Spawninstance_
binding.Filter = "__EventFilter.Name=""MyFilter"""
binding.Consumer = "CommandLineEventConsumer.Name=""MyConsumer"""
binding.Put_
So now you have a filter that looks for when the system has recently started up and a consumer which runs c:\bad\malware.exe.
As a good guy (or girl) how do you catch something like this? There are no events in the Windows Security Log, but thankfully Sysmon 6.10 added 3 new events for catching WMI Filter and Consumer Activity as well as the binding which makes them active.
Sysmon Event ID |
Example |
19 - WmiEventFilter activity detected |
WmiEventFilter activity detected:
EventType: WmiFilterEvent
UtcTime: 2018-04-11 16:26:16.327
Operation: Created
User: LAB\rsmith
EventNamespace: "root\\cimv2"
Name: "MyFilter"
Query: "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA 'Win32_PerfFormattedData_PerfOS_System' AND TargetInstance.SystemUpTime >= 200 AND TargetInstance.SystemUpTime < 320" |
20 - WmiEventConsumer activity detected |
WmiEventConsumer activity detected:
EventType: WmiConsumerEvent
UtcTime: 2018-04-11 16:26:16.360
Operation: Created
User: LAB\rsmith
Name: "MyConsumer"
Type: Command Line
Destination: "c:\\bad\\malware.exe " |
21 - WmiEventConsumerToFilter activity detected |
WmiEventConsumerToFilter activity detected:
EventType: WmiBindingEvent
UtcTime: 2018-04-11 16:27:02.565
Operation: Created
User: LAB\rsmith
Consumer: "CommandLineEventConsumer.Name=\"MyConsumer\""
Filter: "__EventFilter.Name=\"MyFilter\"" |
As you can see, the events provide full details so that you can analyze the WMI operations to determine if they are legitimate or malicious. From event ID 19 I can see that the filter is looking for system startup. Event Id 20 shows me the name of the program that executes and I can see from event ID 21 that they are linked.
If you add these events to your monitoring you’ll want to analyze activity for a while in order whitelist the regular, legitimate producers of these events in your particular environment.
Sidebar:
That’s persistence via WMI for you, but you might have noted that we are not file-less at this point; my malware is just a conventional exe in c:\bad. To stay off the file system, bad guys have resorted to creating new WMI classes and storing their logic in a PowerShell script in a property on that class. Then they set up a filter that kicks off a short PowerShell command that retrieves their larger code from the custom WMI Class and calls. Usually this is combined with some obfuscation like base64 encoding and maybe encryption too.
“This article by Randy Smith was originally published by EventTracker”https://www.eventtracker.com/tech-articles/catch-malware-hiding-in-wmi-with-sysmon/