Building Your First YARA Rule: Detecting Emotet Payloads
For malware analysts and detection engineers who want to learn YARA fundamentals by creating a real-world rule to identify Emotet loader artifacts.

Prerequisites
- YARA installed (
apt install yaraon Debian/Ubuntu or download from https://virustotal.github.io/yara/) - A text editor
- Basic understanding of hexadecimal and strings
- Sample malware files (use malware bazaar or your own test files)
What is YARA?
YARA is a pattern-matching swiss army knife for malware researchers. Think of it as grep on steroids—you define rules with strings, hex patterns, and logical conditions, then scan files to find matches.
Step 1: Understand the Anatomy of a YARA Rule
Every YARA rule has three parts:
bashrule RuleName { meta: // Metadata about the rule strings: // Patterns to search for condition: // Logic that determines a match }
Create a file called emotet_loader.yar and let's build it step by step.
Step 2: Add Metadata
Metadata doesn't affect detection but helps document your rule:
bashrule Emotet_Loader_Basic { meta: description = "Detects Emotet loader based on characteristic strings" author = "Your Name" date = "2025-01-28" threat_level = "high" malware_family = "Emotet"
Step 3: Define String Patterns
Emotet loaders often contain distinctive strings. We'll look for three types:
bashstrings: // API calls commonly used by Emotet $api1 = "WriteProcessMemory" ascii $api2 = "VirtualAllocEx" ascii $api3 = "CreateRemoteThread" ascii // Characteristic hex pattern from unpacking stub $hex_pattern = { 64 A1 30 00 00 00 8B 40 0C 8B 40 14 } // Encoded command strings (wide for Unicode) $cmd1 = "regsvr32" wide nocase $cmd2 = "WScript.Shell" wide // Mutex pattern (Emotet uses GUID-like mutexes) $mutex = /[A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12}/ nocase
The ascii and wide modifiers specify encoding. nocase makes matching case-insensitive. Regular expressions go between / slashes.
Step 4: Write the Condition Logic
Now define what combination of strings triggers a match:
bashcondition: uint16(0) == 0x5A4D and // MZ header (PE file) filesize < 2MB and ( // Option 1: All three APIs + hex pattern (all of ($api*) and $hex_pattern) or // Option 2: Mutex + any 2 APIs + command string ($mutex and #api* >= 2 and any of ($cmd*)) ) }
The uint16(0) checks the first two bytes. #api* counts matches of the wildcard. any of requires at least one match.
Step 5: Test Your Rule
Scan a directory of samples:
bashyara emotet_loader.yar /path/to/samples/
For verbose output showing which strings matched:
bashyara -s emotet_loader.yar /path/to/samples/
Scan recursively:
bashyara -r emotet_loader.yar /path/to/samples/
Step 6: Improve Specificity
If you get false positives, add more constraints:
bashcondition: uint16(0) == 0x5A4D and filesize < 2MB and filesize > 50KB and // Too small likely not Emotet pe.number_of_sections >= 3 and // Requires import of "pe" module pe.imports("kernel32.dll", "CreateRemoteThread") and ( (all of ($api*) and $hex_pattern) or ($mutex and #api* >= 2 and any of ($cmd*)) )
Add import "pe" at the top of your file to use PE module features.
Step 7: Performance Optimization
For large-scale scanning, optimize your rule:
bashrule Emotet_Loader_Optimized { meta: description = "Optimized Emotet detection" strings: $mz = "MZ" $api1 = "WriteProcessMemory" ascii $api2 = "VirtualAllocEx" ascii $hex_pattern = { 64 A1 30 00 00 00 8B 40 0C 8B 40 14 } condition: $mz at 0 and // Fast check before expensive operations filesize < 2MB and all of them }
Putting quick checks first (like $mz at 0) makes YARA skip expensive checks on non-matches.
Where to Go Next
- Study real-world rules: Browse https://github.com/Yara-Rules/rules
- Learn the PE module: Access import tables, sections, timestamps with
pe.*conditions - Use YaraGen: Automatically generate rules from malware samples (https://github.com/Neo23x0/yarGen)
- Master regex: YARA supports powerful regular expressions for complex patterns
- Integrate with tools: Use YARA with ClamAV, Volatility, or your own Python scripts via yara-python
- Read the docs: https://yara.readthedocs.io has comprehensive module references
YARA rules are living documents—refine them as you encounter new samples and reduce false positives. Happy hunting!