Vai al contenuto
New

DeepSeek V4.1 Flash free for 7 days: 10M tokens a day after a top-up of $10 or more. Until Nov 30.

How it works

Scrivi una regola YARA su un file di test innocuo

Scrivi la tua prima regola YARA, falla corrispondere a un file di test innocuo e non a un altro, e capisci perché ogni regola ha bisogno di test positivi e negativi.

Base10 min di letturaDi NotHoly

Cosa fa una regola YARA

YARA è uno strumento di pattern matching. Scrivi una regola che descrive com'è fatto un file, e YARA elenca i file che corrispondono alla descrizione. Lo usano soprattutto gli analisti di malware. Scrivono regole per stringhe, strutture di file e sequenze di byte, poi scansionano cartelle, immagini disco e dump di memoria. Lo stesso meccanismo funziona su qualsiasi file tuo, per esempio un template che non deve mai contenere un marcatore interno o un file di configurazione che non deve mai contenere un token.

YARA non ha idea di cosa sia pericoloso. Trova quello che dice la regola. Una regola è un'affermazione sui byte, e vale quanto quell'affermazione.

Il progetto è ospitato su GitHub sotto VirusTotal. La guida ufficiale alla scrittura su Read the Docs è il riferimento per la sintassi. VirusTotal mantiene anche YARA-X, una riscrittura in Rust che conserva gran parte del linguaggio delle regole. I due si sovrappongono ma non sono identici, quindi leggi le note di compatibilità prima di passare una regola dall'uno all'altro.

Perché le regole contano

Un hash di file risponde a una domanda ristretta: questo file esatto è già noto? Cambia un byte e l'hash cambia. L'articolo sugli hash dei file ne parla in dettaglio. Una regola YARA fa una domanda più ampia: questo file contiene i pezzi che ci aspettiamo? Una regola può corrispondere a molti file che condividono una stringa, una struttura o uno schema di byte, anche quando non ce ne sono due con lo stesso hash.

La domanda più ampia è anche il punto in cui cominciano i guai. Un hash non corrisponde quasi mai a un file sbagliato. Una regola scritta male può corrispondere a mezzo file server. Quindi la sintassi conta meno del saper scrivere una regola che trova quello che vuoi e nient'altro, per poi dimostrarlo con file che controlli tu.

Com'è fatta una regola

Ogni regola ha un nome, poi fino a tre sezioni tra parentesi graffe:

yara
rule Example_Rule {
  meta:
    description = "What this rule is for"

  strings:
    $text = "some text"

  condition:
    $text
}

I nomi delle regole usano lettere, cifre e underscore, e non possono iniziare con una cifra. Il nome compare in ogni report di corrispondenza, quindi scegline uno che dica a chi legge di cosa si occupa la regola.

meta

Meta contiene coppie chiave-valore per le persone: una descrizione, un autore, una data, un link alla ricerca dietro la regola. YARA non usa mai meta per decidere una corrispondenza. Tienila comunque corretta, perché la prossima persona che apre il file se ne fiderà.

strings

Ogni stringa ha un identificatore che inizia con $. La condizione si riferisce alle stringhe con quell'identificatore. Ce ne sono di tre tipi.

Le stringhe di testo vanno tra virgolette doppie:

yara
$marker = "LAB-TRAINING-MARKER"

I modificatori cambiano il modo in cui il testo viene cercato. nocase ignora maiuscole e minuscole. wide trova il testo UTF-16LE, in cui ogni carattere ASCII è seguito da un byte zero, comune nei binari Windows. fullword richiede che la corrispondenza stia da sola, non dentro una parola più lunga.

Le stringhe esadecimali vanno tra parentesi graffe e trovano byte grezzi:

yara
$mz = { 4D 5A }

Quei due byte sono la firma MZ all'inizio di molti eseguibili Windows. ?? corrisponde a un qualsiasi byte singolo, [2-4] ammette un intervallo da due a quattro byte sconosciuti e ( 90 | 91 ) corrisponde a uno dei due byte.

Le espressioni regolari vanno tra barre:

yara
$version = /LAB-[A-Z]+ v[0-9]+/

Le regex sono il tipo più flessibile e il più facile da rendere troppo ampio. Usa una stringa di testo o esadecimale ogni volta che può esprimere lo schema.

condition

La condizione è un'espressione booleana. Combina stringhe e proprietà del file in una sola risposta: corrisponde o non corrisponde.

  • $marker è vero quando la stringa compare almeno una volta.
  • any of them e all of them coprono ogni stringa della regola. 2 of ($a, $b, $c) ne richiede due su tre.
  • $marker at 0 richiede la stringa al primo byte. $marker in (0..512) la richiede da qualche parte nei primi 512 byte.
  • #marker > 3 conta le occorrenze.
  • filesize < 2KB controlla la dimensione del file.
  • uint16(0) == 0x5A4D legge i primi due byte come intero little-endian e cerca la firma MZ.

Ogni regola ha bisogno di una condizione. Una regola con stringhe e senza una condizione sensata è rotta o inutile.

Come YARA legge una regola

  1. YARA analizza il file delle regole e lo compila. Un errore di sintassi ferma l'esecuzione prima che venga letto qualsiasi file.
  2. Per ogni file che scansiona, YARA cerca ogni stringa della sezione strings.
  3. Valuta la condizione usando i risultati del passo 2.
  4. Se la condizione è vera, il file corrisponde. Con -s, YARA stampa anche ogni stringa trovata, con l'offset in byte in cui si trova.

Le stringhe vengono prima e la condizione dopo. Una condizione come $a and $b è rigida: la regola può corrispondere solo se trova entrambe le stringhe.

Lab: un file positivo e un file negativo

L'output atteso qui sotto è descritto e non incollato, perché la formattazione esatta può cambiare tra le versioni di YARA. Confronta quello che vedi con queste descrizioni.

Lavora in una cartella vuota. Su Windows, esegui i comandi in Git Bash. L'heredoc del passo 3 non funziona allo stesso modo in PowerShell.

1. Installa yara

Su Debian e Ubuntu:

bash
sudo apt install yara

Su macOS con Homebrew:

bash
brew install yara

Su Windows, scarica lo zip della release da https://github.com/VirusTotal/yara/releases, estrailo e metti l'eseguibile nel PATH. Il file potrebbe chiamarsi yara64.exe. Rinominalo in yara.exe, o copialo con quel nome, così i comandi qui sotto funzionano come sono scritti.

Controlla l'installazione:

bash
yara --version

Dovresti vedere un numero di versione. Questo articolo non ne fissa una, quindi usa l'ultima release che ti dà il tuo metodo di installazione.

2. Crea un file positivo e un file negativo

bash
mkdir yara-lab && cd yara-lab
printf 'LAB-TRAINING-MARKER v1\n' > match.txt
printf 'ordinary text file\n' > nomatch.txt

Entrambi i file sono testo semplice scritto da te. Il primo dovrebbe corrispondere alla regola. Il secondo no.

3. Scrivi la regola

Le virgolette attorno a EOF contano. Senza, la shell sostituisce $m con una variabile vuota prima che YARA veda il file, e la regola non compila più.

bash
cat > lab.yar <<'EOF'
rule Lab_Training_Marker {
  meta: description = "Matches the lab training marker"
  strings: $m = "LAB-TRAINING-MARKER"
  condition: $m
}
EOF

Leggila in tre parti. Meta dice a cosa serve la regola. La stringa dice che il file deve contenere il testo del marcatore. La condizione dice che un file corrisponde quando quella stringa viene trovata almeno una volta.

4. Esegui il test positivo

bash
yara -s lab.yar match.txt

YARA dovrebbe stampare il nome della regola e il percorso del file. Grazie a -s, stampa anche una riga per la stringa trovata, con l'offset in byte e il testo. Il marcatore inizia al primo byte di match.txt, quindi l'offset dovrebbe essere 0x0.

5. Esegui il test negativo

bash
yara lab.yar nomatch.txt

Output atteso: niente. YARA stampa solo le corrispondenze, quindi il silenzio significa che il file non corrisponde.

Il silenzio ha valore solo se il test positivo ha funzionato. Esegui prima il passo 4. Se il passo 4 non ha stampato niente, la regola o l'installazione sono sbagliate, e il silenzio del passo 5 non ti dice nulla.

6. Aggiungi una quasi corrispondenza

Una quasi corrispondenza è il file negativo più utile, perché fallisce per un solo motivo preciso.

bash
printf 'LAB-TRAINING\n' > near.txt
yara lab.yar near.txt

Output atteso: niente. Il file ha l'inizio del marcatore ma non la stringa completa, quindi la stringa non viene trovata e la condizione è falsa.

7. Scansiona tutta la cartella

bash
yara -r lab.yar .

Il flag -r scansiona la cartella ricorsivamente. Aspettati match.txt nell'output. Probabilmente vedrai anche lab.yar, il file della regola. Il file della regola contiene il testo del marcatore, quindi la regola corrisponde al proprio sorgente. È un errore comune, e la prossima sezione ne parla. Tieni le regole in una cartella diversa dai dati che scansioni.

Rendi la regola più rigida

La regola del lab va bene per un marcatore di addestramento. Le regole reali di solito hanno bisogno di un vincolo che la sola stringa non dà. Supponi di volere solo i file piccoli che contengono il marcatore:

yara
rule Lab_Training_Marker_Small {
  strings: $m = "LAB-TRAINING-MARKER"
  condition: $m and filesize < 1KB
}

Provala allo stesso modo. match.txt dovrebbe corrispondere. nomatch.txt e near.txt no. Ai fini dei test, ogni modifica alle stringhe o alla condizione è una regola nuova, quindi ripeti la prova su entrambi i file di test.

Evita le regole che corrispondono a tutto

Questa regola sembra ragionevole:

yara
rule Too_Broad {
  strings: $a = "text"
  condition: $a
}

Corrisponderà a nomatch.txt, perché la frase ordinary text file contiene la parola text. Puoi verificarlo con il file negativo che hai già creato. Una regola che gli corrisponde ha fallito il proprio test.

Schemi che trovano troppo:

  • Stringhe corte, o parole comuni come text, error, copyright o this program.
  • Uno schema esadecimale di un byte o molto corto, come { 00 } o { 90 }.
  • nocase su una parola comune.
  • any of them su un elenco di stringhe che compaiono ciascuna in file ordinari.
  • Una condizione che è solo un controllo di dimensione, come filesize < 10KB, che corrisponde alla maggior parte dei file piccoli.
  • Una regex poco restrittiva, come /.+/.

Modi per restringere una regola:

  • Scegli stringhe più lunghe e distintive. Chiediti se la stringa comparirebbe in un documento che la tua organizzazione scrive ogni giorno. Se sì, scegline un'altra.
  • Richiedi più di una stringa con and o con 2 of (...), così nessuna stringa comune decide da sola il risultato.
  • Fissa la posizione della ricerca con at o in quando sai dove dovrebbe comparire la stringa.
  • Combina un test sul contenuto con un controllo su intestazione o dimensione, come uint16(0) == 0x5A4D.

Errori comuni

  1. Provare solo il file positivo. Una regola che corrisponde al file per cui l'hai costruita dimostra poco. Potrebbe corrispondere a tutto.
  2. Saltare le quasi corrispondenze. I file ordinari raramente falliscono in modo interessante. Un file che corrisponde quasi è il test che scopre una stringa troppo generica.
  3. Lasciare l'heredoc senza virgolette. La shell sostituisce $m prima che YARA legga il file. Vedi il passo 3.
  4. Scansionare la cartella che contiene le regole. Il file delle regole corrisponde al proprio testo.
  5. Fidarsi di meta. Una descrizione che dice "rileva X" non rileva X. Lo mostrano solo i file di test.
  6. Modificare senza riprovare. Qualsiasi modifica alle stringhe o alla condizione può cambiare il risultato. Riesegui entrambi i test dopo ogni modifica.

Test positivi e negativi prima del deploy di una regola

Questa è la regola che conta di più in questo articolo. Ogni regola YARA ha bisogno di entrambi i tipi di file di test prima che qualcuno ne faccia il deploy.

  • I file positivi sono quelli a cui la regola deve corrispondere. Nel lab è match.txt. Nel lavoro reale vengono da campioni che puoi detenere, secondo le regole di gestione della tua organizzazione.
  • I file negativi sono quelli a cui la regola non deve corrispondere. Includi documenti ordinari, i tipi di file comuni nel tuo ambiente, file puliti dai sistemi che pensi di scansionare e quasi corrispondenze come near.txt.

Una regola passa quando corrisponde a ogni file positivo e a nessun file negativo. Tieni entrambi gli insiemi accanto alla regola, sotto controllo di versione se il tuo team lo usa, e rieseguili dopo ogni modifica. Una regola che ha superato il test positivo ma non è mai stata provata sui negativi non è stata testata.

Per andare oltre

  • Leggi per intero la guida alla scrittura delle regole. Tratta moduli come pe, che permette a una regola di controllare le intestazioni e le sezioni di un eseguibile Windows invece dei byte grezzi.
  • Esegui la stessa regola del lab con YARA-X e confronta i risultati. La documentazione di YARA-X elenca cosa è compatibile e cosa no.
  • Costruisci un corpus pulito: una cartella di file ordinari da macchine che controlli. Ogni nuova regola deve superarlo prima di essere usata altrove.
  • Leggi poi l'articolo sul SIEM. Tratta l'altro lato del rilevamento: regole che girano sui log invece che sui file.

Fonti

Fonti

  1. YARA: Writing rules
  2. VirusTotal/yara on GitHub
  3. YARA-X documentation (VirusTotal)

Altro su Malware e analisi forense

Malware e analisi forense

Perché usare NotHoly per l'analisi del malware

Triage statico in un sandbox che non esegue mai il campione, e un modello che lo spiega e lo mappa su ATT&CK. La detonazione resta nel tuo laboratorio.

Intermedio3 min di lettura