PowerShell is one of the best post-exploitation tools out there—simply because it’s already built in to every modern Windows system. And like the name states, it’s extremely powerful. PowerShell can be used to gather data, steal system information, dump credentials, pivot between systems, create backdoors and much more.
The problem is that, by default, Windows only logs that PowerShell was launched. No additional details about what exactly happened are preserved. The only thing we can tell is that PowerShell called additional programs and possibly opened up a few network sessions. However, there is a way to gather additional details on PowerShell sessions and the command line in general.
How to Gather PowerShell Details
Often, the ideal way to tackle this issue is by implementing Sysmon to capture command line activity (along with much more). However, it does require a bit of upfront configuration. Fortunately, Michael Gough (@HackerHurricane) has put together some great resources on capturing command line log data using only built-in tools with his blog and a recent presentation. Speaking of which, you should also check out his DerbyCon 5 talk—great stuff! Using these simple tips, we can easily detect detailed activity from the host…and even take it a step further by automating alerting for specific activities with the SIEM
The first step is getting PowerShell to log detailed command line activity. To do this, we need to add a
*profile.ps1* file to the PowerShell directory. It’s also a good idea to increase the size of the PowerShell event logs to capture large and possibly encoded commands.
**Profile.ps1** *$LogCommandHealthEvent = $true $LogCommandLifeCycleEvent = $true*
The next step is to track any access / modifications of this file. We could either use LogRhythm’s File Integrity Monitoring, or we could test granular logging on the file itself using Windows. This can be set to fire an alert whenever anyone attempts to disable our new logging ability by tampering with this file.
The next step is to ingest these logs into the SIEM and make use of the data. So, we’ll need a new log source type. Because this is an event log, we’ll follow the Microsoft Event schema.
Then, some RegEx to parse the logs, placing any commands entered into the
<command> metadata tag.
**RegEx** *.*?eventid.*?>(?<vmid>\d+)<.*?<level>(?<severity>.*?)</level>.*?Computer>(?<dname>.*?) </computer>.*?Command\s(?<object>.*?)\s(.*?\n)+?\s+CommandLine=(?<command>.*?)</EventData>*
Create and enable the new Log Processing Policy and define the event to logs to pull from.
Now, generate some PowerShell events and validate that the Command Line logs are parsed out as intended. Now we can see everything that happens on the command line and search through this data quickly and easily from the SIEM.
While it’s great that we can see what’s happening on the command line now, it would be even better if we could alert on known activity at the command line. So, why not create an AI Engine rule to do just that!
The first step is to compile a list of known dangerous functions. So, I went through all the most popular PowerShell attack frameworks such as Empire, PowerSploit, Nishang and so forth, and I pulled out all of the function names and compiled them into a list along with other dangerous PowerShell commands. This list of “bad commands” can be found at the link below.
This list is mostly comprised of known bad commands. However, there are some commands that aren’t inherently dangerous, but they are something that you may wish to monitor closely. For example, a Set-ExecutionPolicy is often used as an initial first step when running custom PowerShell scripts on a host. Invoke-Command is often used to execute commands on remote hosts.
We can then import these items as a list into LogRhythm and configure an alarm to fire whenever any commands that match those on this list are executed. While this should alert the Security Operations team to nefarious activity in the first sign of dangerous commands / functions being executed, this is of course trivial to bypass, as the attacker just needs to change the function calls or execute the scripts in different ways to bypass the rules. However, if an attacker is unaware that you are verbosely monitoring PowerShell command line activity, they will likely trip an alarm.
Now, attempting to run nefarious PowerShell commands or load any dangerous functions (known / have not been renamed) will fire an alarm.
As a bonus, you can do this with the standard Windows command line as well. All you need to do is set the following Registry Key.
HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System\Audit\ ProcessCreationIncludeCmdLine_Enabled DWord - 1
“Figure 8. Command Line Logging”)
As mentioned earlier in this post, you can also do the same thing with Sysmon. LogRhythm can currently parse Sysmon logs and verbose PowerShell logging will be included in a KnowledgeBase update in the very near future.
If you don’t have any of these preemptive measures in place, you can often still find out what command line activity is taking place by using Sysinternals Process Explorer and TCPView. While there are multiple pieces of evidence that will give away that this is a malicious process right away, Process explorer may highlight the command line details, depending on how the commands are being executed. Most notably, you will see obvious beaconing activity over the network, however bear in mind that attackers will often limit their beacons to avoid detection.
With the ability to capture full details of everything entered at the command line and alert on key events, we can easily detect more advanced attacks that avoid installing files, dropping binaries, or other avenues that would leave traces on disk. These are the tactics that adversaries are using on a daily basis to compromise enterprise environments, so it’s imperative that we monitor for this activity. We can also use these techniques to dynamically transition a compromised system into a honeypot, allowing us to watch the attackers and gather more details on what they’re after, how they’re moving between systems, and eventually closing off all avenues in and out of the enterprise environment.