YARA and Sigma: writing detection rules from a real sample
By Elias Lankinen11 min read
I have everything I need: verified primary sources and four confirmed images. Writing the post now.
The domain that stopped the world's worst worm
At 7:45 in the morning, UTC, on 12 May 2017, a piece of software began encrypting hard drives across the planet. Within hours it had reached more than 200,000 computers in over 150 countries, according to Wikipedia's account of the attack. Britain's National Health Service diverted ambulances. FedEx, Honda, Nissan and Renault halted production lines. The malware, WannaCry, demanded around $300 in Bitcoin per machine and threatened to delete files if you did not pay.
It was stopped, temporarily, at 15:03 UTC, not by a government or an antivirus vendor, but by a 22-year-old British researcher named Marcus Hutchins. Poking through the malware's code, he noticed it tried to contact a nonsensical web address before doing anything else: iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com. The domain was unregistered. He registered it, for about $10, and the worm's spread collapsed. The address turned out to be a kill switch.
That gibberish domain is worth remembering, because it appears verbatim inside one of the most-copied detection rules ever written. This is a piece about how those rules work: how a security analyst turns a single malicious file into a reusable description of a threat, using two open formats that do complementary jobs. One, YARA, reads the bytes of files. The other, Sigma, reads the logs a machine produces. Understanding the difference between them is the whole game.
Why hashes are not enough
The obvious way to recognise a known-bad file is to fingerprint it. Run the file through a hashing function such as SHA-256, get a 64-character string, and compare it against a blocklist. WannaCry's main executable hashes to ed01ebfbc9eb5bbea545af4d01bf5f1071661840480439c6e5babe8e080e41aa. Any file with that hash is that file, exactly.
The problem is that a hash describes one file and nothing else. Change a single byte, recompile with a different setting, pack the binary with a compressor, and the hash changes completely while the malware behaves identically. Attackers automate this. A single malware family can spawn thousands of variants a day, each with a unique hash and the same intent.
This is the gap YARA was built to close. It was written by Victor Alvarez, a researcher who later joined VirusTotal, with development beginning around 2009 and a public release on GitHub in 2013, per the project's own history. Its tagline is "the pattern matching swiss knife," and its name is a self-deprecating joke that expands to either "Yet Another Recursive Acronym" or "Yet Another Ridiculous Acronym," depending on who you ask, as Wikipedia notes. Instead of asking "is this exactly that file," YARA lets you ask "does this file contain the fingerprints of a family." You describe the characteristics that variants share, and one rule catches all of them.
The anatomy of a YARA rule
A YARA rule has three parts, as the official documentation lays out. A meta block holds notes that do not affect matching: author, date, a description, reference links. A strings block lists the patterns you are looking for, each given a name that starts with a dollar sign. A condition block is a Boolean expression that decides, using those patterns, whether the rule fires.
The strings are more expressive than the word "string" suggests. You can specify:
- Text, like
$a = "tasksche.exe". Modifiers refine the match:nocaseignores capitalisation,widelooks for the UTF-16 form Windows often uses (each character followed by a null byte),asciikeeps the plain form too, andfullworddemands the text be bounded by non-alphanumeric characters so that "cat" does not match inside "category." - Hexadecimal, like
$h = { 44 24 64 8a c6 }, for matching raw bytes rather than readable text. Hex patterns can include wildcards (??for any byte), jumps ([4-6]for a gap of four to six bytes), and alternatives. - Regular expressions, for structured patterns such as a version string or an embedded URL.
The condition is where the judgement lives. It can count how many times a string appears (
#a == 6), check the byte at a given position, test the file's size (filesize < 10000KB), and combine patterns with quantifiers likeall of them,any of them, or3 of ($op*), which means "at least three of the strings whose names start withop." A well-designed condition is what separates a rule that catches a family from a rule that floods analysts with false alarms.
Reading the actual WannaCry rule
Here is where theory meets a real sample. Shortly after the outbreak, Florian Roth of Nextron Systems published a YARA rule for WannaCry, dated 12 May 2017, the day of the attack. It still lives in his widely used signature-base repository. Trimmed slightly, its logic reads:
rule WannaCry_Ransomware {
meta:
description = "Detects WannaCry Ransomware"
author = "Florian Roth (Nextron Systems) (with the help of binar.ly)"
date = "2017-05-12"
hash1 = "ed01ebfbc9eb5bbea545af4d01bf5f1071661840480439c6e5babe8e080e41aa"
strings:
$x1 = "icacls . /grant Everyone:F /T /C /Q" fullword ascii
$x2 = "taskdl.exe" fullword ascii
$x3 = "tasksche.exe" fullword ascii
$x4 = "Global\\MsWinZonesCacheCounterMutexA" fullword ascii
$x5 = "WNcry@2ol7" fullword ascii
$x6 = "www.iuqerfsodp9ifjaposdfjhgosurijfaewrwergwea.com" ascii
$x7 = "mssecsvc.exe" fullword ascii
$s5 = "\\\\192.168.56.20\\IPC$" fullword wide
$op1 = { 10 ac 72 0d 3d ff ff 1f ac 77 06 b8 01 00 00 00 }
$op2 = { 44 24 64 8a c6 44 24 65 0e c6 44 24 66 80 c6 44 }
condition:
uint16(0) == 0x5a4d and filesize < 10000KB and
( 1 of ($x*) and 1 of ($s*) or 3 of ($op*) )
}
Read the condition first, because it tells you the analyst's reasoning. uint16(0) == 0x5a4d checks that the file's first two bytes are MZ, the signature of a Windows executable. That single test throws away every PDF, image and text file before any expensive string search happens, which matters when you are scanning millions of files. Then filesize < 10000KB rules out anything larger than the malware could plausibly be. Only then does the rule ask its real question: does the file contain at least one strong indicator and one supporting one, or at least three of the recognisable machine-code fragments?
Now the strings themselves. WNcry@2ol7 is the password the malware uses to unpack its own encrypted archive of tools. mssecsvc.exe, tasksche.exe and taskdl.exe are the names of components it drops. The icacls line is the exact command WannaCry runs to grant itself full control over files. Global\MsWinZonesCacheCounterMutexA is a mutex, a named lock the malware creates so it does not infect the same machine twice. And $x6 is that kill-switch domain, the one Hutchins registered, sitting in the rule as a plain string.
These are good choices for a reason. Each is specific to WannaCry and vanishingly unlikely to appear in a legitimate program. The $op entries are raw byte sequences lifted from the malware's compiled code, the kind of thing you would spot in the hex editor pictured above. They survive superficial edits to the malware's text and give the rule a second, independent way to fire. A variant that renamed its files but kept its code would still trip on three of those opcodes.
What a static rule cannot see
YARA is powerful precisely because it is literal. It reads what is on disk, or in a memory dump, and matches patterns. That literalness is also its ceiling. If an attacker encrypts, compresses or "packs" the executable, the tell-tale strings are no longer visible in the file at rest. They only appear once the program unpacks itself in memory at runtime, which is why analysts often run YARA against memory as well as files. Polymorphic malware rewrites its own code on each infection so that no byte sequence stays stable. And a rule built from strings that are too generic will match innocent software: patterns like the word "config" or common library code appear in thousands of legitimate binaries, as Intezer warns in its guidance on false positives. Roth's rule avoids this trap by insisting on combinations of rare, family-specific artifacts rather than any single common one. There is a deeper limit, though, and it points straight at the second tool. YARA can tell you a file is WannaCry. It cannot tell you what WannaCry did to your network last Tuesday at 3 a.m. For that you need to look not at files but at the trail of events a running system leaves behind.
Sigma: describing behaviour, not bytes
WannaCry spread using EternalBlue, an exploit of a flaw in Microsoft's SMBv1 file-sharing protocol on network port 445. The exploit was developed by the US National Security Agency, leaked by a group calling itself the Shadow Brokers, and catalogued as CVE-2017-0144, patched by Microsoft as MS17-010 in March 2017, as SentinelOne recounts. Machines that had installed the March patch were safe. The worm feasted on the ones that had not.
None of that network behaviour is visible in a file. It shows up in logs: a process spawning, a command line being run, a connection to port 445, a system utility being invoked. This is the territory of Sigma, a format created in 2017 by Florian Roth and Thomas Patzke, as the SigmaHQ project describes. If YARA is a way to describe a suspicious file, Sigma is a way to describe a suspicious event, in a form that any log platform can understand.
Sigma rules are written in YAML, a human-readable text format. A rule names its logsource (which kind of logs it applies to), then a detection block containing one or more selection groups of field values to match, optional filters for known-good activity, and a condition that combines them. Crucially, tags map each rule to MITRE ATT&CK, a public catalogue of adversary techniques, so a detection can be labelled with the behaviour it represents.
The same attack, seen through logs
WannaCry, like most ransomware, deletes the victim's Volume Shadow Copies, the automatic backups Windows keeps, so that files cannot simply be restored. It does this by calling built-in Windows utilities. That behaviour is stable across ransomware families, which makes it a far more durable thing to detect than any one binary. Here is the core of the SigmaHQ rule for it, which explicitly references the WannaCry sample:
title: Shadow Copies Deletion Using Operating Systems Utilities
status: stable
tags:
- attack.impact
- attack.t1490
logsource:
category: process_creation
product: windows
detection:
selection1_img:
- Image|endswith:
- '\powershell.exe'
- '\wmic.exe'
- '\vssadmin.exe'
- '\diskshadow.exe'
selection1_cli:
CommandLine|contains|all:
- 'shadow'
- 'delete'
condition: all of selection1*
falsepositives:
- Legitimate administrator deleting shadow copies
level: high
The logic is plain English once you decode the syntax. Look at process-creation logs on Windows. Fire if a process whose name ends in vssadmin.exe, powershell.exe, wmic.exe or diskshadow.exe runs with a command line containing both "shadow" and "delete." The attack.t1490 tag identifies this as ATT&CK technique T1490, "Inhibit System Recovery." The rule honestly flags its own weakness: a legitimate administrator clearing old backups will trip it too, which is why it is rated high rather than critical and needs tuning to the environment.
Notice what this rule does not care about: the file's hash, its strings, its opcodes, whether it was packed. A brand-new ransomware family nobody has ever sampled, with a hash and byte layout no YARA rule has seen, would still delete shadow copies this way and still trigger this detection. Behaviour is harder to disguise than bytes.
Write once, run on any platform
The reason Sigma exists as a separate standard, rather than everyone writing detections directly in their security platform's query language, is portability. Splunk, Microsoft Sentinel, Elastic and the rest each speak a different dialect. A detection written for one does not run on another, so knowledge gets locked to a vendor.
Sigma breaks that lock. You write the rule once in the neutral YAML format, then run it through a converter, called a backend, that translates it into the target's native query language. The original tool, sigmac, has been superseded by pySigma and the sigma-cli command-line tool, which output Splunk's SPL, Elastic's queries, Sentinel's KQL and more. A "pipeline" handles the fiddly part: mapping Sigma's generic field names onto whatever your particular logs call the same thing. The community repository, SigmaHQ, holds thousands of these rules, contributed by vendors, researchers and incident-response teams and free for anyone to use.
The misconception worth killing
It is tempting to file YARA and Sigma as rivals, two competing rule languages, and to ask which is better. That framing is wrong, and it leads teams to lean on one while blind to what the other sees. They operate on different data at different moments. YARA inspects artifacts: files sitting on disk, a suspicious email attachment, the contents of a machine's memory. It answers "what is this thing." Sigma inspects the record of activity: the logs a system emits as programs run, connect and change settings. It answers "what happened here." You use YARA to scan a captured sample or sweep a fleet of endpoints for a known-bad file. You use Sigma to alert, in near real time, when a machine starts behaving like it is under attack. The WannaCry case needs both. Roth's YARA rule identifies the binary; the shadow-copy Sigma rule catches the damage the binary tries to do, and would catch the next family too. Neither is a verdict on its own. A YARA hit on a generic string, or a Sigma alert on an admin legitimately clearing backups, is a lead, not a conviction. Both formats reward the same discipline: build from indicators that are common inside the threat and rare outside it, document your assumptions, and retire rules when they go noisy or stale. What makes both formats matter beyond their mechanics is that they are shareable. When a new threat lands, a researcher who has analysed one sample can encode what they learned into a few lines of text and hand it to everyone else the same day, exactly as Roth did on 12 May 2017. The interesting question now is how much of that encoding survives the shift to malware that mutates automatically and, increasingly, is generated by machines. A signature written by hand from one careful look at a sample is a bet that the next sample will look enough like this one. The attackers are working hard to make that bet lose. Watch whether the humans writing rules, or the systems designed to make rules obsolete, adapt faster.
Sources
- Wikipedia, WannaCry ransomware attack, 2017 onward.
- VirusTotal, YARA project repository and history, 2013 onward.
- Wikipedia, YARA, accessed 2026.
- YARA project, Writing YARA rules (official documentation), 2024.
- Florian Roth / Nextron Systems, WannaCry YARA rule in the signature-base repository, 2017.
- SigmaHQ, About Sigma, accessed 2026.
- SigmaHQ, Sigma rule structure (documentation), accessed 2026.
- SigmaHQ, Shadow Copies Deletion Using Operating Systems Utilities (Sigma rule), 2019, modified 2022.
- SigmaHQ, Backends and conversion with pySigma, accessed 2026.
- SentinelOne, EternalBlue: the NSA-developed exploit that just won't die, 2019.
- Intezer, How to write YARA rules that minimize false positives, 2021.
- MITRE, ATT&CK knowledge base, accessed 2026.