SOP-25: Malicious PowerShell / Script Engine Execution Response

·

PowerShell is the most abused scripting engine in Windows environments. It provides attackers with a built-in, trusted execution environment capable of downloading payloads, injecting shellcode, querying Active Directory, moving laterally via WinRM, and bypassing traditional antivirus — all without writing a binary to disk. It is present on every modern Windows system and cannot be safely removed.

The primary evasion technique is command-line obfuscation: base64 encoding (-EncodedCommand), execution policy bypass flags, hidden window style, and AMSI patching. This SOP guides analysts through decoding these commands, correlating Script Block Logging output (which captures the decoded payload), and identifying the network and process chain that follows a malicious PowerShell execution.

◈ Table of Contents

01 Background 02 Identification 03 Containment 04 Eradication 05 Escalation
01

Background

CONTEXT
B1MITRE ATT&CK Mapping
MITRETechniquePowerShell PatternWhat Attacker Achieves
T1059.001Command and Scripting Interpreter — PowerShellpowershell.exe -EncodedCommand, IEX, Invoke-Expression, DownloadStringArbitrary code execution in a trusted, signed process — common for all stages of attack chain
T1027Obfuscated Files or Information-EncodedCommand (base64), -Enc, string concatenation, char code replacement, SecureString encodingHides payload content from command-line logging and signature-based detection
T1562.001Impair Defenses — Disable or Modify ToolsSet-MpPreference -DisableRealtimeMonitoring $true; AMSI patch via memory write to amsi.dllDisables Windows Defender real-time monitoring or patches AMSI in-memory to bypass script scanning
T1105Ingress Tool Transfer(New-Object Net.WebClient).DownloadString('http://...'); Invoke-WebRequestDownloads second-stage payload directly into memory without writing to disk
T1086 / T1059PowerShell RemotingEnter-PSSession, Invoke-Command -ComputerName, New-PSSessionLateral movement via WinRM — executes commands on remote hosts using current credentials
B2Log Sources & Prerequisites
SourceSentinel TableKey FieldsRequired Setting
MDE Process EventsDeviceProcessEventsFileName, ProcessCommandLine, InitiatingProcessFileName — captures the outer encoded command lineDefender for Endpoint onboarded
PowerShell Script Block LoggingEvent (EventID=4104)RenderedDescription — contains the DECODED PowerShell content before execution. Most important log source for obfuscated PS.GPO: Computer Config → Windows Settings → Administrative Templates → Windows Components → Windows PowerShell → Turn on PowerShell Script Block Logging = Enabled
PowerShell Module LoggingEvent (EventID=4103)Pipeline execution details — shows module imports and command outputsGPO: Turn on Module Logging = Enabled; specify * for all modules
Windows Security EventsSecurityEvent (EventID=4688)CommandLine field — process creation. Less detail than MDE but available without Defender.Audit Process Creation + command-line logging GPO

Script Block Logging (Event 4104) is the single most important control for PowerShell threat detection. Without it, encoded commands are invisible to analysts — you only see the base64 blob, not the decoded payload. Confirm GPO is deployed on all endpoints before declaring an investigation complete.

02

Identification

DETECT & INVESTIGATE
◈ Malicious PowerShell — Investigation Workflow
I1Identify Obfuscation Flags & Decode the PayloadMANUAL + KQL
WHY

Attackers encode PowerShell commands in base64 to prevent command-line logging systems from reading the actual instructions. The -EncodedCommand flag tells PowerShell to decode and execute the base64 blob — analysts must decode it manually or via Script Block Logging (Event 4104) to understand what the command actually did. Without decoding, you cannot determine intent, scope, or payload type.

◈ Where to Check — MDE Device Timeline
security.microsoft.com→Endpoints→[Device]→Timeline→Filter: powershell.exe
  • 1
    Locate the PowerShell process creation event in the device timeline. Note the full command line including all flags. If you see -EncodedCommand, -Enc, or -e followed by a long string of characters — that string is base64-encoded PowerShell.
  • 2
    To decode: extract the base64 string (everything after the flag). In PowerShell: [System.Text.Encoding]::Unicode.GetString([System.Convert]::FromBase64String('BASE64STRING')). In CyberChef: use "From Base64" → "Decode text" (UTF-16LE encoding). The decoded content reveals the actual commands.
  • 3
    Note the parent process. If the parent is WINWORD.EXE, EXCEL.EXE, Outlook.exe, or chrome.exe — this is a phishing/macro execution chain. Immediately check the parent document or email for the delivery vector.
◈ Where to Check — Script Block Logging (Event 4104)
Event Viewer→Applications and Services Logs→Microsoft→Windows→PowerShell→Operational
  • 4
    Filter for Event ID 4104 in the time window around the alert. The Message field contains the fully decoded PowerShell script content — even if the outer command was base64 encoded. This is the ground truth of what PowerShell executed.
  • 5
    Search the 4104 message body for any of the key indicator patterns in the table below. Presence of amsiInitFailed, [Ref].Assembly.GetType, or Set-MpPreference -DisableRealtimeMonitoring indicates defense evasion — escalate to SEV1 immediately.
Key Indicators — PowerShell Abuse Patterns
Flag / PatternMeaningAnalyst Action
-EncodedCommand / -Enc / -eBase64-encoded payload passed to PowerShell — hides actual instructions from command-line loggingDecode immediately. Check Event 4104 for the decoded content.
-ExecutionPolicy BypassOverrides the machine execution policy — tells PowerShell to run unsigned scripts regardless of policyNot malicious alone, but in combination with other flags = deliberate evasion. Context-dependent.
-WindowStyle Hidden / -w hHides the PowerShell window from the user — attacker does not want the user to see the script runningStrong indicator of malicious intent. No legitimate admin tool hides its window by default.
IEX / Invoke-ExpressionExecutes a string as PowerShell code — classic fileless execution: download string, then IEX it without writing to diskCheck Event 4104 for what was passed to IEX. DownloadString + IEX = fileless payload execution.
DownloadString / DownloadFile / WebClientDownloads content from a URL — used to fetch second-stage payloads or shellcode directly into memoryExtract the URL. Block it. Check network events for the connection. Check if download succeeded.
amsiInitFailed / [Ref].Assembly.GetTypeAMSI bypass — patches the Windows Antimalware Scan Interface in memory so subsequent scripts are not scannedAUTOMATIC SEV1. AMSI bypass = attacker is actively evading detection. Isolate device immediately.
Set-MpPreference -Disable*Disables Windows Defender features (real-time monitoring, cloud protection, behaviour monitoring)AUTOMATIC SEV1. Defense tampering = T1562.001. Re-enable Defender as first containment action.
DETECTS: All PowerShell executions containing obfuscation flags, download commands, AMSI bypass patterns, or Defender tamper commands in the last 7 days — grouped by device and user for triage prioritisation.
KQL — Microsoft Sentinel: Malicious PowerShell detection
DeviceProcessEvents | where TimeGenerated > ago(7d) | where FileName =~ "powershell.exe" or FileName =~ "pwsh.exe" | where ProcessCommandLine has_any ( "-EncodedCommand","-Enc ","-e ", "DownloadString","DownloadFile","Invoke-WebRequest", "IEX","Invoke-Expression", "amsiInitFailed","amsi.dll","GetType(", "Set-MpPreference","DisableRealtimeMonitoring", "-WindowStyle Hidden","-w h","-NonInteractive -NoProfile" ) | extend SuspFlags = extract_all(@"(-EncodedCommand|-Enc |-e |-w h|-WindowStyle Hidden|IEX|DownloadString|amsiInitFailed|Set-MpPreference)", ProcessCommandLine) | project TimeGenerated, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessFileName, SuspFlags | order by TimeGenerated desc
DETECTS: Script Block Logging Event 4104 entries containing AMSI bypass or Defender tamper content — captures decoded payload even when the outer command was base64 obfuscated.
KQL — Sentinel: Script Block Log — AMSI bypass & defense evasion
Event | where TimeGenerated > ago(7d) | where Source == "Microsoft-Windows-PowerShell" | where EventID == 4104 | where RenderedDescription has_any ( "amsiInitFailed","amsi.dll","GetType(", "Set-MpPreference","DisableRealtimeMonitoring", "DownloadString","Invoke-Expression", "sekurlsa","mimikatz","Invoke-Mimikatz" ) | project TimeGenerated, Computer, RenderedDescription | order by TimeGenerated desc
SPL — Splunk: Encoded PowerShell & AMSI bypass
index=windows (EventCode=4688 OR EventCode=4104) (CommandLine="*-EncodedCommand*" OR CommandLine="*-Enc *" OR CommandLine="*IEX*" OR CommandLine="*DownloadString*" OR CommandLine="*amsiInitFailed*" OR CommandLine="*Set-MpPreference*" OR Message="*amsiInitFailed*" OR Message="*DownloadString*") process_name="powershell.exe" | eval Source=if(EventCode=4104,"ScriptBlock","ProcessCreate") | table _time, ComputerName, user, Source, CommandLine, Message | sort -_time
I2Correlate Network Download & Child Process Spawned by PowerShellMANUAL + KQL
WHY

Malicious PowerShell rarely acts alone — it either downloads a second-stage payload (proving active C2 communication) or spawns a child process to execute that payload (proving successful delivery). Identifying both the download URL and the child process reveals the complete attack chain: initial access vector → PowerShell → C2 download → implant execution. Without this correlation you cannot scope the incident correctly.

◈ Where to Check — MDE Network Events from PowerShell
security.microsoft.com→[Device]→Timeline→Filter: Network connection + Process = powershell.exe
  • 1
    In the device timeline, set event type filter to Network connection. Filter Process name = powershell.exe. Check ±10 minutes around the alert time. Any external IP connection from PowerShell is suspicious — legitimate admin PS should not be reaching out to unknown IPs.
  • 2
    Note the Remote URL or Remote IP. If the URL matches the DownloadString argument decoded from Event 4104 — the download was successful. If only an IP is shown (no URL) — the script used direct IP communication (common for C2 beacons). Run the IP through threat intel (VirusTotal, MDTI).
  • 3
    Check for Process created events by powershell.exe — these are child processes spawned after the download. Common patterns: powershell.exe spawning cmd.exe, net.exe, whoami.exe, rundll32.exe, or an unknown executable from %TEMP%.
DETECTS: Network connections made by PowerShell to external IPs/domains — confirms active download or C2 communication from the malicious script. Filters out private IP ranges to reduce noise.
KQL — Network connections from PowerShell processes
DeviceNetworkEvents | where TimeGenerated > ago(7d) | where InitiatingProcessFileName in~ ("powershell.exe","pwsh.exe") | where ActionType == "ConnectionSuccess" | where not(ipv4_is_private(RemoteIP)) | project TimeGenerated, DeviceName, AccountName, InitiatingProcessCommandLine, RemoteIP, RemoteUrl, RemotePort | order by TimeGenerated desc
DETECTS: Child processes spawned by PowerShell — reveals what executed after the download. Executables or scripts launched from user-writable paths are near-certain stage-2 payloads.
KQL — Child processes spawned by PowerShell
DeviceProcessEvents | where TimeGenerated > ago(7d) | where InitiatingProcessFileName in~ ("powershell.exe","pwsh.exe") | where FileName !in~ ("conhost.exe","powershell.exe","pwsh.exe") | project TimeGenerated, DeviceName, AccountName, FileName, ProcessCommandLine, FolderPath, InitiatingProcessCommandLine | order by TimeGenerated desc

If the PowerShell script used IEX (New-Object Net.WebClient).DownloadString(...), the payload was executed entirely in memory and may not appear as a dropped file. Check for an injected process instead: look for unusual memory regions (shellcode signatures) in the same powershell.exe PID, or check if the PS process opened a handle to another process (e.g. explorer.exe) within seconds of the download — that would indicate reflective injection.

03

Containment

STOP IT
Based on Identification Findings:
Confirmed
-EncodedCommand with decoded payload containing DownloadString/IEX, OR Event 4104 shows AMSI bypass / Set-MpPreference disable, OR network outbound to external IP from powershell.exe confirmed, OR child process spawned to user-writable path → Execute C1 immediately. AMSI bypass alone = SEV1, escalate to L2 before containment completes.
Uncertain
-EncodedCommand present but decoded content appears to be a legitimate admin script (no download URLs, no AMSI bypass, no suspicious child processes), parent is cmd.exe opened by a known IT admin → Contact the admin to verify. Review decoded content with a senior analyst. Hold containment for 15 minutes maximum while verifying.
False Pos.
Script Block Logging shows the decoded content is a known IT management script (SCCM, Intune, monitoring agent), parent process is an approved IT tool, no external network connections, no suspicious child processes → Document, close, add exclusion for the specific script hash or parent tool path in the analytics rule.
C1Isolate Device & Restore Defender if TamperedImmediate
  • 1
    Isolate the device via MDE: security.microsoft.com → Endpoints → Device inventory → [Device] → Isolate device → Full isolation. This stops any ongoing C2 communication while preserving the device for forensics.
  • 2
    If Defender was disabled by the script: Via MDE Live Response, run Set-MpPreference -DisableRealtimeMonitoring $false and Start-Service WinDefend to restore real-time protection before the PowerShell process is killed — so Defender can scan the memory of the running process.
  • 3
    Kill the PowerShell process: Via Live Response, run Stop-Process -Name powershell -Force. If a child process was spawned, kill it by name or PID as well.
  • 4
    Block the C2 URL/IP: If a download URL or C2 IP was identified — add it as a Custom Block Indicator in MDE. Also submit to your Sentinel watchlist and firewall block list.
04

Eradication

CLEAN UP
E1Remove Persistence & Hunt Org-Wide
  • 1
    Check for persistence created by the PowerShell script: The most common follow-on actions are scheduled tasks (schtasks), registry run keys, and WMI subscriptions. Run the SOP-26 identification steps on this device.
  • 2
    Search for the download URL org-wide: Run the I2 network KQL across all devices. If other devices connected to the same C2 IP — you have a broader campaign. Escalate to IR.
  • 3
    Confirm Defender protections are restored: Check Device page → Security recommendations — all protections should show green. If AMSI was patched in-process, a device restart after isolation will restore it.
  • 4
    Reset the affected user's credentials: The PowerShell script may have used the session token or harvested credentials in memory. Issue a password reset and re-enrol MFA before the user's account is re-enabled.
  • 5
    Confirm Script Block Logging is deployed org-wide: Use the B2 GPO reference to verify coverage. If this attack was initially detected only by a command-line flag and not by 4104 content — you have a logging gap that must be closed before considering eradication complete.
Eradication Complete When
  • Device isolated; PowerShell process and any spawned child processes terminated
  • Windows Defender real-time monitoring confirmed enabled; AMSI functioning normally (device restarted)
  • C2 URL/IP blocked as Custom Indicator org-wide in MDE and Sentinel watchlist
  • No persistence mechanisms (scheduled tasks, run keys) identified from the PS execution
  • Org-wide hunt for same C2 IP returns clean across all devices
  • Script Block Logging (Event 4104) confirmed deployed and ingesting into Sentinel
05

Escalation

TIERS
ESCEscalation Decision Table
TierTrigger ConditionWho to NotifyAction
L1 → L2Single device, encoded PS with confirmed malicious payload (DownloadString/IEX), no AMSI bypass, no Defender tamper, device isolated, C2 blocked, no lateral movementL2 SOC AnalystHand off: device name, user, decoded payload content, C2 URL/IP, containment actions taken
L2 → IR (SEV1)Any of: AMSI bypass pattern confirmed in Event 4104, Defender disabled by the script, multiple devices connecting to same C2 IP, PowerShell used for lateral movement (PSSession to other hosts), credential harvesting commands found in decoded payload (Invoke-Mimikatz, sekurlsa)IR Team + CISODeclare SEV1. Full forensic collection. Map lateral movement. Credential reset across all potentially touched accounts. Regulatory assessment if any data exfiltration occurred.
L2 → Security EngineeringScript Block Logging (Event 4104) was not enabled on affected devices; Constrained Language Mode not enforced; PowerShell v2 downgrade was used to bypass loggingSecurity ArchitectureImmediate: deploy Script Block Logging GPO. Disable PowerShell v2 (Disable-WindowsOptionalFeature -Online -FeatureName MicrosoftWindowsPowerShellV2Root). Consider Constrained Language Mode for non-admin users.

Authorized security research & penetration testing only. Unauthorized use is illegal. Built by Rudra Verma | Senior Cyber Security Architect & Researcher | CyberHawk Threat Intel

◈ Stay Connected

Follow CyberHawk Threat Intel for threat intelligence, SOC playbooks, and detection engineering content.

🌐 Website ▶️ YouTube ▶️ YouTube (2) 𝕏 Twitter / X ♪ TikTok ✈️ Telegram
🔍 IOC Scanner 🛠️ Live Tools 📚 Courses 🚨 Threat Intel 📝 Blog 📋 SOPs

"They can't exploit you if you are the Exploit."