YARA-X Cheat Sheet
Overview
YARA-X is the official next-generation rewrite of YARA, the industry-standard pattern matching tool used by malware researchers, threat hunters, and security teams worldwide. Built from the ground up in Rust, YARA-X delivers significant performance improvements, better error handling, stricter rule validation, and enhanced reliability compared to the original C-based YARA. It maintains backward compatibility with existing YARA rules while introducing new features such as improved regular expression support, better Unicode handling, and a more robust module system.
YARA-X is designed as a drop-in replacement for YARA in most workflows. It provides the same core functionality — scanning files, processes, and memory against pattern-based rules to classify and identify malware families, variants, and suspicious behaviors. Rules combine text strings, hexadecimal patterns, regular expressions, and conditions with boolean logic. YARA-X includes built-in modules for parsing PE, ELF, Mach-O, .NET, and other file formats, allowing rules to reference structural metadata beyond raw byte patterns. The Rust implementation eliminates entire categories of memory safety bugs and provides better multithreading support for high-throughput scanning environments.
Installation
Pre-built Binaries
# Download latest release
wget https://github.com/VirusTotal/yara-x/releases/latest/download/yr-x86_64-unknown-linux-gnu.gz
gunzip yr-x86_64-unknown-linux-gnu.gz
chmod +x yr-x86_64-unknown-linux-gnu
sudo mv yr-x86_64-unknown-linux-gnu /usr/local/bin/yr
# macOS
wget https://github.com/VirusTotal/yara-x/releases/latest/download/yr-x86_64-apple-darwin.gz
gunzip yr-x86_64-apple-darwin.gz
chmod +x yr-x86_64-apple-darwin
sudo mv yr-x86_64-apple-darwin /usr/local/bin/yr
Via Cargo (Rust)
# Install Rust toolchain if needed
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
# Install YARA-X CLI
cargo install yara-x-cli
# Verify
yr --version
Python Bindings
pip install yara-x
# Verify
python3 -c "import yara_x; print(yara_x.__version__)"
From Source
git clone https://github.com/VirusTotal/yara-x.git
cd yara-x
cargo build --release
sudo cp target/release/yr /usr/local/bin/
Core Commands
| Command | Description |
|---|---|
yr scan <rules> <target> | Scan file or directory against rules |
yr scan -r <rules_dir> <target> | Recursively load rules from directory |
yr check <rules> | Validate rule syntax |
yr fmt <rules> | Format/prettify rule files |
yr dump <file> | Dump module data for a file |
yr completion <shell> | Generate shell completions |
# Scan a single file
yr scan rules.yar suspicious.exe
# Scan a directory recursively
yr scan rules.yar /malware/samples/
# Scan with multiple rule files
yr scan rule1.yar rule2.yar rule3.yar target.exe
# Scan with all rules in a directory
yr scan -r /opt/yara-rules/ target.exe
# Show matched strings
yr scan --print-strings rules.yar target.exe
# Show metadata from matched rules
yr scan --print-meta rules.yar target.exe
# Scan with timeout (seconds)
yr scan --timeout 120 rules.yar large_file.bin
# Output as JSON
yr scan --output-format json rules.yar target.exe
# Only show specific number of matches
yr scan --max-matches-per-rule 5 rules.yar target_dir/
# Scan with specific modules disabled
yr scan --disable-module dotnet rules.yar target.exe
Rule Validation and Formatting
# Check rule syntax
yr check my_rules.yar
# Check all rules in directory
yr check -r /opt/yara-rules/
# Format rules (fix indentation, style)
yr fmt my_rules.yar
# Format and overwrite in place
yr fmt --in-place my_rules.yar
# Dump PE module data for a file
yr dump --module pe sample.exe
# Dump all available module data
yr dump sample.exe
Rule Writing
Basic Rule Structure
rule ExampleRule {
meta:
author = "analyst"
description = "Detect example malware family"
date = "2026-01-15"
reference = "https://example.com/report"
severity = "high"
hash = "a1b2c3d4..."
strings:
$str1 = "malicious_string"
$str2 = "another_string" nocase
$hex1 = { 4D 5A 90 00 03 00 }
$regex1 = /https?:\/\/[a-z0-9\-\.]+\.[a-z]{2,}/
condition:
uint16(0) == 0x5A4D and
($str1 or $str2) and
#hex1 > 2
}
String Modifiers
rule StringModifiers {
strings:
$plain = "hello world"
$nocase = "password" nocase // Case-insensitive
$wide = "config" wide // UTF-16LE
$both = "data" ascii wide // Both encodings
$fullword = "cmd" fullword // Word boundary match
$xor = "secret" xor // XOR with all single-byte keys
$xor_range = "secret" xor(0x01-0xFF) // XOR with specific range
$base64 = "admin" base64 // Base64 encoded
$base64wide = "admin" base64wide // Base64 of wide string
condition:
any of them
}
Hex Patterns
rule HexPatterns {
strings:
// Exact bytes
$exact = { 4D 5A 90 00 }
// Wildcards
$wild = { 4D 5A ?? 00 }
// Nibble wildcards
$nibble = { 4D 5? ?0 00 }
// Jumps (variable length)
$jump = { E8 [4] 85 C0 } // Exactly 4 bytes between
$range = { E8 [2-6] 85 C0 } // 2 to 6 bytes between
$unlimited = { E8 [-] 85 C0 } // Any number of bytes
// Alternatives
$alt = { (4D | 5A) 90 00 }
condition:
any of them
}
Conditions
rule ConditionExamples {
strings:
$a = "string_a"
$b = "string_b"
$c = "string_c"
condition:
// Boolean logic
$a and ($b or $c)
// Count of matches
#a > 3 // More than 3 occurrences
#a in (100..500) >= 2 // At least 2 in byte range
// String position
$a at 0 // At offset 0
$a in (0..1024) // Within first 1KB
// File size
filesize < 1MB
// Set operations
any of ($a, $b, $c)
all of them
2 of ($a, $b, $c)
any of ($str*) // Wildcard on string names
// Integer functions
uint16(0) == 0x5A4D // MZ header
uint32(0) == 0x464C457F // ELF header
int32(pe.entry_point) == 0xCCC3 // INT3 + RET at EP
}
Module Usage
PE Module
import "pe"
rule SuspiciousPE {
condition:
pe.is_pe and
pe.number_of_sections > 7 and
pe.entry_point_raw > pe.sections[pe.number_of_sections - 1].raw_data_offset and
pe.timestamp > 1700000000 and
not pe.is_signed
}
rule HighEntropySections {
condition:
pe.is_pe and
for any section in pe.sections : (
section.name == ".text" and
math.entropy(section.raw_data_offset, section.raw_data_size) > 7.0
)
}
ELF Module
import "elf"
rule SuspiciousELF {
condition:
elf.type == elf.ET_EXEC and
elf.machine == elf.EM_X86_64 and
elf.number_of_sections < 3
}
Math Module
import "math"
rule HighEntropy {
condition:
math.entropy(0, filesize) > 7.5
}
rule SpecificEntropy {
condition:
math.entropy(0, 1024) > 7.0 and
math.mean(0, filesize) > 200
}
Advanced Usage
Python API
import yara_x
# Compile rules
compiler = yara_x.Compiler()
compiler.add_source('''
rule test {
strings:
$a = "malware"
condition:
$a
}
''')
rules = compiler.build()
# Scan file
results = rules.scan_file("suspect.exe")
for rule in results.matching_rules:
print(f"Matched: {rule.identifier}")
for pattern in rule.patterns:
for match in pattern.matches:
print(f" Offset: {match.offset}, Length: {match.length}")
# Scan data
with open("suspect.exe", "rb") as f:
data = f.read()
results = rules.scan(data)
Performance Tuning
# Parallel scanning with multiple threads
yr scan --threads 8 rules.yar /malware/samples/
# Scan with limited stack size (for complex rules)
yr scan --stack-size 32768 rules.yar target.exe
# Skip files larger than threshold
find /samples -type f -size -10M | xargs -P4 yr scan rules.yar
Migrating from YARA to YARA-X
# Check compatibility of existing rules
yr check legacy_rules.yar
# Common migration issues:
# 1. Stricter type checking in conditions
# 2. Some deprecated features removed
# 3. Module API differences
# Format rules to YARA-X style
yr fmt --in-place legacy_rules.yar
Rule Development Workflow
# Validate rules before deployment
yr check -r /opt/yara-rules/
# Test rule against known samples
yr scan new_rule.yar /malware/confirmed/family_x/
# Test for false positives
yr scan new_rule.yar /known-good/system32/
# Dump module info for rule development
yr dump --module pe target.exe
Troubleshooting
| Issue | Solution |
|---|---|
| Rule compilation error | Run yr check for detailed error messages with line numbers |
| Performance degradation | Reduce regex complexity, avoid unbounded jumps [-], add filesize conditions |
| False positives | Add filesize constraints, use fullword modifier, combine with PE/ELF module checks |
| Module not found | Check available modules with yr dump, verify YARA-X version supports the module |
| Encoding issues in strings | Use explicit ascii, wide, or nocase modifiers |
| Stack overflow on complex rules | Increase stack size with --stack-size flag |
| Legacy rule incompatibility | Check YARA-X migration guide, fix stricter type requirements |
| Slow directory scanning | Use --threads for parallelism, exclude large non-target files |