Lesson 5 of 5 · 25 min read

Worked Example: Write a Sigma Rule for T1059.001 Encoded PowerShell

The best way to learn Sigma is to write a rule from scratch for a real technique. This lesson walks through the complete process: from ATT&CK technique → detection requirement → Sigma rule → conversion → validation.

Technique: T1059.001 — Command and Scripting Interpreter: PowerShell Specific behavior: Encoded command execution via -EncodedCommand (or abbreviations)


Step 1: Understand the Technique

From ATT&CK T1059.001:

What we want to detect: PowerShell launched with an encoded command flag, indicating likely obfuscation attempt.

What we DON’T want to detect: Legitimate PowerShell scripts that happen to use encoded commands (some admin tools do this).


Step 2: Identify the Data Source

ATT&CK T1059.001 data sources:

Choice: Use process creation — wider deployment, catches the invocation even if ScriptBlock logging is disabled.

Logsource in Sigma:

logsource:
  category: process_creation
  product: windows

Step 3: Write the Selection Block

The attacker runs something like:

powershell.exe -NoP -sta -NonI -W Hidden -Enc SGVsbG8gV29ybGQ=

The discriminating field: Image ends with powershell.exe AND CommandLine contains an encoding flag.

detection:
  selection_img:
    Image|endswith:
      - '\powershell.exe'
      - '\pwsh.exe'       # PowerShell 7
  
  selection_encoded:
    CommandLine|contains:
      - ' -enc '
      - ' -EncodedCommand '
      - ' -e '

Wait-e is a partial match. Remove-Item -e would match. Use more specific patterns:

  selection_encoded:
    CommandLine|contains:
      - ' -enc '
      - ' -EncodedCommand '
      - ' -enco '
      - '/e '         # slash variant
      - '/enc '
      - '/EncodedCommand '

Still imperfect — -e followed by anything matches. Better: require that after -e there’s a base64-looking string. But regex in Sigma can be fragile. Let’s stick with the common variants and document the limitation.


Step 4: Add a False Positive Filter

Legitimate use cases:

  filter_legitimate:
    ParentImage|contains:
      - '\ccmexec.exe'      # SCCM client
      - '\ccmsetup.exe'     # SCCM setup
    CommandLine|contains:
      - 'chocolatey'

Condition: selection_img and selection_encoded and not filter_legitimate


Step 5: Write the Complete Rule

title: PowerShell Encoded Command Execution
id: 8ef91d92-abad-4a3e-8e74-7e0a5e9f0e31
status: test
description: Detects PowerShell launched with an encoded command argument, often used to obfuscate malicious payloads
references:
  - https://attack.mitre.org/techniques/T1059/001/
  - https://ss64.com/ps/powershell.html
author: TDL Detection Team
date: 2024/03/15
modified: 2024/03/15
tags:
  - attack.execution
  - attack.t1059.001
  - attack.defense_evasion
  - attack.t1027
logsource:
  category: process_creation
  product: windows
detection:
  selection_img:
    Image|endswith:
      - '\powershell.exe'
      - '\pwsh.exe'
  
  selection_encoded:
    CommandLine|contains:
      - ' -enc '
      - ' -EncodedCommand '
      - ' -enco '
      - ' /enc '
      - ' /EncodedCommand '
  
  filter_sccm:
    ParentImage|contains:
      - '\ccmexec.exe'
      - '\ccmsetup.exe'
  
  condition: (selection_img and selection_encoded) and not filter_sccm

falsepositives:
  - SCCM/ConfigMgr client (filtered)
  - Some legitimate administrative scripts using encoded commands for safe transport
  - Remote management tools (Ansible, Puppet) that use encoded commands

level: medium

fields:
  - Image
  - CommandLine
  - ParentImage
  - User
  - ComputerName

Step 6: Convert and Test

# Convert to Elastic ECS
sigma convert -t elasticsearch -p ecs-windows \
  powershell-encoded-command.yml

# Output:
# (process.executable:(*\\powershell.exe OR *\\pwsh.exe) AND process.command_line:(*\ \-enc\ * OR *\ \-EncodedCommand\ * OR *\ \-enco\ * OR *\ \/enc\ * OR *\ \/EncodedCommand\ *)) AND NOT (process.parent.executable:(*\\ccmexec.exe* OR *\\ccmsetup.exe*))

# Convert to SPL
sigma convert -t splunk -p sysmon \
  powershell-encoded-command.yml

# Output:
# (Image IN ("*\powershell.exe","*\pwsh.exe") (CommandLine="* -enc *" OR CommandLine="* -EncodedCommand *" OR CommandLine="* -enco *" OR CommandLine="* /enc *" OR CommandLine="* /EncodedCommand *")) NOT (ParentImage IN ("*\ccmexec.exe*","*\ccmsetup.exe*"))

Validation test:

# Generate a test command that should trigger the rule
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes('Write-Host "test"'))
powershell.exe -EncodedCommand $encoded

Verify the alert fires. Then verify it doesn’t fire for:

# Non-encoded PowerShell (should NOT alert)
powershell.exe -Command "Write-Host 'hello'"
Sigma rule: PowerShell Encoded Command— SigmaHQ EVTX-ATTACK-SAMPLES— GitHub