Month Of PowerShell: Process Threat Hunting, Part 1 | SANS Institute

#monthofpowershell

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: [code]Get-Process[/code] and [code]Get-CimInstance[/code] using the [code]Win32_Process[/code] 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.

Listing Processes

PowerShell makes it easy to list processes using [code]Get-Process[/code]:

PS C:\Users\Sec504> Get-Process Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName ------- ------ ----- ----- ------ -- -- ----------- 317 32 42576 107816 2.77 1520 1 chrome 310 33 103376 81224 2.98 1708 1 chrome 151 9 2008 6980 0.02 2660 1 chrome 209 13 6788 16640 0.05 4844 1 chrome 988 42 51576 114540 3.28 6368 1 chrome ...

We can investigate a specific process by supplying the process name as an argument:

PS C:\Users\Sec504> Get-Process explorer Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName ------- ------ ----- ----- ------ -- -- ----------- 2332 93 82448 134420 14.31 4808 1 explorer

Wildcards work too:

PS C:\Users\Sec504> Get-Process vm* Handles NPM(K) PM(K) WS(K) CPU(s) Id SI ProcessName ------- ------ ----- ----- ------ -- -- ----------- 92 7 1328 920 0.03 6520 1 vm3dservice 445 23 8672 10872 3200 0 vmtoolsd 541 36 23796 28980 13.64 6356 1 vmtoolsd

In the [code]Get-Process[/code] output, we get several columns of detail for each process:

  • Handles: The number of handles (threads, open files, registry objects, etc.) accessible
  • NPM(K): Non-paged memory in use
  • PM(K): Pageable memory in use
  • WS(K): Memory working set (memory that is actively in use)
  • VM(M): Virtual memory in use (real and paged memory on disk)
  • CPU(s): Cumulative processor time used, in seconds.
  • ID: Process ID (PID)
  • ProcessName: Process name

The defaults are useful, but perhaps more to system administrators than security analysts. Fortunately, [code]Get-Process[/code] offers more process details as well.

Process Details

We can get a list of the process properties details available with [code]Get-Process[/code] using [code]Get-Member[/code]:

PS C:\Users\Sec504> Get-Process | Get-Member -MemberType Properties TypeName: System.Diagnostics.Process Name MemberType Definition ---- ---------- ---------- Handles AliasProperty Handles = Handlecount Name AliasProperty Name = ProcessName NPM AliasProperty NPM = NonpagedSystemMemorySize64 PM AliasProperty PM = PagedMemorySize64 SI AliasProperty SI = SessionId VM AliasProperty VM = VirtualMemorySize64 WS AliasProperty WS = WorkingSet64 __NounName NoteProperty string __NounName=Process BasePriority Property int BasePriority {get;} Container Property System.ComponentModel.IContainer Container {get;} EnableRaisingEvents Property bool EnableRaisingEvents {get;set;} ...

For incident response investigations, I like to examine the following parameters for processes:

  • Name
  • Handle count
  • Id
  • Path
  • Command line
  • Bytes read and written to the disk
  • Memory used (real and virtual)
  • Parent Id
  • Process creation date and time

Here's where I get disappointed with [code]Get-Process[/code]: 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 [code]Select-Object[/code]:

PS C:\Users\Sec504> Get-Process chrome | Select-Object -Property Name, Id, Path, WorkingSet64 Name Id Path WorkingSet64 ---- -- ---- ------------ chrome 1520 C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 110432256 chrome 1708 C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 82894848 chrome 2660 C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 7159808 chrome 4844 C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 16973824 chrome 6368 C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 117047296 chrome 7496 C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 26345472 chrome 7528 C:\Program Files (x86)\Google\Chrome\Application\chrome.exe 26374144

Unfortunately, [code]Get-Process[/code] doesn't offer all of the detail we want. Fortunately, Microsoft also makes [code]Get-CimInstance[/code] available.

Detailed Process ... Details

[code]Get-Process[/code] is good for simple interrogation of processes, but if you want detailed information, you'll want to use [code]Get-CimInstance[/code] instead with the [code]Win32_Process[/code] class.

PS C:\Users\Sec504> Get-CimInstance -Class Win32_Process ProcessId Name HandleCount WorkingSetSize VirtualSize --------- ---- ----------- -------------- ----------- 0 System Idle Process 0 8192 8192 4 System 2471 36864 3985408 92 Registry 0 27586560 94515200 316 smss.exe 53 274432 2203359694848 424 csrss.exe 578 2191360 2203413659648 ...

At first glance, [code]Get-CimInstance -Class Win32_Process[/code] returns information that is similar to that of [code]Get-Process[/code], but we can get a lot more process detail information from [code]Get-CimInstance[/code]:

PS C:\Users\Sec504> Get-CimInstance -Class Win32_Process | Get-Member -MemberType Properties TypeName: Microsoft.Management.Infrastructure.CimInstance#root/cimv2/Win32_Process Name MemberType Definition ---- ---------- ---------- Handles AliasProperty Handles = Handlecount ProcessName AliasProperty ProcessName = Name VM AliasProperty VM = VirtualSize WS AliasProperty WS = WorkingSetSize Caption Property string Caption {get;} CommandLine Property string CommandLine {get;} CreationClassName Property string CreationClassName {get;} ...

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:

PS C:\Users\Sec504> Get-CimInstance -Class Win32_Process | Select-Object -Property Name, HandleCount, ProcessId, ParentProcessId, Path, CommandLine, WriteTransferCount, ReadTransferCount, WorkingSetSize ... Name : chrome.exe HandleCount : 317 ProcessId : 1520 ParentProcessId : 6368 Path : C:\Program Files (x86)\Google\Chrome\Application\chrome.exe CommandLine : "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --type=renderer --display-capture-permissions-policy-allowed --lang=en-US --device-scale-factor=2 --num-raster-threads=1 --renderer-client-id=5 --launch-time-ticks=3385309652 --mojo-platform-channel-handle=2832 --field-trial-handle=1804,i,7538668890417119548,1058345838094988730,131072 /prefetch:1 WriteTransferCount : 22843548 ReadTransferCount : 2816643 WorkingSetSize : 110432256 ...

[code]Get-CimInstance[/code] does not allow us to specify a process name as an argument like [code]Get-Process[/code] does. If you want to use [code]Get-CimInstance[/code] to return information about a specific process by name, you can add a [code]Where-Object[/code] command to the pipeline:

PS C:\Users\Sec504> Get-CimInstance -Class Win32_Process | Select-Object -Property Name, HandleCount, ProcessId, ParentProcessId, Path, CommandLine, WriteTransferCount, ReadTransferCount, WorkingSetSize | Where-Object -Property Name -E "explorer.exe" Name : explorer.exe HandleCount : 2244 ProcessId : 4808 ParentProcessId : 4760 Path : C:\WINDOWS\Explorer.EXE CommandLine : C:\WINDOWS\Explorer.EXE WriteTransferCount : 89089 ReadTransferCount : 5787331 WorkingSetSize : 131350528

PID Relationships

Let's look at an example of applying these PowerShell process-interrogation techniques: parent and child relationships. Using [code]Get-CimInstance[/code], we can identify the parent process ID ([code]ParentProcessId[/code]) 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:

PS C:\Users\Sec504> Get-Process chrome |Select-Object -Property Name, Id Name Id ---- -- chrome 1520 chrome 1708 chrome 2660 chrome 4844 chrome 6368 chrome 7496 chrome 7528

Here we see [code]Get-Process[/code] has identified 7 Chrome processes with different process ID values. Unfortunately, [code]Get-Process[/code] can't identify the parent process ID, so we turn to [code]Get-CimInstance[/code] for that:

PS C:\Users\Sec504> Get-CimInstance -Class Win32_Process | Where-Object -Property Name -EQ chrome.exe | Select-Object Name, ProcessId, ParentProcessId Name ProcessId ParentProcessId ---- --------- --------------- chrome.exe 6368 4808 chrome.exe 2660 6368 chrome.exe 1708 6368 chrome.exe 7496 6368 chrome.exe 4844 6368 chrome.exe 7528 6368 chrome.exe 1520 6368

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.

That's great, but how do we identify the parent of process ID 6368? Just a slight modification to the [code]Get-CimInstance[/code] command gives us the answer:

PS C:\Users\Sec504> Get-CimInstance -Class Win32_Process | Where-Object -Property ProcessId -EQ 4808 | Select-Object Name, ProcessId, ParentProcessId Name ProcessId ParentProcessId ---- --------- --------------- explorer.exe 4808 4760

After identifying process ID 4808 as the parent for the first Chrome process, we can identify the process name by changing the [code]Where-Object[/code] clause to filter on the [code]ProcessId[/code] field, revealing the parent process as [code]explorer.exe[/code]. We can repeat this process for Explorer as well:

PS C:\Users\Sec504> Get-CimInstance -Class Win32_Process | Where-Object -Property ProcessId -EQ 4760 | Select-Object Name, ProcessId, ParentProcessId PS C:\Users\Sec504>

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.

Summary

We looked at the [code]Get-Process[/code] command as a tool to retrieve information about running processes. [code]Get-Process[/code] accepts a process name or wildcard, allowing us to quickly filter the results. This is convenient, but [code]Get-Process[/code] is also limited: it doesn't allow us to inspect several properties that are useful for incident response analysis.

We also looked at [code]Get-CimInstance[/code] using the [code]Win32_Process[/code] class. [code]Get-CimInstance[/code] can reveal valuable process properties for incident response analysts: path, command line, parent process ID, and more. Filtering is a little more complicated with [code]Get-CimInstance[/code], but the [code]Where-Object[/code] command helps out here.

Finally we looked at a practical investigation opportunity using [code]Get-CimInstance[/code], 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.

-Joshua Wright

Return to Getting Started With PowerShell

Joshua Wright is the author of SANS SEC504: Hacker Tools, Techniques, and Incident Handling, a faculty fellow for the SANS Institute, and a senior technical director at Counter Hack.

Từ khóa » Npm(k) Pm(k) Ws(k) Vm(m)