Aller au contenu

Chaînes YARA : texte, hexadécimal et regex

Écrire les chaînes d’une règle YARA : texte et échappements, modificateurs nocase, wide, xor et base64, chaînes hexadécimales avec jokers et sauts, regex.

Publié le 4 min de lecture

Les motifs — YARA les appelle strings, même quand ce sont des octets ou des regex — sont ce que YARA recherche avant d’évaluer la condition. Bien les choisir décide à la fois de la précision et de la vitesse d’une règle. Ce guide couvre les trois types de motifs et leurs modificateurs.

Chaînes de texte

Une chaîne de texte s’écrit entre guillemets et est comparée octet par octet :

rule Text_Strings
{
    strings:
        $a = "Global\\MyMutex_2024"
        $b = "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0)"
        $c = "tab\there and a quote \" inside"
        $d = "\x4D\x5A with raw bytes"
    condition:
        any of them
}

Échappements acceptés : \", \\, \t, \n, \r et \xNN pour un octet quelconque. YARA-X refuse les séquences inconnues au lieu de les ignorer silencieusement — source d’erreurs fréquente lors du portage d’anciennes règles (voir YARA-X vs YARA).

Modificateurs de chaînes

Les modificateurs suivent la valeur et changent la façon dont elle est recherchée.

ModificateurEffetRemarques
asciiOctets tels quelsPar défaut en l’absence d’encodage
wideUTF-16LE (chaque caractère suivi de 00)Combiner avec ascii pour chercher les deux
nocaseInsensible à la casseMultiplie les variantes internes ; à éviter sur des chaînes courtes
fullwordDélimitée par des caractères non alphanumériques"evil" ne trouvera plus "devil"
xorAussi la chaîne XORée avec chaque clé d’un octet (1–255)xor(1-255) ou xor(0x20) pour restreindre
base64 / base64wideLa chaîne à l’intérieur de données base64Alphabet personnalisé possible ; incompatible avec nocase, xor, fullword
privateCorrespond mais n’apparaît pas dans les résultatsUtile pour des motifs auxiliaires
rule Modifier_Examples
{
    strings:
        $cfg = "ConfigBlock" wide ascii
        $cmd = "invoke-expression" nocase
        $key = "SuperSecretKey!" xor(1-255)
        $b64 = "powershell -nop" base64
        $word = "backdoor" fullword
    condition:
        2 of them
}

Réservez xor, base64 et nocase aux chaînes d’au moins six à huit caractères : chaque modificateur démultiplie le motif, et des variantes courtes correspondent à des données aléatoires.

Chaînes hexadécimales

Les chaînes hexadécimales décrivent des octets bruts entre accolades. C’est l’outil de choix pour les séquences de code, les en-têtes et les blocs de configuration binaires.

rule Hex_Syntax
{
    strings:
        $fixed = { 4D 5A 90 00 03 00 00 00 }
        $wild = { E8 ?? ?? ?? ?? 83 C4 04 }
        $nibble = { 6A 4? 68 00 30 00 00 }
        $jump = { 55 8B EC [2-6] 83 EC 20 }
        $alt = { 68 ( 00 10 | 00 20 ) 00 00 }
    condition:
        any of them
}
SyntaxeSignification
??N’importe quel octet
4? / ?AJoker sur un quartet
[4], [2-6], [8-]Saut d’exactement 4, de 2 à 6, ou d’au moins 8 octets
( AA | BB CC )Alternatives, éventuellement de longueurs différentes
~00Tout octet sauf 00 (YARA 4.3+ et YARA-X)

Les instructions avec adresses relatives (call, jmp, lea rip) doivent avoir leurs opérandes en joker, sinon la règle ne correspond qu’à une seule compilation. Gardez au moins quatre octets fixes consécutifs pour que YARA puisse extraire un bon atome.

Expressions régulières

Les regex s’écrivent entre barres obliques, avec une syntaxe proche de Perl : classes, quantificateurs, alternatives, groupes, ancres. Deux options peuvent suivre la barre finale : i (insensible à la casse) et s (le point accepte les retours à la ligne). Les modificateurs ascii, wide, nocase, fullword et private s’appliquent aussi.

rule Regex_Examples
{
    strings:
        $url = /https?:\/\/[a-z0-9\-.]{3,64}\.(top|xyz|click)\/[a-z0-9]{8}/ nocase
        $ip_port = /\b(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}:[0-9]{2,5}\b/
        $mutex = /Global\\[A-F0-9]{8}-[A-F0-9]{4}/
    condition:
        any of them
}

Pièges classiques :

  • Pas de partie littérale : /[a-z]{10}\.exe/ n’a que .exe comme ancrage ; /[a-z]{5,}/ n’en a aucun et doit être tentée presque partout.
  • .* en tête : les motifs ne sont déjà pas ancrés ; un .* initial ajoute seulement du travail.
  • Répétitions non bornées : préférez {1,64} à + ou * quand la longueur maximale est connue.
  • Échappements : la barre oblique s’écrit \/. YARA-X est plus strict que YARA 4 sur les échappements invalides.

Choisir le bon type

Vous cherchez…Utilisez
Une chaîne lisible et unique (mutex, user agent, chemin PDB)Texte, avec wide si elle peut être en UTF-16
Du code, un en-tête, une structure binaireHexadécimal avec jokers sur les adresses
Quelques variantes d’une séquence d’octetsAlternatives hexadécimales ( … | … )
Une partie variable ou structurée (URL, GUID)Regex avec un ancrage littéral
Une chaîne obfusquéexor ou base64 sur une chaîne assez longue

La performance en un paragraphe

YARA extrait de chaque motif une courte séquence fixe (un atome) et recherche tous les atomes en une seule passe ; le motif complet n’est vérifié que là où son atome apparaît. Les chaînes de moins de quatre octets, les motifs hexadécimaux faits de jokers, les octets fréquents comme 00 00 00 00 et les regex sans littéral produisent de mauvais atomes et ralentissent tout le jeu de règles. Le guide performance détaille le mécanisme, et le linter signale ces cas automatiquement.

Étape suivante : combiner vos motifs dans les conditions YARA.

FAQ

Que fait le modificateur wide ?
wide recherche la chaîne encodée en UTF-16LE, c’est-à-dire chaque caractère ASCII suivi d’un octet nul. Ajoutez ascii si la chaîne peut apparaître dans les deux encodages.
Comment accepter n’importe quel octet dans une chaîne hexadécimale ?
?? remplace un octet entier, un ? seul remplace un quartet (par exemple 4? ou ?A), et [n-m] saute entre n et m octets quelconques.
Quand utiliser une regex plutôt qu’une chaîne de texte ?
Seulement quand la partie variable ne peut pas s’exprimer en texte ou en hexadécimal. Les regex sont plus lentes et doivent contenir une partie littérale de quelques octets pour rester efficaces.