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.
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.
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.
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.
Ogni regola ha un nome, poi fino a tre sezioni tra parentesi graffe:
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 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à.
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:
$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:
$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:
$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.
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.
-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.
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.
Su Debian e Ubuntu:
sudo apt install yaraSu macOS con Homebrew:
brew install yaraSu 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:
yara --versionDovresti vedere un numero di versione. Questo articolo non ne fissa una, quindi usa l'ultima release che ti dà il tuo metodo di installazione.
mkdir yara-lab && cd yara-lab
printf 'LAB-TRAINING-MARKER v1\n' > match.txt
printf 'ordinary text file\n' > nomatch.txtEntrambi i file sono testo semplice scritto da te. Il primo dovrebbe corrispondere alla regola. Il secondo no.
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ù.
cat > lab.yar <<'EOF'
rule Lab_Training_Marker {
meta: description = "Matches the lab training marker"
strings: $m = "LAB-TRAINING-MARKER"
condition: $m
}
EOFLeggila 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.
yara -s lab.yar match.txtYARA 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.
yara lab.yar nomatch.txtOutput 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.
Una quasi corrispondenza è il file negativo più utile, perché fallisce per un solo motivo preciso.
printf 'LAB-TRAINING\n' > near.txt
yara lab.yar near.txtOutput atteso: niente. Il file ha l'inizio del marcatore ma non la stringa completa, quindi la stringa non viene trovata e la condizione è falsa.
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.
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:
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.
Questa regola sembra ragionevole:
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:
text, error, copyright o this program.{ 00 } o { 90 }.nocase su una parola comune.any of them su un elenco di stringhe che compaiono ciascuna in file ordinari.filesize < 10KB, che corrisponde alla maggior parte dei file piccoli./.+/.Modi per restringere una regola:
and o con 2 of (...), così nessuna stringa comune decide da sola il risultato.at o in quando sai dove dovrebbe comparire la stringa.uint16(0) == 0x5A4D.$m prima che YARA legga il file. Vedi il passo 3.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.
match.txt. Nel lavoro reale vengono da campioni che puoi detenere, secondo le regole di gestione della tua organizzazione.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.
pe, che permette a una regola di controllare le intestazioni e le sezioni di un eseguibile Windows invece dei byte grezzi.Malware e analisi forense
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.
Malware e analisi forense
Come gli hash identificano i file, perché SHA-256 ha sostituito MD5, come NSRL filtra il software noto e perché caricare un file su VirusTotal significa condividerlo.