Dynamic IEX Reconstruction via Method String Access

Detects PowerShell scripts that rebuilds IEX by converting method references to strings (for example, ''.IndexOf.ToString()) and extracting multiple indexed characters (for example, [n,n,n]). Attackers use method-string reconstruction to conceal dynamic execution and bypass static 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 rebuilds IEX by converting method references to strings (for example,
 11''.IndexOf.ToString()) and extracting multiple indexed characters (for example, [n,n,n]). Attackers use method-string
 12reconstruction to conceal dynamic execution and bypass static detections and AMSI.
 13"""
 14from = "now-9m"
 15language = "esql"
 16license = "Elastic License v2"
 17name = "Dynamic IEX Reconstruction via Method String Access"
 18note = """## Triage and analysis
 19
 20> **Disclaimer**:
 21> 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.
 22
 23### Investigating Dynamic IEX Reconstruction via Method String Access
 24
 25This alert indicates PowerShell script block content that uses method-to-string conversion and indexed character extraction to assemble an execution primitive at runtime, commonly "IEX" (Invoke-Expression). This obfuscation technique can conceal dynamic execution intent and is often used to reduce obvious keywords in the script body.
 26
 27#### Key alert fields to review
 28
 29- `user.name`, `user.domain`, `user.id`: Account execution context for correlation, prioritization, and scoping.
 30- `host.name`, `host.id`: Host execution context for correlation, prioritization, and scoping.
 31- `file.path`, `file.directory`, `file.name`: File-origin context when the script block is sourced from an on-disk file.
 32- `powershell.file.script_block_text`: Script block content that matched the detection logic.
 33- `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.
 34- `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.
 35- `Esql.script_block_pattern_count`: Count of matches for the detection pattern(s) observed in the script block content.
 36- `powershell.file.script_block_entropy_bits`: Shannon entropy of the script block. Higher values may indicate obfuscation.
 37- `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.
 38- `powershell.file.script_block_unique_symbols`: Count of distinct characters present in the script block.
 39- `powershell.file.script_block_length`: Script block length (size) context.
 40
 41#### Possible investigation steps
 42
 43- Establish execution context and scope:
 44  - Review `host.name` and `host.id` to identify the affected endpoint and its role/criticality.
 45  - Review `user.name`, `user.domain`, and `user.id` to determine whether the activity aligns with expected administrative or automation usage.
 46  - Review `file.path`, `file.directory`, and `file.name` (when present) to understand whether the script originated from an on-disk file.
 47  - Review `agent.id` to pivot to other telemetry from the same endpoint and timeframe.
 48
 49- Validate what matched and how extensively it appears:
 50  - Review `Esql.script_block_pattern_count` to gauge how often the technique appears within the script block (higher counts can indicate heavier obfuscation).
 51  - Use `Esql.script_block_tmp` to quickly locate the matched regions, then review the corresponding locations in `powershell.file.script_block_text` for the exact construct and nearby context.
 52  - Review `powershell.file.script_block_length` alongside `powershell.file.script_block_entropy_bits`, `powershell.file.script_block_surprisal_stdev`, and `powershell.file.script_block_unique_symbols` to help distinguish isolated string tricks from broader obfuscation.
 53
 54- Reconstruct the full script block when content is split:
 55  - Pivot on `powershell.file.script_block_id` and order results by `powershell.sequence`.
 56  - Use `powershell.total` to confirm you have all fragments before making a final assessment.
 57  - Preserve the reassembled content from `powershell.file.script_block_text` for follow-on analysis and scoping.
 58
 59- Determine the reconstructed token and follow-on behavior:
 60  - In `powershell.file.script_block_text`, identify the method string being indexed and the associated index list (for example, [n,n,n]) to determine what characters are being assembled.
 61  - Identify how the reconstructed string is used (for example, invoked directly, assigned to a variable, or passed as an argument) and what content it ultimately executes.
 62  - Capture any secondary artifacts referenced in the script content (for example, embedded payload strings, additional script blocks, or external resource locations) and use them to drive further correlation.
 63
 64- Validate likely origin and initiating source:
 65  - If `file.path` is present, validate whether the script location is expected for the user and host, and whether it appears in a user-writable location or a standard administrative tooling path.
 66  - If file origin fields are not present, the script may have been executed interactively or generated at runtime; rely on surrounding endpoint telemetry to identify the initiating process and any related activity.
 67
 68- Correlate with adjacent activity to understand impact:
 69  - Review other PowerShell script blocks on the same `host.id` and `user.id` around the alert time to identify staging steps and any follow-on execution.
 70  - If process telemetry is available, identify the PowerShell process and its parent process that initiated execution, and check for suspicious child processes near the alert time.
 71  - If network or file telemetry is available, look for downloads, outbound connections, and file writes temporally aligned with the script block execution and the content referenced within `powershell.file.script_block_text`.
 72
 73- Assess prevalence across the environment:
 74  - Search for similar patterns (including stable substrings from `powershell.file.script_block_text`) across other hosts and users.
 75  - Prioritize results with higher `Esql.script_block_pattern_count` and higher obfuscation metrics to identify likely common tooling or shared payloads.
 76
 77### False positive analysis
 78
 79- PowerShell developers or automation teams may experiment with unconventional string manipulation, but method-string indexing to assemble execution primitives is uncommon in routine administration.
 80- Authorized security testing, malware analysis, or threat emulation activities can intentionally use this technique; validate against approved testing windows and operator accounts.
 81- Some script packaging or code protection approaches can introduce non-standard string operations; treat as benign only when the script origin (`file.path` / `file.name`), execution context (`user.id`), and surrounding host activity support a known, approved workflow.
 82
 83### Response and remediation
 84
 85- If malicious or suspicious activity is confirmed:
 86  - Contain the affected host identified by `host.id` to prevent additional execution and lateral movement.
 87  - Preserve evidence from the alert, including `powershell.file.script_block_text`, `powershell.file.script_block_id`, `powershell.sequence`, `powershell.total`, `file.path`, and `Esql.script_block_pattern_count`.
 88  - Scope for related activity by searching for similar content patterns across the environment and identifying additional impacted hosts and accounts.
 89  - If an on-disk script is involved (`file.path` present), collect the file for analysis and remove or quarantine it according to your incident handling process.
 90  - Review the associated account (`user.id`) for additional suspicious activity and remediate credential exposure as appropriate (for example, reset credentials and review recent authentication activity).
 91
 92- If the activity is determined to be benign:
 93  - Document the legitimate script source, expected hosts, and operator accounts for future triage.
 94  - Reduce noise with narrowly scoped suppression using stable characteristics available in the alert (for example, consistent `file.path` and repeatable non-sensitive substrings in `powershell.file.script_block_text`), while continuing to monitor for deviations.
 95"""
 96risk_score = 21
 97rule_id = "9f432a8b-9588-4550-838e-1f77285580d3"
 98setup = """## Setup
 99
100PowerShell Script Block Logging must be enabled to generate the events used by this rule (e.g., 4104).
101Setup instructions: https://ela.st/powershell-logging-setup
102"""
103severity = "low"
104tags = [
105    "Domain: Endpoint",
106    "OS: Windows",
107    "Use Case: Threat Detection",
108    "Tactic: Defense Evasion",
109    "Data Source: PowerShell Logs",
110    "Resources: Investigation Guide",
111]
112timestamp_override = "event.ingested"
113type = "esql"
114
115query = '''
116from logs-windows.powershell_operational* metadata _id, _version, _index
117| where event.code == "4104"
118
119// Filter out smaller scripts that are unlikely to implement obfuscation using the patterns we are looking for
120| eval Esql.script_block_length = length(powershell.file.script_block_text)
121| where Esql.script_block_length > 500
122
123// replace the patterns we are looking for with the 🔥 emoji to enable counting them
124// The emoji is used because it's unlikely to appear in scripts and has a consistent character length of 1
125| eval Esql.script_block_tmp = replace(
126    powershell.file.script_block_text,
127    """(?i)['"]['"].(Insert|Normalize|Chars|substring|Remove|LastIndexOfAny|LastIndexOf|IsNormalized|IndexOfAny|IndexOf)[^\[]+\[\d+,\d+,\d+\]""",
128    "🔥"
129)
130
131// count how many patterns were detected by calculating the number of 🔥 characters inserted
132| eval Esql.script_block_pattern_count = length(Esql.script_block_tmp) - length(replace(Esql.script_block_tmp, "🔥", ""))
133
134// keep the fields relevant to the query, although this is not needed as the alert is populated using _id
135| keep
136    Esql.script_block_pattern_count,
137    Esql.script_block_length,
138    Esql.script_block_tmp,
139    powershell.file.*,
140    file.path,
141    file.directory,
142    powershell.sequence,
143    powershell.total,
144    _id,
145    _version,
146    _index,
147    host.name,
148    host.id,
149    agent.id,
150    user.id
151
152// Filter for scripts that match the pattern at least once
153| where Esql.script_block_pattern_count >= 1
154
155| where not (
156    file.directory like "C:\\\\Program Files\\\\WindowsPowerShell\\\\Modules\\\\Maester\\\\1.1.0*" or
157    file.directory like "C:\\\\Users\\\\*\\\\Documents\\\\WindowsPowerShell\\\\Modules\\\\Maester\\\\1.1.0*"
158  )
159  // ESQL requires this condition, otherwise it only returns matches where file.directory exists.
160  or file.directory is null
161'''
162
163
164[[rule.threat]]
165framework = "MITRE ATT&CK"
166[[rule.threat.technique]]
167id = "T1027"
168name = "Obfuscated Files or Information"
169reference = "https://attack.mitre.org/techniques/T1027/"
170
171[[rule.threat.technique]]
172id = "T1140"
173name = "Deobfuscate/Decode Files or Information"
174reference = "https://attack.mitre.org/techniques/T1140/"
175
176
177[rule.threat.tactic]
178id = "TA0005"
179name = "Defense Evasion"
180reference = "https://attack.mitre.org/tactics/TA0005/"
181[[rule.threat]]
182framework = "MITRE ATT&CK"
183[[rule.threat.technique]]
184id = "T1059"
185name = "Command and Scripting Interpreter"
186reference = "https://attack.mitre.org/techniques/T1059/"
187[[rule.threat.technique.subtechnique]]
188id = "T1059.001"
189name = "PowerShell"
190reference = "https://attack.mitre.org/techniques/T1059/001/"
191
192
193
194[rule.threat.tactic]
195id = "TA0002"
196name = "Execution"
197reference = "https://attack.mitre.org/tactics/TA0002/"
198
199[rule.investigation_fields]
200field_names = [
201    "@timestamp",
202    "user.name",
203    "user.id",
204    "user.domain",
205    "powershell.file.script_block_text",
206    "powershell.file.script_block_id",
207    "powershell.sequence",
208    "powershell.total",
209    "file.path",
210    "file.directory",
211    "file.name",
212    "process.pid",
213    "host.name",
214    "host.id",
215    "powershell.file.script_block_length"
216]

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 Dynamic IEX Reconstruction via Method String Access

This alert indicates PowerShell script block content that uses method-to-string conversion and indexed character extraction to assemble an execution primitive at runtime, commonly "IEX" (Invoke-Expression). This obfuscation technique can conceal dynamic execution intent and is often used to reduce obvious keywords in the script body.

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

  • Establish execution context and scope:

    • Review host.name and host.id to identify the affected endpoint and its role/criticality.
    • Review user.name, user.domain, and user.id to determine whether the activity aligns with expected administrative or automation usage.
    • Review file.path, file.directory, and file.name (when present) to understand whether the script originated from an on-disk file.
    • Review agent.id to pivot to other telemetry from the same endpoint and timeframe.
  • Validate what matched and how extensively it appears:

    • Review Esql.script_block_pattern_count to gauge how often the technique appears within the script block (higher counts can indicate heavier obfuscation).
    • Use Esql.script_block_tmp to quickly locate the matched regions, then review the corresponding locations in powershell.file.script_block_text for the exact construct and nearby context.
    • Review powershell.file.script_block_length alongside powershell.file.script_block_entropy_bits, powershell.file.script_block_surprisal_stdev, and powershell.file.script_block_unique_symbols to help distinguish isolated string tricks from broader obfuscation.
  • Reconstruct the full script block when content is split:

    • Pivot on powershell.file.script_block_id and order results by powershell.sequence.
    • Use powershell.total to confirm you have all fragments before making a final assessment.
    • Preserve the reassembled content from powershell.file.script_block_text for follow-on analysis and scoping.
  • Determine the reconstructed token and follow-on behavior:

    • In powershell.file.script_block_text, identify the method string being indexed and the associated index list (for example, [n,n,n]) to determine what characters are being assembled.
    • Identify how the reconstructed string is used (for example, invoked directly, assigned to a variable, or passed as an argument) and what content it ultimately executes.
    • Capture any secondary artifacts referenced in the script content (for example, embedded payload strings, additional script blocks, or external resource locations) and use them to drive further correlation.
  • Validate likely origin and initiating source:

    • If file.path is present, validate whether the script location is expected for the user and host, and whether it appears in a user-writable location or a standard administrative tooling path.
    • If file origin fields are not present, the script may have been executed interactively or generated at runtime; rely on surrounding endpoint telemetry to identify the initiating process and any related activity.
  • Correlate with adjacent activity to understand impact:

    • Review other PowerShell script blocks on the same host.id and user.id around the alert time to identify staging steps and any follow-on execution.
    • If process telemetry is available, identify the PowerShell process and its parent process that initiated execution, and check for suspicious child processes near the alert time.
    • If network or file telemetry is available, look for downloads, outbound connections, and file writes temporally aligned with the script block execution and the content referenced within powershell.file.script_block_text.
  • Assess prevalence across the environment:

    • Search for similar patterns (including stable substrings from powershell.file.script_block_text) across other hosts and users.
    • Prioritize results with higher Esql.script_block_pattern_count and higher obfuscation metrics to identify likely common tooling or shared payloads.

False positive analysis

  • PowerShell developers or automation teams may experiment with unconventional string manipulation, but method-string indexing to assemble execution primitives is uncommon in routine administration.
  • Authorized security testing, malware analysis, or threat emulation activities can intentionally use this technique; validate against approved testing windows and operator accounts.
  • Some script packaging or code protection approaches can introduce non-standard string operations; treat as benign only when the script origin (file.path / file.name), execution context (user.id), and surrounding host activity support a known, approved workflow.

Response and remediation

  • If malicious or suspicious activity is confirmed:

    • Contain the affected host identified by host.id to prevent additional execution and lateral movement.
    • Preserve evidence from the alert, including powershell.file.script_block_text, powershell.file.script_block_id, powershell.sequence, powershell.total, file.path, and Esql.script_block_pattern_count.
    • Scope for related activity by searching for similar content patterns across the environment and identifying additional impacted hosts and accounts.
    • If an on-disk script is involved (file.path present), collect the file for analysis and remove or quarantine it according to your incident handling process.
    • Review the associated account (user.id) for additional suspicious activity and remediate credential exposure as appropriate (for example, reset credentials and review recent authentication activity).
  • If the activity is determined to be benign:

    • Document the legitimate script source, expected hosts, and operator accounts for future triage.
    • Reduce noise with narrowly scoped suppression using stable characteristics available in the alert (for example, consistent file.path and repeatable non-sensitive substrings in powershell.file.script_block_text), while continuing to monitor for deviations.

Related rules

to-top