
Fuzzer per driver del kernel Linux
Questo repository contiene tutti i sorgenti (inclusi gli script di configurazione) necessari per mettere in funzione difuze.
Ubuntu >= 14.04.5 LTS
Fare riferimento al readme
Come spiegato nel nostro articolo, ci sono due componenti principali di difuze: Interface Recovery e Fuzzing Engine
Il meccanismo di recupero dell'interfaccia si basa su passi di analisi LLVM. Ogni fase del recupero dell'interfaccia è scritta come passi individuali. Segui le istruzioni seguenti per mettere in funzione il Recupero dell'Interfaccia.
Questo passaggio si occupa di installare LLVM e c2xml:
Prima, assicurati di avere libxml (richiesto per c2xml):
sudo apt-get install libxml2-dev
sudo pip install lxml
Successivamente, abbiamo creato un singolo script che scarica e compila tutti gli strumenti necessari.
cd helper_scripts
python setup_difuze.py --help
usage: setup_difuze.py [-h] [-b TARGET_BRANCH] [-o OUTPUT_FOLDER]
optional arguments:
-h, --help mostra questo messaggio di aiuto ed esci
-b TARGET_BRANCH Branch (cioè versione) di LLVM da configurare. Default: release_38 ad esempio release_38
-o OUTPUT_FOLDER Cartella dove tutto deve essere configurato.
Esempio:
python setup_difuze.py -o difuze_deps
Per completare la configurazione devi anche modificare la variabile d'ambiente PATH locale. Lo script di configurazione ti darà le modifiche esatte da fare.
Questo dipende dal completamento con successo della Configurazione. Abbiamo un singolo script che compila tutto, prego.
cd InterfaceHandlers
./build.sh
Questo dipende dal completamento con successo della Compilazione. Per eseguire i componenti di Recupero dell'Interfaccia sui driver del kernel, dobbiamo prima i driver in bitcode LLVM.
Prima, abbiamo bisogno di un kernel compilabile. Significa che dovresti essere in grado di compilare il kernel usando la normale configurazione di compilazione, cioè make.
Prima catturiamo l'output del comando make, da questo output estraiamo il comando di compilazione esatto.
makebear make <all the options to make>
Esempio: bear make -j8Questo genererà un file compile_commands.json nella directory corrente.
Basta passare V=1 e reindirizzare l'output al file.
Esempio:
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1
NOTA: NON USARE PROCESSI MULTIPLI cioè -j. Eseguire in modalità multi-processo rovinerà il file di output poiché più processi cercano di scrivere sul file di output.
Tutto qui. Successivamente, nel passaggio seguente il nostro script prende il makeout.txt generato ed esegue il Recupero dell'Interfaccia su tutti i driver riconosciuti.
Tutti i vari passaggi del Recupero dell'Interfaccia sono racchiusi in un unico script helper_scripts/run_all.py
Come eseguire:
cd helper_scripts
python run_all.py --help
usage: run_all.py [-h] [-l LLVM_BC_OUT] [-a CHIPSET_NUM] [-m MAKEOUT]
[-c COMPJSON] [-g COMPILER_NAME] [-n ARCH_NUM] [-o OUT]
[-k KERNEL_SRC_DIR] [-isclang] [-clangp CLANG_PATH]
[-llvmlinkp LLVMLINK_PATH] [-skb] [-skl] [-skp] [-skP]
[-ske] [-skI] [-ski] [-skv] [-skd] [-f IOCTL_FINDER_OUT]
optional arguments:
-h, --help mostra questo messaggio di aiuto ed esci
-l LLVM_BC_OUT Directory di destinazione dove devono essere memorizzati tutti i file bitcode generati.
-a CHIPSET_NUM Numero del chipset. I numeri validi sono: 1(mediatek)|2(qualcomm)|3(huawei)|4(samsung)
-m MAKEOUT Percorso del file makeout.txt.
-c COMPJSON Percorso del file compile_commands.json generato da Bear.
-g COMPILER_NAME Nome del compilatore usato in makeout.txt, necessario per filtrare i comandi di compilazione. Es: aarch64-linux-android-gcc
-n ARCH_NUM Architettura di destinazione, 32 bit (1) o 64 bit (2).
-o OUT Percorso della cartella out. Questa è la cartella che potrebbe essere usata come directory di output durante la compilazione di alcuni kernel.
-k KERNEL_SRC_DIR Directory base dei sorgenti del kernel.
-isclang flag per indicare che clang è stato usato per compilare il kernel
-clangp CLANG_PATH Percorso assoluto del binario clang (se non fornito, verrà usato quello disponibile nel PATH)
-llvmlinkp LLVMLINK_PATH Percorso assoluto del binario llvm-link (se non fornito, verrà usato quello disponibile nel PATH)
-skb Salta la compilazione LLVM (default: non saltato).
-skl Salta Dr Linker (default: non saltato).
-skp Salta il parsing degli header (default: non saltato).
-skP Salta la generazione dei file preprocessati (default: non saltato).
-ske Salta l'identificazione dei punti di ingresso (default: non saltato).
-skI Salta la generazione degli include (default: non saltato).
-ski Salta l'esecuzione di IoctlCmdParser (default: non saltato).
-skv Salta l'elaborazione degli ioctl V4L2 (default: non saltato).
-skd Salta il finder del nome del dispositivo (default: non saltato).
-f IOCTL_FINDER_OUT Percorso della cartella di output dove deve essere memorizzato l'output dell'ioctl command finder.
Lo script compila, collega ed esegue il Recupero dell'Interfaccia su tutti i driver riconosciuti, quindi potrebbe richiedere tempo considerevole (45 min-90 min).
Lo script sopra esegue i seguenti compiti in modalità multiprocessore per utilizzare tutti i core della CPU:
Tutti i file bitcode generati verranno posizionati nella cartella fornita all'argomento -l.
Questo passaggio richiede tempo considerevole, a seconda del numero di core che hai.
Quindi, se hai già eseguito questo passaggio, puoi saltarlo passando -skb.
Questo esegue il collegamento, passa attraverso tutti i file bitcode e identifica i file bitcode correlati che devono essere collegati e li collega (usando llvm-link) in un file bitcode consolidato (che verrà memorizzato accanto al file bitcode corrispondente).
Simile al passaggio precedente, puoi saltare questo passaggio passando -skl.
Questo passaggio cerca le dichiarazioni dei punti di ingresso nei file header e memorizza la loro configurazione nel file: hdr_file_config.txt sotto la directory di compilazione LLVM.
Per saltare: -skp
Questo passaggio identifica tutti i punti di ingresso in tutti i file bitcode consolidati dei driver.
L'output verrà memorizzato nel file: entry_point_out.txt sotto la directory di compilazione LLVM.