Threat Hunting for Suspicious PowerShell Script Execution
PowerShell is the administrative backbone of the modern Windows ecosystem. Its deep integration with the .NET framework, access to the Windows API, and ability to manipulate the registry and WMI (Windows Management Instrumentation) make it an unparalleled tool for systems engineers. However, these same capabilities make it the weapon of choice for adversaries engaged in "Living off the Land" (LotL) attacks.
For a threat hunter, the challenge is not merely detecting PowerShell usage-which is ubiquitous-but distinguishing between a legitimate automated deployment script and a sophisticated, memory-resident payload designed to bypass traditional EDR (Endpoint Detection and Response) signatures.
The Adversary's Playbook: Why PowerShell?
Attackers leverage PowerShell because it allows for fileless execution. By executing code directly in memory, they can bypass legacy antivirus solutions that rely heavily on scanning files on disk. The primary techniques include:
- Encoded Commands: Using the `-EncodedCommand` (or `-e`, `-enc`) flag to pass Base64-encoded blobs. This hides the intent of the script from simple command-line inspection.
- Obfuscation: Using backticks (`` ` ``), string manipulation (e.g., `'I'+'EX'`), or character replacement to break up recognizable keywords like `DownloadString` or `Invoke-Expression`.
- Reflective Injection: Utilizing PowerShell to load .NET assemblies directly into the process memory, effectively injecting malicious DLLs without ever touching the filesystem.
- Downloader Patterns: Using `Net.WebClient` or `Invoke-WebRequest` to pull secondary stages from a C2 (Command and Control) server.
The Telemetry Foundation: What to Monitor
Effective hunting requires high-fidelity telemetry. If you are only monitoring Process Creation events (Event ID 4688), you are already behind. You must focus on the following:
1. PowerShell Script Block Logging (Event ID 4104)
This is the most critical telemetry source. When enabled, Windows logs the actual code executed within a script block. Crucially, Script Block Logging captures the de-obfuscated code. If an attacker uses multiple layers of Base64 encoding, the 4104 event will log the final, plain-text command that was actually executed by the engine.
2. PowerShell Module Logging (Event ID 4103)
This provides visibility into the pipeline execution and the specific modules being loaded. It is invaluable for tracking the usage of sensitive modules like `ActiveDirectory` or `BitsTransfer`.
3. Transcription Logging
Transcription creates a text-based record of every command and the resulting output. While resource-intensive, it provides a complete "session replay" of what the attacker did after gaining access.
Hunting Hypotheses and Implementation
A successful hunt begins with a hypothesis. Below are three actionable hunting strategies.
Hypothesis 1: Suspicious Parent-Child Relationships
Concept: PowerShell is rarely launched by a web browser, a word processor, or an unexpected service account.
The Hunt: Search for `powershell.exe` or `pwsh.exe` where the parent process is an application that should not be executing system administration tasks.
Example KQL (Kusto Query Language) for Microsoft Sentinel/Defender:
```kql
DeviceProcessEvents
| where ProcessCommandLine has_any ("powershell.exe", "pwsh.exe")
| where InitiatingProcessFileName in~ ("winword.exe", "excel.exe", "outlook.exe", "chrome.exe", "msedge.exe")
| project TimeGenerated, DeviceName, InitiatingProcessFileName, ProcessCommandLine
```
Hypothesis 2: Detection of Obfuscation and Command-Line Flags
Concept: Attackers use specific flags to suppress user interaction and bypass execution policies.
The Hunt: Look for high-entropy command lines containing flags like `-NoProfile`, `-WindowStyle Hidden`, `-ExecutionPolicy Bypass`, and `-Enc`.
Example Splunk Query:
```spl
index=windows sourcpl=Sysmon EventCode=1
| eval cmd_lower=lower(CommandLine)
| where (match(cmd_lower, "-enc") OR match(cmd_lower, "-encodedcommand") OR match(cmd_lower, "-nop") OR match(cmd_lower, "-windowstyle hidden"))
| table _time, host, User, CommandLine
```
Hypothesis 3: Identifying Network-Oriented Scripting
Concept: Malicious scripts almost always attempt to communicate with the outside world to fetch payloads or exfiltrate data.
The Hunt: Scan Script Block Logs (4104) for high-risk .NET classes and methods used for web requests.
Example KQL for Script Block Content:
```kql
DeviceEvents
| where ActionType == "PowerShellCommand"
| where AdditionalFields contains "Net.WebClient"
or AdditionalFields contains "DownloadString"
or AdditionalESSFields contains "Invoke-WebRequest"
or AdditionalFields contains "DownloadFile"
| project TimeGenerated, DeviceName, AdditionalFields
```
Operational Considerations and Trade-offs
Implementing deep PowerShell visibility is not without cost
Conclusion
As shown across "The Adversary's Playbook: Why PowerShell?", "The Telemetry Foundation: What to Monitor", "Hunting Hypotheses and Implementation", a secure implementation for threat hunting for suspicious powershell script execution depends on execution discipline as much as design.
The practical hardening path is to enforce strict token/claim validation and replay resistance, host hardening baselines with tamper-resistant telemetry, and behavior-chain detection across process, memory, identity, and network telemetry. This combination reduces both exploitability and attacker dwell time by forcing failures across multiple independent control layers.
Operational confidence should be measured, not assumed: track time from suspicious execution chain to host containment and policy-gate coverage and vulnerable artifact escape rate, then use those results to tune preventive policy, detection fidelity, and response runbooks on a fixed review cadence.