PowerShell Obfuscation via Negative Index String Reversal
Detects PowerShell scripts that uses negative index ranges (for example, $var[-1..0]) to reverse strings or arrays and rebuild content at runtime. Attackers use index reversal to reconstruct hidden commands or payloads and evade static analysis and AMSI.
Elastic rule (View on GitHub)
1[metadata]
2creation_date = "2025/04/14"
3integration = ["windows"]
4maturity = "production"
5updated_date = "2026/10/05"
6
7[rule]
8author = ["Elastic"]
9description = """
10Detects PowerShell scripts that uses negative index ranges (for example, $var[-1..0]) to reverse strings or arrays and
11rebuild content at runtime. Attackers use index reversal to reconstruct hidden commands or payloads and evade static
12analysis and AMSI.
13"""
14from = "now-9m"
15language = "esql"
16license = "Elastic License v2"
17name = "PowerShell Obfuscation via Negative Index String Reversal"
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 PowerShell Obfuscation via Negative Index String Reversal
24
25This alert flags PowerShell script block content that uses negative index ranges to reverse strings or arrays and rebuild content at runtime. This pattern can be used to hide command text and reduce readability during review, so the primary goal is to recover the reconstructed content and determine what it does in the observed execution context.
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- Review `powershell.file.script_block_text` and locate the reversal logic. Use `Esql.script_block_tmp` to quickly find match positions, then identify:
44 - The variable or array being reversed
45 - The reconstructed output (string, byte array, or command fragment)
46 - The sink where the output is used (for example, passed into a dynamic execution routine, used as a URL, or written to disk)
47- Reconstruct the final value produced by the reversal. Focus on what the script is trying to rebuild (commands, URLs, file paths, registry paths, encoded blobs, or arguments) and record the recovered strings for scoping.
48- If the script block is fragmented, pivot on `powershell.file.script_block_id` and use `powershell.sequence` and `powershell.total` to rebuild the full script in order. Reassess intent based on the complete content rather than a single fragment.
49- Use `Esql.script_block_pattern_count` to prioritize reviews:
50 - Single-use reversal may be utility logic and requires context to judge
51 - Repeated reversal across a long script is more consistent with obfuscation wrappers
52- Use script complexity signals to guide triage:
53 - High `powershell.file.script_block_entropy_bits` and high `powershell.file.script_block_unique_symbols` can indicate encoded or staged content
54 - Compare `powershell.file.script_block_surprisal_stdev` with the script content to determine whether the script mixes readable logic with high-randomness segments
55- Validate execution context with `user.name`, `user.domain`, `user.id`, `host.name`, and `host.id`. Prioritize investigation when the user is unexpected for the host, the host is sensitive, or similar activity is new for that account.
56- Review `file.path`, `file.directory`, and `file.name` (if present) to understand script origin. Treat unknown locations, new or renamed scripts, and ambiguous naming as higher risk, and check for additional script blocks tied to the same path.
57- Scope related activity by searching for additional PowerShell script block events on the same `host.id` and `user.id` around `@timestamp`, and by pivoting on the same `powershell.file.script_block_id`. Look for:
58 - Follow-on script blocks with clearer (deobfuscated) commands
59 - Repeated use of similar reversal segments or reconstructed indicators
60- If other endpoint telemetry is available, correlate activity on the same host and time window to identify what happened next (process launches, network connections, file writes, or other changes) and validate whether outcomes align with the reconstructed content.
61
62### False positive analysis
63
64- Legitimate scripts may reverse arrays or strings for formatting, parsing, or testing. These cases typically remain readable end-to-end and do not rely on multiple layers of reconstruction to produce executable behavior.
65- Developer utilities and automation tooling can include dense string manipulation. Validate whether the observed `file.path` and execution context (`user.name`, `host.name`) align with approved workflows and whether the same script content recurs consistently across expected hosts.
66- If activity is confirmed benign, prefer context-based tuning using stable attributes visible in the alert (for example, consistent `file.path` and recognizable script content patterns) rather than suppressing the technique broadly.
67
68### Response and remediation
69
70- If the reconstructed content indicates malicious behavior, isolate the affected host to limit further execution and reduce the risk of lateral movement.
71- Preserve evidence by retaining the full `powershell.file.script_block_text` and all related fragments grouped by `powershell.file.script_block_id`. Capture the reconstructed strings and relevant metadata (`powershell.sequence`, `powershell.total`, `Esql.script_block_pattern_count`) in case notes.
72- Identify and contain the execution source. If an unauthorized on-disk script is referenced by `file.path`, remove or quarantine it and investigate how it was introduced using your standard incident response workflow.
73- Investigate the associated account (`user.id`) for signs of compromise. Apply account controls (credential reset, session invalidation, privilege review) based on your procedures and observed scope.
74- Hunt for additional exposure by pivoting on recovered indicators and on recurrence of the reversal technique across hosts and users. Remediate any additional impacted endpoints identified during scoping.
75- After containment, improve preventative controls appropriate for your environment, such as restricting PowerShell usage to approved users/hosts and enhancing monitoring for obfuscation and dynamic execution patterns.
76"""
77risk_score = 21
78rule_id = "9edd1804-83c7-4e48-b97d-c776b4c97564"
79setup = """## Setup
80
81PowerShell Script Block Logging must be enabled to generate the events used by this rule (e.g., 4104).
82Setup instructions: https://ela.st/powershell-logging-setup
83"""
84severity = "low"
85tags = [
86 "Domain: Endpoint",
87 "OS: Windows",
88 "Use Case: Threat Detection",
89 "Tactic: Defense Evasion",
90 "Data Source: PowerShell Logs",
91 "Resources: Investigation Guide",
92 "Noise: Medium",
93 "Performance: Normal",
94 "Threat: Script-Based Execution",
95 "Rule Type: ES|QL",
96 "Platform: Windows",
97]
98timestamp_override = "event.ingested"
99type = "esql"
100
101query = '''
102from logs-windows.powershell_operational* metadata _id, _version, _index
103| where event.code == "4104"
104
105// Filter out smaller scripts that are unlikely to implement obfuscation using the patterns we are looking for
106| eval Esql.script_block_length = length(powershell.file.script_block_text)
107| where Esql.script_block_length > 500
108
109// replace the patterns we are looking for with the 🔥 emoji to enable counting them
110// The emoji is used because it's unlikely to appear in scripts and has a consistent character length of 1
111| eval Esql.script_block_tmp = replace(
112 powershell.file.script_block_text,
113 """\$\w+\[\-\s?1\.\.""",
114 "🔥"
115)
116
117// count how many patterns were detected by calculating the number of 🔥 characters inserted
118| eval Esql.script_block_pattern_count = length(Esql.script_block_tmp) - length(replace(Esql.script_block_tmp, "🔥", ""))
119
120// keep the fields relevant to the query, although this is not needed as the alert is populated using _id
121| keep
122 Esql.script_block_pattern_count,
123 Esql.script_block_length,
124 Esql.script_block_tmp,
125 powershell.file.*,
126 file.name,
127 file.path,
128 powershell.sequence,
129 powershell.total,
130 _id,
131 _version,
132 _index,
133 host.name,
134 host.id,
135 agent.id,
136 user.id
137
138// Filter for scripts that match the pattern at least once
139| where Esql.script_block_pattern_count >= 1
140
141| where file.name not like ("PSFzf.psm1", "Tenable_API_AssetLists_IPv6Seeder.ps1", "Utility.ps1")
142 // ESQL requires this condition, otherwise it only returns matches where file.name exists.
143 or file.name is null
144'''
145
146
147[[rule.threat]]
148framework = "MITRE ATT&CK"
149
150[[rule.threat.technique]]
151id = "T1027"
152name = "Obfuscated Files or Information"
153reference = "https://attack.mitre.org/techniques/T1027/"
154
155[[rule.threat.technique.subtechnique]]
156id = "T1027.010"
157name = "Command Obfuscation"
158reference = "https://attack.mitre.org/techniques/T1027/010/"
159
160[[rule.threat.technique]]
161id = "T1140"
162name = "Deobfuscate/Decode Files or Information"
163reference = "https://attack.mitre.org/techniques/T1140/"
164
165[rule.threat.tactic]
166id = "TA0005"
167name = "Defense Evasion"
168reference = "https://attack.mitre.org/tactics/TA0005/"
169
170[[rule.threat]]
171framework = "MITRE ATT&CK"
172
173[[rule.threat.technique]]
174id = "T1059"
175name = "Command and Scripting Interpreter"
176reference = "https://attack.mitre.org/techniques/T1059/"
177
178[[rule.threat.technique.subtechnique]]
179id = "T1059.001"
180name = "PowerShell"
181reference = "https://attack.mitre.org/techniques/T1059/001/"
182
183[rule.threat.tactic]
184id = "TA0002"
185name = "Execution"
186reference = "https://attack.mitre.org/tactics/TA0002/"
187[rule.investigation_fields]
188field_names = [
189 "@timestamp",
190 "user.name",
191 "user.id",
192 "user.domain",
193 "powershell.file.script_block_text",
194 "powershell.file.script_block_id",
195 "powershell.sequence",
196 "powershell.total",
197 "file.path",
198 "file.directory",
199 "file.name",
200 "process.pid",
201 "host.name",
202 "host.id",
203 "powershell.file.script_block_length"
204]
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 PowerShell Obfuscation via Negative Index String Reversal
This alert flags PowerShell script block content that uses negative index ranges to reverse strings or arrays and rebuild content at runtime. This pattern can be used to hide command text and reduce readability during review, so the primary goal is to recover the reconstructed content and determine what it does in the observed execution context.
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
- Review
powershell.file.script_block_textand locate the reversal logic. UseEsql.script_block_tmpto quickly find match positions, then identify:- The variable or array being reversed
- The reconstructed output (string, byte array, or command fragment)
- The sink where the output is used (for example, passed into a dynamic execution routine, used as a URL, or written to disk)
- Reconstruct the final value produced by the reversal. Focus on what the script is trying to rebuild (commands, URLs, file paths, registry paths, encoded blobs, or arguments) and record the recovered strings for scoping.
- If the script block is fragmented, pivot on
powershell.file.script_block_idand usepowershell.sequenceandpowershell.totalto rebuild the full script in order. Reassess intent based on the complete content rather than a single fragment. - Use
Esql.script_block_pattern_countto prioritize reviews:- Single-use reversal may be utility logic and requires context to judge
- Repeated reversal across a long script is more consistent with obfuscation wrappers
- Use script complexity signals to guide triage:
- High
powershell.file.script_block_entropy_bitsand highpowershell.file.script_block_unique_symbolscan indicate encoded or staged content - Compare
powershell.file.script_block_surprisal_stdevwith the script content to determine whether the script mixes readable logic with high-randomness segments
- High
- Validate execution context with
user.name,user.domain,user.id,host.name, andhost.id. Prioritize investigation when the user is unexpected for the host, the host is sensitive, or similar activity is new for that account. - Review
file.path,file.directory, andfile.name(if present) to understand script origin. Treat unknown locations, new or renamed scripts, and ambiguous naming as higher risk, and check for additional script blocks tied to the same path. - Scope related activity by searching for additional PowerShell script block events on the same
host.idanduser.idaround@timestamp, and by pivoting on the samepowershell.file.script_block_id. Look for:- Follow-on script blocks with clearer (deobfuscated) commands
- Repeated use of similar reversal segments or reconstructed indicators
- If other endpoint telemetry is available, correlate activity on the same host and time window to identify what happened next (process launches, network connections, file writes, or other changes) and validate whether outcomes align with the reconstructed content.
False positive analysis
- Legitimate scripts may reverse arrays or strings for formatting, parsing, or testing. These cases typically remain readable end-to-end and do not rely on multiple layers of reconstruction to produce executable behavior.
- Developer utilities and automation tooling can include dense string manipulation. Validate whether the observed
file.pathand execution context (user.name,host.name) align with approved workflows and whether the same script content recurs consistently across expected hosts. - If activity is confirmed benign, prefer context-based tuning using stable attributes visible in the alert (for example, consistent
file.pathand recognizable script content patterns) rather than suppressing the technique broadly.
Response and remediation
- If the reconstructed content indicates malicious behavior, isolate the affected host to limit further execution and reduce the risk of lateral movement.
- Preserve evidence by retaining the full
powershell.file.script_block_textand all related fragments grouped bypowershell.file.script_block_id. Capture the reconstructed strings and relevant metadata (powershell.sequence,powershell.total,Esql.script_block_pattern_count) in case notes. - Identify and contain the execution source. If an unauthorized on-disk script is referenced by
file.path, remove or quarantine it and investigate how it was introduced using your standard incident response workflow. - Investigate the associated account (
user.id) for signs of compromise. Apply account controls (credential reset, session invalidation, privilege review) based on your procedures and observed scope. - Hunt for additional exposure by pivoting on recovered indicators and on recurrence of the reversal technique across hosts and users. Remediate any additional impacted endpoints identified during scoping.
- After containment, improve preventative controls appropriate for your environment, such as restricting PowerShell usage to approved users/hosts and enhancing monitoring for obfuscation and dynamic execution patterns.
Related rules
- Potential PowerShell Obfuscation via String Reordering
- Potential PowerShell Obfuscated Script via High Entropy
- Potential PowerShell Obfuscation via Backtick-Escaped Variable Expansion
- Potential PowerShell Obfuscation via Character Array Reconstruction
- Potential PowerShell Obfuscation via Concatenated Dynamic Command Invocation