Thursday, August 19, 2021

Detecting the use of malicious DLLs at scale using Sysmon and Splunk

TL;DR 

From a behavioral perspective the Windows© operating system is constantly writing dll files to disk at a fairly high volume per host and process. It's rare for the rate of dll's written to disk to be low and slow, and is almost always the result of user behaviour or a threat. Therefore, it's possible to identify such threats as Nobelium, various dll search order hijacking scenarios as well as any persistence where a dll is written to disk using Sysmon eid 11, Splunk and the eventstats search command.

Back in May Microsoft provided a great report on Nobelium which detailed the use of rundll32.exe to execute a dll that was Cobalt Strike beacon loader. This past week Red Canary dropped another great threat intel report https://redcanary.com/blog/grief-ransomware/ on Dridex and Grief ransomware in which they detailed the use of dynamic link library (dll) search order hijacking. If you're not familiar with this these threats, head over to the ATT&CK framework to read up on these two techniques, T1574.001 or  T1218.011

In a nutshell this threat is primarily used for defense evasion in order to execute a malicious dll with the help of a benign executable. Typically the benign binary is introduced into the victim environment alongside the malicious dll like in the case of the Red Canary report, however the dll file can also be dropped without any binary and just executed via rundll32 like in the case of Nobelium. 

However this is not the only way the threat can be realized. More mature threat actors will also leverage this technique to not only gain execution but also persistence once within the victim network by only dropping a malicious dll to disk where it will be loaded by an existing binary or application that runs at startup/user logon. This way there's no need to introduce any additional binaries into the environment whose execution has a much greater chance of being logged and scrutinized by the Blue team.

All that said, the threat or scenario this blog post will focus on the more difficult task of trying to identify when an adversary has decided to introduce a single lonely dll to disk to order to gain execution and persistence after gaining an initial foothold on a workstation.

To begin, in order to ever detect such a threat, you'll need to be using some form a endpoint data source that can provide insight into dll's either being loaded into the memory of a process or when dll files are being written to disk. This could be a commercial EDR or System Monitor (Sysmon) from Sysinternals. The benefit of Sysmon is that is free and has a full customizable configuration, for which there are many great example configurations online. Here is a sample config snippet specifically for logging any file with a extension of .dll using Sysmon event id 11 which logs file create operations.

<RuleGroup groupRelation="or">

<FileCreate onmatch="include">

<TargetFilename name="Any .dll file written to disk" condition="end with">.dll</TargetFilename>

</FileCreate>

</RuleGroup>

With this configuration deployed we can shift focus to Splunk and write a search that looks for any process that writes X number of .dll files within X minutes of time using the eventstats search command. 

For this search, I'm going to scope the detection to any process that writes a dll file to disk within the C:\users\, C:\ProgramData\ and C:\Windows\System32\ directories as these are either user writable directories or the default location of vulnerable binaries, where an adversary will be likely write their malicious dll. This scope of course can be changed based on your needs.

Here is what the search looks like:

You can find a copy of this search in my Github repo here: T1574/MaliciousDLLs

This search can be used for hunting retroactively or even better can be deployed as a correlation search with very low false negatives given the broad scope and very manageable false positives based on my testing. I hope you find it useful :)

Sunday, August 15, 2021

Detecting Command & Control beaconing with Sysmon and Splunk

 TL;DR

It's possible to detect short-haul, nearly interactive, C2 beaconing activity including remote access software such as TeamViewer or QuickAssist using Sysmon event id 3 combined with multiple Splunk stats search commands. That said the search can be tweaked to capture whichever beaconing interval or process scope you'd like to target and can be deployed as an automated correlation search rather than a point-in-time hunt.

Effective detection of command and control beaconing behaviour has always been difficult to perform at scale due to the shear volume of network data produced within an enterprise environment and its impact on search performance and rate of false positives, at least from what I've observed. Therefore, this type of detection typically is used in more of a targeted hunt scenario, maybe upon a host suspected of being compromised or as part of long tail analysis. 

I wanted to try to develop a search that could be deployed as a automated correlation search in Splunk without blowing up the SIEM with alerts. Gaining near real-time detection of this tactic based on the general behaviour of beaconing means that the blue team wins regardless of the implant and C2 framework used. 

Ok, let's get into the details...

In order to power this search, you'll need to be collecting all http & https egress traffic using Sysmon event id 3.  

A sample config could look something like this:

<RuleGroup groupRelation="or">
<NetworkConnect onmatch="include">
<DestinationPort name="All traffic on port 443" condition="is">443</DestinationPort>
<DestinationPort name="All traffic on port 80" condition="is">80</DestinationPort>
</NetworkConnect>
</RuleGroup>

Of course you'll need to choose a different destination port if your environment has a web proxy and you may decide to filter out known good processes with the understanding that processes can be spoofed or injected into which could introduce blind spots.

Now that you've got the required data, let's scope this detection based on the available threat intelligence. 

From all the data that I've seen and my understanding of short haul C2, the most popular interval is 60 seconds with some amount of jitter, around 5-25%. From an operator perspective this make sense because having to wait anymore than one minute makes it difficult to perform action on objectives unless many of the tasks are automated. I can see this interval being higher but only for more advanced adversaries.

Here is a screenshot of what this beaconing would look like in Splunk. Each minute there is anywhere from 1-3 events with no sudden spikes and this behaviour remains consistent over time, in this case two hours.

Based on the uptick in the use of Cobalt Strike we can look at which processes are likely to be used for C2. The default process would be rundll32.exe however there are many other options, most of which are binaries located in either C:\Windows\System32\ or C:\Windows\Syswow64. But maybe we also concerning about binary executing out of user land, C:\users\, C:\Programdata, C:\Windows\Temp or C:\Users\Public. I think this is a great starting point.

With the threat defined and the detection scoped, let's look at the Splunk search.


You can find a copy of this search here T1071.001/C2_beaconing in my Git repo. Please take a look at the comments as they contain the logic of what the intention of the search. This search should identify any beacon activity from 30 seconds to 75 seconds. Like with almost all searches, some processes will need to be ignored/allowed as they will exhibit C2 behaviour and therefore blind spots will be introduced as a result. It's important to develop analytics for these blind spots using either additional host or network data given processes can be spoofed or injected into causing this search to miss such malicious activity.

Would love to get feedback on this search and any incorrect assumptions or logic and I really hope you find this search useful in identifying processes of interest.

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 http://www.exploit-monday.com/2012_05_20_archive.html 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.

 

Conclusion

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.