
Ein Linux-Systemaufruf-Fuzzer mit TriforceAFL
Neu: Für alle, die mit TriforceAFL und TLSF herumspielen möchten, hat Richard Johnson ein Dockerfile erstellt, das beide installiert (und sogar einen Linux-Kernel für euch baut). Es ist hier verfügbar https://hub.docker.com/r/moflow/afl-triforce/tags/.
Dies ist eine Sammlung von Dateien, die verwendet werden, um
Systemaufruf-Fuzzing von Linux-x86_64-Kerneln mit AFL und QEMU durchzuführen.
Um es zu verwenden, benötigt ihr TriforceAFL von https://github.com/nccgroup/TriforceAFL
und ein Kernel-Image zum Fuzzing. Die Skripte gehen davon aus, dass TriforceAFL
in $TAFL oder ../TriforceAFL/ zu finden ist (Hinweis: Das Erstellen von testAfl erfordert,
dass ../TriforceAFL/config.h existiert).
Zum Erstellen:
make
Zum Ausführen installiert zuerst einen Kernel in ./kern/bzImage und extrahiert
/proc/kallsyms
in ./kern/kallsyms. Setzt die Umgebungsvariable K=kern, um auf euren
Kernel zu verweisen. Führt dann Folgendes aus:
make inputs
./runFuzz -M M0
Beachtet, dass das runFuzz-Skript einen Master- oder Slave-Namen erwartet, da
es immer im Master/Slave-Modus läuft. Weitere Verwendungshinweise findet ihr im
runFuzz-Skript.
Beachtet außerdem, dass dadurch nur eine kleine Menge an Beispieleingaben erstellt wird. Um
eine große Anzahl wichtiger Systemaufrufe zu testen, solltet ihr wahrscheinlich
ein Beispiel für jeden Systemaufruf erzeugen, oder zumindest ein Beispiel
für jede "Form" von Systemaufruf. Diese sollten in inputs/ abgelegt werden.
Siehe gen2.py für ein Beispiel.
Zum Reproduzieren von Testfällen (wie Abstürzen) führt ihr Folgendes aus:
./runTest inputs/ex1
./runTest outputs/crashes/id*
Ihr könnt den Treiber auch außerhalb der emulierten Umgebung
mit der Option -t, mit ausführlicher Protokollierung mit -vv
und ohne die Systemaufrufe tatsächlich auszuführen mit -x ausführen:
./driver -tvvx < inputs/ex1
strace ./driver -t < inputs/ex1
Es ist manchmal nützlich, den Kernel zu booten und Tests interaktiv auszuführen. Bearbeitet dazu die rootTemplate-Dateien nach Bedarf (zum Beispiel, um weitere Testwerkzeuge zum Root-Dateisystem hinzuzufügen), und führt dann Folgendes aus:
./runCmd
Andere Befehle als die Shell können aufgerufen werden, indem sie
als Befehlszeilenargumente an runCmd übergeben werden.
Hinweis: Wenn ihr mit der Shell fertig seid, verwendet ^A-c, um die QEMU-Eingabeaufforderung zu erhalten
und gebt quit ein.
Das Debugging ist am einfachsten mit einem Kernel, der mit aktivierten Debugging-Symbolen gebaut wurde.
Verwendet runTest, um den Kernel zu starten und einen Test durch den
Treiber auszuführen, oder verwendet runCmd, um einen Testfall manuell aus der Shell auszuführen.
Bearbeitet euer Run-Skript, um die Option -s beim Starten von afl-qemu-system-trace einzufügen.
Dies aktiviert gdb-Unterstützung auf TCP-Port 1234. Verwendet getvmlinux, um das
vmlinux-Kernel-Image aus eurem bzImage-Kernel zu extrahieren, und führt gdb aus, nachdem
das System gebootet ist:
cp kern/bzImage .
./getvmlinux
gdb ./vmlinux
target remote :1234
break somefunction
continue
Ihr könnt den Debugger anhängen, nachdem runTest einen Absturz verursacht hat,
oder bevor ihr den Fehler in runCmd manuell auslöst.
Beachtet, dass Linux-Quellen standardmäßig mit aktivierter Optimierung
kompiliert werden. Dies kann das Debugging verwirrend und schwierig machen.
Ihr könnt die Optimierung dateiweise deaktivieren,
indem ihr die Linux-Makefile für das Unterverzeichnis, in dem sich eine Datei befindet, bearbeitet
und CFLAGS_name.o = -O0 zur Makefile hinzufügt. Zum
Beispiel deaktiviert das Bearbeiten von kernel/Makefile und das Hinzufügen von CFLAGS_sys_ni.o = -O0
die Optimierung beim Erstellen von kernel/sys_ni.o.
Das Shell-Skript getSyms verwendet runCmd, um cat /proc/kallsyms auszuführen
und es in eine lokale Datei namens kallsyms zu extrahieren. Dies wird typischerweise
verwendet, um euren Kernel für das Fuzzing vorzubereiten:
K=yourKernDir ./getSyms aus, um kallsyms zu erhaltenmv kallsyms yourKernDir aus, um es zu installierenHinweis: Beim Fuzzing eines Linux-2.-Kernels müsst ihr den
CPU-Timer aktivieren. Wenn der Timer nicht aktiviert ist, scheinen Panik- und Protokoll-
erkennung nicht ordnungsgemäß zu funktionieren, und Paniken führen
zu Hängern. Um den Timer zu aktivieren, ruft startForkserver(1) in
driver.c auf, anstatt startForkserver(0). Dieses Problem
scheint bei Linux-3.- und Linux-4.*-Kerneln nicht aufzutreten.