Potential PowerShell Obfuscation via High Special Character Proportion
edit
A newer version is available. Check out the latest documentation.
Potential PowerShell Obfuscation via High Special Character Proportion
editIdentifies PowerShell scripts with an abnormally high proportion of non-alphanumeric characters, often resulting from encoding, string mangling, or dynamic code generation.
Rule type: esql
Rule indices: None
Severity: low
Risk score: 21
Runs every: 5m
Searches indices from: now-9m (Date Math format, see also Additional look-back time
)
Maximum alerts per execution: 100
References: None
Tags:
- Domain: Endpoint
- OS: Windows
- Use Case: Threat Detection
- Tactic: Defense Evasion
- Data Source: PowerShell Logs
- Rule Type: BBR
Version: 1
Rule authors:
- Elastic
Rule license: Elastic License v2
Setup
editSetup
The PowerShell Script Block Logging logging policy must be enabled. Steps to implement the logging policy with Advanced Audit Configuration:
Computer Configuration > Administrative Templates > Windows PowerShell > Turn on PowerShell Script Block Logging (Enable)
Steps to implement the logging policy via registry:
reg add "hklm\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /v EnableScriptBlockLogging /t REG_DWORD /d 1
Rule query
editFROM logs-windows.powershell_operational* metadata _id, _version, _index | WHERE event.code == "4104" // Look for scripts with more than 1000 chars that contain a related keyword | EVAL script_len = LENGTH(powershell.file.script_block_text) | WHERE script_len > 1000 // Replace string format expressions with 🔥 to enable counting the occurrence of the patterns we are looking for // The emoji is used because it's unlikely to appear in scripts and has a consistent character length of 1 // Excludes spaces, #, = and - as they are heavily used in scripts for formatting | EVAL replaced_with_fire = REPLACE(powershell.file.script_block_text, """[^0-9A-Za-z\s#=-]""", "🔥") // Count the occurrence of special chars and their proportion to the total chars in the script | EVAL special_count = script_len - LENGTH(REPLACE(replaced_with_fire, "🔥", "")) | EVAL proportion = special_count::double / script_len::double // Keep the fields relevant to the query, although this is not needed as the alert is populated using _id | KEEP special_count, script_len, proportion, replaced_with_fire, powershell.file.script_block_text, powershell.file.script_block_id, file.path, powershell.sequence, powershell.total, _id, _index, host.name, agent.id, user.id // Filter for scripts with a 25%+ proportion of special chars | WHERE proportion > 0.25
Framework: MITRE ATT&CKTM
-
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/
-
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/