Friday, January 1, 2021

Detecting Malicious PowerShell


Ever since the first offensive security PowerShell talk by Dave Kennedy and Josh Kelly at DefCon 18 PowerShell...OMFG and the adoption of PowerShell by the offensive security community, such as Matt Graeber’s PowerSploit in 2012, PowerShell has been a cornerstone in any red teamer or threat actors toolbox. Over the years, to combat this trend, the PowerShell team at Microsoft have introduced telemetry such as script block, module and transcript logging, within PowerShell to aid defenders in identifying post exploitation activities conducted with PowerShell.

One of the most, if not the most, abused cmdlets built into PowerShell is Invoke-Expression.  Invoke-Expression is used by PowerShell Empire and Cobalt Strike for their stagers and by all sorts of malware as an execution method to allow for a ‘fileless attack’. Needless to say, if you’re a blue teamer, you’re going to want to know whenever the Invoke-Expression cmdlet is used within your environment outside of your IT admins and sanctioned enterprise software. 

In this blog post I'll be providing an alternative reliable method for detecting malicious at scale using a feature built into the older PowerShell module logging via the 'Windows PowerShell' log channel and event ID 800. These logs are often overlooked in favour of the newer 4103 module logs however in my testing, the 4103 logs were unable to provide any details around the execution of specifically the Invoke-Expression cmdlet. In addition, the 4104 script-block and transcript logs only displayed the obfuscated or aliased cmdlet details, making detection difficult. This feature of EID 800 was, to my knowledge, discovered by and verbally documented by Daniel Bohannon in his talk last year at Walmart's Sp4rkCon, Malicious Payloads vs Deep Visibility: A PowerShell Story so hat tip to Daniel.

To simulate a threat I'll be using Lee Holmes' timeless Rick ASCII one-liner which uses  Invoke-Expression to execute a remote payload in memory. If you've never check it out you can read more about on Lee's blog here. I'll be using some very basic obfuscation and also an alternative alias for Invoke-Expression to show how no matter what is provided on the command line, the older Event ID 800 PowerShell module logs provide the defender with the result of which cmdlet was run.

Before moving onto some demos, if you'd like to replicate this in your lab you'll need to ensure to configure the appropriate PowerShell logging and for that I would recommend following FireEye's blog post here. Okay, let's look at some examples...

Demo 1 - The Rick ASCII one-liner without obfuscation 


In the screenshot above you can see the exact command that was executed and the fact that both command line values in EID 800 and EID 4104 are identical. But you'll also notice an additional field in the EID 800 called 'Details'. It's this field value of "Invoke-Expression" that makes the EID 800 event unique. As for the 4103 module log, it didn't log anything related to the Invoke-Expression cmdlet.

As you'll see in the next example, not matter how Invoke-Expression is referenced or obfuscated in EID it is always returned as "Invoke-Expression"

Demo 2 - The Rick ASCII one-liner with basic obfuscation

In this example the obfuscation carries over into the command line of both events but the value of the 'Details:' field remains the same. Let's give one more example using a previously applied alias using the Import-Alias cmdlet.

Demo 3 - Invoke-Expression aliased as 'TotesLegit'

Once again EID 800 is a champ and let's us know that is was actually Invoke-Expression that was executed and that TotesLegit was just an alias used to throw off the Blue Team. If you we're familiar with the ability to set arbitrary aliases for cmdlets you'd have missed that threat. That said, Import-Alias just like Invoke-Expression can be reliably detected using EID 800.



This approach to detecting various PowerShell threats using Event ID 800 can be applied to any cmdlet of your choosing and so I would encourage you to look at which cmdlets are of interest to you and test this method of detection in your own lab. For example, some additional cmdlets which have known to be abused are Invoke-WebRequest, Add-Type, Start-BitsTransfer, Invoke-Command, Invoke-WmiMethod etc.