---
title: Potential PowerShell Obfuscation via Backtick-Escaped Variable Expansion
description: Detects PowerShell scripts that uses backtick-escaped characters inside ${} variable expansion (multiple backticks between word characters) to reconstruct...
url: https://www.elastic.co/docs/reference/security/prebuilt-rules/rules/windows/defense_evasion_posh_obfuscation_backtick_var
products:
  - Elastic Security
---

# Potential PowerShell Obfuscation via Backtick-Escaped Variable Expansion
Detects PowerShell scripts that uses backtick-escaped characters inside `${}` variable expansion (multiple backticks
between word characters) to reconstruct strings at runtime. Attackers use variable-expansion obfuscation to split
keywords, hide commands, and evade static analysis and AMSI.
**Rule type**: esql
**Rule indices**:
**Rule Severity**: high
**Risk Score**: 73
**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**: 9
**Rule authors**:
- Elastic

**Rule license**: Elastic License v2

## 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](https://ela.st/powershell-logging-setup)

## Investigation guide


## 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 PowerShell Obfuscation via Backtick-Escaped Variable Expansion

This rule identifies Windows PowerShell Script Block Logging events where backtick-escaped characters are embedded within `${}` variable expansion. This technique can be used to split tokens and reconstruct variable names or keywords at runtime, reducing the effectiveness of simple string-based detections and content scanning.
Focus analysis on (1) who executed the script, (2) where it executed, (3) how much of the script is obfuscated, and (4) what the script ultimately does after deobfuscation. Higher `Esql.script_block_pattern_count`, elevated `powershell.file.script_block_entropy_bits`, and unexpected script origin (for example, unusual `file.path`) increase the likelihood of malicious intent.

#### 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

- Validate execution scope and context:
  - Review `host.name` / `host.id` to understand where the script ran and whether the endpoint role makes this activity unexpected.
- Review `user.name`, `user.domain`, and `user.id` to determine whether the account is expected to run PowerShell on this host and to identify any unusual account usage patterns in your environment.
- If `file.path` / `file.name` / `file.directory` are present, determine whether the script appears to originate from an expected location (for example, a managed scripts directory) versus an unusual or user-writable location.
- Reconstruct the complete script before interpreting intent:
  - Pivot on `powershell.file.script_block_id` and collect all related fragments.
- Use `powershell.sequence` and `powershell.total` to verify you have the full set of fragments and to order them correctly.
- Review the reconstructed `powershell.file.script_block_text` for staging behavior (for example, an initial deobfuscation routine followed by a second stage that performs the primary action).
- Locate the obfuscated variable expansions and normalize the content:
  - Use `Esql.script_block_tmp` to quickly identify the positions of suspicious `${}` expansions, then review the corresponding sections in `powershell.file.script_block_text`.
- Use `Esql.script_block_pattern_count` to estimate how pervasive the obfuscation is. A higher count is more consistent with deliberate evasion than isolated escaping.
- In the matched `${}` segments, assess what the obfuscated expansion is intended to represent by mentally removing backtick escapes and looking for recognizable tokens (cmdlet/function names, variable names, or string literals) that the script is trying to hide.
- Assess behavior indicated by the script content:
  - Identify whether the script uses dynamic invocation patterns, such as building an invocation target at runtime or executing reconstructed strings.
- Look for decoding and deobfuscation constructs (string concatenation, character-by-character reconstruction, data transformation, decompression) that may reveal embedded or second-stage content.
- Extract and document any clear indicators contained in the script text (remote endpoints, file paths, registry paths, service/task names, or additional scripts referenced). Use these indicators to scope impact across hosts.
- Use alert-side obfuscation metrics to prioritize and focus review:
  - Compare `powershell.file.script_block_entropy_bits`, `powershell.file.script_block_unique_symbols`, and `powershell.file.script_block_surprisal_stdev` against what is typical in your environment for administrative scripts.
- Treat scripts with high entropy and many unique symbols as higher risk, especially when combined with multiple obfuscated `${}` expansions.
- Scope prevalence and recurrence:
  - Search for other Script Block Logging events on the same `host.id` and `user.id` that include similar backtick-escaped `${}` patterns.
- Look for repeated occurrences of the same `file.name` / `file.path` across multiple hosts, which may indicate a shared script or distributed execution.
- If the script contains unique strings or indicators, use them to identify additional affected endpoints.


### False positive analysis

- Legitimate scripts that implement complex string building or variable-name handling and happen to use backticks within `${}` expansion (more common in developer tooling, templating, or edge-case input handling).
- Auto-generated PowerShell produced by administrative automation that uses nonstandard escaping or runtime string construction.

When evaluating potential false positives, weigh consistency (same `user.id`, `host.id`, and `file.path` over time) against indicators of compromise (unexpected user/host pairing, high obfuscation density, high entropy, or evidence of follow-on actions).

### Response and remediation

- If the activity is suspicious or confirmed malicious:
  - Contain the affected endpoint to prevent additional execution and limit potential lateral movement.
- Preserve evidence from the alert, including the full reconstructed `powershell.file.script_block_text`, `powershell.file.script_block_id`, `powershell.sequence` / `powershell.total`, and any `file.path` / `file.name` values.
- If an on-disk source is indicated by `file.path`, collect the referenced script and related files for review and remove or quarantine malicious artifacts according to your procedures.
- Investigate for follow-on effects suggested by the script content (persistence, payload delivery, configuration changes) and remediate any identified artifacts.
- Review the impacted `user.id` for compromise, revoke active sessions as appropriate, and reset credentials based on your incident response policy.
- Use extracted indicators and distinctive script fragments to hunt for additional affected hosts and users.
- If the activity is verified benign:
  - Document the legitimate script source, expected `file.path` / `file.name`, and the normal execution context (`user.id`, `host.id`) to speed up future triage.
- Monitor for deviations in execution context or significant changes in obfuscation metrics (for example, increased `Esql.script_block_pattern_count` or higher entropy) that could indicate abuse of an otherwise legitimate script.


## Rule Query

```esql
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, """\$\{(\w++`){2,}\w++\}""", "🔥")

// 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,
    file.name,
    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/](https://attack.mitre.org/tactics/TA0005/)](https://attack.mitre.org/tactics/TA0005/)
- Technique:
  - Name: Obfuscated Files or Information
- Id: T1027
- Reference URL: [[https://attack.mitre.org/techniques/T1027/](https://attack.mitre.org/techniques/T1027/)](https://attack.mitre.org/techniques/T1027/)
- Sub Technique:
  - Name: Command Obfuscation
- Id: T1027.010
- Reference URL: [[https://attack.mitre.org/techniques/T1027/010/](https://attack.mitre.org/techniques/T1027/010/)](https://attack.mitre.org/techniques/T1027/010/)
- Technique:
  - Name: Deobfuscate/Decode Files or Information
- Id: T1140
- Reference URL: [[https://attack.mitre.org/techniques/T1140/](https://attack.mitre.org/techniques/T1140/)](https://attack.mitre.org/techniques/T1140/)

**Framework:** MITRE ATT&CK
- Tactic:
  - Name: Execution
- Id: TA0002
- Reference URL: [[https://attack.mitre.org/tactics/TA0002/](https://attack.mitre.org/tactics/TA0002/)](https://attack.mitre.org/tactics/TA0002/)
- Technique:
  - Name: Command and Scripting Interpreter
- Id: T1059
- Reference URL: [[https://attack.mitre.org/techniques/T1059/](https://attack.mitre.org/techniques/T1059/)](https://attack.mitre.org/techniques/T1059/)
- Sub Technique:
  - Name: PowerShell
- Id: T1059.001
- Reference URL: [[https://attack.mitre.org/techniques/T1059/001/](https://attack.mitre.org/techniques/T1059/001/)](https://attack.mitre.org/techniques/T1059/001/)