Why PowerShell Is Still Attacker-Favourite

PowerShell gives attackers a signed, trusted, network-capable scripting environment built into every Windows installation. It can download payloads, interact with COM objects, manipulate the registry, query WMI, and execute .NET code — all without dropping a file. Despite years of defender awareness, PowerShell abuse remains one of the most frequently observed initial execution and post-exploitation techniques, appearing in ransomware pre-deployment, hands-on-keyboard intrusions, and commodity malware delivery chains alike.

The detection challenge is layered: attackers encode commands in Base64, layer obfuscation, use string concatenation to defeat signature matching, and increasingly leverage constrained language mode bypasses and AMSI patching to evade defences. A complete detection approach requires multiple logging sources working in concert.

The Detection Stack

1. Script Block Logging (Event ID 4104)

Script block logging captures the actual content of every PowerShell script block executed — after obfuscation is decoded by the PowerShell engine. This is the highest-fidelity source for detecting malicious content because it sees the deobfuscated command.

Enable via Group Policy: Computer Configuration > Administrative Templates > Windows Components > Windows PowerShell > Turn on PowerShell Script Block Logging

Or via registry:

Set-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" -Name "EnableScriptBlockLogging" -Value 1

Key Event ID 4104 fields to inspect:

  • ScriptBlockText — the actual command content (post-decode)
  • Path — empty path indicates inline/encoded execution
  • MessageNumber / MessageTotal — large script blocks are split across multiple events

2. Module Logging (Event ID 4103)

Module logging records pipeline execution details — cmdlet names, parameters, and output. It generates more volume than script block logging but catches different patterns, particularly cmdlet-level activity.

3. PowerShell Transcription

Transcription writes a plain-text log of every PowerShell session to a file. Useful for incident response but high volume for SIEM ingestion. Best used as a secondary source.

4. AMSI (Anti-Malware Scan Interface)

AMSI passes script content to registered security products before execution. Detection telemetry from AMSI-capable EDRs provides a complementary signal — attackers who patch AMSI in-memory leave behavioural traces that can be detected independently.

High-Signal Detection Patterns

Encoded Command Execution

The -EncodedCommand (-enc, -e) flag is the most common obfuscation primitive. Any PowerShell process spawned with this flag warrants inspection:

title: PowerShell Encoded Command Execution
id: 7f135fb7-6ef0-4fc3-8aaa-3a1123f69c7a
status: stable
logsource:
  category: process_creation
  product: windows
detection:
  selection:
    Image|endswith: '\powershell.exe'
    CommandLine|contains:
      - ' -enc '
      - ' -EncodedCommand '
      - ' -e '
  condition: selection
falsepositives:
  - Some legitimate software uses encoded commands during installation
level: medium
tags:
  - attack.execution
  - attack.t1059.001

Download Cradles

Web download cradles — IEX, Invoke-Expression, Net.WebClient, Invoke-WebRequest, Start-BitsTransfer — are a staple of fileless malware delivery:

title: PowerShell Download Cradle
id: 3b6a8f62-d1f5-4f3e-a8e6-f1c1a9e4b2d3
status: stable
logsource:
  category: ps_script
  product: windows
  definition: Script block logging must be enabled
detection:
  selection:
    ScriptBlockText|contains:
      - 'Net.WebClient'
      - 'Invoke-WebRequest'
      - 'Start-BitsTransfer'
      - 'WebProxy'
      - 'DownloadString'
      - 'DownloadFile'
  iex:
    ScriptBlockText|contains:
      - 'IEX'
      - 'Invoke-Expression'
  condition: selection and iex
falsepositives:
  - Legitimate software deployment scripts
level: high
tags:
  - attack.execution
  - attack.t1059.001
  - attack.t1105

AMSI Bypass Attempts

AMSI patching attempts have known signatures — look for reflection calls targeting AmsiUtils or direct memory writes to bypass scanning:

title: PowerShell AMSI Bypass via Reflection
id: a2f87c3d-91b5-4e6c-b8d2-c3f4a1e9b7c1
status: stable
logsource:
  category: ps_script
  product: windows
detection:
  selection:
    ScriptBlockText|contains:
      - 'AmsiUtils'
      - 'amsiInitFailed'
      - '[Ref].Assembly.GetType'
      - 'GetField'
      - 'NonPublic'
  condition: selection
level: high
tags:
  - attack.defense_evasion
  - attack.t1562

KQL for Microsoft Sentinel

// High-confidence PowerShell abuse indicators
SecurityEvent
| where EventID == 4104
| extend ScriptBlock = tostring(EventData.ScriptBlockText)
| where ScriptBlock has_any (
    "IEX", "Invoke-Expression",
    "Net.WebClient", "DownloadString",
    "AmsiUtils", "amsiInitFailed",
    "-EncodedCommand", "-enc ",
    "FromBase64String"
  )
| project TimeGenerated, Computer, Account, ScriptBlock
| order by TimeGenerated desc

Tuning Recommendations

Start broad and tune down rather than building narrow rules. Common false positive sources to baseline:

  • SCCM / software deployment — encoded commands during package execution
  • Azure Arc and management agents — regular encoded heartbeat commands
  • Pester test frameworks — legitimate security testing tools

Tag known-good processes and accounts as exclusions after establishing a baseline, rather than adding blanket exclusions that blind the rule.

Quick-Win Coverage Gaps

If you only have process creation logs and no script block logging yet, start there. Even without 4104, you can detect:

  • PowerShell spawned from winword.exe, excel.exe, outlook.exe (macro execution)
  • PowerShell spawned from cmd.exe with -nop -w hidden flags
  • PowerShell spawned from wscript.exe or cscript.exe

These parent-child relationships catch commodity malware delivery before any obfuscation needs decoding.