Potential Dynamic IEX Reconstruction via Environment Variables
Detects PowerShell scripts that reconstructs IEX (Invoke-Expression) by indexing environment variable strings (for example, $env:VAR[1,2,3]) or related .name[...] slices and joining characters at runtime.
Attackers use environment-variable slicing to hide dynamic execution and evade keyword-based detections and AMSI.
Rule type: esql
Rule indices:
Rule Severity: medium
Risk Score: 47
Runs every:
Searches indices from: now-9m
Maximum alerts per execution: 100
References:
Tags:
- Domain: Endpoint
- OS: Windows
- Use Case: Threat Detection
- Tactic: Defense Evasion
- Data Source: PowerShell Logs
- Resources: Investigation Guide
Version: 8
Rule authors:
- Elastic
Rule license: Elastic License v2
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
Disclaimer: This guide was created by humans with the assistance of generative AI. While its contents have been manually curated to include the most valuable information, always validate assumptions and adjust procedures to match your internal runbooks and incident triage and response policies.
This alert indicates PowerShell Script Block Logging captured a script that builds "IEX" (Invoke-Expression) at runtime by indexing characters from environment variable strings or related name properties and combining them. This technique is commonly used to obscure dynamic execution and can indicate an attempt to execute attacker-controlled content.
user.name,user.domain,user.id: Account execution context for correlation, prioritization, and scoping.host.name,host.id: Host execution context for correlation, prioritization, and scoping.file.path,file.directory,file.name: File-origin context when the script block is sourced from an on-disk file.powershell.file.script_block_text: Script block content that matched the detection logic.powershell.file.script_block_id,powershell.sequence,powershell.total: Script block metadata to pivot to other fragments or reconstruct full script content when split across multiple events.Esql.script_block_tmp: Transformed script block where detection patterns replace original content with a marker to support scoring/counting and quickly spot match locations.Esql.script_block_pattern_count: Count of matches for the detection pattern(s) observed in the script block content.powershell.file.script_block_entropy_bits: Shannon entropy of the script block. Higher values may indicate obfuscation.powershell.file.script_block_surprisal_stdev: Standard deviation of surprisal across the script block. Low values indicate uniform randomness. High values indicate mixed patterns and variability.powershell.file.script_block_unique_symbols: Count of distinct characters present in the script block.powershell.file.script_block_length: Script block length (size) context.
Confirm scope and execution context:
- Review
host.nameandhost.idto identify the impacted endpoint and determine whether it is a typical user workstation, server, or a special-purpose system in your environment. - Review
user.name,user.domain, anduser.idto understand who executed the script and whether the account is expected to run PowerShell on this host (interactive user, service account, or administrative context). - Use
agent.id(if available) to identify the reporting agent and to support correlation with other telemetry collected from the same endpoint. - Use the alert timestamp as the anchor to correlate activity immediately before and after the script block ran.
- Review
Analyze the obfuscation and intended execution:
- Examine
powershell.file.script_block_textto locate environment-variable slicing patterns (for example,$env:<var>[<idx>],$env:<var>[<idx1>,<idx2>,<idx3>], or.name[<idx1>,<idx2>,<idx3>]) and identify the variable names and indices being used. - Use
Esql.script_block_tmpto quickly find the match locations, then review the surrounding context inpowershell.file.script_block_textto determine how the reconstructed string is used (assignment, concatenation/join, or immediate invocation). - Determine whether the reconstructed output is used as a dynamic execution primitive (for example, passed to
Invoke-Expression/IEX, used with the call operator, or invoked via a method). Focus on what content is ultimately evaluated or executed.
- Examine
Reconstruct full script content:
- If the script appears incomplete or staged across multiple events, use
powershell.file.script_block_idwithpowershell.sequenceandpowershell.totalto collect all fragments and rebuild the full script in order. - After reconstruction, identify where string construction occurs versus where execution occurs to understand the end-to-end flow.
- If the script appears incomplete or staged across multiple events, use
Assess obfuscation level and intent using available enrichments:
- Review
Esql.script_block_pattern_countto understand how frequently the reconstruction pattern appears within the script block; repeated occurrences can indicate systematic obfuscation rather than an isolated string operation. - Review
powershell.file.script_block_lengthfor size context and compare it with typical script sizes seen for the same host or user. - Review
powershell.file.script_block_entropy_bits,powershell.file.script_block_surprisal_stdev, andpowershell.file.script_block_unique_symbolsto gauge whether the script contains encoded or highly obfuscated content (for example, large high-entropy blocks that may indicate packed or encoded data).
- Review
Identify script origin and potential spread:
- If
file.pathis populated, reviewfile.nameandfile.directoryto determine where the script was sourced from and whether the location aligns with approved administrative tooling or software distribution paths. - If
file.pathis not populated, treat the activity as potentially inline or dynamically generated and prioritize identifying the initiating process or source using adjacent telemetry. - Scope for other alerts or script blocks on the same
host.idor associated with the sameuser.idthat show similar reconstruction patterns, especially within the same time window.
- If
Correlate with adjacent telemetry (as available in your environment):
- Using
host.id/host.name,user.id, and the alert time, correlate with process execution data to identify the PowerShell host process and the initiating parent process or source (for example, interactive session, script runner, scheduled task, service, or another application). - Correlate with network, file, registry, and authentication telemetry on the same host around the alert time to identify follow-on activity that supports malicious intent (download or retrieval of content, creation or modification of files, persistence-related changes, or suspicious logons).
- Using
- Legitimate automation or administration scripts may construct command strings dynamically, including deriving short tokens from environment variables for compatibility or to reduce hard-coded strings.
- Security testing and purple-team or red-team activity may intentionally use environment-variable slicing to emulate evasive tradecraft.
- Developer tooling, obfuscation research, or PowerShell training content may include this technique. Benign usage is typically tied to known owners, consistent hosts, predictable execution windows, and the absence of suspicious downstream activity.
If the activity is suspected or confirmed malicious:
- Contain the affected host to prevent additional execution and reduce lateral movement risk.
- Preserve evidence by collecting the complete script content using
powershell.file.script_block_id,powershell.sequence, andpowershell.total, and retain the originalpowershell.file.script_block_textfor analysis. - Extract and track indicators from the script content (for example, URLs, domains, IP addresses, file names, or unique strings) and scope for additional occurrences across the environment using
host.id,host.name,user.id, andfile.pathwhen present. - Identify and remediate the initial execution source (parent process or launching mechanism) and remove or quarantine any associated script files referenced by
file.path. - If account compromise is suspected, reset affected credentials and review for additional suspicious PowerShell activity associated with the same
user.id.
If the activity is determined to be benign:
- Document the business justification, owning team, expected hosts, and expected script location (
file.pathwhen present). - Monitor for deviations in execution context (new hosts, new users, or materially different script content) and consider targeted tuning based on stable attributes such as
file.pathand knownuser.idvalues.
- Document the business justification, owning team, expected hosts, and expected script location (
from logs-windows.powershell_operational* metadata _id, _version, _index
| where event.code == "4104"
// Filter out smaller scripts that are unlikely to implement obfuscation using the patterns we are looking for
| eval Esql.script_block_length = length(powershell.file.script_block_text)
| where Esql.script_block_length > 500
// replace the patterns we are looking for with the 🔥 emoji to enable counting them
// The emoji is used because it's unlikely to appear in scripts and has a consistent character length of 1
| eval Esql.script_block_tmp = replace(
powershell.file.script_block_text,
"""(?i)(\$(?:\w+|\w+\:\w+)\[\d++\]\+\$(?:\w+|\w+\:\w+)\[\d++\]\+['"]x['"]|\$(?:\w+\:\w+)\[\d++,\d++,\d++\]|\.name\[\d++,\d++,\d++\])""",
"🔥"
)
// count how many patterns were detected by calculating the number of 🔥 characters inserted
| eval Esql.script_block_pattern_count = length(Esql.script_block_tmp) - length(replace(Esql.script_block_tmp, "🔥", ""))
// keep the fields relevant to the query, although this is not needed as the alert is populated using _id
| keep
Esql.script_block_pattern_count,
Esql.script_block_length,
Esql.script_block_tmp,
powershell.file.*,
file.path,
powershell.sequence,
powershell.total,
_id,
_version,
_index,
host.name,
host.id,
agent.id,
user.id
// Filter for scripts that match the pattern at least once
| where Esql.script_block_pattern_count >= 1
Framework: MITRE ATT&CK
Tactic:
- Name: Defense Evasion
- Id: TA0005
- Reference URL: https://attack.mitre.org/tactics/TA0005/
Technique:
- Name: Obfuscated Files or Information
- Id: T1027
- Reference URL: https://attack.mitre.org/techniques/T1027/
Technique:
- Name: Deobfuscate/Decode Files or Information
- Id: T1140
- Reference URL: https://attack.mitre.org/techniques/T1140/
Framework: MITRE ATT&CK
Tactic:
- Name: Execution
- Id: TA0002
- Reference URL: https://attack.mitre.org/tactics/TA0002/
Technique:
- Name: Command and Scripting Interpreter
- Id: T1059
- Reference URL: https://attack.mitre.org/techniques/T1059/
Sub Technique:
- Name: PowerShell
- Id: T1059.001
- Reference URL: https://attack.mitre.org/techniques/T1059/001/