detection-rules icon indicating copy to clipboard operation
detection-rules copied to clipboard

[Rule Tuning] Potential PowerShell Obfuscation via High Special Character Proportion

Open khalavak opened this issue 6 months ago • 0 comments

Link to Rule

https://github.com/elastic/detection-rules/blob/f52aedf41d6b9203647ff37588b14095137e49d2/rules/windows/defense_evasion_posh_obfuscation_whitespace_special_proportion.toml#L10

Rule Tuning Type

False Positives - Reducing benign events mistakenly identified as threats.

Description

The rule is detecting Powershell Obfuscation in Microsoft Defender Datacollection scripts in folder. This can be tuned by excluding the C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\DataCollection\ folder by file.path in the ESQL rule:

from logs-windows.powershell_operational* metadata _id, _version, _index
| where event.code == "4104"

// Filter out Microsoft Defender Datacollection Scripts
| where file.path RLIKE "C:\\\\ProgramData\\\\Microsoft\\\\Windows Defender Advanced Threat Protection\\\\DataCollection\\\\.*"

// 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 > 1000

// 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
// Excludes spaces, #, = and - as they are heavily used in scripts for formatting
| eval Esql.script_block_tmp = replace(powershell.file.script_block_text, """[^0-9A-Za-z\s#=-]""", "🔥")

// count how many patterns were detected by calculating the number of 🔥 characters inserted
| eval Esql.script_block_pattern_count = Esql.script_block_length - length(replace(Esql.script_block_tmp, "🔥", ""))

// Calculate the ratio of special characters to total length
| eval Esql.script_block_ratio = Esql.script_block_pattern_count::double / Esql.script_block_length::double

// 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_ratio,
    Esql.script_block_tmp,
    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 high special character ratio
| where Esql.script_block_ratio > 0.30

Example Data

C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\DataCollection\8809.13876609.0.13876609-48d2992a17713f98499f1f2f57e520c1b41bf3f9\a391f42c-7e1a-4611-8494-1817d2420e09.ps1

khalavak avatar Oct 29 '25 04:10 khalavak