
Fuzzer für Linux-Kernel-Treiber
Dieses Repository enthält alle Quellen (einschließlich Setup-Skripte), die Sie benötigen, um difuze zum Laufen zu bringen.
Ubuntu >= 14.04.5 LTS
Siehe die Readme
Wie in unserem Paper erläutert, gibt es zwei Hauptkomponenten von difuze: Interface Recovery und Fuzzing Engine
Der Interface-Recovery-Mechanismus basiert auf LLVM-Analyse-Passes. Jeder Schritt der Interface-Recovery ist als einzelner Pass geschrieben. Befolgen Sie die folgenden Anweisungen, um Interface Recovery zum Laufen zu bringen.
Dieser Schritt kümmert sich um die Installation von LLVM und c2xml:
Stellen Sie zunächst sicher, dass Sie libxml haben (erforderlich für c2xml):
sudo apt-get install libxml2-dev
sudo pip install lxml
Als nächstes haben wir ein Skript erstellt, das alle erforderlichen Werkzeuge herunterlädt und compiliert.
cd helper_scripts
python setup_difuze.py --help
usage: setup_difuze.py [-h] [-b TARGET_BRANCH] [-o OUTPUT_FOLDER]
optional arguments:
-h, --help show this help message and exit
-b TARGET_BRANCH Branch (i.e. version) of the LLVM to setup. Default:
release_38 e.g., release_38
-o OUTPUT_FOLDER Folder where everything needs to be setup.
Beispiel:
python setup_difuze.py -o difuze_deps
Um die Einrichtung abzuschließen, müssen Sie auch Ihre lokale PATH-Umgebungsvariable anpassen. Das Setup-Skript gibt Ihnen die genauen Änderungen, die Sie vornehmen müssen.
Dies setzt den erfolgreichen Abschluss von Setup voraus. Wir haben ein Skript, das alles baut, bitte sehr.
cd InterfaceHandlers
./build.sh
Dies setzt den erfolgreichen Abschluss von Build voraus. Um die Interface-Recovery-Komponenten auf Kernel-Treibern auszuführen, müssen wir die Treiber zunächst in LLVM-Bitcode umwandeln.
Zuerst benötigen wir einen baubaren Kernel. Das bedeutet, Sie sollten den Kernel mit der normalen Build-Konfiguration compilieren können, d.h. make.
Zuerst erfassen wir die Ausgabe des make-Befehls; aus dieser Ausgabe extrahieren wir den genauen Compilierungsbefehl.
makebear make <all the options to make>
Beispiel: bear make -j8Dadurch wird eine Datei compile_commands.json im aktuellen Verzeichnis erstellt.
Übergeben Sie einfach V=1 und leiten Sie die Ausgabe in die Datei um.
Beispiel:
make V=1 O=out ARCH=arm64 > makeout.txt 2>&1
HINWEIS: VERWENDEN SIE KEINE MEHREREN PROZESSE, d.h. -j. Das Ausführen im Multiprozessmodus bringt die Ausgabedatei durcheinander, da mehrere Prozesse versuchen, in die Ausgabedatei zu schreiben.
Das war's. Im nächsten Schritt verwendet unser Skript die generierte makeout.txt und führt die Interface Recovery auf allen erkannten Treibern aus.
Alle verschiedenen Schritte der Interface Recovery sind in einem einzigen Skript helper_scripts/run_all.py gebündelt.
So führen Sie es aus:
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 show this help message and exit
-l LLVM_BC_OUT Destination directory where all the generated bitcode
files should be stored.
-a CHIPSET_NUM Chipset number. Valid chipset numbers are:
1(mediatek)|2(qualcomm)|3(huawei)|4(samsung)
-m MAKEOUT Path to the makeout.txt file.
-c COMPJSON Path to the compile_commands_json generated by Bear.
-g COMPILER_NAME Name of the compiler used in the makeout.txt, This is
needed to filter out compilation commands. Ex: aarch64
-linux-android-gcc
-n ARCH_NUM Destination architecture, 32 bit (1) or 64 bit (2).
-o OUT Path to the out folder. This is the folder, which
could be used as output directory during compiling
some kernels.
-k KERNEL_SRC_DIR Base directory of the kernel sources.
-isclang flag to indicate that clang was used to built the
kernel
-clangp CLANG_PATH Absolute path to the clang binary (if not provided,
the one available in the path will be used)
-llvmlinkp LLVMLINK_PATH
Absolute path to the llvm-link binary (if not
provided, the one available in the path will be used)
-skb Skip LLVM Build (default: not skipped).
-skl Skip Dr Linker (default: not skipped).
-skp Skip Parsing Headers (default: not skipped).
-skP Skip Generating Preprocessed files (default: not
skipped).
-ske Skip Entry point identification (default: not
skipped).
-skI Skip Generate Includes (default: not skipped).
-ski Skip IoctlCmdParser run (default: not skipped).
-skv Skip V4L2 ioctl processing (default: not skipped).
-skd Skip Device name finder (default: not skipped).
-f IOCTL_FINDER_OUT Path to the output folder where the ioctl command
finder output should be stored.
Das Skript baut, linkt und führt Interface Recovery auf allen erkannten Treibern aus, daher kann es beträchtliche Zeit (45 min - 90 min) in Anspruch nehmen.
Das obige Skript führt die folgenden Aufgaben im Multiprozessormodus aus, um alle CPU-Kerne zu nutzen:
Alle erzeugten Bitcode-Dateien werden in dem Ordner abgelegt, der dem Argument -l übergeben wurde.
Dieser Schritt dauert beträchtliche Zeit, abhängig von der Anzahl Ihrer Kerne.
Wenn Sie diesen Schritt bereits durchgeführt haben, können Sie ihn durch Übergabe von -skb überspringen.
Dies führt das Linking durch, durchläuft alle Bitcode-Dateien, identifiziert die zugehörigen, die gelinkt werden müssen, und linkt sie (mit llvm-link) zu einer konsolidierten Bitcode-Datei (die zusammen mit der entsprechenden Bitcode-Datei gespeichert wird).
Ähnlich wie beim obigen Schritt können Sie diesen Schritt durch Übergabe von -skl überspringen.
Dieser Schritt sucht nach den Entry-Point-Deklarationen in den Header-Dateien und speichert deren Konfiguration in der Datei: hdr_file_config.txt im LLVM-Build-Verzeichnis.
Zum Überspringen: -skp
Dieser Schritt identifiziert alle Entry Points in allen konsolidierten Treiber-Bitcode-Dateien.
Die Ausgabe wird in der Datei entry_point_out.txt im LLVM-Build-Verzeichnis gespeichert.