Introduction to Sigma: Rule Syntax, Backends, and Converting Rules to SIEM Queries

By Debraj Basak·Aug 18, 2026·14 min readAdversary Emulation

Two analysts spot the same suspicious behavior: PowerShell launched with -EncodedCommand. One runs Splunk, the other runs Sentinel. Without a shared format, each rewrites the same logic in a different query language, and neither can hand the detection to the third team on Elastic. That duplication is the exact problem Sigma solves. Write the detection once, in YAML, then compile it down to whatever SIEM the target environment happens to run.

Objective: Learn to read, write, validate, and convert Sigma rules into live SIEM queries (Splunk SPL, KQL, Elastic Lucene) using the modern sigma-cli and pySigma toolchain, and map every rule cleanly to MITRE ATT&CK for purple-team work.


1. What Is Sigma and Why It Matters

Sigma is a generic, open signature format that describes log-event detections in plain YAML. The canonical analogy holds up well: Sigma is for log files what Snort is for network traffic and YARA is for files. You author one vendor-agnostic rule, share it, and let a backend translate it into a SIEM-native query.

A quick history helps frame the tooling. Sigma appeared publicly at Hack.lu in 2017, matured through the v1.x line with the old sigmac converter, and then the whole conversion engine was rewritten as pySigma. In August 2024 the specification jumped to v2.0, adding new fields, new modifiers, and a formal correlation capability for multi-event detections.

One opinion up front, because it saves you grief: Sigma’s value is not the YAML, it is the portability. Teams over-invest in perfectly clever rules and under-invest in reading the generated query before they ship it. Always read the compiled output. The rule that looks correct in YAML can compile into something that matches nothing.


2. Anatomy of a Sigma Rule

Every rule is a YAML document with a fixed set of top-level keys. Only title, logsource, and detection are strictly required to convert, but production rules carry the full metadata block so they are searchable, attributable, and mappable to ATT&CK.

FieldRole
titleBrief description of what the rule detects (max 256 characters).
idGlobally unique identifier, a randomly generated UUID version 4.
statusLifecycle state: stable, test, experimental, deprecated, unsupported.
descriptionLonger explanation of the detection.
authorRule author(s).
dateCreation or last-modified date.
tagsCategorization, including ATT&CK tags (attack.tXXXX).
levelSeverity: informational, low, medium, high, critical.
logsourceWhat log data the rule targets.
detectionNamed selection groups plus a condition.
falsepositivesKnown benign triggers.
referencesExternal links.

Generate the id correctly. Do not copy one from another rule.

python -c "import uuid; print(uuid.uuid4())"

Illustration of a Sigma rule document divided into metadata, logsource, and detection sections
A Sigma rule is a structured YAML document where every section – metadata, logsource, and detection – plays a distinct role in producing a portable detection.

3. The logsource Section In Depth

The logsource section tells the backend which slice of log data to search rather than scanning every index. It splits into three fields:

  • category describes a class of products (process_creation, webserver, firewall, edr).
  • product describes a specific product (windows, linux, cisco).
  • service describes a service inside a product (security, sysmon, powershell, kerberos).

The backend and its pipeline turn that abstract logsource into concrete index routing and field names. This is where the vendor-agnostic promise becomes real: category: process_creation + product: windows can compile against Sysmon Event ID 1 on one stack and Security Event ID 4688 on another, with no change to your rule.

Logsource CombinationWindows Log Source
category: process_creation + product: windowsSysmon Event ID 1 / Security Event ID 4688
product: windows + service: securityWindows Security log
product: windows + service: sysmonSysmon operational log
product: windows + service: powershellPowerShell operational log (4103/4104)

4. Detection Logic: Selections, Conditions, and Boolean Operators

The detection block holds one or more named selection groups and a condition that combines them. Sigma expresses Boolean logic through YAML structure itself:

  • A YAML list (- value1, - value2) is an OR.
  • A YAML dictionary (multiple Field: value keys) is an AND.
detection:
  selection_img:
    Image|endswith:
      - '\powershell.exe'   # OR
      - '\pwsh.exe'
  selection_flag:
    CommandLine|contains: '-EncodedCommand'
  condition: selection_img and selection_flag

Inside selection_img, the two list values are ORed. Across selection_img and selection_flag, the condition ANDs them. The condition field supports the operators you need for real detections:

Condition ExpressionMeaning
selection and not filterMatch selection, exclude filter (tuning).
1 of selection*Any selection group whose name starts with selection.
all of selection*Every matching selection group must fire.
1 of themAny defined selection group.
all of themEvery defined selection group.

The not filter idiom is your primary false-positive lever. Build the malicious pattern in selection, then carve out known-good parents and paths in a filter group and subtract it: selection and not filter.


Flow diagram showing how Sigma OR logic within selection groups combines via AND in the condition to produce a detection match
YAML lists produce OR logic within each selection group; the condition ANDs those groups together to fire the final alert.

5. Field Modifiers Deep Dive

Modifiers transform how a field’s value is matched. Chain them with the pipe character: FieldName|modifier1|modifier2: value. This is where Sigma gets expressive.

ModifierEffect
containsWraps value in * wildcards, matches anywhere in the field.
startswithValue must appear at the start of the field.
endswithValue must appear at the end of the field.
allChanges a value list from OR to AND.
reApplies a regular-expression match.
casedCase-sensitive match (Sigma defaults to case-insensitive).
existsBoolean check that a field is present or absent, ignoring value.
cidrMatches an IP against a CIDR range.
windashGenerates permutations of hyphen, forward slash, and Unicode dash variants for command-line flags.
base64, base64offsetBase64-encodes the value before matching.
utf16le, utf16be, wideCharacter-encoding transforms.
lt, lte, gt, gteNumeric comparisons.

Two chaining rules matter, and both bit me once:

First, startswith, endswith, and contains must not be followed by base64 or base64offset. The encoder will happily encode the wildcards too, silently destroying their meaning. I once shipped CommandLine|contains|base64 and the rule matched nothing for a week before I diffed the converted query and saw the wildcards baked into the Base64 blob.

Second, a chain must not end on a character-set encoding modifier (utf16, utf16le, utf16be, wide), because the resulting byte sequences contain null characters that most query languages cannot represent cleanly. Encode, then convert, then match.

The windash modifier deserves a callout for command-line detections. Windows treats -enc, /enc, and several Unicode dash characters as the same flag. CommandLine|windash|contains: '-EncodedCommand' expands to catch every variant an attacker might use to dodge a naive -EncodedCommand string match.


6. The sigma-cli Toolchain and pySigma Architecture

Ignore sigmac. The legacy toolchain is unmaintained and was replaced by pySigma (the library) and sigma-cli (the command-line tool). pySigma parses and converts rules; it stays deliberately slim by pushing SIEM-specific logic into separate backend and pipeline plugins.

  • Backends are the drivers that emit a specific query language.
  • Pipelines apply environment-specific transforms: field mapping, logsource mapping, index routing.

Python 3.10 or later is required.

pip install sigma-cli
sigma list backends
sigma list pipelines
sigma plugin list

Backends install individually as plugins so you only pull what you need:

Backend PackageTarget Language / SIEM
pysigma-backend-splunkSplunk SPL
pysigma-backend-elasticsearchElastic Lucene / EQL
pysigma-backend-microsoft365defenderKQL (Sentinel / Defender XDR)
pysigma-backend-qradar-aqlIBM QRadar AQL
pysigma-backend-opensearchOpenSearch

Package names occasionally shift between minor releases, so confirm the exact target name with sigma list backends after install before you script anything around it.


7. Lab: From TTP to Telemetry

The lab target is a controlled Windows endpoint, not a CVE. The TTP is PowerShell encoded-command execution (T1059.001), a universally understood behavior that exercises the full Sigma workflow end to end. Run the offensive step only on your own lab VM.

Lab setup:

  • Analyst host: Kali or Windows with Python 3.10+, sigma-cli, and the backend plugins.
  • Victim VM: Windows 10/11 with Sysmon v15+ (SwiftOnSecurity or Olaf Hartong config).
  • Detection engine: Splunk Free locally, a Sentinel trial, or offline with Zircolite against exported EVTX.

Step 1: Generate telemetry on the lab VM

# Lab VM only - simulate an attacker's encoded PowerShell
$cmd = "Write-Output 'GenXCyber Lab - T1059.001 simulation'"
$encoded = [Convert]::ToBase64String([Text.Encoding]::Unicode.GetBytes($cmd))
powershell.exe -EncodedCommand $encoded

This produces a Sysmon Event ID 1 with CommandLine containing -EncodedCommand and a Base64 blob.

Step 2: Export the EVTX

Export Microsoft-Windows-Sysmon/Operational from Event Viewer (or with wevtutil epl) for offline analysis.

Step 3: Write the rule

title: PowerShell Encoded Command Execution
id: 3b6a2f8e-4c1d-4a7e-b9f0-2e5c3d1a0f8b
status: test
description: Detects PowerShell invoked with the -EncodedCommand switch, a common
  technique used to obfuscate payload delivery.
author: GenXCyber Lab
date: 2024-01-01
tags:
  - attack.execution
  - attack.t1059.001
  - attack.defense_evasion
  - attack.t1027
references:
  - https://attack.mitre.org/techniques/T1059/001/
logsource:
  category: process_creation
  product: windows
detection:
  selection_img:
    Image|endswith:
      - '\powershell.exe'
      - '\pwsh.exe'
  selection_cli:
    CommandLine|windash|contains:
      - '-EncodedCommand'
      - '-EncodedC'
      - '-enc '
  condition: selection_img and selection_cli
falsepositives:
  - Legitimate administrative scripts using encoded commands
  - Software deployment tooling (SCCM, PDQ)
level: medium

Note the deliberate choices: |endswith anchors on the binary name so a parent-process path never triggers it; |windash|contains catches both -enc and /enc families; the two selection groups are ANDed; and the tags carry the correct sub-technique attack.t1059.001.

Step 4: Validate before converting

sigma check rules/powershell_encoded_command.yml

sigma check runs validators including logsource_valid (recognized logsource fields), field_name_condition_valid (condition references defined selections), and regex checks. Fix validation errors here, not after you have deployed a broken query.


8. Converting the Rule to SIEM Queries

The command structure is consistent across every target:

sigma convert -t <backend> -p <pipeline> [-p <pipeline2>] -f <format> <file_or_dir>

Splunk SPL

pip install pysigma-backend-splunk
sigma convert -t splunk -p splunk_windows_sysmon -f default rules/powershell_encoded_command.yml

Approximate output:

(Image IN ("*\\powershell.exe","*\\pwsh.exe") AND (CommandLine IN ("*-EncodedCommand*","*-EncodedC*","*-enc *") OR CommandLine IN ("*/EncodedCommand*","*/EncodedC*","*/enc *")))

The windash expansion is visible: the backend emitted both hyphen and slash variants for you.

KQL for Microsoft Sentinel / Defender XDR

pip install pysigma-backend-microsoft365defender
sigma convert -t microsoft365defender -p microsoft_365_defender rules/powershell_encoded_command.yml

Elastic Lucene

pip install pysigma-backend-elasticsearch
sigma convert -t elasticsearch -p ecs_windows -f lucene rules/powershell_encoded_command.yml

The pipeline is the load-bearing argument. ecs_windows maps Sigma’s abstract Image and CommandLine fields onto Elastic Common Schema (process.executable, process.command_line). Pick the wrong pipeline and the query compiles cleanly against field names your data does not have, matching nothing. Read the output every time.

Step 8b: Confirm offline with Zircolite

pip install zircolite
zircolite --evtx /path/to/Sysmon.evtx --ruleset rules/powershell_encoded_command.yml

Zircolite runs the Sigma rule directly against the EVTX you exported in Step 2, closing the loop: your generated telemetry should light up as a detection. Hayabusa and Chainsaw do the same job with native Sigma support and are worth having in the kit.


Flow diagram showing a Sigma YAML rule passing through the pySigma parser and a pipeline before being emitted as SPL, KQL, or Lucene queries by separate backends
sigma-cli feeds the rule through pySigma’s parser, applies a pipeline for field and index mapping, then dispatches to a SIEM-specific backend to emit the native query.

9. MITRE ATT&CK Tagging and Coverage Mapping

Tags are namespaced with the dot as separator, and the attack namespace maps rules to the ATT&CK framework. Get the format exactly right or Navigator integration breaks.

  • Technique: attack.t1059 (no leading zero padding for the four-digit ID).
  • Sub-technique: attack.t1059.001.
  • Tactic: attack.execution, attack.defense_evasion, attack.persistence.

Correct tags let you export a coverage layer into the ATT&CK Navigator and see, at a glance, which techniques your rule set actually covers versus the emulation plan you are running. That gap analysis is the whole point of purple teaming: run the adversary’s TTPs, then confirm which ones your Sigma rules caught and which slipped through untagged.

TechniqueMITRE IDDetection
Command and Scripting Interpreter: PowerShellT1059.001Sysmon EID 1 CommandLine with -EncodedCommand; PowerShell 4104
Obfuscated Files or InformationT1027Base64 blobs in command line; decoded script block content
Command ObfuscationT1027.010windash and encoding permutations in CommandLine
System Binary Proxy Execution: Rundll32T1218.011Sysmon EID 1 Image|endswith: \rundll32.exe
Impair Defenses: Disable/Modify ToolsT1562.001AMSI bypass strings; correlated 4104 events
Ingress Tool TransferT1105Network connection (EID 3) following encoded execution

Tooling glue is worth knowing: Atomic Threat Coverage automatically links Sigma rules to ATT&CK techniques, Atomic Red Team tests, and response playbooks, which makes an emulation-to-detection workflow far less manual.


10. Sigma Correlation Rules (v2.0)

A single encoded-PowerShell event is medium severity. Five of them from one host in five minutes is an incident. The v2.0 correlation specification links several events into more sophisticated detections. Four types exist:

Correlation TypeFires On
event_countNumber of matching events crosses a threshold.
value_countNumber of distinct field values crosses a threshold.
temporalMultiple different rules match within a timespan.
temporal_orderedMultiple rules match in a specified order within a timespan.

Here is a value_count-style correlation that references the base rule by its name and fires when one host racks up five or more encoded-command executions inside five minutes:

title: Repeated PowerShell Encoded Command Execution
name: ps_encoded_exec
type: correlation
rules:
  powershell_encoded: powershell_encoded_command   # references base rule by 'name'
group-by:
  - ComputerName
timespan: 5m
condition:
  gte: 5
level: high

Correlation support varies by backend. temporal_ordered in particular is not implemented everywhere yet, so verify your target backend handles the correlation type before you promise cross-SIEM coverage. Verify, do not assume.


11. Common Attacker Techniques This Workflow Catches

The encoded-command pattern is one instance of a broad family of command-line abuse that Sigma is unusually good at catching, because process-creation logs are rich and consistent.

TechniqueDescription
Encoded command executionpowershell -EncodedCommand <base64> to hide the payload string.
Download cradlesIEX (New-Object Net.WebClient).DownloadString(...) staged over HTTP.
AMSI bypassIn-memory patching of AmsiScanBuffer before running malicious script.
LOLBin proxy executionrundll32.exe, regsvr32.exe, mshta.exe running attacker code.
Constrained-mode evasionDowngrade or bypass of PowerShell Constrained Language Mode.

Each maps to at least one ATT&CK technique from section 9, and each is expressible as a Sigma selection over Image, CommandLine, and ParentImage.


12. Defensive Strategies & Detection

Sigma only catches what your logging exposes. Get the telemetry right first, then the rules have something to match.

Sysmon Event IDs

Event IDDescription
1Process Create (Image, CommandLine, ParentImage, Hashes, User).
3Network Connection.
7Image Loaded.
10Process Access.
11File Create.
13Registry value set.
22DNS Query.

Windows and ETW sources

  • Security Event ID 4688 for process creation, but only after enabling command-line capture.
  • PowerShell Operational log: Event ID 4104 (Script Block Logging, which records the decoded content) and 4103 (Module Logging).
  • ETW provider Microsoft-Windows-PowerShell (GUID {A0C1853B-5C40-4B15-8766-3CF1C58F985A}) backs the 4103/4104 events; Microsoft-Windows-Sysmon is {5770385F-C22A-43E0-BF4C-06F5698FFBD9}.

Hardening knobs

# Script Block Logging (Event ID 4104) - captures decoded PowerShell
New-ItemProperty -Path "HKLM:\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" `
  -Name "EnableScriptBlockLogging" -Value 1 -PropertyType DWord -Force

# Command-line auditing for Security 4688
AuditPol /set /subcategory:"Process Creation" /success:enable

Also deploy Sysmon with a curated config and consider Constrained Language Mode in sensitive environments. Script Block Logging is the single highest-value control here because it defeats the encoding entirely: 4104 logs the decoded script, so the Base64 blob stops being a blind spot.

Sigma detection sketch (the deployable form)

title: PowerShell Encoded Command Execution
logsource:
  category: process_creation
  product: windows
detection:
  selection_img:
    Image|endswith:
      - '\powershell.exe'
      - '\pwsh.exe'
  selection_cli:
    CommandLine|windash|contains:
      - '-EncodedCommand'
      - '-enc '
  filter_legit:
    ParentImage|endswith: '\ccmexec.exe'   # SCCM known-good, tune per environment
  condition: selection_img and selection_cli and not filter_legit
level: medium

Start at level: medium and status: test. Promote to high and stable only after the filter_legit group has been tuned against a week of real data. Document every exclusion in the falsepositives field so the next analyst knows why it is there.


Illustration of layered defensive controls dissolving obfuscated PowerShell into visible plain text as it passes through each layer
Defense-in-depth – from Sysmon telemetry to Script Block Logging – strips away obfuscation at each layer so that encoded commands cannot hide from detection.

13. Tools for Sigma Analysis

ToolDescriptionLink
sigma-cliConvert, validate, and list backends/pipelinesgithub.com/SigmaHQ/sigma-cli
pySigmaConversion library underpinning sigma-cligithub.com/SigmaHQ/pySigma
ZircoliteStandalone Sigma engine for EVTX/JSON logsgithub.com/wagga40/Zircolite
HayabusaFast Windows EVTX Sigma scannergithub.com/Yamato-Security/hayabusa
ChainsawDFIR EVTX hunting with Sigma supportgithub.com/WithSecureLabs/chainsaw
SysmonRich Windows telemetry sourcelearn.microsoft.com/sysinternals
ATT&CK NavigatorCoverage-layer visualizationmitre-attack.github.io/attack-navigator
SigmaHQ rule repoCommunity rule baselinegithub.com/SigmaHQ/sigma

14. Summary

  • Sigma is the vendor-agnostic detection language: write once in YAML, compile to any SIEM query. It is to logs what Snort is to packets and YARA is to files.
  • Rule logic lives in logsource (what to search) and detection (named selections plus a condition), where YAML lists are OR and dictionaries are AND.
  • Modifiers like contains, endswith, and windash make rules precise; respect the chaining rules, especially never following contains with base64.
  • Use the modern sigma-cli and pySigma toolchain with per-target backends and pipelines. Ignore the unmaintained sigmac. Always read the compiled query before deploying.
  • Tag rules correctly (attack.t1059.001, attack.execution) so coverage maps into ATT&CK Navigator, and lean on v2.0 correlations plus Script Block Logging (Event ID 4104) to turn single events into real detections.

Related Tutorials

References

Get new drops in your inbox

Windows internals, exploit dev, and red-team write-ups - no spam, unsubscribe anytime.