Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
YARA-Performance-Guidelines — Un guide sur la façon d'écrire des règles YARA rapides et économes en mémoire | Kitploit
Outils/GitHubGitHub/neo23x0/yara-performance-guidelines
Analyse StatiqueAnalyse de MalwareApprentissage et Éducation
GitHubneo23x0/yara-performance-guidelines

YARA-Performance-Guidelines

Un guide sur la façon d'écrire des règles YARA rapides et économes en mémoire

Voir le dépôt

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
17423il y a 1 anVérifié par Kitploit
Partager

Directives de performance YARA

Écrire des règles YARA efficaces est essentiel pour maintenir des performances de scan rapides et précises. Ce guide fournit des principes clés et des bonnes pratiques pour vous aider à optimiser vos règles, réduire les calculs inutiles et éviter les pièges courants. Il intègre des idées d'experts du secteur, notamment Victor M. Alvarez, WXS, et des contributions de la communauté YARA.

  • Révision 1.6, février 2025, s'applique à toutes les versions de YARA supérieures à 3.7

Points clés

Cette section fournit un résumé concis des bonnes pratiques de performance YARA. Pour des explications détaillées et des exemples, reportez-vous au guide complet ci-dessous.

Comprendre le processus de scan de YARA

« Pensez à YARA comme à un processus en deux étapes : d'abord, rechercher tous les motifs listés dans les chaînes, puis évaluer les conditions. Vous ne pouvez pas utiliser des conditions bien formées pour compenser des chaînes mal choisies. » — Wesley Shields

YARA suit quatre étapes principales lors du scan d'un fichier :

  1. Compilation des règles – Extraction des atomes (sous-chaînes de 4 octets) à partir des chaînes définies.
  2. Recherche Aho-Corasick – Scan des fichiers pour trouver ces atomes.
  3. Moteur de bytecode – Vérification des correspondances complètes de chaînes.
  4. Évaluation des conditions – Vérification de la logique supplémentaire des règles.

Sélection des chaînes – Le facteur le plus important

YARA recherche d'abord les chaînes, ce qui fait de la sélection des chaînes le facteur le plus important pour l'efficacité des règles.

✅ Bonnes pratiques pour les chaînes :

  • Évitez les chaînes courtes (< 4 octets) – Elles génèrent trop de faux positifs.
  • Utilisez des atomes uniques de 4 octets – YARA s'appuie sur eux pour un scan rapide.
  • Minimisez les caractères génériques dans les chaînes hexadécimales – Conservez au moins un segment concret long.
  • Utilisez les regex avec parcimonie – Si nécessaire, incluez une ancre fixe de 4 octets pour améliorer l'efficacité.
  • Évitez les motifs répétés d'un seul octet – Par exemple, \x00\x00\x00\x00 apparaît trop fréquemment.
  • Utilisez nocase avec précaution – Cela génère exponentiellement plus de variations de recherche.

Optimiser les conditions et le court-circuit

YARA évalue les conditions séquentiellement et s'arrête au premier échec.

✅ Bonnes pratiques pour les conditions :

  • Placez les vérifications rapides en premier (par exemple, filesize < X) avant les conditions coûteuses.
  • Évitez les boucles sur de grandes quantités de données (for all i in (1..filesize) est inefficace).
  • Utilisez des décalages directs (@) au lieu de regex pour les vérifications de séquence.

⚠ Remarque : Les conditions regex ne se court-circuitent pas et sont toujours évaluées en dernier.

Modules – À utiliser avec prudence

Les modules comme pe, elf ou magic doivent analyser l'intégralité du fichier avant l'évaluation, ce qui augmente le temps de scan.

✅ Alternatives :

  • Au lieu de pe.is_pe, utilisez uint16(0) == 0x5A4D pour identifier les fichiers PE.
  • Évitez d'utiliser des modules sauf si une inspection approfondie du fichier est nécessaire.

Gérer les trop nombreuses correspondances et les scans lents

Des correspondances excessives ralentissent le scan et peuvent déclencher des erreurs « too many matches ».

✅ Corriger les correspondances inefficaces :

  • Vérifiez les quantificateurs de regex – Évitez .*, .+ ou {x,} sans borne supérieure.
  • Réduisez les caractères génériques dans les chaînes hexadécimales.
  • Divisez les alternatives en chaînes distinctes lorsque c'est possible.

Tutoriel vidéo

@herrcore a créé un tutoriel vidéo utile couvrant les sujets abordés dans ce guide de performance.

Introduction à YARA - Écrire des règles YARA efficaces

Les bases

Pour mieux comprendre quoi et où optimiser dans les performances de YARA, il est utile de comprendre le processus de scan. Il est essentiellement divisé en 4 étapes qui seront expliquées de manière très simplifiée à l'aide de cette règle d'exemple :

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. Compilation des règles

Cette étape se déroule avant le scan proprement dit. YARA recherche des « atomes » dans les chaînes de recherche pour alimenter l'automate Aho-Corasick. Les détails sont expliqués dans le chapitre atome, mais pour l'instant il suffit de savoir qu'ils font au maximum 4 octets et que YARA les choisit assez intelligemment pour éviter trop de correspondances. Dans notre exemple, YARA pourrait choisir les 4 atomes suivants :

  • <?ph
  • GET
  • POST
  • sser (à partir d'assert)

2. Automate Aho-Corasick

Ici, le scan a commencé. Les étapes 2 à 4 seront exécutées sur tous les fichiers. YARA recherchera dans chaque fichier les 4 atomes définis ci-dessus à l'aide d'un arbre préfixe appelé automate Aho-Corasick. Toutes les correspondances sont transmises au moteur de bytecode.

3. Moteur de bytecode

S'il y a par exemple une correspondance sur sser, YARA vérifiera si elle était précédée d'un a et se poursuit avec un t. Si c'est le cas, il enchaînera avec la regex [\t ]{0,100}\(. Grâce à cette approche intelligente, YARA évite d'utiliser un moteur de regex lent sur l'ensemble des fichiers et ne sélectionne que certaines parties pour un examen plus approfondi.

4. Conditions

Après que toute la recherche de motifs est terminée, les conditions sont vérifiées. YARA dispose d'un autre mécanisme d'optimisation pour n'effectuer la vérification math.entropy, intensive en CPU, de notre règle d'exemple que si les 4 conditions précédentes sont satisfaites. Ceci est expliqué plus en détail dans le chapitre Conditions et évaluation en court-circuit

Si les conditions sont satisfaites, une correspondance est signalée. Le scan continue avec le fichier suivant à l'étape 2.

Atomes

YARA extrait des chaînes de courtes sous-chaînes pouvant aller jusqu'à 4 octets, appelées « atomes ». Ces atomes peuvent être extraits de n'importe quel endroit de la chaîne, et YARA recherche ces atomes lors du scan du fichier ; s'il en trouve un, il vérifie ensuite que la chaîne correspond effectivement.

Par exemple, considérez ces chaînes :

root@kitploit:~
/abc.*cde/

=> les atomes possibles sont abc et cde, l'un ou l'autre peut être utilisé. L'atome abc est actuellement préféré car ils ont la même qualité et c'est le premier des deux.

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

=> les atomes possibles sont one, two, thre et hree ; on peut rechercher thre (ou hree) seul, ou à la fois one et two. L'atome thre est préféré car il conduira à moins de correspondances potentielles que one et two (qui sont plus courts) et il ne contient pas de double e (plus la lettre est unique, mieux c'est).

YARA fait de son mieux pour sélectionner les meilleurs atomes de chaque chaîne, par exemple :

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

=> ici, YARA utilise l'atome 01 02 03 04, car 00 00 00 00 est trop courant

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

=> 01 02 03 04 est préféré à 01 02 car il est plus long

Le point important est donc que les chaînes doivent contenir de bons atomes. Ces chaînes sont mauvaises car elles contiennent des atomes trop courts ou trop courants :

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)/

Les pires chaînes sont celles qui ne contiennent aucun atome, comme :

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

Cette expression régulière ne contient aucune sous-chaîne fixe pouvant être utilisée comme atome, elle doit donc être évaluée à chaque décalage du fichier pour voir si elle correspond.

Trop d'itérations de boucle

Une autre bonne recommandation est d'éviter les boucles avec trop d'itérations, surtout si l'instruction à l'intérieur de la boucle est trop complexe, par exemple :

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

Cette règle présente deux problèmes. Le premier est que la chaîne $a est trop courante ; le second est que, parce que $a est trop courante, #a peut être trop élevé et être évalué des milliers de fois.

Cette autre condition est également inefficace car le nombre d'itérations dépend de filesize, qui peut être également très élevé :

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

Module Magic

Évitez d'utiliser le module « magic » qui n'est pas disponible sur la plateforme Windows. L'utilisation du module « magic » ralentit le scan mais fournit des correspondances exactes.

Définition personnalisée de l'en-tête magique GIF :

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

Utilisation du module « magic » :

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

Chaînes trop courtes

Évitez de définir des chaînes trop courtes. Toute chaîne de moins de 4 octets apparaîtra probablement dans de nombreux fichiers OU comme contenu uniforme dans un fichier XORé.

Contenu uniforme

Certaines chaînes sont assez longues mais ne devraient pas être utilisées pour une autre raison : l'uniformité. Voici quelques exemples de chaînes à ne pas utiliser car elles pourraient provoquer trop de correspondances dans les fichiers.

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

Le message d'erreur ressemblerait à :

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

Conseils sur les chaînes

Essayez de décrire les définitions de chaînes de la manière la plus précise possible. Évitez l'attribut « nocase » si possible, car de nombreux atomes seront générés et recherchés (utilisation mémoire plus élevée, plus d'itérations). Rappelez-vous qu'en l'absence de modificateurs, « ascii » est supposé par défaut. Les combinaisons possibles sont :

FAIBLE - un seul atome est généré

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

ÉLEVÉ - Toutes les combinaisons de lettres majuscules et minuscules pour les 4 octets choisis par YARA seront générées comme atomes

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

Si vous souhaitez faire correspondre des commandes de script, vérifiez si le langage est insensible à la casse (par exemple php, batch Windows) avant d'utiliser nocase. Si vous n'avez besoin que d'une casse différente pour une ou deux lettres, il est préférable d'utiliser une regex, par exemple.

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

Soyez prudent lorsque vous travaillez avec des alternatives telles que :

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

Ces chaînes génèrent des atomes courts qui peuvent ralentir le scan. Dans les cas où il y a un petit nombre de variantes, il est recommandé d'écrire la chaîne séparément :

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

Expressions régulières

N'utilisez les expressions régulières que lorsque c'est nécessaire. L'évaluation des expressions régulières est intrinsèquement plus lente que la correspondance simple de chaînes et consomme une quantité importante de mémoire. Ne les utilisez pas si des chaînes hexadécimales avec sauts et caractères génériques peuvent résoudre le problème.

Si vous devez utiliser des expressions régulières, évitez les quantificateurs gourmands .* et même les quantificateurs paresseux .*?. Utilisez plutôt des nombres exacts comme .{1,30} ou même .{1,3000}. N'oubliez pas non plus la borne supérieure (évitez par exemple .{2,}).

Lorsque nous utilisons des quantificateurs, deux situations peuvent se produire :

Si le début de l'expression régulière est ancré à une position et que seul le suffixe peut varier, YARA fera correspondre la correspondance la plus longue possible. Dans des cas comme .* et .+ ou .{2,}, cela peut conduire à de longues chaînes et à des problèmes de ralentissement du scan.

S'il y a plusieurs débuts possibles pour l'expression régulière, YARA les fera correspondre tous.

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

Le nombre de correspondances plus courtes peut facilement dépasser la limite et créer une erreur « too many matches ».

L'exemple suivant est l'expression régulière pour une adresse e-mail. Lors de l'utilisation de [-a-z0-9._%+] avec des quantificateurs, YARA fera correspondre une même adresse plusieurs fois, ce qui n'est pas idéal. Dans ce cas, il est recommandé de trouver un sous-ensemble raisonnablement petit d'adresses fournissant suffisamment d'informations pour l'analyse.

À UTILISER

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

À ÉVITER

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}/

Si vous voulez vous assurer, par exemple, que exec est suivi de /bin/sh, vous pouvez utiliser les décalages fournis par le symbole @. Ceci serait la version lente avec regex :

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

Voici la méthode plus rapide avec décalages :

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

Essayez également d'inclure de longues séquences de chaînes qui pourraient servir d'ancres dans le processus de correspondance. Encore une fois, plus c'est long, mieux c'est.

MAUVAIS

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

MEILLEUR

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

OPTIMAL

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

Erreur « Too Many Matches » et ralentissement du scan

Les erreurs « too many matches » sont causées par des chaînes trop générales présentes trop souvent dans l'entrée, ou par YARA qui fait correspondre une même instance plusieurs fois.

Le ralentissement du scan est causé par des chaînes qui génèrent des atomes trop courts, ou pas d'atomes du tout. En conséquence, YARA utilise un algorithme naïf de correspondance de motifs, ce qui provoque le ralentissement.

Ces deux problèmes peuvent, dans certains cas, être résolus par les étapes suivantes :

  1. Vérifiez les quantificateurs .* et .+, .*?
  2. Vérifiez les quantificateurs sans borne supérieure tels que x{14,}
  3. Vérifiez les plages trop grandes (par exemple x{1,300000})
  4. Vérifiez les grands sauts dans les chaînes hexadécimales
  5. Vérifiez les caractères génériques : peuvent-ils être spécifiés plus précisément, ou la chaîne pourrait-elle être divisée en 2, en omettant le caractère générique ?
  6. Vérifiez les alternatives : peuvent-elles être divisées en 2 chaînes ou plus ?
  7. Essayez d'ajouter une spécification pour la correspondance de mots (fullword, \b, ...)

Notez que dans le chapitre suivant, Conditions et évaluation en court-circuit, quelques conseils pour les conditions sont mentionnés. Cependant, les modifications apportées à celles-ci ne résoudront pas les erreurs « too many matches » et de ralentissement du scan.

Conditions et évaluation en court-circuit

Essayez d'écrire des instructions de condition dans lesquelles les éléments les plus susceptibles d'être « False » sont placés en premier. La condition est évaluée de gauche à droite. Plus tôt le moteur identifie qu'une règle n'est pas satisfaite, plus tôt il peut passer à la règle suivante et l'évaluer. L'amélioration de vitesse apportée par cette façon d'ordonner les instructions de condition dépend de la différence de cycles CPU nécessaires pour traiter chacune des instructions. Si toutes les instructions sont plus ou moins aussi coûteuses, réordonner les instructions n'apporte aucune amélioration notable. Si l'une des instructions peut être traitée très rapidement, il est recommandé de la placer en premier afin d'éviter l'évaluation coûteuse dans les cas où la première instruction est FALSE.

Changer l'ordre dans l'instruction suivante n'entraîne pas d'amélioration significative :

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

Cependant, si le temps d'exécution des instructions est très différent, réordonner pour déclencher le court-circuit améliorera considérablement la vitesse du scan :

LENT

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

RAPIDE

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

L'évaluation en court-circuit a été introduite pour aider à optimiser les instructions coûteuses, en particulier les instructions « for ». Certaines personnes utilisaient des conditions comme celle de l'exemple suivant :

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

Parce que filesize peut être un très grand nombre, « whatever » peut être exécuté un grand nombre de fois, ralentissant l'exécution. Désormais, avec l'évaluation en court-circuit, l'instruction « for » ne sera exécutée que si la première partie de la condition est satisfaite. Ainsi, cette règle ne sera lente que pour les fichiers MZ. Une amélioration supplémentaire pourrait être :

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

De cette façon, une borne supérieure au nombre d'itérations est définie.

À partir de la version 3.10, les boucles sur plages d'entiers ont également été optimisées :

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.

Pas de court-circuit pour les expressions régulières

Malheureusement, cela ne fonctionne pas avec les expressions régulières car elles sont toutes initialement transmises au moteur de correspondance de chaînes. L'exemple suivant ralentira la recherche pour n'importe quel fichier, et pas seulement pour ceux dont la taille est inférieure à 200 octets :

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

Cette évaluation « en court-circuit » est appliquée depuis la version 3.4 de YARA.

Métadonnées

Toutes les données de la section métadonnées sont lues dans la RAM par YARA. (Vous pouvez facilement le tester en insérant 100 000 hachages dans une règle et en vérifiant l'utilisation de la RAM du scan YARA avant et après.) Bien sûr, vous ne voulez pas supprimer définitivement les métadonnées des règles, mais si vous manquez de RAM, vous pouvez supprimer certaines parties inutiles de celles-ci dans votre flux de travail juste avant le scan.

Télécharger l’outil