Ingénierie de détection

Écrire des règles YARA

Apprenez à écrire des règles YARA qui détectent des familles de malwares entières : chaînes, conditions, modules, tests avec yara et YARA-X.

1 Introduction

YARA est un outil de recherche de motifs qui permet de décrire toute une famille de fichiers en quelques lignes lisibles : « un exécutable Windows de moins de 2 Mo qui contient ces deux chaînes et cette séquence d'octets ». Créé par Victor M. Alvarez chez VirusTotal, il est devenu la langue commune des analystes malware, des équipes de réponse à incident et de threat intelligence. On le surnomme souvent le « grep des malwares », mais il est bien plus expressif que grep.

Pourquoi ne pas simplement bloquer un hash de fichier ? Parce qu'un hash change du tout au tout dès que l'attaquant recompile son code ou modifie un seul octet (voir la pyramide de la douleur). Une règle YARA vise ce qui reste stable d'une variante à l'autre : un nom de mutex, un marqueur de configuration, un bout de code, une faute de frappe dans une demande de rançon. Une bonne règle peut attraper des centaines d'échantillons jamais vus auparavant.

3 blocs

meta, strings et condition : c'est toute la règle

1 hash

c'est ce que détecte un IOC. Une règle YARA détecte une famille entière

Partout

VirusTotal, EDR, sandbox, outils forensiques et scanners mémoire parlent YARA

À quoi sert YARA ?

Threat hunting

Passer au peigne fin partages réseau, postes ou base de malwares pour trouver des fichiers proches d'un échantillon décrit dans un rapport CTI.

Réponse à incident

Une machine infectée identifiée ? On écrit une règle à partir de l'échantillon et on scanne tout le parc pour trouver les autres.

Tri des malwares

Classer automatiquement les échantillons entrants : les sandbox appliquent YARA aux fichiers et aux dumps mémoire pour nommer la famille.

Partage de renseignement

Les règles sont du simple texte : elles circulent dans les flux de threat intel, les rapports et les indicateurs STIX.

2 Anatomie d'une règle

Voici une règle complète pour un « MLAB demo loader » imaginaire. Chaque partie est commentée, et les paragraphes suivants détaillent chaque mot-clé. Les commentaires s'écrivent comme en C : // sur une ligne, /* */ sur plusieurs.

demo_loader.yar

import "pe"                                  // facultatif : charge un module (pe, elf, math, hash...)

rule MLAB_Demo_Loader : demo loader          // nom de la règle + tags facultatifs
{
    meta:                                    // contexte libre clé/valeur, jamais utilisé pour la détection
        author      = "mlab Academy"
        description = "Detects the fictional MLAB demo loader (training sample)"
        date        = "2026-10-21"
        reference   = "https://academy.mlab.sh/page/regles-yara"
        hash        = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
        tlp         = "CLEAR"

    strings:                                 // ce que l'on cherche
        $s1 = "mlab-demo-loader" ascii wide nocase    // chaîne texte + modificateurs
        $s2 = "/gate.php?id=" ascii
        $s3 = "MLAB_MUTEX_7f3a" ascii wide fullword
        $h1 = { 4D 4C 41 42 ?? ?? 00 [2-4] FF }        // chaîne hexa : ?? = octet quelconque, [2-4] = saut
        $r1 = /beacon_[0-9]{4}\.dat/                   // expression régulière
        $x1 = "S3cr3tC0nf1g" xor(0x01-0xff)           // XOR mono-octet, toutes les clés de 1 à 255

    condition:                               // logique booléenne qui décide du match
        uint16(0) == 0x5A4D                  // le fichier commence par « MZ » (PE Windows)
        and filesize < 2MB
        and pe.number_of_sections > 2
        and 2 of ($s*)                       // au moins deux des chaînes $s
        and ($h1 or $r1 or $x1)
}

L'en-tête : nom, tags, préfixes

Le nom d'une règle est un identifiant (lettres, chiffres, tiret bas, 128 caractères au plus, sans chiffre en première position) unique dans son espace de noms. Une convention répandue est TYPE_Famille_Détail (MAL_ pour un malware, SUSP_ pour du suspect, HKTL_ pour un outil offensif). Les tags facultatifs placés après les deux-points servent à filtrer les résultats (yara -t loader). On peut préfixer une règle par private (elle ne remonte jamais de résultat elle-même mais peut servir à d'autres règles) ou par global (sa condition s'applique à toutes les règles du fichier).

meta : le contexte, pour les humains et les outils

Des paires clé/valeur (chaîne, entier ou booléen) qui ne servent jamais à la détection. Renseignez au minimum author, description, date et reference, ainsi que le hash d'un échantillon sur lequel la règle a été testée. Dans six mois, l'analyste qui traitera l'alerte vous dira merci.

strings : trois types de motifs

Type Syntaxe Usage
Texte"mlab-demo-loader"Chaînes lisibles : URL, mutex, messages d'erreur, chemins PDB. Les échappements \n \t \" \\ \x41 sont acceptés.
Hexa{ 4D 4C ?? [2-4] (41 | 42) }Octets bruts et code. ?? = octet quelconque, 4? = joker sur un quartet, [2-4] = saut de 2 à 4 octets, ( A | B ) = alternative.
Regex/beacon_[0-9]{4}\.dat/Motifs variables. Très puissantes mais les plus lentes : ancrez-les toujours sur quelques caractères fixes.

Les modificateurs s'écrivent après le motif et changent la façon dont il est recherché :

Modificateur Effet
asciiRecherche classique, un octet par caractère. Implicite, sauf si wide est présent.
wideCaractères entrecoupés d'octets nuls (UTF-16LE), le format de la plupart des programmes Windows. ascii wide cherche les deux.
nocaseInsensible à la casse.
fullwordNe correspond que si la chaîne est délimitée par des caractères non alphanumériques : "mal" ne sortira pas dans "normal".
xor / xor(1-255)Cherche aussi toutes les versions de la chaîne chiffrées par un XOR mono-octet, une astuce courante des malwares. Incompatible avec nocase.
base64 / base64wideCherche les formes encodées en base64 de la chaîne (utile pour les scripts et documents).
privateLa chaîne est recherchée mais jamais affichée dans les résultats (pratique pour les chaînes auxiliaires bruyantes).

condition : la décision

La condition est une expression booléenne qui peut utiliser and, or, not, des comparaisons et de l'arithmétique. Un identifiant seul ($a) est vrai si la chaîne est trouvée. Chaque chaîne déclarée doit être utilisée dans la condition, sinon la règle ne compile pas.

Expression Signification
2 of ($s*)Au moins deux chaînes dont le nom commence par $s. Existe aussi : any of them, all of them, none of ($x*).
#url >= 3# = nombre d'occurrences de la chaîne.
$mz at 0La chaîne se trouve exactement à l'offset 0.
$cfg in (0..4096)La chaîne apparaît dans les 4 premiers Ko.
@url[1]@ = offset de la n-ième occurrence (numérotée à partir de 1).
filesize < 2MBTaille du fichier, avec les suffixes KB / MB.
uint16(0) == 0x5A4DLit 2 octets à l'offset 0 (petit-boutiste) : la signature MZ d'un exécutable Windows. Existent aussi uint8, uint32, uint32be…
for all i in (1..#a) : ( ... )Boucle sur des occurrences, des entiers ou des tableaux fournis par un module.
pe.number_of_sectionsDonnée issue d'un module. pe, elf, macho, dotnet, math, hash… analysent le fichier à votre place.

3 Exemples guidés

On part d'une règle d'une ligne pour arriver à une règle réaliste. Tous les marqueurs sont inventés pour l'exercice : ces règles ne feront pas réagir votre antivirus sur cette page, et vous pouvez les reproduire sans risque en créant des fichiers de test contenant les mêmes chaînes.

Étape 1 : la plus petite règle utile

Une chaîne, une condition. Le bloc meta est facultatif ; seule la section condition est obligatoire.

demo_hello.yar

rule Demo_Hello_Marker
{
    strings:
        $marker = "MLAB-ACADEMY-TEST-MARKER"
    condition:
        $marker
}

Pour tester : printf 'xx MLAB-ACADEMY-TEST-MARKER yy' > sample.txt puis yara -s demo_hello.yar sample.txt. Vous devez voir le nom de la règle, le nom du fichier et l'offset de la correspondance.

Étape 2 : combiner des chaînes (PowerShell suspect)

Un mot-clé isolé comme DownloadString apparaît dans quantité de scripts d'administration légitimes. L'astuce consiste à exiger une combinaison : quelque chose qui télécharge et quelque chose qui exécute en mémoire, dans un petit fichier texte qui n'est pas un exécutable.

ps_cradle.yar

rule SUSP_PS_Download_Cradle
{
    meta:
        author      = "mlab Academy"
        description = "PowerShell script that downloads content and executes it in memory"
        date        = "2026-10-21"
        score       = 60

    strings:
        $dl1 = "Net.WebClient" ascii wide nocase
        $dl2 = "DownloadString" ascii wide nocase
        $dl3 = "Invoke-WebRequest" ascii wide nocase
        $ex1 = "Invoke-Expression" ascii wide nocase
        $ex2 = "IEX(" ascii wide nocase
        $ex3 = "IEX (" ascii wide nocase
        $b64 = "FromBase64String" ascii wide nocase

    condition:
        filesize < 200KB
        and uint16(0) != 0x5A4D
        and 1 of ($ex*)
        and (1 of ($dl*) or $b64)
}
$ yara -s ps_cradle.yar invoice_update.ps1
SUSP_PS_Download_Cradle invoice_update.ps1
0x11:$dl1: Net.WebClient
0x28:$dl2: DownloadString
0x1f:$ex3: IEX (

Remarquez le nommage $dl* / $ex* : regrouper les chaînes par rôle grâce à un préfixe rend des conditions comme 1 of ($ex*) courtes et lisibles. Le champ meta score est une convention utilisée par des scanners comme THOR et LOKI pour pondérer les résultats.

Étape 3 : une règle de famille avec contrôle du format et module

C'est la règle commentée de la section 2. Elle illustre la structure classique d'une règle de famille de malware : d'abord des contrôles structurels peu coûteux (en-tête MZ, taille, nombre de sections PE), puis un seuil de chaînes « faibles » (2 of ($s*)), puis au moins un indicateur « fort » (motif d'octets, regex ou chaîne masquée par XOR). Exiger plusieurs indices indépendants, c'est ce qui limite les faux positifs.

Étape 4 : règles privées, comptages, offsets et boucles

Une règle private sert de brique réutilisable. Ici, Is_PE vérifie à la fois l'en-tête MZ et la signature PE\0\0 située à l'offset indiqué en 0x3C. La règle principale exige ensuite un marqueur de configuration dans les 4 premiers Ko et au moins trois URL, toutes placées après ce marqueur.

demo_config.yar

private rule Is_PE
{
    condition:
        uint16(0) == 0x5A4D and uint32(uint32(0x3C)) == 0x00004550
}

rule MLAB_Demo_Config_Block
{
    meta:
        description = "Demo: string counts, offsets and loops"
    strings:
        $cfg = "[mlab-cfg]"
        $url = /https?:\/\/[a-z0-9.-]{4,64}\/[a-z]{3,10}\.php/ nocase
    condition:
        Is_PE
        and $cfg in (0..4096)
        and #url >= 3
        and for all i in (1..#url) : ( @url[i] > @cfg[1] )
}

Bonus : hash et entropie, sans aucune chaîne

Une règle peut se passer de section strings. Le module hash sait comparer un SHA-256 exact (ici celui d'un fichier vide, en guise d'exemple) et le module math repère les contenus compressés ou chiffrés, dont l'entropie approche 8 (voir aussi le rapport d'analyse de fichier). Le hash dans YARA est pratique mais lent (tout le fichier est haché) : pour de simples IOC de type hash, une recherche dans votre EDR ou sur mlab.sh va plus vite.

import "hash"
import "math"

rule MLAB_Demo_Exact_Hash_And_Entropy
{
    condition:
        filesize < 5MB
        and (
            hash.sha256(0, filesize) == "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"
            or math.entropy(0, filesize) >= 7.5
        )
}

4 Tests et outils

La ligne de commande yara

Installez-la avec votre gestionnaire de paquets (apt install yara, brew install yara) ou depuis les releases GitHub de VirusTotal/yara. Les commandes essentielles :

# 1. Vérifier qu'un fichier de règles compile (aucune sortie = OK)
$ yara -w demo_hello.yar /dev/null

# 2. Scanner un fichier et afficher les chaînes trouvées (-s)
$ yara -s demo_hello.yar sample.txt
Demo_Hello_Marker sample.txt
0x3:$marker: MLAB-ACADEMY-TEST-MARKER

# 3. Scanner un dossier récursivement (-r) en affichant le bloc meta (-m)
$ yara -r -m rules/ ./samples/

# 4. Compiler une fois avec yarac, puis scanner autant de fois que voulu avec -C
$ yarac rules.yar rules.yarc
$ yara -C rules.yarc ./samples/suspicious.bin

Le compilateur est votre premier relecteur. Voici de vrais messages qu'il affiche ; chacun pointe une erreur classique détaillée en section 5 :

error: rule "bad" in bad.yar(1): unreferenced string "$b"
warning: rule "slow" in slow.yar(1): string "$a" may slow down scanning
warning: rule "slow" in slow.yar(1): $r contains .*, .+ or .{x,} consider using .{,N}, .{1,N} or {x,N} with a reasonable value for N

YARA-X, la nouvelle génération

YARA-X est une réécriture complète de YARA en Rust par la même équipe, stable depuis sa version 1.0 sortie en 2025 et présentée comme l'avenir du projet (YARA 4.x ne reçoit désormais pour l'essentiel que des correctifs). Le langage de règles reste le même, à quelques rares incompatibilités près, les messages d'erreur sont bien plus clairs et les règles complexes s'exécutent plus vite. Toutes les règles de cette page compilent avec YARA 4.5 comme avec YARA-X.

# YARA-X : la réécriture de YARA en Rust par VirusTotal (commande : yr)
$ yr check rules/                    # vérifie que chaque fichier compile
$ yr fmt demo_loader.yar             # normalise l'indentation et la mise en forme
$ yr scan demo_loader.yar ./samples/ # scanne, avec le même langage de règles

Une routine de test qui fonctionne vraiment

1. Vrais positifs

Conservez les échantillons qui ont servi à écrire la règle (dans une archive protégée par mot de passe, hors des dossiers synchronisés) et vérifiez que chacun est bien détecté.

2. Fichiers sains

Scannez un gros volume de fichiers légitimes : C:\Windows\System32, /usr/bin, installeurs courants, documents Office. Chaque résultat est un faux positif à corriger avant le déploiement.

3. Retro-hunt

Des plateformes comme VirusTotal Retrohunt, YARAify ou MalwareBazaar (abuse.ch) appliquent votre règle à des millions d'échantillons passés et montrent ce qu'elle aurait détecté d'autre.

4. Versionnez

Rangez vos règles dans Git, lancez yara ou yr check en CI, et mettez à jour le champ date/modified à chaque modification.

YARA-L n'est pas YARA

Google Security Operations (anciennement Chronicle) utilise un langage appelé YARA-L. Malgré son nom et une structure proche (meta / events / condition), il détecte des événements de logs dans un SIEM, pas des octets dans des fichiers. Pour écrire des détections sur les logs de façon portable, tournez-vous plutôt vers les règles Sigma.

Partez d'un vrai échantillon sur mlab.sh

Avant d'écrire une règle, analysez le fichier suspect : hash, chaînes et verdicts vous donnent les marqueurs stables que votre règle YARA doit cibler.

Analyser un fichier sur mlab.sh

5 Pièges courants

Les erreurs qui créent des faux positifs (ou des oublis)

Cibler des chaînes de bibliothèque ou de compilateur

Des chaînes comme "This program cannot be run in DOS mode", les messages d'erreur d'OpenSSL ou les symboles du runtime Go se retrouvent dans des milliers de binaires légitimes. Choisissez des chaînes propres à l'auteur, pas à sa chaîne de compilation.

any of them sur des chaînes génériques

Une chaîne faible ne suffit jamais. Combinez plusieurs indices, ajoutez un contrôle du type de fichier (uint16(0) == 0x5A4D) et une borne sur filesize.

Oublier wide

Les programmes Windows stockent souvent leurs chaînes en UTF-16. Si une chaîne copiée depuis un rapport de sandbox ne matche pas, essayez ascii wide.

Scanner des fichiers packés ou compressés

YARA voit des octets bruts. Les chaînes d'un ZIP, d'un document Office (qui est un ZIP) ou d'un exécutable packé avec UPX restent invisibles tant qu'on ne les décompresse pas ; sinon, scannez plutôt la mémoire du processus.

Une règle qui se déclenche sur son propre rapport

Une règle purement textuelle (sans contrôle du format) détecte aussi les PDF, pages web et fichiers de règles qui citent ces chaînes. L'antivirus qui met en quarantaine votre propre dépôt de règles, c'est un classique.

Conseils de performance

YARA commence par extraire de chaque chaîne de courts atomes (4 octets au plus) qu'il recherche tous en une passe grâce à l'algorithme d'Aho-Corasick ; ce n'est qu'ensuite qu'il vérifie les chaînes complètes et évalue les conditions. Une règle aux atomes médiocres ralentit tous les scans, pas seulement le sien.

Utilisez des chaînes d'au moins 4 octets distinctifs

Évitez { 00 00 00 00 }, { ?? ?? 00 } ou "abc" : si le compilateur avertit « may slow down scanning », ce n'est pas pour rien.

Bornez vos expressions régulières

Jamais de .* ni de .+ ; préférez .{1,64}. Commencez la regex par des caractères littéraux pour que YARA puisse en extraire un atome.

Placez les tests peu coûteux en tête de condition

L'évaluation s'arrête dès que le résultat est connu : mettre filesize et uint16(0) avant les boucles, math.entropy ou les calculs de hash évite un travail coûteux sur les fichiers qui ne correspondent pas.

Préférez des chaînes hexa qui commencent par des octets fixes

Des jokers et des sauts en début de chaîne hexa ne laissent rien sur quoi s'ancrer. Commencez et terminez par des octets connus, et gardez des sauts courts.

Compilez les gros jeux de règles

Avec des milliers de règles, compiler une fois avec yarac (ou les charger une seule fois dans votre scanner) économise le temps d'analyse syntaxique à chaque exécution.

6 Aller plus loin

Les règles de la communauté

Inutile de repartir de zéro : lisez de bonnes règles pour en apprendre le style, puis réutilisez-les. Vérifiez toujours la licence avant de les intégrer à un produit commercial.

Neo23x0/signature-base

La vaste collection, très bien maintenue, de Florian Roth, utilisée par les scanners LOKI et THOR. Publiée sous Detection Rule License (DRL).

YARA-Forge

Agrège, teste et dédoublonne des dizaines de dépôts publics en paquets prêts à l'emploi (core, extended, full) aux métadonnées homogènes.

elastic/protections-artifacts

Les règles YARA qu'Elastic Defend utilise en production : une excellente référence de style propre et peu bruyant.

abuse.ch YARAify

Plateforme communautaire pour partager des règles et y confronter des fichiers, reliée à MalwareBazaar.

La place de YARA dans votre dispositif de détection

Outil Observe Question type
YARAFichiers et mémoire« Ce fichier appartient-il à la famille X ? »
SigmaLogs (SIEM)« Un processus a-t-il appliqué la technique Y ? »
Suricata / SnortTrafic réseau« Une machine communique-t-elle avec l'infrastructure Z ? »

Les trois se complètent : un fichier détecté par YARA fournit des IOC (domaines de C2, hash) pour les règles réseau et logs, et associer chaque règle à sa technique MITRE ATT&CK dans le bloc meta permet de mesurer votre couverture. Pour comprendre ce que font réellement les familles que vous détectez, consultez les modules malware et familles de menaces.

Modules connexes