
Un guide sur la façon d'écrire des règles YARA rapides et économes en mémoire
É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.
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.
« 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 :
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 :
\x00\x00\x00\x00 apparaît trop fréquemment.nocase avec précaution – Cela génère exponentiellement plus de variations de recherche.YARA évalue les conditions séquentiellement et s'arrête au premier échec.
✅ Bonnes pratiques pour les conditions :
filesize < X) avant les conditions coûteuses.for all i in (1..filesize) est inefficace).@) 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.
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 :
pe.is_pe, utilisez uint16(0) == 0x5A4D pour identifier les fichiers PE.Des correspondances excessives ralentissent le scan et peuvent déclencher des erreurs « too many matches ».
✅ Corriger les correspondances inefficaces :
.*, .+ ou {x,} sans borne supérieure.@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
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 :
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
}
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 :
<?phGETPOSTsser (à partir d'assert)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.
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.
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.
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 :
/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.
/(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 :
{ 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
{ 01 02 [1-4] 01 02 03 04 }
=> 01 02 03 04 est préféré à 01 02 car il est plus long