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.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2025/04/16"
3integration = ["windows"]
4maturity = "production"
5updated_date = "2026/02/09"
6
7[rule]
8author = ["Elastic"]
9description = """
10Detects 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.
11Attackers use environment-variable slicing to hide dynamic execution and evade keyword-based detections and AMSI.
12"""
13from = "now-9m"
14language = "esql"
15license = "Elastic License v2"
16name = "Potential Dynamic IEX Reconstruction via Environment Variables"
17note = """## Triage and analysis
18
19> **Disclaimer**:
20> 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.
21
22### Investigating Potential Dynamic IEX Reconstruction via Environment Variables
23
24This 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.
25
26#### Key alert fields to review
27
28- `user.name`, `user.domain`, `user.id`: Account execution context for correlation, prioritization, and scoping.
29- `host.name`, `host.id`: Host execution context for correlation, prioritization, and scoping.
30- `file.path`, `file.directory`, `file.name`: File-origin context when the script block is sourced from an on-disk file.
31- `powershell.file.script_block_text`: Script block content that matched the detection logic.
32- `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.
33- `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.
34- `Esql.script_block_pattern_count`: Count of matches for the detection pattern(s) observed in the script block content.
35- `powershell.file.script_block_entropy_bits`: Shannon entropy of the script block. Higher values may indicate obfuscation.
36- `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.
37- `powershell.file.script_block_unique_symbols`: Count of distinct characters present in the script block.
38- `powershell.file.script_block_length`: Script block length (size) context.
39
40#### Possible investigation steps
41
42- Confirm scope and execution context:
43 - Review `host.name` and `host.id` to identify the impacted endpoint and determine whether it is a typical user workstation, server, or a special-purpose system in your environment.
44 - Review `user.name`, `user.domain`, and `user.id` to understand who executed the script and whether the account is expected to run PowerShell on this host (interactive user, service account, or administrative context).
45 - Use `agent.id` (if available) to identify the reporting agent and to support correlation with other telemetry collected from the same endpoint.
46 - Use the alert timestamp as the anchor to correlate activity immediately before and after the script block ran.
47
48- Analyze the obfuscation and intended execution:
49 - Examine `powershell.file.script_block_text` to 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.
50 - Use `Esql.script_block_tmp` to quickly find the match locations, then review the surrounding context in `powershell.file.script_block_text` to determine how the reconstructed string is used (assignment, concatenation/join, or immediate invocation).
51 - 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.
52
53- Reconstruct full script content:
54 - If the script appears incomplete or staged across multiple events, use `powershell.file.script_block_id` with `powershell.sequence` and `powershell.total` to collect all fragments and rebuild the full script in order.
55 - After reconstruction, identify where string construction occurs versus where execution occurs to understand the end-to-end flow.
56
57- Assess obfuscation level and intent using available enrichments:
58 - Review `Esql.script_block_pattern_count` to understand how frequently the reconstruction pattern appears within the script block; repeated occurrences can indicate systematic obfuscation rather than an isolated string operation.
59 - Review `powershell.file.script_block_length` for size context and compare it with typical script sizes seen for the same host or user.
60 - Review `powershell.file.script_block_entropy_bits`, `powershell.file.script_block_surprisal_stdev`, and `powershell.file.script_block_unique_symbols` to gauge whether the script contains encoded or highly obfuscated content (for example, large high-entropy blocks that may indicate packed or encoded data).
61
62- Identify script origin and potential spread:
63 - If `file.path` is populated, review `file.name` and `file.directory` to determine where the script was sourced from and whether the location aligns with approved administrative tooling or software distribution paths.
64 - If `file.path` is not populated, treat the activity as potentially inline or dynamically generated and prioritize identifying the initiating process or source using adjacent telemetry.
65 - Scope for other alerts or script blocks on the same `host.id` or associated with the same `user.id` that show similar reconstruction patterns, especially within the same time window.
66
67- Correlate with adjacent telemetry (as available in your environment):
68 - 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).
69 - 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).
70
71### False positive analysis
72
73- 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.
74- Security testing and purple-team or red-team activity may intentionally use environment-variable slicing to emulate evasive tradecraft.
75- 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.
76
77### Response and remediation
78
79- If the activity is suspected or confirmed malicious:
80 - Contain the affected host to prevent additional execution and reduce lateral movement risk.
81 - Preserve evidence by collecting the complete script content using `powershell.file.script_block_id`, `powershell.sequence`, and `powershell.total`, and retain the original `powershell.file.script_block_text` for analysis.
82 - 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`, and `file.path` when present.
83 - Identify and remediate the initial execution source (parent process or launching mechanism) and remove or quarantine any associated script files referenced by `file.path`.
84 - If account compromise is suspected, reset affected credentials and review for additional suspicious PowerShell activity associated with the same `user.id`.
85
86- If the activity is determined to be benign:
87 - Document the business justification, owning team, expected hosts, and expected script location (`file.path` when present).
88 - 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.path` and known `user.id` values.
89"""
90risk_score = 47
91rule_id = "b0c98cfb-0745-4513-b6f9-08dddb033490"
92setup = """## Setup
93
94PowerShell Script Block Logging must be enabled to generate the events used by this rule (e.g., 4104).
95Setup instructions: https://ela.st/powershell-logging-setup
96"""
97severity = "medium"
98tags = [
99 "Domain: Endpoint",
100 "OS: Windows",
101 "Use Case: Threat Detection",
102 "Tactic: Defense Evasion",
103 "Data Source: PowerShell Logs",
104 "Resources: Investigation Guide",
105]
106timestamp_override = "event.ingested"
107type = "esql"
108
109query = '''
110from logs-windows.powershell_operational* metadata _id, _version, _index
111| where event.code == "4104"
112
113// Filter out smaller scripts that are unlikely to implement obfuscation using the patterns we are looking for
114| eval Esql.script_block_length = length(powershell.file.script_block_text)
115| where Esql.script_block_length > 500
116
117// replace the patterns we are looking for with the 🔥 emoji to enable counting them
118// The emoji is used because it's unlikely to appear in scripts and has a consistent character length of 1
119| eval Esql.script_block_tmp = replace(
120 powershell.file.script_block_text,
121 """(?i)(\$(?:\w+|\w+\:\w+)\[\d++\]\+\$(?:\w+|\w+\:\w+)\[\d++\]\+['"]x['"]|\$(?:\w+\:\w+)\[\d++,\d++,\d++\]|\.name\[\d++,\d++,\d++\])""",
122 "🔥"
123)
124
125// count how many patterns were detected by calculating the number of 🔥 characters inserted
126| eval Esql.script_block_pattern_count = length(Esql.script_block_tmp) - length(replace(Esql.script_block_tmp, "🔥", ""))
127
128// keep the fields relevant to the query, although this is not needed as the alert is populated using _id
129| keep
130 Esql.script_block_pattern_count,
131 Esql.script_block_length,
132 Esql.script_block_tmp,
133 powershell.file.*,
134 file.path,
135 powershell.sequence,
136 powershell.total,
137 _id,
138 _version,
139 _index,
140 host.name,
141 host.id,
142 agent.id,
143 user.id
144
145// Filter for scripts that match the pattern at least once
146| where Esql.script_block_pattern_count >= 1
147'''
148
149
150[[rule.threat]]
151framework = "MITRE ATT&CK"
152[[rule.threat.technique]]
153id = "T1027"
154name = "Obfuscated Files or Information"
155reference = "https://attack.mitre.org/techniques/T1027/"
156
157[[rule.threat.technique]]
158id = "T1140"
159name = "Deobfuscate/Decode Files or Information"
160reference = "https://attack.mitre.org/techniques/T1140/"
161
162
163[rule.threat.tactic]
164id = "TA0005"
165name = "Defense Evasion"
166reference = "https://attack.mitre.org/tactics/TA0005/"
167[[rule.threat]]
168framework = "MITRE ATT&CK"
169[[rule.threat.technique]]
170id = "T1059"
171name = "Command and Scripting Interpreter"
172reference = "https://attack.mitre.org/techniques/T1059/"
173[[rule.threat.technique.subtechnique]]
174id = "T1059.001"
175name = "PowerShell"
176reference = "https://attack.mitre.org/techniques/T1059/001/"
177
178
179
180[rule.threat.tactic]
181id = "TA0002"
182name = "Execution"
183reference = "https://attack.mitre.org/tactics/TA0002/"
184
185[rule.investigation_fields]
186field_names = [
187 "@timestamp",
188 "user.name",
189 "user.id",
190 "user.domain",
191 "powershell.file.script_block_text",
192 "powershell.file.script_block_id",
193 "powershell.sequence",
194 "powershell.total",
195 "file.path",
196 "file.directory",
197 "file.name",
198 "process.pid",
199 "host.name",
200 "host.id",
201 "powershell.file.script_block_length"
202]
Triage and analysis
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.
Investigating Potential Dynamic IEX Reconstruction via Environment Variables
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.
Key alert fields to review
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.
Possible investigation steps
-
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
False positive analysis
- 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.
Response and remediation
-
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 (
Related rules
- Dynamic IEX Reconstruction via Method String Access
- Potential PowerShell Obfuscation via Reverse Keywords
- Potential PowerShell Obfuscation via String Concatenation
- Potential PowerShell Obfuscation via String Reordering
- Potential PowerShell Obfuscation via Backtick-Escaped Variable Expansion