YARA-Performance: Atome, Strings und Bedingungen
Warum manche YARA-Regeln langsam sind und wie man sie beschleunigt: Atome und Vorfilter, gute und schlechte Strings, Hex mit festen Bytes, verankerte Regex, günstige Prüfungen.
Eine einzige langsame Regel kann den Scan tausender Dateien bremsen, weil alle Regeln eines kompilierten Satzes denselben Suchdurchlauf teilen.
Wie ein Scan abläuft
- Mustersuche: Beim Kompilieren wählt YARA aus jedem Muster eine feste Folge von bis zu vier Bytes, das Atom. Alle Atome landen in einem Aho-Corasick-Automaten; die Daten werden einmal durchlaufen, und nur bei Atom-Treffern wird das ganze Muster geprüft.
- Bedingungsauswertung mit Treffern, Dateieigenschaften und Moduldaten.
Die Kosten hängen davon ab, wie häufig Atome vorkommen: E8 45 FF 0A ist selten, 00 00 millionenfach.
Gute und schlechte Atome
| Muster | Qualität | Grund |
|---|---|---|
"EvilCorpUpdater" | Sehr gut | Langer, seltener Text |
{ 8B 45 FC 33 D2 F7 75 F8 } | Gut | Feste Code-Bytes |
"abc" | Schlecht | Drei Bytes, zu häufig |
{ 00 00 00 00 ?? ?? 00 00 } | Sehr schlecht | Nur Nullen fest |
/[a-z]{8}\.dll/ | Schlecht | Nur .dll ist literal |
YARA-X warnt beim Kompilieren vor manchen langsamen Mustern; der Editor zeigt diese Warnungen, der Linter ergänzt Heuristiken.
Schnelle Strings
- Mindestens vier aufeinanderfolgende feste Bytes, idealerweise am Anfang.
- Häufige Bytes meiden:
00,FF,90,CC, Leerzeichen. - Wildcards nur für Veränderliches (Adressen, Immediates), nicht für Opcodes.
nocase,xor,base64nur für lange Strings.- Regex mit Literalen verankern.
rule Fast_Code_Pattern
{
strings:
$decrypt = { 8A 04 0E 34 ?? 88 04 0F 41 81 F9 ?? ?? ?? ?? 72 }
$cfg = "cfg_version=" ascii
condition:
uint16(0) == 0x5A4D and filesize < 3MB and all of them
}
Günstiges zuerst
import "pe"
import "math"
rule Ordered_Condition
{
strings:
$a = "ReflectiveLoader" ascii
condition:
uint16(0) == 0x5A4D and
filesize < 4MB and
$a and
pe.number_of_sections > 3 and
math.entropy(0, 0x1000) < 7.0
}
Eine filesize-Grenze schützt auch vor riesigen Dateien, die zufällig ein Atom enthalten.
Schleifen und Modulfunktionen
Über Treffer iterieren (for any i in (1..#a)), nie über jeden Offset (0..filesize). math.entropy und hash.* über (0, filesize) lesen die ganze Datei — Bereich begrenzen oder absichern.
Messen
yr scan rules.yar korpus/ vor und nach einer Änderung stoppen, den Satz mit und ohne verdächtige Regel vergleichen und yaraQA für bekannte Probleme nutzen.
Checkliste
- Jedes Muster hat mindestens vier feste Bytes am Stück.
- Kein Muster besteht überwiegend aus
00,FF,90,CCoder Leerzeichen. nocase,xor,base64nur bei Strings ab acht Zeichen.- Regex enthalten ein Literal ab drei Zeichen und kein führendes
.*. - Die Bedingung beginnt mit Magic Bytes und einer
filesize-Grenze. - Schleifen laufen über Treffer, Modulfunktionen über begrenzte Bereiche.
Regel im Linter prüfen und mit Tests und CI weitermachen.
FAQ
- Was ist ein Atom in YARA?
- Eine kurze feste Byte-Folge von höchstens vier Bytes, die YARA aus jedem Muster extrahiert. Alle Atome werden gleichzeitig gesucht; das ganze Muster wird nur dort geprüft, wo sein Atom vorkommt.
- Warum ist meine YARA-Regel langsam?
- Meist fehlt einem Muster ein gutes Atom: String unter vier Bytes, Hex fast nur aus Wildcards, sehr häufige Bytes wie 00 00 00 00 oder Regex ohne Literal.
- Spielt die Reihenfolge in der Bedingung eine Rolle?
- Ja. Ausgewertet wird von links nach rechts mit Kurzschluss, daher gehören filesize und Magic Bytes vor Module, Schleifen, Entropie und Hashes.