By Randy Franklin Smith
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. This is so that 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 two 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 to 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”
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 happens 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"""
At this point, 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 three new events for catching WMI Filter and Consumer Activity as well as the binding which makes them active.
|Sysmon Event ID
|19 - WmiEventFilter activity detected
||WmiEventFilter activity detected:
UtcTime: 2018-04-11 16:26:16.327
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:
UtcTime: 2018-04-11 16:26:16.360
Type: Command Line
Destination: "c:\\bad\\malware.exe "
|21 - WmiEventConsumerToFilter activity detected
||WmiEventConsumerToFilter activity detected:
UtcTime: 2018-04-11 16:27:02.565
As you can see, the events provide full details so that you 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 they are linked.
If you add these events to your monitoring you’ll want to analyze activity for a while in order to whitelist the regular, legitimate producers of these events in your particular environment.
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.