Month of PowerShell Process Threat Hunting, Part 2

Month of PowerShell Process Threat Hunting, Part 2

In this article we’ll build on our knowledge of the Get-Process and Get-CimInstance -Class Win32_Process PowerShell features to investigate malicious code running on a Windows system. If you haven’t already read Part 1, spend some time checking that out first, then come back here to see how you can apply these commands to your incident response or threat hunting investigations.

On a Windows system, I will investigate the running processes using PowerShell. I will look for suspicious indicators, including:

For this article I’ve used Metasploit to compromise and deploy malware on a Windows 10 system. Let’s apply the process threat hunting techniques to evaluate this system.

Although I used Metasploit as the attack framework for demonstration purposes here, these techniques can be useful for any Windows incident response analysis, even when attackers leverage different attack frameworks or Command & Control (C2) tools.

It’s straightforward to get a list of running process names using Get-Process:

Using this output, we can look for process names that are unusual. The problem with this kind of analysis if that you have to have a baseline of what is usual to compare to. We’ll cover using PowerShell for differential baseline analysis in a later article.

Sometimes you can spot process names that appear randomly generated (e.g., iciSUnrH.exe), but it’s not always obvious. It’s a good idea to do a quick glance at process names to see if anything unusual jumps out, but you’ll also want to investigate other process characteristics before coming to any kind of conclusion about a threat.

We saw in the first part of this article about how Get-Process can’t tell us the system path for the process. For this, we turn to Get-CimInstance:

Most users will run programs from the C:\Windows, C:\Program Files and C:\Program Files (x86) directories. We can uses Where-Object to quickly get a list of processes launched from a path outside of one of these directories:

In this example we uses two notlike expressions with wildcards to exclude the C:\Windows and C:\Program Files/C:\Program Files (x86) directories. It’s a little awkward and inefficient since we invoke Where-Object multiple times, but it gets the job done.

Alternatively, you can use a PowerShell array to specify a list elements using regular expression syntax in an array:

The Windows|Program Files regular expression syntax (where | is used as an or indicator between each string) is far from perfect, but it gets the job done, is a little faster, and can be more easily extended if you identify other directories you want exclude from the results.

Result: That C:\temp\calc.exe process is sus. Users don’t run programs from temporary directories normally; it’s a good candidate for further investigation.

With the C:\temp\calc process in mind, let’s investigate the parent/child relationships. We know the process ID for C:\temp\calc.exe is 2140 from the previous command. Let’s identify the parent process:

Here we learn the parent process ID is 6604. Let’s find out what that process name and path is:

This output indicates that 6604 is not an active process. There was once a process with ID 6604 that launched C:\temp\calc.exe, but that process has since exited, making this Calc process an orphan. This is not necessarily an Indicator of Compromise (IoC) though, as terminating parent processes are fairly common.

TIP: Be careful when specifying the property name that you are using for comparison in the Where-Object command. PowerShell has a bad habit of not warning you about some mistakes. For example, if you were to type Where-Object -Property PrcessId -EQ 6604 (note the missing o in PrcessId), PowerShell will not return an error, and will return no matches for the query.

Let’s see if there are any child processes associated with C:\temp\calc.exe:

This output tells us that C:\temp\calc.exe has launched a CMD shell. We can repeat this query, this time identifying any child processes of the CMD shell using process ID 5144:

Here we learn that the CMD shell has launched a PowerShell session and the [conhost.exe](https://www.howtogeek.com/howto/4996/what-is-conhost.exe-and-why-is-it-running/) process.

We could keep digging into the child relationships, looking at the PowerShell process ID 3776 next. At this point though, this behavior of a “Calc” process launching CMD, and PowerShell is even more sus. It not outside of the possibility of normal though, so let’s keep investigating.

TIP: Eelco Ligtvoet has an excellent PowerShell script to display an indented tree-like view of all processes and child processes. It uses some deprecated PowerShell functionality, but it works with the latest PowerShell at the time of this writing. Check it out as an option to quickly and visually assess all processes and their parent/child relationships.

Probably my GO-TO technique for Windows process analysis is to get a list of all processes from Get-CimInstance with name, handle count, process ID, parent process ID, path, and command line details. Since this is a lot of data (some command lines can be very long), I export all of this into a CSV file and check it out in Excel:

After turning on text wrapping, it’s easy to spot very long command lines, including this example of a PowerShell script supplied as a hidden window:

Using a slightly different Where-Object clause, you can filter the Get-CimInstance results to only return command lines that have over 1000 characters:

NOTE: This is similar to one of the checks we use in DeepBlueCLI to detect threats on a Windows system.

Let’s break this command down, step-by-step:

In the first article, we looked at the PowerShell Get-Process and Get-CimInstance -Class Win32_Process commands to retrieve process information. In this article, we applied those concepts to investigate a Windows system for threats.

Using these commands and the PowerShell pipeline, we looked at the steps to investigate new or unrecognized processes, random-looking names, non-standard paths, curious parent/child relationships, and command line parameters. As an incident response analyst, these are important techniques to apply when evaluating a live system, potentially revealing threats to your organization.

Until next time!

END
 0
Comment(No Comments)