Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
YARA-Performance-Guidelines — Ein Leitfaden zum Schreiben schneller und speicherschonender YARA-Regeln. | Kitploit
Tools/GitHubGitHub/neo23x0/yara-performance-guidelines
Statische AnalyseMalware-AnalyseLernen & Bildung
GitHubneo23x0/yara-performance-guidelines

YARA-Performance-Guidelines

Ein Leitfaden zum Schreiben schneller und speicherschonender YARA-Regeln.

Repository anzeigen

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen
17423vor 1 JahrVon Kitploit geprüft

YARA-Leistungsrichtlinien

Das Schreiben effizienter YARA-Regeln ist entscheidend, um eine schnelle und genaue Scan-Leistung zu gewährleisten. Dieser Leitfaden enthält wichtige Prinzipien und Best Practices, die Ihnen helfen, Ihre Regeln zu optimieren, unnötige Berechnungen zu reduzieren und häufige Fallstricke zu vermeiden. Er beinhaltet Erkenntnisse von Branchenexperten, darunter Victor M. Alvarez, WXS, und Beiträge aus der YARA-Community.

  • Revision 1.6, Februar 2025, gilt für alle YARA-Versionen höher als 3.7

Wichtige Erkenntnisse

Dieser Abschnitt bietet eine kurze Zusammenfassung der YARA-Performance-Best-Practices. Für ausführliche Erklärungen und Beispiele siehe den vollständigen Leitfaden weiter unten.

Den Scan-Prozess von YARA verstehen

„Betrachten Sie YARA als einen zweistufigen Prozess: Zuerst wird nach allen in den Strings aufgeführten Mustern gesucht, und zweitens werden die Bedingungen ausgewertet. Sie können gut formulierte Bedingungen nicht nutzen, um schlecht gewählte Strings auszugleichen.“
— Wesley Shields

YARA durchläuft beim Scannen einer Datei vier Hauptschritte:

  1. Kompilieren der Regeln – Extrahieren von Atomen (4-Byte-Teilstrings) aus definierten Strings.
  2. Aho-Corasick-Suche – Durchsuchen von Dateien nach diesen Atomen.
  3. Bytecode-Engine – Überprüfen vollständiger String-Übereinstimmungen.
  4. Bedingungsauswertung – Prüfen zusätzlicher Regellogik.

String-Auswahl – Der wichtigste Faktor

YARA sucht zuerst nach Strings, was die String-Auswahl zum wichtigsten Einzelfaktor für die Effizienz von Regeln macht.

✅ Best Practices für Strings:

  • Vermeiden Sie kurze Strings (<4 Bytes) – Sie erzeugen zu viele False Positives.
  • Verwenden Sie eindeutige 4-Byte-Atome – YARA verlässt sich auf sie für schnelles Scannen.
  • Minimieren Sie Wildcards in Hex-Strings – Behalten Sie mindestens ein langes konkretes Segment bei.
  • Verwenden Sie Regex sparsam – Wenn nötig, fügen Sie einen festen 4-Byte-Anker hinzu, um die Effizienz zu verbessern.
  • Vermeiden Sie sich wiederholende Einzelbyte-Muster – Z. B. kommt \x00\x00\x00\x00 zu häufig vor.
  • Setzen Sie nocase sorgfältig ein – Es erzeugt exponentiell mehr Suchvarianten.

Bedingungen optimieren und Short-Circuiting

YARA wertet Bedingungen sequenziell aus und stoppt beim ersten Fehlschlag.

✅ Best Practices für Bedingungen:

  • Setzen Sie schnelle Prüfungen zuerst (z. B. filesize < X) vor teuren Bedingungen.
  • Vermeiden Sie Schleifen über große Datenmengen (for all i in (1..filesize) ist ineffizient).
  • Verwenden Sie direkte Offsets (@) anstelle von Regex für Sequenzprüfungen.

⚠ Hinweis: Regex-Bedingungen unterstützen kein Short-Circuit und werden immer zuletzt ausgewertet.

Module – Mit Vorsicht verwenden

Module wie pe, elf oder magic müssen die gesamte Datei parsen, bevor die Auswertung erfolgt, was die Scan-Zeit erhöht.

✅ Alternativen:

  • Verwenden Sie anstelle von pe.is_pe den Ausdruck uint16(0) == 0x5A4D, um PE-Dateien zu identifizieren.
  • Vermeiden Sie die Verwendung von Modulen, sofern keine tiefgehende Dateiinspektion erforderlich ist.

Umgang mit zu vielen Übereinstimmungen und langsamem Scannen

Übermäßige Übereinstimmungen verlangsamen das Scannen und können „too many matches“-Fehler auslösen.

✅ Beheben ineffizienter Übereinstimmungen:

  • Überprüfen Sie Regex-Quantifizierer – Vermeiden Sie .*, .+ oder {x,} ohne obere Grenze.
  • Reduzieren Sie Wildcards in Hex-Strings.
  • Teilen Sie Alternationen nach Möglichkeit in separate Strings auf.

Video-Tutorial

@herrcore hat ein hilfreiches Video-Tutorial erstellt, das die in diesem Performance-Leitfaden behandelten Themen abdeckt.

Einführung in YARA – Effiziente YARA-Regeln schreiben

Die Grundlagen

Um ein besseres Verständnis dafür zu bekommen, was und wo an der YARA-Leistung optimiert werden kann, ist es hilfreich, den Scan-Prozess zu verstehen. Er ist grundsätzlich in vier Schritte unterteilt, die anhand dieser Beispielregel stark vereinfacht erklärt werden:

root@kitploit:~
import "math"
rule example_php_webshell_rule
{
    meta:
        description = "Just an example php webshell rule"
        date = "2021/02/16"
    strings:
        $php_tag = "<?php"
        $input1   = "GET"
        $input2   = "POST"
        $payload = /assert[\t ]{0,100}\(/
    condition:
        filesize < 20KB and
        $php_tag and
        $payload and
        any of ( $input* ) and
        math.entropy(500, filesize-500) >= 5
}

1. Kompilieren der Regeln

Dieser Schritt erfolgt vor dem eigentlichen Scan. YARA sucht nach sogenannten Atomen in den Suchstrings, um den Aho-Corasick-Automaten zu speisen. Die Details werden im Kapitel Atom erklärt, aber für jetzt reicht es zu wissen, dass sie maximal 4 Bytes lang sind und YARA sie ziemlich klug auswählt, um zu viele Übereinstimmungen zu vermeiden. In unserem Beispiel könnte YARA die folgenden 4 Atome auswählen:

  • <?ph
  • GET
  • POST
  • sser (aus assert)

2. Aho-Corasick-Automat

Hier hat der Scan begonnen. Die Schritte 2.-4. werden für alle Dateien ausgeführt. YARA sucht in jeder Datei nach den oben definierten 4 Atomen mithilfe eines Präfixbaums, dem sogenannten Aho-Corasick-Automaten. Alle Übereinstimmungen werden an die Bytecode-Engine übergeben.

3. Bytecode-Engine

Wenn es z. B. eine Übereinstimmung mit sser gibt, prüft YARA, ob ein a vorangestellt war und es mit einem t weitergeht. Wenn das zutrifft, wird mit dem Regex [\t ]{0,100}\( fortgefahren. Mit diesem cleveren Ansatz vermeidet YARA, mit einer langsamen Regex-Engine über die gesamten Dateien zu gehen, und wählt stattdessen bestimmte Teile zur genaueren Untersuchung aus.

4. Bedingungen

Nachdem das gesamte Pattern Matching abgeschlossen ist, werden die Bedingungen geprüft.
YARA verfügt über einen weiteren Optimierungsmechanismus, um die CPU-intensive math.entropy-Prüfung aus unserer Beispielregel nur dann durchzuführen, wenn die 4 Bedingungen davor erfüllt sind. Näher erläutert wird dies im Kapitel Bedingungen und Short-Circuit-Auswertung.

Wenn die Bedingungen erfüllt sind, wird eine Übereinstimmung gemeldet. Der Scan wird mit der nächsten Datei in Schritt 2 fortgesetzt.

Atome

YARA extrahiert aus den Strings kurze Teilstrings mit einer Länge von bis zu 4 Bytes, die als „Atome“ bezeichnet werden. Diese Atome können an beliebiger Stelle innerhalb des Strings extrahiert werden, und YARA sucht beim Scannen der Datei nach diesen Atomen. Wenn es eines der Atome findet, überprüft es, ob der String tatsächlich übereinstimmt.

Betrachten Sie zum Beispiel diese Strings:

root@kitploit:~
/abc.*cde/

=> mögliche Atome sind abc und cde, entweder das eine oder das andere kann verwendet werden. Das Atom abc wird derzeit bevorzugt, weil beide die gleiche Qualität haben und es das erste der beiden ist.

root@kitploit:~
/(one|two)three/

=> mögliche Atome sind one, two, thre und hree. Wir können nach thre (oder hree) allein suchen oder sowohl nach one als auch nach two. Das Atom thre wird bevorzugt, weil es zu weniger potenziellen Übereinstimmungen führt als one und two (diese sind kürzer) und kein doppeltes e enthält (je eindeutiger der Buchstabe, desto besser).

YARA gibt sein Bestes, um die besten Atome aus jedem String auszuwählen, zum Beispiel:

root@kitploit:~
{ 00 00 00 00 [1-4] 01 02 03 04 }

=> hier verwendet YARA das Atom 01 02 03 04, weil 00 00 00 00 zu häufig vorkommt.

root@kitploit:~
{ 01 02 [1-4] 01 02 03 04 }

=> 01 02 03 04 wird gegenüber 01 02 bevorzugt, weil es länger ist.

Der wichtige Punkt ist also, dass Strings gute Atome enthalten sollten. Dies sind schlechte Strings, weil sie entweder zu kurze oder zu häufige Atome enthalten:

root@kitploit:~
{00 00 00 00 [1-2] FF FF [1-2] 00 00 00 00}
{AB  [1-2] 03 21 [1-2] 01 02}
/a.*b/
/a(c|d)/

Die schlechtesten Strings sind jene, die überhaupt keine Atome enthalten, wie:

root@kitploit:~
/\w.*\d/
/[0-9]+\n/

Diese regulären Ausdrücke enthalten keinen festen Teilstring, der als Atom verwendet werden kann, daher müssen sie an jedem Offset der Datei ausgewertet werden, um zu sehen, ob sie dort übereinstimmen.

Zu viele Schleifeniterationen

Eine weitere gute Empfehlung ist es, Schleifen mit zu vielen Iterationen zu vermeiden, insbesondere wenn die Anweisung innerhalb der Schleife zu komplex ist, zum Beispiel:

root@kitploit:~
strings:
	$a = {00 00}
condition:
	for all i in (1..#a) : (@a[i] < 10000)

Diese Regel hat zwei Probleme. Erstens ist der String $a zu häufig, zweitens kann #a, weil $a zu häufig ist, zu hoch sein und tausende Male ausgewertet werden.

Diese andere Bedingung ist ebenfalls ineffizient, da die Anzahl der Iterationen von der Dateigröße abhängt, die ebenfalls sehr hoch sein kann:

root@kitploit:~
for all i in (1..filesize) : ($a at i)

Magic-Modul

Vermeiden Sie die Verwendung des „magic“-Moduls, das auf der Windows-Plattform nicht verfügbar ist. Die Verwendung des „magic“-Moduls verlangsamt das Scannen, liefert aber exakte Übereinstimmungen.

Benutzerdefinierte GIF-Magic-Header-Definition:

root@kitploit:~
rule gif_1 {
  condition:
    (uint32be(0) == 0x47494638 and uint16be(4) == 0x3961) or
    (uint32be(0) == 0x47494638 and uint16be(4) == 0x3761)
}

Verwendung des „magic“-Moduls:

root@kitploit:~
import "magic"
rule gif_2 {
  condition:
    magic.mime_type() == "image/gif"
}

Zu kurze Strings

Vermeiden Sie die Definition zu kurzer Strings. Jeder String mit weniger als 4 Bytes wird wahrscheinlich in vielen Dateien oder als gleichförmiger Inhalt in einer XORed-Datei vorkommen.

Gleichförmiger Inhalt

Manche Strings sind lang genug, sollten aber aus einem anderen Grund nicht verwendet werden – Gleichförmigkeit. Hier sind einige Beispiele für Strings, die nicht verwendet werden sollten, da sie zu viele Übereinstimmungen in Dateien verursachen könnten.

root@kitploit:~
$s1 = "22222222222222222222222222222222222222222222222222222222222222"
$s2 = "\x00\x20\x00\x20\x00\x20\x00\x20\x00\x20\x00\x20\x00\x20"  // wide formatted spaces

Die Fehlermeldung würde wie folgt aussehen:

root@kitploit:~
error scanning yara-killer.dat: string "$mz" in rule "shitty_mz" caused too many matches

String-Empfehlungen

Versuchen Sie, String-Definitionen so eng wie möglich zu beschreiben. Vermeiden Sie nach Möglichkeit das Attribut „nocase“, da viele Atome generiert und durchsucht werden (höhere Speichernutzung, mehr Iterationen). Denken Sie daran, dass ohne Modifikatoren standardmäßig „ascii“ angenommen wird. Die möglichen Kombinationen sind:

NIEDRIG – Es wird nur ein Atom generiert.

root@kitploit:~
$s1 = "cmd.exe"		       // (ascii only)
$s2 = "cmd.exe" ascii          // (ascii only, same as $s1)
$s3 = "cmd.exe" wide           // (UTF-16 only)
$s4 = "cmd.exe" ascii wide     // (both ascii and UTF-16) two atoms will be generated 
$s5 = { 63 6d 64 2e 65 78 65 } // ascii char code in hex

HOCH – Alle Kombinationen aus Groß- und Kleinbuchstaben für die von YARA ausgewählten 4 Bytes werden als Atome generiert.

root@kitploit:~
$s5 = "cmd.exe" nocase      (all different cases, e.g. "Cmd.", "cMd.", "cmD." ..)

Wenn Sie Skriptbefehle abgleichen möchten, prüfen Sie, ob die Sprache überhaupt case-insensitiv ist (z. B. PHP, Windows-Batch), bevor Sie nocase verwenden. Wenn Sie nur eine andere Groß-/Kleinschreibung für ein oder zwei Buchstaben benötigen, sind Sie mit einem Regex besser beraten, z. B.:

root@kitploit:~
$re = /[Pp]assword/

Seien Sie vorsichtig bei der Arbeit mit Alternationen wie:

root@kitploit:~
$re = /(a|b)cde/
$hex = {C7 C3 00 (31 | 33)}

Diese Strings erzeugen kurze Atome, die das Scannen verlangsamen können. In Fällen, in denen es nur wenige Varianten gibt, wird empfohlen, die Strings getrennt zu schreiben:

root@kitploit:~
$re1 = /acde/
$re2 = /bcde/
$hex1 = {C7 C3 00 31}
$hex2 = {C7 C3 00 33}

Reguläre Ausdrücke

Verwenden Sie reguläre Ausdrücke nur, wenn es notwendig ist. Die Auswertung von regulären Ausdrücken ist grundsätzlich langsamer als einfaches String-Matching und verbraucht eine erhebliche Menge an Speicher. Verwenden Sie sie nicht, wenn Hex-Strings mit Sprüngen und Wildcards das Problem lösen können.

Wenn Sie reguläre Ausdrücke verwenden müssen, vermeiden Sie gierige .* und auch widerwillige Quantifizierer .*?. Verwenden Sie stattdessen exakte Zahlen wie .{1,30} oder sogar .{1,3000}. Vergessen Sie außerdem nicht die obere Grenze (vermeiden Sie z. B. .{2,}).

Bei der Verwendung von Quantifizierern können zwei Situationen auftreten:

Wenn der Anfang des regulären Ausdrucks an einer Position verankert ist und nur das Suffix variieren kann, wird YARA die längstmögliche Übereinstimmung finden. In Fällen wie .* und .+ oder .{2,} kann dies zu langen Strings führen und das Scannen verlangsamen.

Wenn es mehrere mögliche Anfänge des regulären Ausdrucks gibt, wird YARA alle davon abgleichen.

root@kitploit:~
$re1 = /Tom.{0,2}/		// will find Tomxx in "Tomxx"
$re2 = /.{0,2}Tom/      // will find Tom, xTom, xxTom in "xxTom"

Die Anzahl der kürzeren Übereinstimmungen kann leicht die Grenze überschreiten und einen „too many matches“-Fehler erzeugen.

Das folgende Beispiel ist der reguläre Ausdruck für eine E-Mail-Adresse. Bei Verwendung von [-a-z0-9._%+] mit Quantifizierern wird YARA eine Adresse mehrfach abgleichen, was nicht ideal ist. In diesem Fall wird empfohlen, eine vernünftig kleine Teilmenge von Adressen zu finden, die genügend Informationen für die Analyse liefert.

VERWENDEN

root@kitploit:~
/[-a-z0-9._%+]@[-a-z0-9.]{2,10}\.[a-z]{2,4}/
OR
/@[-a-z0-9.]{2,10}\.[a-z]{2,4}/ 

VERMEIDEN

root@kitploit:~
/[-a-z0-9._%+]*@[-a-z0-9.]{2,10}\.[a-z]{2,4}/
/[-a-z0-9._%+]+@[-a-z0-9.]{2,10}\.[a-z]{2,4}/
/[-a-z0-9._%+]{x,y}@[-a-z0-9.]{2,10}\.[a-z]{2,4}/

Wenn Sie sicherstellen möchten, dass z. B. auf exec ein /bin/sh folgt, können Sie die vom @-Symbol gelieferten Offsets verwenden. Dies wäre die langsame Regex-Version:

root@kitploit:~
$ = /exec.*\/bin\/sh/

Dies ist der schnellere Weg über Offsets:

root@kitploit:~
strings:
  $exec = "exec" 
  $sh   = "/bin/sh"
conditions:
  $exec and $sh and
  @exec < @sh

Versuchen Sie außerdem, lange String-Sequenzen einzubeziehen, die als Anker im Abgleichprozess dienen können. Auch hier gilt: Je länger, desto besser.

SCHLECHT

root@kitploit:~
$s1 = /http:\/\/[.]*\.hta/	// greedy [.]*

BESSER

root@kitploit:~
$s1 = /http:\/\/[a-z0-9\.\/]{3,70}\.hta/ 	// better, with an the upper bound

AM BESTEN

root@kitploit:~
$s1 = /mshta\.exe http:\/\/[a-z0-9\.\/]{3,70}\.hta/

Fehler „Too Many Matches“ und verlangsamtes Scannen

Fehler „Too many matches“ werden durch zu allgemeine Strings verursacht, die im Eingabematerial zu häufig vorkommen, oder dadurch, dass YARA eine Instanz mehrfach abgleicht.

Ein verlangsamtes Scannen wird durch Strings verursacht, die zu kurze Atome oder gar keine erzeugen. Infolgedessen verwendet YARA einen naiven Pattern-Matching-Algorithmus, was die Verlangsamung verursacht.

Beide Probleme können in einigen Fällen durch die folgenden Schritte behoben werden:

  1. Überprüfen Sie die Quantifizierer .* und .+, .*?
  2. Überprüfen Sie Quantifizierer ohne obere Grenze, wie x{14,}
  3. Überprüfen Sie zu große Bereiche (z. B. x{1,300000})
  4. Überprüfen Sie große Sprünge in den Hex-Strings
  5. Überprüfen Sie Wildcard-Zeichen – können sie präziser angegeben werden oder könnte der String in 2 Teile aufgeteilt werden, wobei das Wildcard-Zeichen weggelassen wird?
  6. Überprüfen Sie Alternationen: Können sie in zwei oder mehr Strings aufgeteilt werden?
  7. Versuchen Sie, eine Spezifikation für Wortübereinstimmungen hinzuzufügen (fullword, \b, ...)

Hinweis: Im nächsten Kapitel Bedingungen und Short-Circuit-Auswertung werden einige Tipps für Bedingungen erwähnt. Diese Änderungen werden jedoch die Fehler „too many matches“ und das verlangsamte Scannen nicht beheben.

Bedingungen und Short-Circuit-Auswertung

Versuchen Sie, Bedingungsanweisungen so zu schreiben, dass die Elemente, die am wahrscheinlichsten „False“ ergeben, zuerst platziert werden. Die Bedingung wird von links nach rechts ausgewertet. Je früher die Engine erkennt, dass eine Regel nicht erfüllt ist, desto eher kann sie die aktuelle Regel überspringen und die nächste auswerten. Die Geschwindigkeitsverbesserung durch diese Art der Anordnung der Bedingungsanweisungen hängt vom Unterschied der erforderlichen CPU-Zyklen zur Verarbeitung der einzelnen Anweisungen ab. Wenn alle Anweisungen mehr oder weniger gleich teuer sind, bewirkt eine Umordnung keine spürbare Verbesserung. Wenn eine der Anweisungen sehr schnell verarbeitet werden kann, wird empfohlen, sie zuerst zu platzieren, um die teure Auswertung der Anweisung in Fällen zu überspringen, in denen die erste Anweisung FALSE ist.

Eine Änderung der Reihenfolge in der folgenden Anweisung führt zu keiner signifikanten Verbesserung:

root@kitploit:~
$string1 and $string2 and uint16(0) == 0x5A4D

Wenn sich die Ausführungszeit der Anweisungen jedoch stark unterscheidet, verbessert eine Umordnung zur Auslösung des Short-Circuit die Scan-Geschwindigkeit erheblich:

LANGSAM

root@kitploit:~
// EXPENSIVE and CHEAP
math.entropy(0, filesize) > 7.0 and uint16(0) == 0x5A4D

SCHNELL

root@kitploit:~
// CHEAP and EXPENSIVE
uint16(0) == 0x5A4D and math.entropy(0, filesize) > 7.0

Die Short-Circuit-Auswertung wurde eingeführt, um teure Anweisungen zu optimieren, insbesondere „for“-Anweisungen. Manche Leute verwendeten Bedingungen wie die im folgenden Beispiel:

root@kitploit:~
strings:
	$mz = "MZ"
	...
condition:
	$mz at 0 and for all i in (1..filesize) : ( whatever )

Da die Dateigröße eine sehr große Zahl sein kann, kann „whatever“ sehr oft ausgeführt werden, was die Ausführung verlangsamt. Mit der Short-Circuit-Auswertung wird die „for“-Anweisung nun nur dann ausgeführt, wenn der erste Teil der Bedingung erfüllt ist. Diese Regel wird also nur für MZ-Dateien langsam sein. Eine zusätzliche Verbesserung könnte sein:

root@kitploit:~
$mz at 0 and filesize < 100KB and for all i in (1..filesize) : ( whatever )

Auf diese Weise wird eine obere Grenze für die Anzahl der Iterationen festgelegt.

Seit Version 3.10 wurden auch Schleifen über Integer-Bereiche optimiert:

root@kitploit:~
for all i in (0..100): (false)
for any i in (0..100): (true)

Both of these loops will stop iterating after the first time through.

Kein Short-Circuit für reguläre Ausdrücke

Leider funktioniert dies nicht mit regulären Ausdrücken, da sie alle zunächst in die String-Matching-Engine eingespeist werden. Das folgende Beispiel verlangsamt die Suche für jede Datei und nicht nur für diejenigen mit einer Dateigröße von weniger als 200 Bytes:

root@kitploit:~
strings:
  $expensive_regex = /\$[a-z0-9_]+\(/ nocase
conditions:
  filesize < 200 and
  $expensive_regex

Diese „Short-Circuit“-Auswertung wird seit YARA-Version 3.4 angewendet.

Metadaten

Alle Daten im Metadatenabschnitt werden von YARA in den RAM gelesen. (Sie können dies leicht testen, indem Sie 100.000 Hashes in eine Regel einfügen und die RAM-Nutzung des YARA-Scans vorher und nachher überprüfen.) Natürlich möchten Sie die Metadaten nicht dauerhaft aus den Regeln entfernen, aber wenn Sie wenig RAM haben, könnten Sie in Ihrem Workflow unmittelbar vor dem Scannen einige unnötige Teile davon entfernen.

Tool herunterladen