Potential PowerShell Obfuscation via Concatenated Dynamic Command Invocation
Detects PowerShell scripts that builds commands from concatenated string literals inside dynamic invocation constructs like &() or .(). Attackers use concatenated dynamic invocation to obscure execution intent, bypass keyword-based detections, and evade 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: 7
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 rule identifies PowerShell script block content where a command is built from concatenated string literals and executed through dynamic invocation using the call operator (&) or dot invocation (.). This technique can hide the true command name (for example, splitting cmdlet, function, alias, or script names into fragments) and is often paired with additional obfuscation to hinder quick 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.
Establish scope and execution context:
- Review
host.nameandhost.idto understand where the script ran, and identify whether the host is an admin workstation, server, or user endpoint. - Review
user.name,user.domain, anduser.idto understand who initiated the activity and whether PowerShell use is expected for that identity. - Use the alert timestamp to bound the activity window for correlation and scoping.
- Review
Reconstruct the dynamically invoked command(s):
- Review
powershell.file.script_block_textand useEsql.script_block_tmpto quickly locate the dynamic invocation expression(s) inside the script block. - Identify each invocation using
&(...)or.(...)where multiple quoted strings are joined with+. - Concatenate the quoted string fragments in their observed order to derive the effective command/function/script name being invoked.
- Use
Esql.script_block_pattern_countto prioritize review; multiple dynamic concatenation invocations in the same script block generally indicate stronger intent to obscure execution.
- Review
Determine whether the operator changes execution semantics:
- For
&(...)(call operator), focus on the command being executed and any arguments passed immediately before/after the invocation. - For
.(...)(dot invocation), assess whether the script is intended to run in the current scope (for example, to define or modify functions/variables) and whether that scope change is expected for the host and user context.
- For
Reassemble full script content when fragmented:
- Pivot on
powershell.file.script_block_idto locate other fragments of the same script block. - If
powershell.totalindicates the content is split across multiple events, usepowershell.sequenceandpowershell.totalto reconstruct the full script block in order before making a determination.
- Pivot on
Identify script origin and persistence opportunities:
- If
file.path,file.directory, orfile.nameare present, determine whether the script block is associated with an on-disk script and whether its location aligns with approved administrative tooling or known automation paths. - Treat unusual user-writable or temporary locations as higher risk, especially when paired with high
Esql.script_block_pattern_count.
- If
Evaluate obfuscation characteristics and intent:
- Use
powershell.file.script_block_entropy_bits,powershell.file.script_block_surprisal_stdev,powershell.file.script_block_unique_symbols, andpowershell.file.script_block_lengthto assess how atypical the content is compared to known-good scripts in your environment. - Review surrounding logic in
powershell.file.script_block_textfor additional obfuscation patterns (for example, layered string operations, indirect invocation, or hidden payload material) that may not be captured by this specific match.
- Use
Correlate with adjacent endpoint activity (if available):
- Pivot using
host.idand the alert time window to identify the PowerShell host process, its parent process, and any child processes that indicate follow-on execution. - Review network, file, and registry activity on
host.idaround the same time for signs of payload retrieval, on-disk staging, persistence, or system configuration changes. - Review authentication activity associated with
user.idaround the same time window for anomalous logons, new session sources, or unusual access patterns. - Pivot on
user.idto identify similar activity across other hosts, which may indicate shared automation, credential reuse, or lateral movement.
- Pivot using
Capture and operationalize investigation artifacts:
- Document the reconstructed command strings, notable script fragments, and any referenced file locations (
file.path) for escalation and threat hunting. - Use those artifacts to search for additional occurrences across the environment, focusing on the same
user.id,host.id, and similarpowershell.file.script_block_textpatterns.
- Document the reconstructed command strings, notable script fragments, and any referenced file locations (
- Administrative scripts, modules, or internal frameworks that dynamically assemble short command names (cmdlets, functions, aliases) via string concatenation before invoking them for indirection or compatibility.
- Legitimate automation that uses dot invocation to load or execute helper logic in the current scope, including scripts that intentionally reduce readability for code protection.
If the activity is confirmed or strongly suspected to be malicious or unauthorized:
- Contain the affected host identified by
host.idto prevent further execution and potential lateral movement. - Preserve evidence, including the full reconstructed
powershell.file.script_block_text(usingpowershell.sequence/powershell.totalif needed) and any associated on-disk script referenced byfile.path.
- Contain the affected host identified by
If an on-disk script is involved (
file.pathpresent):- Acquire the referenced script file for analysis and validate its provenance.
- Remove or quarantine the script if it is unauthorized, and assess for additional copies using the same
file.nameorfile.pathpatterns across hosts.
If account misuse is suspected:
- Scope recent activity for the implicated
user.idacross hosts, prioritize investigation for privileged accounts, and reset credentials per policy. - Review and reduce unnecessary privileges associated with the account, especially if PowerShell access is not required.
- Scope recent activity for the implicated
Eradication and recovery:
- Identify and remediate follow-on artifacts discovered during scoping (for example, dropped scripts/binaries or persistence mechanisms) using established response procedures.
- Increase monitoring for recurrence by hunting for similar dynamic concatenation patterns (high
Esql.script_block_pattern_count) on the samehost.idanduser.id.
Post-incident hardening:
- Ensure PowerShell Script Block Logging coverage is consistently enabled and centrally collected for systems where PowerShell use is permitted.
- Limit PowerShell use to approved users and hosts, and review controls that reduce the impact of dynamic invocation and obfuscation in your environment.
from logs-windows.powershell_operational* metadata _id, _version, _index
| where event.code == "4104" and powershell.file.script_block_text like "*+*"
// 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,
"""[.&]\(\s*(['"][A-Za-z0-9.-]+['"]\s*\+\s*)+['"][A-Za-z0-9.-]+['"]\s*\)""",
"🔥"
)
// 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_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/