Hooking Windows events without knowing anything about C/C++

Hooking Windows events without knowing anything about C/C++

Whenever someone thinks about hooking Microsoft Windows events, one thinks about rootkits, low level C++ code, and Windows API calls. There’s another approach to achieve similar things using just pre-installed Windows tools and without knowing anything about Windows internals. WMI is its name.

Introduction

From the Microsoft Developer Network (MSDN):

WMI (Windows Management Instrumentation) is the infrastructure for management data and operations on Windows-based operating systems. You can write WMI scripts or applications to automate administrative tasks on remote computers but WMI also supplies management data to other parts of the operating system and products.

That definition gives us a glimpse into the power that WMI provides by telling us that you can execute administrative tasks and, more importantly, on remote computers! But that’s only the tip of the iceberg and several threat actors such as CozyDuke or Deep Panda have already realized it. In fact, there’s a trend in these last few years where threat actors have started using Windows native tools to carry out their activities.

This type of “living off the land” provides advantages. First, attackers don’t have to drop as many tools to the compromised system, thus lowering the likelihood of detection. Second, this leaves fewer traces that could be identified by incident responders.

WMI can be leveraged by PowerShell, the WMI Console or by using Managed Object Format (MOF) scripts.

To use WMI from PowerShell you can open a PowerShell terminal (powershell.exe) and execute the get-wmiobject (or gwmi) command as follows:

$ get-wmiobject win32_logicaldisk name, freespace, systemname, size -filter drivetype=3

__GENUS      	: 2
__CLASS      	: Win32_LogicalDisk
__SUPERCLASS 	:
__DYNASTY    	:
__RELPATH    	:
__PROPERTY_COUNT : 4
__DERIVATION 	: {}
__SERVER     	:
__NAMESPACE  	:
__PATH       	:
FreeSpace    	: 34652438528
Name         	: C:
Size         	: 106901270528
SystemName   	: AI-PINCHEWEEEY-VM
PSComputerName   :

As shown, we were able to obtain several system drive attributes by using the Win32_LogicalDisk class. Each of these classes can have properties or methods you can execute. You can get information about each class by reading their respective MSDN documentation. You can get references and documentation on all the classes available here.

An attacker could execute a WMI command that creates a Shadow Copy of the C:\ drive and retrieves its ID so it can be used later to delete the shadow copy in the scenario cleanup stage. We have seen this technique being used to decrypt the SAM file and obtain Windows credentials. In this case, the method Create() from the class Win32_ShadowCopy is called:

$ Get-WMIObject Win32_ShadowCopy -List).Create("C:\", "ClientAccessible").ShadowID

By the way, if you want moar cookies about shadow copies, you can read the shadow copy of this awesome blog post, lol.

Exploring other ways to execute WMI commands, you can also use the WMI Console from the Windows command line. As can be seen, the syntax is similar:

$ wmic logicaldisk where drivetype=3 get name, freespace, systemname, size
FreeSpace	Name  Size      	SystemName
33230168064  C:	106901270528  AI-PINCHEWEEEY-VM

Having some fun

We’ve illustrated many classes you can use through WMI and also that classes have methods you can execute. How can attackers leverage WMI to achieve their objectives?

What about starting processes?

$ wmic process call create "notepad.exe"
Executing (Win32_Process)->Create()
Method execution successful.
Out Parameters:
instance of __PARAMETERS
{
    	ProcessId = 2416;
    	ReturnValue = 0;
};

Or what about killing them?

$ wmic process where name="notepad.exe" delete
Deleting instance \\AI-PINCHEWEEEY-VM\ROOT\CIMV2:Win32_Process.Handle="2416"
Instance deletion successful.

Things start getting scary, right?

diabolical!

Even more if you take a look to the gazillions of OS classes you can access. Things like:

And I hope you have not forgotten the most interesting thing, you can run commands remotely!

$ wmic /node: "192.168.1.10" /username:domain\user /password:pwd process call create 'notepad.exe'
Executing (Win32_Process)->Create()
Method execution successful.
Out Parameters:
instance of __PARAMETERS
{
    	ProcessId = 5176;
    	ReturnValue = 0;
};

This is an easy way for attackers to move laterally from one computer to another without having to drop tools like PSExec to the compromised system.

So, what about hooking Windows events?

We have not talked about MOF (Managed Object Format) scripts yet! In my own words (therefore, easy to understand!) a MOF script is a file that has to be “compiled” using the mofcomp.exe utility and with which you can access some WMI capabilities.

With a MOF script you can decide what to execute and when to execute it. The following objects are used to define the what and when:

One of the most interesting aspects about Event Consumers is that you can execute Visual Basic Scripts! So you can get as crazy as you want. One example of an Event Consumer (the what) might be the following:

instance of ActiveScriptEventConsumer as $Cons
{
	Name = "ASEC";
	ScriptingEngine = "VBScript";
	ScriptText =
    	"Set objShell = CreateObject(\"WScript.Shell\") \n"  
    	"objShell.Exec(\"c:\\windows\\system32\\cmd.exe /c echo MOF Script Output>c:\\mof_output.txt\")\n";
};

This Event Consumer will execute the Windows command line and write some text to an output file through a Visual Basic Script. Something easy to check.

Then comes the Event Filter (the when):

instance of __EventFilter as $Filt
{
	Name = "EF";
	EventNamespace = "root\\cimv2";
	QueryLanguage = "WQL";
	Query = "SELECT * FROM __InstanceCreationEvent "  
        	"WITHIN 2 WHERE TargetInstance ISA 'Win32_Process' "
        	"AND TargetInstance.Name = 'notepad.exe'";
};

For Event Filters, a language called WQL (WMI Query language) is used. This language is what can be used to hook on different system events. In this case we are defining the “when to be triggered”, to when an instance creation event happens, as can be read in its documentation. There we are looking for the creation of an instance of the Wind32_Process class with the “notepad.exe” name.

This is a really easy way of achieving something similar to hooking the CreateProcess call. Attackers can look to specific processes and then execute something e.g killing the process.

Now let’s define the binding between “what” and “when”:

instance of __FilterToConsumerBinding
{
	Filter = $Filt;
	Consumer = $Cons;
};

The final MOF script looks like this:

#pragma namespace ("\\\\.\\root\\subscription")

instance of ActiveScriptEventConsumer as $Cons
{
	Name = "ASEC";
	ScriptingEngine = "VBScript";
	ScriptText =
    	"Set objShell = CreateObject(\"WScript.Shell\") \n"  
    	"objShell.Exec(\"c:\\windows\\system32\\cmd.exe /c echo MOF Script Output>c:\\mof_output.txt\")\n";
};

instance of __EventFilter as $Filt
{
	Name = "EF";
	EventNamespace = "root\\cimv2";
	QueryLanguage = "WQL";
	Query = "SELECT * FROM __InstanceCreationEvent "  
        	"WITHIN 2 WHERE TargetInstance ISA 'Win32_Process' "
        	"AND TargetInstance.Name = 'notepad.exe'";
};

instance of __FilterToConsumerBinding
{
	Filter = $Filt;
	Consumer = $Cons;
};  

To execute it we only have to compile the MOF script by executing the mofcomp.exe tool as administrator.

$ mofcomp.exe .\mof_script.mof
Microsoft (R) MOF Compiler Version 10.0.10586.0
Copyright (c) Microsoft Corp. 1997-2006. All rights reserved.
Parsing MOF file: .\mof_script.mof
MOF file has been successfully parsed
Storing data in the repository...
WARNING: File .\mof_script.mof does not contain #PRAGMA AUTORECOVER.
If the WMI repository is rebuilt in the future, the contents of this MOF file will not be included in the new WMI repository.
To include this MOF file when the WMI Repository is automatically reconstructed, place the #PRAGMA AUTORECOVER statement on the first line of the MOF file.
Done!

If you open the notepad you will see how the mof_output.txt file is created in C:.

Getting sophisticated…

I’m sure that if you are here, at some point, when you were a kid or when watching a movie (yes, I’m looking at you Swordfish!) you heard about so called “Logic Bombs” (or Time Bombs). Well, let’s write one to make happy the kid inside you!

sophisticated!

With what we have seen until now, changing our code to be executed on a certain date will be easy. We only have to change the Event Filter to something like this:

instance of __EventFilter as $Filt
{
	Name = "EF";
	EventNamespace = "root\\cimv2";
	QueryLanguage = "WQL";
	Query = "SELECT * FROM __InstanceModificationEvent WITHIN 20 WHERE "
        	"TargetInstance ISA 'Win32_LocalTime' AND "
        	"TargetInstance.Hour = 10 AND "
        	"TargetInstance.Minute = 34";
};

In this case, the Event Consumer will be triggered at 10:34AM. We achieve that by hooking the system time and monitoring its changes. The WITHIN clause specifies a polling interval of 20 seconds.

We’ve shown how WMI and MOF scripts can be used to achieve many of the things that attackers used to do with custom tools. You can execute things at certain times (useful to decide when to exfiltrate information from the compromised system), execute things when processes or services are started or stopped (useful to deactivate security technologies), when files are written or deleted from the filesystem, when windows events are logged, and so on.

Wasn’t it cool?

cool!

How can I check if I’m compromised?

Now that you know how powerful WMI attacks are, the next question is how do I protect from them? The first step, as always, is understanding what is running in your systems. You should know what Events do you have registered in your system so you can monitor their creation or deletion. You can list the Event Consumers, Event Filters and Filter To Consumer Bindings using the following PowerShell commands:

For removing events, you can use the following commands:

Now you can write your own scripts to monitor your system Events and remove all the ones that should not be there.

You can also use the Event Tracing for Windows to Trace WMI activity. Conclusions WMI attacks are on the rise and for a reason. Attackers can use WMI for reconnaissance, persistence, lateral movement and everything that crosses your mind. And Windows gives you native support for all these actions.

As always, every powerful tool that can be used to do good, can (and will) also be used to harm. WMI attacks have been used by actors and malware like Wiper (Sony Picture Compromise to move laterally), Flame (trigger execution through a MOF file that executes a DLL using rundll32), Kjw0rm (TV5Monde Compromise to get system information), PowerWorm (malware found in the wild that uses WMI to persist and to infect USB drive files when plugged in), Operation Mangal (installation of custom malware), etc and it does not seem it’s going to stop anytime soon.

With all that said, I hope that you start considering to add WMI to your threat model.

And that’s all for today, kiddos…

3!

Some useful links:

TheMalwareHunter

Back