EXPLORE
← Back to Explore
sigmamediumHunting

Powershell Token Obfuscation - Powershell

Detects TOKEN OBFUSCATION technique from Invoke-Obfuscation in Powershell scripts. Use this rule as a threat-hunting baseline to find obfuscated scripts in your environment. Once tested and tuned, consider deploying a production detection rule based on this hunting rule.

MITRE ATT&CK

defense-evasion

Detection Query

selection:
  - ScriptBlockText|re: \w+`(\w+|-|.)`[\w+|\s]
  - ScriptBlockText|re: '"(\{\d\}){2,}"\s*-f'
  - ScriptBlockText|re: (?i)\$\{`?e`?n`?v`?:`?p`?a`?t`?h`?\}
filter_envpath:
  ScriptBlockText|contains: ${env:path}
filter_chocolatey:
  ScriptBlockText|contains:
    - it will return true or false instead
    - The function also prevents `Get-ItemProperty` from failing
filter_exchange:
  Path|startswith: C:\Program Files\Microsoft\Exchange Server\
  Path|endswith: \bin\servicecontrol.ps1
  ScriptBlockText|contains: "`r`n"
condition: selection and not 1 of filter_*

Author

frack113

Created

2022-12-27

Data Sources

windowsps_script

Platforms

windows

Tags

attack.defense-evasionattack.t1027.009detection.threat-hunting
Raw Content
title: Powershell Token Obfuscation - Powershell
id: f3a98ce4-6164-4dd4-867c-4d83de7eca51
related:
    - id: deb9b646-a508-44ee-b7c9-d8965921c6b6
      type: similar
status: test
description: |
    Detects TOKEN OBFUSCATION technique from Invoke-Obfuscation in Powershell scripts.
    Use this rule as a threat-hunting baseline to find obfuscated scripts in your environment.
    Once tested and tuned, consider deploying a production detection rule based on this hunting rule.
references:
    - https://github.com/danielbohannon/Invoke-Obfuscation
author: frack113
date: 2022-12-27
modified: 2025-10-19
tags:
    - attack.defense-evasion
    - attack.t1027.009
    - detection.threat-hunting
logsource:
    product: windows
    category: ps_script
    definition: 'Requirements: Script Block Logging must be enabled'
detection:
    selection:
        # Examples:
        #   IN`V`o`Ke-eXp`ResSIOn (Ne`W-ob`ject Net.WebClient).DownloadString
        #   &('In'+'voke-Expressi'+'o'+'n') (.('New-Ob'+'jec'+'t') Net.WebClient).DownloadString
        #   &("{2}{3}{0}{4}{1}"-f 'e','Expression','I','nvok','-') (&("{0}{1}{2}"-f'N','ew-O','bject') Net.WebClient).DownloadString
        - ScriptBlockText|re: '\w+`(\w+|-|.)`[\w+|\s]'
        # - ScriptBlockText|re: '\((\'(\w|-|\.)+\'\+)+\'(\w|-|\.)+\'\)' TODO: fixme
        - ScriptBlockText|re: '"(\{\d\}){2,}"\s*-f'  # trigger on at least two placeholders. One might be used for legitimate string formatting
        #   ${e`Nv:pATh}
        - ScriptBlockText|re: '(?i)\$\{`?e`?n`?v`?:`?p`?a`?t`?h`?\}'
    filter_envpath:
        ScriptBlockText|contains: '${env:path}' # TODO: Fix this. See https://github.com/SigmaHQ/sigma/pull/4964
    filter_chocolatey:
        ScriptBlockText|contains:
            - 'it will return true or false instead'  # Chocolatey install script https://github.com/chocolatey/chocolatey
            - 'The function also prevents `Get-ItemProperty` from failing' # https://docs.chocolatey.org/en-us/create/functions/get-uninstallregistrykey
    filter_exchange:
        Path|startswith: 'C:\Program Files\Microsoft\Exchange Server\'
        Path|endswith: '\bin\servicecontrol.ps1'
        ScriptBlockText|contains: '`r`n'
    condition: selection and not 1 of filter_*
falsepositives:
    - Edge case might be possible with heavy use of string formatting or obfuscation in legitimate scripts.
level: medium