PowerShell Suspicious Payload Encoded and Compressed

edit
IMPORTANT: This documentation is no longer updated. Refer to Elastic's version policy and the latest documentation.

PowerShell Suspicious Payload Encoded and Compressed

edit

Identifies PowerShell script block content that combines Base64 decoding with .NET decompression (Deflate/GZip). Attackers use this pattern to deobfuscate and reconstruct payloads in memory to evade defenses.

Rule type: query

Rule indices:

  • logs-windows.powershell*
  • winlogbeat-*

Severity: high

Risk score: 73

Runs every: 5m

Searches indices from: now-9m (Date Math format, see also Additional look-back time)

Maximum alerts per execution: 100

References: None

Tags:

  • Domain: Endpoint
  • OS: Windows
  • Use Case: Threat Detection
  • Tactic: Defense Evasion
  • Resources: Investigation Guide
  • Data Source: PowerShell Logs

Version: 320

Rule authors:

  • Elastic

Rule license: Elastic License v2

Investigation guide

edit

Triage and analysis

Investigating PowerShell Suspicious Payload Encoded and Compressed

Possible investigation steps

  • After reconstructing all fragments, does the script block decode, decompress, and run a second stage?
  • Why: split 4104 events can hide the payload boundary or execution call.
  • Focus: powershell.file.script_block_id, powershell.sequence, powershell.total, and reconstructed powershell.file.script_block_text on host.id. !{investigate{"description":"","label":"Script block fragments for the same script","providers":[[{"excluded":false,"field":"powershell.file.script_block_id","queryType":"phrase","value":"{{powershell.file.script_block_id}}","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • Hint: collect same-powershell.file.script_block_id fragments on host.id, order by powershell.sequence, and verify count against powershell.total before interpreting code.
  • Implication: escalate or keep suspicious when the full block decodes Base64, decompresses it with a .NET compression stream, then invokes the result; lower suspicion only when reconstructed content is inert static data, configuration, or installer resource with no execution path.
  • Was the script file-backed or fileless, and does the origin fit the user and host?
  • Focus: origin first: file.path or absence, file.name, and user.id plus host.id for workflow scope. For file-backed scripts, compare same-origin script block events on the host. !{investigate{"description":"","label":"Script block events for the same file path","providers":[[{"excluded":false,"field":"event.category","queryType":"phrase","value":"process","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"file.path","queryType":"phrase","value":"{{file.path}}","valueType":"string"}]],"relativeFrom":"now-48h/h","relativeTo":"now"}}
  • Implication: escalate when file.path is absent or points to user-writable, temporary, mounted, or delivery-oriented locations inconsistent with the user and host; lower suspicion when the same path or fileless pattern belongs to a stable packaging, deployment, or updater workflow for the same user.id and host.id.
  • If endpoint process telemetry is available, how was the PowerShell instance launched?
  • Why: script block events preserve code but not the command line or parent that explains delivery.
  • Focus: recover the matching process via host.id + process.pid; then interpret process.command_line and process.parent.command_line. !{investigate{"description":"","label":"Process events for the PowerShell instance","providers":[[{"excluded":false,"field":"process.pid","queryType":"phrase","value":"{{process.pid}}","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"event.category","queryType":"phrase","value":"process","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • Hint: start around @timestamp; expand if no start event appears because PowerShell may predate script-block logging.
  • Implication: escalate when the launch chain starts from a browser, document process, scheduled task, remote-management tool, or user-writable script path that does not fit the user; lower suspicion only when command line and parent align with the exact benign packaging, deployment, or updater workflow. Missing endpoint process telemetry leaves launch context unresolved; continue with content, origin, decoded indicators, and scope.
  • What payload behavior is exposed by the reconstructed or decoded content?
  • Focus: reconstructed powershell.file.script_block_text after Base64 and Deflate/GZip expansion, execution sinks, embedded indicators, and same-PID file plus network/DNS events for writes or retrieval. !{investigate{"description":"","label":"File events for the PowerShell PID","providers":[[{"excluded":false,"field":"event.category","queryType":"phrase","value":"file","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"process.pid","queryType":"phrase","value":"{{process.pid}}","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}} !{investigate{"description":"","label":"Network and DNS events for the PowerShell PID","providers":[[{"excluded":false,"field":"event.category","queryType":"phrase","value":"network","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"process.pid","queryType":"phrase","value":"{{process.pid}}","valueType":"string"}],[{"excluded":false,"field":"event.category","queryType":"phrase","value":"dns","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"},{"excluded":false,"field":"process.pid","queryType":"phrase","value":"{{process.pid}}","valueType":"string"}]],"relativeFrom":"now-1h","relativeTo":"now"}}
  • Implication: escalate when decoded content reaches Invoke-Expression, reflection, assembly load, payload writes, remote retrieval, or another encoded/compressed layer; lower suspicion when decoded content stays inert with no execution sink, staging write, or retrieval path. Missing network/DNS telemetry is unresolved, not benign.
  • If local evidence remains suspicious or incomplete, does the same wrapper or decoded indicator change scope?
  • Focus: distinctive strings from powershell.file.script_block_text, recurring file.path or file.name, and related alerts for the same user.id. !{investigate{"description":"","label":"Alerts associated with the user","providers":[[{"excluded":false,"field":"event.kind","queryType":"phrase","value":"signal","valueType":"string"},{"excluded":false,"field":"user.id","queryType":"phrase","value":"{{user.id}}","valueType":"string"}]],"relativeFrom":"now-48h/h","relativeTo":"now"}}
  • Hint: if the user view is quiet or identity is incomplete, check related alerts for the same host.id. !{investigate{"description":"","label":"Alerts associated with the host","providers":[[{"excluded":false,"field":"event.kind","queryType":"phrase","value":"signal","valueType":"string"},{"excluded":false,"field":"host.id","queryType":"phrase","value":"{{host.id}}","valueType":"string"}]],"relativeFrom":"now-48h/h","relativeTo":"now"}}
  • Implication: broaden scope when the same Base64-plus-compression wrapper, decoded indicator, or file origin appears on unrelated hosts or accounts; keep scope local when confined to one exact benign automation cohort, but do not close solely because recurrence is absent.
  • Escalate when reconstruction, origin, launch context, decoded behavior, or scope points to staged execution. Close only when full reconstruction and same-host evidence prove one exact benign workflow, using records only when telemetry cannot prove legitimacy. If evidence is incomplete, preserve script fragments, decoded indicators, and recovered process evidence and escalate.

False positive analysis

  • Software deployment and vendor updater scripts can legitimately embed Base64-compressed resources in PowerShell. Confirm only when reconstructed powershell.file.script_block_text is installer, updater, or administrative resource logic; file.path or stable fileless origin fits that workflow; and user.id plus host.id match scope. When endpoint process telemetry exists, recover through host.id + process.pid before using process.command_line or process.parent.executable as corroboration. Use records or inventories only when telemetry cannot prove it.
  • Before creating an exception, validate that the telemetry-confirmed benign workflow is stable across prior alerts for the same scope. Anchor to user.id, host.id, stable file.path or stable fileless origin, and distinctive reconstructed script structure. Do not suppress on powershell.file.script_block_entropy_bits, file.name, or user.name alone.

Response and remediation

  • If confirmed benign, reverse any temporary containment and document the evidence that explained the alert: reconstructed script purpose, validated file.path or stable fileless origin, user.id, host.id, and any recovered launch context. Create a narrow exception only after the same benign pattern recurs consistently.
  • If suspicious but unconfirmed, preserve evidence first: the original and reconstructed powershell.file.script_block_text, all fragments grouped by powershell.file.script_block_id, decoded strings or indicators, file.path evidence, user.id, host.id, and recovered process context when available. Apply reversible containment such as heightened monitoring, temporary destination blocking for decoded indicators, or host isolation only if the host role can tolerate it, then escalate before deleting artifacts or resetting accounts.
  • If confirmed malicious, preserve the same script, decoded indicator, origin, host, user, and recovered process evidence before destructive actions. Isolate the host if its role allows it, record the malicious PowerShell process context before termination when available, block confirmed malicious decoded domains, IPs, URLs, hashes, or payload paths, and review related hosts and users for the same indicators before removing scripts, binaries, scheduled tasks, registry persistence, or policy changes tied to the decoded payload. Reset credentials only when investigation shows account misuse or credential access beyond local execution.
  • Post-incident hardening: retain PowerShell script-block logging and endpoint process telemetry needed for host.id + process.pid recovery, restrict PowerShell execution to trusted administrative paths where feasible, and document the confirmed benign workflow or malicious artifact set for future triage.

Setup

edit

Setup

PowerShell Script Block Logging must be enabled to generate the events used by this rule (e.g., 4104). Setup instructions: https://ela.st/powershell-logging-setup

This rule uses the following fields that require the Windows Integration v3.3.0 and up: powershell.file.script_block_entropy_bits.

Rule query

edit
event.category:process and host.os.type:windows and
  powershell.file.script_block_entropy_bits >= 4.5 and
  powershell.file.script_block_text : (
    (
      "System.IO.Compression.DeflateStream" or
      "System.IO.Compression.GzipStream" or
      "IO.Compression.DeflateStream" or
      "IO.Compression.GzipStream"
    ) and
    FromBase64String
  ) and
  not user.id : "S-1-5-18"

Framework: MITRE ATT&CKTM