Esistono sostanzialmente due tecniche per l’analisi dei malware:
- analisi statica: viene effettuata senza eseguire il malware ma studiando il codice, qualora non sia offuscato. A seconda della complessità delle tecniche usate e del livello di approfondimento, distingueremo tra:
- analisi statica base: in questa fase l’esame viene condotto senza guardare il codice del malware: viene fatta la scansione con uno o più antivirus per vedere se il malware viene riconosciuto, viene utilizzato un servizio come VirusTotal, vengono estratte eventuali stringhe, si cerca di capire se il codice è offuscato o meno, si calcola l’hash (anche per verificare che i file che si stanno esaminando non vengano modificati durante l’analisi), si cerca di dedurre data e ora di compilazione e di installazione e si cerca di capire la struttura del file PE (Portable executable), per i sistemi Windows, che vedremo meglio più avanti;
- analisi statica avanzata: si utilizzano strumenti appositi di disassembling per capire la struttura di flusso e dati del programma, analizzare le chiamate a sistema/API.
- analisi dinamica: in questo caso il malware viene eseguito in un ambiente virtuale o in un sistema emulato allo scopo di monitorare il comportamento del malware e, in particolare le chiamate di sistema/API (in particolare file scritti e processi creati) e l’attività di rete. A seconda della complessità delle tecniche usate e del livello di approfondimento, distingueremo tra:
- analisi dinamica base: si esegue il malware in un ambiente sandbox e si monitorano processi, connessioni di rete, filesystem, voci di Registro ecc.;
- analisi dinamica avanzata: si sfruttano strumenti di debugging per l’esecuzione controllata riga per riga.
Il risultato di queste operazioni sarà un Malware Analysis Report. Un esempio può essere visualizzato qui.
Schema logico con le fasi principali di un’analisi dei malware che portano alla realizzazione di un Malware Analysis Report.
Le tecniche di analisi statica valutano il comportamento del codice di un programma senza eseguirlo. Il vantaggio di questo tipo di analisi è che così si può studiare l’intero flusso del programma, eccezioni comprese, mentre l’analisi dinamica (che vedremo in un successivo articolo) analizza solo un determinato cammino di esecuzione che potrebbe anche non essere rivelatore. Pensiamo ad esempio al caso di un malware costruito in modo da attivarsi a una determinata data o in presenza di certe condizioni al contorno, ad esempio su computer con una configurazione specifica. Ci sono malware che si attivano solo se contattati dal server dell’attaccante con opportuni comandi, oppure in grado di restare quiescenti se sono eseguiti in un ambiente virtuale. Il limite dell’analisi statica, d’altra parte, è che il codice non deve essere offuscato, problema questo che invece non impatta l’analisi dinamica.
Indice degli argomenti
L’analisi statica base dei malware: i passi da seguire
Il primo passo da compiere è quello di calcolare l’impronta (hash) dei file che si vogliono studiare. Questo per poter essere in grado di capire se questi dovessero cambiare durante l’analisi. Per questo, l’operazione andrà periodicamente ripetuta. Ci sono parecchi strumenti che possono essere utilizzati per fare questa operazione: md5deep (e hashdeep), md5sum, hex workshop, hashr e altri ancora.
Fatto questo, si sottopone il campione da analizzare a un antivirus (possibilmente più di uno). Il modo migliore è quello di fare l’upload su VirusTotal, che fornisce un servizio di scansione gratuito per usi non commerciali con più di 70 antivirus, servizi di URL/domain blacklisting e altri strumenti.
Questa operazione può essere svolta con varie modalità: via browser;
- con l’utility desktop VirusTotal Windows Uploade;
- via e-mail;
- tramite API con HTTP POST;
- con un’estensione browser (come VTzilla, per Firefox, VTchromizer per Chrome e VTexplorer per Internet Explorer);
- con un’app per Android.
Esiste anche una vivace community con cui interagire. Il file può essere inviato anche in formato criptato compresso in formato ZIP con password scelta tra infected, password, test, 1234, virustotal, virus, compressed qualora sia impossibile inviarlo in chiaro a causa delle restrizioni della propria rete.
L’output viene aggregato a partire dai risultati parziali ottenuti con ciascuno degli strumenti di analisi utilizzati.
Altri servizi simili a VirusTotal sono MetaDefender, VirScan, Hybrid Analysis e Jotti.
Ricercare le stringhe che identificano il malware
Il passo successivo consiste nel ricercare eventuali stringhe presenti all’interno del programma. Questa attività è molto importante perché potremmo trovare indirizzi IP, URL, e-mail, chiamate a dll o eseguibili esterni e così via. La limitazione è data dal fatto che queste stringhe potrebbero essere state messe apposta dall’attaccante per metterci fuori strada.
Più in generale, tutto il processo di analisi del malware dovrebbe darci tutta una serie di indizi che a un certo punto dovrebbero darci un quadro consistente. E’ bene, perciò, che ogni analista utilizzi più strumenti e metodologie perché ognuno di essi potrebbe farci scoprire cose diverse.
Gli strumenti da utilizzare in questa fase potrebbero essere: il comando strings su Linux/Unix o l’analogo su Windows, bintext, Hex Workshop o IDA Pro. Uno strumento più avanzato da usare nel caso le stringhe fossero offuscate è FLOSS.
Oltre alle stringhe, più in generale, converrà fare una ricerca anche delle altre risorse e cioè cursori, icone, bitmap, finestre di dialogo, menu, versioni del file e font. Una risorsa è costituita da dati non eseguibili che vengono distribuiti in modo logico con un’applicazione. Una risorsa può essere visualizzata in un’applicazione sotto forma di messaggi di errore o come parte dell’interfaccia utente. Le risorse possono contenere dati in diversi formati, tra cui stringhe, immagini e oggetti persistenti.
Una buona raccolta di strumenti per l’estrazione di risorse in file eseguibili e dll (ad esempio Resource Hacker) è visualizzabile qui.
Il passo successivo consiste nel cercare di capire se il codice del malware è offuscato no.
Analisi statica base dei malware: l’entropia di un file
Una utile grandezza che vale la pena calcolare e che dà indicazioni in tal senso è l’entropia.
Un indicatore importante per l’analista è l’entropia che, nel caso di un file, indica il livello di “casualità” cioè quanto disordinatamente sono disposti i byte al suo interno o, detta differentemente, la probabilità che un determinato valore si ripeta, conoscendo i valori precedenti.
Essa misura il livello di compressione o offuscamento del codice. Se un file non è compresso/offuscato allora avrà entropia bassa e questo significa che verosimilmente l’analisi statica sarà più appropriata. Se il file è compresso/offuscato allora la sua entropia è alta e quindi converrà passare direttamente all’analisi dinamica.
Ci sono vari modi per definire l’entropia. Se usiamo la formulazione di Shannon essa sarà sempre compresa tra 0 (massimo ordine, zero offuscamento/compressione) e 8 (completamente offuscato/compresso).
La formula di Shannon afferma che l’entropia è:
La formula di Shannon per il calcolo dell’entropia di un file.
dove pi è la probabilità dell’evento i.
Supponiamo di avere un file composto da 100 byte tutti di valore zero.
In questo caso:
p0=1 e p0log 1/p0 = 0.
D’altra parte:
p1=0 per cui p1log 1/p1 = 0,
per cui il valore della somma totale è 0 (=massimo ordine).
Supponiamo ora che il nostro file sia composto per metà da byte di valore 0 e per metà di 1.
In questo caso:
p0=p1=1/2 e la somma totale darà valore 1 (il logaritmo è in base 2).
Se adesso comprimiamo il file con Winrar e calcoliamo di nuovo l’entropia troveremo il valore 5,059246862.
Infine, se lo stesso file costituito per metà di 0 e per metà di 1 viene criptato con PGP, allora l’entropia sarà uguale a 7,8347915272.
L’altro aspetto interessante è che è possibile calcolare l’entropia del file per sezioni. Ci sono malware che non sono interamente criptati ma lo sono solo in certe parti come ad esempio quelle che contengono il payload. In questo modo, sarà possibile localizzare la sezione di maggior interesse.
L’entropia da sola non è un indicatore fantastico dato che esistono molti tipi di file già di suo altamente compressi (come i documenti Word, ad esempio) e quindi difficilmente distinguibili da un file criptato da un ransomware.
D’altra parte, molti tipi di dati hanno una struttura, con un header che include dei byte significativi (i cosiddetti “magic bytes”) che ci aiutano a identificare il file come, ad esempio, i valori “PK” per i file pkzip o “MZ” per un eseguibile PE32. L’utility di Linux “files” legge proprio questi valori per identificare il tipo di file. Di solito, la criptazione di un malware, oltre a essere molto spinta e quindi tendente a generare valori di entropia elevati, è completa per cui cancella questi magic bytes rendendo difficile l’identificazione del tipo di file.
Per calcolare l’entropia di un file si possono utilizzare programmi come Radare2, Binwalk (anche qui), entropie o Detect It Easy.
Portable Executable (PE) file: la firma dei file
A questo punto, è arrivato il momento di aprire il nostro campione di malware con un editor esadecimale, come WinHex o Hexdump. Ogni tipo di file ha una sua “firma” specifica per consentire al sistema operativo di essere identificato. Una lista completa si trova qui. In particolare, a noi interesseranno quei file i cui primi due byte, tradotti in caratteri ASCII, sono uguali a “MZ”. Questa è la firma caratteristica dei file di tipo PE (Portable Executable).
PE è il formato di file nativo Win32 da Windows NT 3.1 in poi. Tutti gli eseguibili (eccetto VxDs e 16-bit DLLs) usano il formato PE come ad esempio 32bit DLL, COM files, controlli OCX, Control Panel Applets (.CPL files) e eseguibili .NET.
Tutti i file eseguibili, sia UNIX che Windows, posseggono un header, cioè una sezione iniziale in cui viene specificata al sistema operativo la struttura del file stesso e, in particolare, l’indirizzo a cui inizia la porzione di codice eseguibile e le varie parti da cui è composto per poter essere caricato in memoria.
La struttura tipica dei file eseguibili (fonte).
Il DOS Header è la prima parte del file ed è grande 64 byte. È identificabile dal fatto che i primi due byte contengono i valori 4D e 5A (“MZ” in ASCII) dal nome di un noto architetto di MS-DOS, Mark Zbikowsky. L’ultima parte del DOS Header è una DWORD (4 bytes in un’architettura16-bit) che contiene l’indirizzo del PE Header. Quando il Windows Loader legge questo valore salta il DOS Stub, la sezione successiva che è richiesta per l’esecuzione in MS-DOS, per arrivare direttamente al PE Header.
Il DOS Stub contiene il programma da eseguire in DOS ed è grande 128 byte. Di default, contiene la stringa “This program cannot be run in DOS mode.”. Questo pezzo risale alle versioni di Windows più vecchie che erano fortemente interconnesse con DOS e serviva qualora un utente cercasse di eseguire in modalità DOS un programma pensato per Windows.
A seguire, troviamo il PE Header, denominato anche IMAGE_NT_HEADER, che contiene tre parti:
- .SIGNATURE inizia con una DWORD che contiene il valore 50h, 45h, 00, 00 (cioè “PE” seguito da due zeri). È semplicemente un segnaposto per indicare che l’header PE inizia qui;
- .FILEHEADER è grande 20 byte e contiene informazioni sulla struttura del file. Le più importanti sono:
- NUMBER OF SECTIONS è il numero di sezioni in cui è diviso il file. Se contiene il valore 04h, 00 significa che ha solo 4 sezioni;
- TIMEDATESTAMP rappresenta l’ora in cui il linker o il compilatore per un file OBJ lo ha prodotto;
- CHARACTERISTICS contiene un flag che indica se si tratta di una dll o di un eseguibile;
- .OPTIONALHEADER è grande 224 byte e contiene informazioni sulla struttura logica del file. Tra queste abbiamo:
- ADDRESSOFENTRYPOINT è l’indirizzo da cui inizia l’esecuzione del file;
- MAGEBASE è l’indirizzo di caricamento in memoria del file PE. Nella maggior parte dei casi è 400000h;
- SECTIONALIGNMENT è la dimensione del blocco base con cui vengono caricate le sezioni in memoria. Di solito è 4096 (1000h). Ogni sezione viene caricata in un multiplo di blocchi di dimensione pari a questo valore;
- FILEALIGNMENT è la dimensione del blocco base con cui vengono immagazzinate le sezioni in un file. Il valore di default è 512 bytes (200h);
- SIZE OF IMAGE è la dimensione dell’immagine del PE in memoria. E’ la somma degli header e di tutti i blocchi costituenti le sezioni. Gli ultimi 228 byes sono la DataDirectory, cioè un array di 16 strutture IMAGE_DATA_DIRECTORY, ciascuna delle quali si riferisce a strutture importanti nel file PE, come la Import table, l’Export table ecc. La Import table contiene la lista delle funzioni importate da librerie esterne. Per ciascuna libreria viene riportata la lista delle rispettive funzioni con gli indirizzi. La Export Table, invece, contiene la lista delle funzioni che sono rese disponibili all’esterno. Per ogni funzione viene riportato un insieme di metadati, tra cui nome e indirizzo. L’analisi di entrambe le tabelle è importante ma non esaustiva dal momento che potrebbero essere dichiarate, per confondere l’analista, anche funzioni che il malware potrebbe non utilizzare effettivamente.
La sezione SECTION TABLE contiene le informazioni sulle Sezioni presenti nel file PE, come i loro attributi e gli offset virtuali (da quali indirizzi in memoria iniziano). A ogni sezione corrisponde la struttura IMAGE_SECTION_HEADER di dimensione 40 byte, subito dopo l’header del file PE.
Dopo la SECTION TABLE, troviamo le sezioni vere e proprie. Tra queste:
.TEXT: in questa sezione, nota anche con il nome di CODE, contiene le istruzioni che la CPU eseguirà ed è qui che punterà l’Entry Point citato in precedenza;
.RDATA: contiene le informazioni di Import e Export ed altri dati read-only, come stringhe, letterali ecc. usati dal programma;
.DATA: contiene i dati globali, cioè quelli che possono essere acceduti da ogni punto del programma;
.RSRC: contiene le risorse, come icone, gruppi di cursori, menu ecc. usati dall’eseguibile. Questa sezione viene vista come un albero se si utilizzano editor di risorse come Resource Hacker o XN Resource Editor.
Per l’analisi dei file PE si possono usare PEFrame, MAnalyze, PE studio, PEV, Mastiff, PEID, Exeinfo PE, PEview, REMnux e altri ancora.