When performing threat hunting and live system analysis, I will often look at the processes running on the system. Often, a compromised system will run one or more processes that look suspicious, which gives us an opportunity to identify the threat.
Let’s look at how we can use PowerShell to evaluate a running system. We’ll focus on two primary PowerShell commands: Get-Process and Get-CimInstance using the Win32_Process class. This first article will focus on using the PowerShell commands and collecting the data. In the second article, we’ll look at applying these commands to investigate malicious code running on a Windows host.
TIP: If you are reading this article from Windows, you can follow along with each of the examples to practice! If you use a browser other than Chrome, substitute that browser name where I use chrome below.
PowerShell makes it easy to list processes using Get-Process:
We can investigate a specific process by supplying the process name as an argument:
NOTE: Don’t specify the .exe part of the process executable name when using Get-Process.
Wildcards work too:
In the Get-Process output, we get several columns of detail for each process:
The defaults are useful, but perhaps more to system administrators than security analysts. Fortunately, Get-Process offers more process details as well.
We can get a list of the process properties details available with Get-Process using Get-Member:
For incident response investigations, I like to examine the following parameters for processes:
Here’s where I get disappointed with Get-Process: it offers a lot of useful information, but it also omits lots of useful details about processes. We can modify the columns retrieved to get specific properties using Select-Object:
Unfortunately, Get-Process doesn’t offer all of the detail we want. Fortunately, Microsoft also makes Get-CimInstance available.
Get-Process is good for simple interrogation of processes, but if you want detailed information, you’ll want to use Get-CimInstance instead with the Win32_Process class.
NOTE: Get-CimInstance is powerful, but it is only available for systems that implement the full Common Information Model. Practically, this means that Get-CimInstance is only useful on Windows systems.
At first glance, Get-CimInstance -Class Win32_Process returns information that is similar to that of Get-Process, but we can get a lot more process detail information from Get-CimInstance:
Often I’ll use the following set of parameters to collect information about running processes when I’m looking for threats on a Windows system:
Get-CimInstance does not allow us to specify a process name as an argument like Get-Process does. If you want to use Get-CimInstance to return information about a specific process by name, you can add a Where-Object command to the pipeline:
TIP: Using Where-Object is this style is very handy, since we can filter the results using any of the properties returned by Get-CimInstance. We’ll look at this again in the next article where we apply these techniques to investigate malware.
Let’s look at an example of applying these PowerShell process-interrogation techniques: parent and child relationships. Using Get-CimInstance, we can identify the parent process ID (ParentProcessId) for a given process. The parent process ID tells us the process that launched the process. Let’s get the PID of the Chrome process first:
Here we see Get-Process has identified 7 Chrome processes with different process ID values. Unfortunately, Get-Process can’t identify the parent process ID, so we turn to Get-CimInstance for that:
In this output we see that the first Chrome process has a process ID of 6368; all other Chrome processes are children of this first Chrome process since they all have process ID 6368 as their parent process ID.
NOTE: One the things that is confusing to PowerShell beginners (and annoying to everyone else) is the inconsistency in how properties are named. Get-Process uses ID for the process ID property; Get-CimInstance uses ProcessId for the same property. Get-Process does not include the .exe extension in the process name; Get-CimInstance does include the .exe extension in the same property. These are little things that trip people up on a regular basis. It’s better to accept that PowerShell is confusing and inconsistent, instead of expecting it to be clear and consistent.
That’s great, but how do we identify the parent of process ID 6368? Just a slight modification to the Get-CimInstance command gives us the answer:
After identifying process ID 4808 as the parent for the first Chrome process, we can identify the process name by changing the Where-Object clause to filter on the ProcessId field, revealing the parent process as explorer.exe. We can repeat this process for Explorer as well:
Notably here, Explorer has no parent. It’s a special process launched by Userinit when a user logs in, and then Userinit exits. This makes Explorer an orphan process, revealing no parent information when we investigate the parent process ID.
We looked at the Get-Process command as a tool to retrieve information about running processes. Get-Process accepts a process name or wildcard, allowing us to quickly filter the results. This is convenient, but Get-Process is also limited: it doesn’t allow us to inspect several properties that are useful for incident response analysis.
We also looked at Get-CimInstance using the Win32_Process class. Get-CimInstance can reveal valuable process properties for incident response analysts: path, command line, parent process ID, and more. Filtering is a little more complicated with Get-CimInstance, but the Where-Object command helps out here.
Finally we looked at a practical investigation opportunity using Get-CimInstance, investigating the relationship between process ID and parent process ID. We’ll continue to leverage this in the next article, where we use these process threat hunting skills on a compromised system to hunt our malware.