Obfuscated scriptblock
A PowerShell script block that decompresses or decodes a payload and executes it directly from memory.
What it detects
A PowerShell script block that decompresses or decodes a payload and executes it directly from memory. The recognisable shape is a base64 string fed through a GzipStream or DeflateStream and handed to [scriptblock]::Create or IEX — the standard packaging for offensive PowerShell, because the payload never touches disk and the visible command is a single unreadable line.
This detects the WRAPPER rather than any particular payload, which is the point: it fires the same way regardless of what was hidden inside, and script-block logging captures the decoded text for the analyst even though nothing was written to disk.
MITRE ATT&CK mapping
False positives and triage
Some legitimate tooling compresses embedded resources this way — a few configuration-management and packaging frameworks do it, and so do some vendor installers.
To confirm: script-block logging records the DECODED text, so read what the payload actually was rather than judging the wrapper. Look for a second 4104 event moments later carrying the decoded script — that is the real evidence. Establish the parent process too: a wrapper executed by a management agent is plausible, one executed by Office, a browser, or a script host that a user just opened is not.
The rule
Declarative YAML read by the detection engine — data, never executed. Confidence 80%. Source: rules/windows/obfuscated_scriptblock.yaml, licensed under the Apache License 2.0.
id: windows.powershell.obfuscated_scriptblock
version: 1.0.0
status: stable
severity: high
confidence: 0.8
platforms: [windows]
mitre_techniques: [T1027, T1059.001, T1140]
description: |
A PowerShell script block that decompresses or decodes a payload and executes it
directly from memory. The recognisable shape is a base64 string fed through a
`GzipStream` or `DeflateStream` and handed to `[scriptblock]::Create` or `IEX` —
the standard packaging for offensive PowerShell, because the payload never touches
disk and the visible command is a single unreadable line.
This detects the WRAPPER rather than any particular payload, which is the point: it
fires the same way regardless of what was hidden inside, and script-block logging
captures the decoded text for the analyst even though nothing was written to disk.
match:
event_action: script_executed
command_line_regex: '(?i)(frombase64string[^|]{0,400}(gzipstream|deflatestream)|(gzipstream|deflatestream)[^|]{0,400}frombase64string|\[scriptblock\]::create\([^|]{0,200}frombase64string)'
correlation_keys: [hostname, user_name]
false_positive_guidance: |
Some legitimate tooling compresses embedded resources this way — a few
configuration-management and packaging frameworks do it, and so do some vendor
installers.
To confirm: script-block logging records the DECODED text, so read what the payload
actually was rather than judging the wrapper. Look for a second 4104 event moments
later carrying the decoded script — that is the real evidence. Establish the parent
process too: a wrapper executed by a management agent is plausible, one executed by
Office, a browser, or a script host that a user just opened is not.
Related detections
Run this rule on your own logs — offline
KIROSEC runs this rule and the rest of the library over Windows, Linux, macOS and cloud audit logs on the analyst's own machine. Every alert links to the events that raised it, and nothing leaves the device.
