ssdeep: il fuzzy hashing spiegato

Fra l'hash crittografico, che grida «diverso!» per un solo bit, e l'hash percettivo, che guarda le immagini con gli occhi socchiusi, c'è una terza famiglia: il fuzzy hashing. Risponde a una domanda che le altre due non sanno formulare: «quanto si assomigliano questi due file, come sequenze di byte?»

Il problema che risolve

Hai due documenti Word. Uno è la bozza, l'altro la versione firmata, con tre righe cambiate su ottocento. SHA-256 ti dice che sono file diversi — vero e inutile. Un hash percettivo non si applica: non sono immagini.

Hai due varianti dello stesso malware, ricompilate con un nome di funzione diverso. Stessi byte al 95%. SHA-256 non li mette in relazione, e ogni catalogo basato su impronte esatte li considera due minacce scollegate.

Qui serve un'impronta che cambi proporzionalmente a quanto cambia il contenuto binario. È esattamente ciò che fa ssdeep, l'implementazione più diffusa di una tecnica chiamata CTPHcontext triggered piecewise hashing, hashing a pezzi innescato dal contesto.

Come funziona: tagliare dove lo dice il contenuto

L'intuizione è elegante, e sta tutta nel modo di tagliare il file a fette.

Se lo tagliassi ogni 4096 byte, inserire un solo carattere all'inizio sposterebbe di un byte tutti i confini successivi: ogni fetta cambierebbe, e l'impronta sarebbe irriconoscibile. È il problema dell'allineamento, e affonda l'idea prima ancora di cominciare.

CTPH taglia in modo diverso. Fa scorrere sul file una finestra di pochi byte e calcola su di essa un rolling hash, un valore che si aggiorna a costo costante mentre la finestra avanza. Quando quel valore cade su un pattern prestabilito — un «innesco» — il file viene tagliato lì. Il confine, cioè, non dipende dalla posizione, ma dal contenuto locale.

Inserisci un carattere all'inizio: il primo blocco cambia, il suo innesco si sposta, ma tutti gli inneschi successivi ricompaiono esattamente dove erano, perché il contenuto che li provoca non è cambiato. I blocchi dal secondo in poi sono identici.

TAGLIO A LUNGHEZZA FISSA — un byte in più e crolla tutto blocco 1blocco 2blocco 3blocco 4 1'2'3'4' Un byte inserito in testa sposta ogni confine: tutti i blocchi cambiano, l'impronta è irriconoscibile. TAGLIO INNESCATO DAL CONTENUTO (CTPH) — i confini restano blocco 1blocco 2blocco 3blocco 4 innescoinnescoinnesco 1' diverso2 identico 3 identico4 identico Il confine dipende dal contenuto locale, non dalla posizione: cambia un blocco solo. Tre quarti dell'impronta coincidono. Schema concettuale: ssdeep concatena un carattere per blocco, ottenendo due stringhe confrontabili con una distanza di edit.
La finestra scorrevole cerca un pattern nei byte. Dove lo trova, taglia. È per questo che un'inserzione non trascina con sé tutti i confini successivi.

Da ogni blocco ssdeep ricava un solo carattere e li concatena. Il risultato è una stringa breve, che ha un aspetto simile a questo:

3072:aBcDeF1gH2iJkL3mN4:aBcD1gH2iJ3mN4

La prima parte è la dimensione del blocco, che ssdeep sceglie in funzione della lunghezza del file. Poi ci sono due impronte, calcolate con dimensione di blocco b e 2b: servono a confrontare file di taglia diversa senza che la scelta del blocco falsi il risultato.

Due stringhe così si confrontano con una distanza di edit — quante inserzioni, cancellazioni e sostituzioni servono per trasformare l'una nell'altra — normalizzata in un punteggio da 0 a 100.

Che cosa fa Probatio, e cosa non fa

Va detto con precisione, perché è il punto in cui la letteratura su ssdeep e questo software divergono.

Probatio calcola l'impronta ssdeep di un file durante l'analisi file, e la mostra insieme a entropia, magic bytes, stringhe, sezioni degli eseguibili e YARA. È un dato che puoi copiare, annotare in relazione, interrogare su servizi esterni.

Probatio non confronta due impronte ssdeep fra loro. Non esiste, oggi, un punteggio di similarità ssdeep nell'interfaccia. Il confronto lo fai tu, con lo strumento che preferisci.

E non implementa TLSH, l'altro fuzzy hash oggi molto usato in ambito antimalware. Se leggi una comparativa che lo attribuisce a Probatio, non viene da qui.

Tre impronte, tre domande

SHA-256 «sono lo stesso file?» byte identici · sì o no resiste a un avversario sigilla la prova ssdeep «quanti byte condividono?» byte simili · punteggio 0-100 non resiste a un avversario raggruppa le varianti pHash «sembrano uguali?» aspetto simile · distanza in bit solo immagini ritrova la foto Un file .docx modificato: SHA-256 dice «diverso», ssdeep dice «97», pHash non si applica. Una foto ricompressa: SHA-256 dice «diverso», ssdeep dice «0», pHash dice «96,9%». Nessuna delle tre è sostituibile con le altre due.
Il secondo esempio spiega l'equivoco più comune: ssdeep su una foto ricompressa dà zero, perché la compressione JPEG riscrive i byte da capo. Il fuzzy hashing non è un hash percettivo.

I limiti, che sono seri

  • Non è crittografico. Chi conosce l'algoritmo può costruire due file con impronte ssdeep quasi identiche e contenuti diversissimi. Un punteggio alto non prova nulla contro un avversario intenzionale.
  • Soffre la compressione. Due archivi ZIP che contengono lo stesso documento con una modifica minima hanno ssdeep scorrelati: la compressione riscrive tutto. Vale per JPEG, PDF ottimizzati, eseguibili compressi con UPX.
  • Il punteggio non è una probabilità. «72» non significa che i file sono uguali al 72%. È un indice di quanti frammenti condividono, ed è sensibile alla dimensione del blocco.
  • Non dice dove. Un punteggio alto non ti indica quali parti del file coincidono. Per quello serve un confronto binario, che in Probatio è il modulo di diff.

Quando usarlo, in pratica

  1. Per raggruppare, non per concludere. Su un volume sequestrato con diecimila documenti, ssdeep individua i quasi-duplicati e riduce il lavoro. Poi si guardano.
  2. Su formati non compressi. Testo, log, dump di memoria, eseguibili non impacchettati: qui il fuzzy hashing rende. Su un PDF ottimizzato, molto meno.
  3. Come indizio, mai come sigillo. In relazione l'ssdeep si annota accanto a SHA-256, non al suo posto.
  4. Insieme al diff binario. ssdeep dice «questi due si assomigliano»; il diff dice «ecco esattamente dove differiscono». La seconda frase è quella che finisce in perizia.

Il fuzzy hashing è uno strumento da investigazione, non da certificazione. Serve a decidere cosa aprire per primo — che, quando i file sono decine di migliaia, è già moltissimo.