PowerShell script block logging (4104)

When enabled, Windows records the actual text of every PowerShell block before it runs, after deobfuscation. It is the single highest-value log on a Windows host and it is off by default.

windows · Execution · T1059.001T1027

where it lives

C:\Windows\System32\winevt\Logs\Microsoft-Windows-PowerShell%4Operational.evtx

PowerShell 5.0 and later

Event 4104 carries the script text. 4103 carries pipeline execution detail.

SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging

All

EnableScriptBlockLogging must be 1. Check this before concluding anything from an absence.

what it proves

  • The literal text of what was executed, after the layers of encoding are stripped
  • Base64 and compressed payloads in their decoded form, which is why obfuscation does not defeat it
  • The order of execution, and which blocks came from a file rather than the console

what it does not prove

  • Anything at all when the policy is off, which is the default. An empty log is a configuration finding, not an absence of activity
  • That the script succeeded, only that it was compiled and run
  • Activity from a downgraded session: an attacker invoking PowerShell 2.0 avoids this entirely, which is why version 2 should be removed

parsing it

  • EvtxECmd (Eric Zimmerman)
  • Chainsaw
  • Hayabusa
  • Get-WinEvent

tampering and anti-forensics

Clearing this log raises 104 in the same channel. The more common evasion is never triggering it: PowerShell 2.0 downgrade, or using a .NET runspace directly rather than powershell.exe.

how long it survives

Rolls by size, 15MB by default. On an administrative workstation that can be days.

where this comes from

read next

prefetch · run keys

Query Vault

ProT1059.001T1027

Find obfuscated or downloading script blocks without drowning in administrative PowerShell.

Splunk SPLSentinel KQLElastic EQL

The three queries, what each field in the results means, and the benign activity each one will return, are part of a Pro membership.

Verify against the host in front of you before this reaches a report. Paths and behaviour move between Windows builds, and a documented default is not necessarily the setting on that machine. Corrections are published.

PowerShell script block logging (4104), artifact reference · Security Artifacts