
AFL/QEMU-Fuzzing mit Vollsystem-Emulation.
Neu: Für alle, die mit TriforceAFL und TLSF herumspielen möchten, hat Richard Johnson ein Dockerfile erstellt, das beides installiert (und sogar einen Linux-Kernel für euch baut). Es ist hier verfügbar https://hub.docker.com/r/moflow/afl-triforce/tags/.
Ebenfalls neu: afl-tmin funktioniert jetzt mit dem Forkserver!
https://github.com/nccgroup/TriforceAFL Jesse Hertz [email protected] Tim Newsham [email protected]
Dies ist eine gepatchte Version von AFL, die Full-System-Fuzzing mit QEMU unterstützt. Das enthaltene QEMU wurde aktualisiert, um die Verfolgung von Verzweigungen zu ermöglichen, wenn ein Systememulator für x86_64 ausgeführt wird. Es wurden zusätzliche Anweisungen hinzugefügt, um AFLs Forkserver zu starten, Fuzz-Einstellungen vorzunehmen und den Beginn und das Ende von Testfällen zu markieren.
Hinweis: Nicht alle AFL-Werkzeuge wurden mit den neuen Änderungen getestet. Diese Werkzeuge wurden etwas getestet:
Zum Erstellen:
make
So erhaltet ihr eine Coverage-Map:
echo hello > /tmp/hello
./afl-showmap -o coverage.txt -QQ --
./afl-qemu-system-trace -kernel ../bzImage
-initrd ../initramfs.cpio.gz -m 1G -nographic
-append "console=ttyS0" -aflFile /tmp/hello
cat coverage.txt
So fuzzt ihr:
egrep ' (panic|log_store)$' ../mykern/kallsyms ffffffff8108e570 t log_store ffffffff8181064b T panic
mkdir inputs
echo hello > inputs/hello
./afl-fuzz -i inputs -o outputs -QQ --
afl-qemu-system-trace -kernel bzImage -initrd root.cpio.gz
-m 1G -nographic -append "console=ttyS0"
-aflPanicAddr ffffffff8181064b -aflDmesgAddr ffffffff8108e570
-aflFile @@
(Hinweis: Anders als bei Verwendung der Option „-Q" müsst ihr bei Verwendung der Option „-QQ" die vollständige Befehlszeile für afl-qemu-system-trace angeben).
Weitere Einzelheiten zur Verwendung dieser modifizierten Version von AFL findest du in unserem Linux-Syscall-Fuzzer unter https://github.com/nccgroup/TriforceLinuxSyscallFuzzer.
Neue AFL-Flags: -QQ - QEMU in Vollsystem-Emulation anstelle des Benutzermodus (-Q) verwenden
Neue QEMU-Flags: -aflFile - Der Name der Datei, die die Fuzzer-Eingaben enthält -aflPanicAddr - Eine Adresse einer Kernel-Panic-Adresse zur Panikerkennung -aflDmesgAddr - Linux-Kernel-Adresse der dmesg-Logging-Funktion zur Erkennung von Logging und zum Abfangen von Logmeldungen
Neue QEMU-Anweisungen: 0f 24 - aflCall edi=1 startForkserver(esi=enableTicks) Startet den Fork-Server von AFL. Ab diesem Punkt läuft jeder Test in einem separaten, gegabelten Kindprozess. Wenn enableTicks ungleich Null ist, aktiviert QEMU den Timer der CPUs nach dem Forken eines Kindprozesses wieder; ansonsten wird er nicht aktiviert. edi=2 getWork(esi=ptr, edx=sz) Füllt ptr[0..sz] mit dem nächsten Eingabe-Testfall. Gibt die tatsächlich gefüllte Größe zurück (<= sz). edi=3 startWork(esi=ptr) Weist AFL an, mit dem Tracing zu beginnen. Das Argument zeigt auf einen Puffer mit zwei Quadwords, die die Start- und Endadresse des zu verfolgenden Codes angeben. Anweisungen außerhalb dieses Bereichs werden nicht verfolgt. edi=4 doneWork(esi=exitCode) Teilt AFL mit, dass der Testfall abgeschlossen ist. Wenn eine Panik erkannt wird, stoppt AFL den Testfall sofort. Andernfalls läuft er, bis doneWork aufgerufen wird. Der angegebene exitCode wird an AFL zurückgegeben. (Der Code kann – tut es derzeit aber nicht – den Wert 64 per OR in alle Exit-Codes einbeziehen, wenn während des Testfalls dmesg-Logs erkannt wurden.)
Neuer QEMU-Blocktreiber: -drive filename=privmem: Dieser Blocktreiber hält das Abbild des Laufwerks im Copy-on-Write-Speicher, sodass Änderungen nie auf die Festplatte geschrieben werden. Änderungen, die von einem Testfall vorgenommen werden, sind von anderen Testfällen isoliert.
Geschrieben und gepflegt von Michal Zalewski [email protected]
Copyright 2013, 2014, 2015, 2016 Google Inc. All rights reserved. Veröffentlicht unter den Bedingungen der Apache License, Version 2.0.
Für neue Versionen und weitere Informationen siehe: http://lcamtuf.coredump.cx/afl/
Um sich mit anderen Benutzern auszutauschen oder über wichtige neue Funktionen informiert zu werden, sendet eine E-Mail an [email protected].
** Siehe QuickStartGuide.txt, wenn du keine Zeit hast, diese Datei zu lesen. **
Fuzzing ist eine der leistungsfähigsten und bewährtesten Strategien zur Identifizierung von Sicherheitsproblemen in realer Software; es ist verantwortlich für die überwiegende Mehrheit der bislang gefundenen Remote-Codeausführungs- und Privilege-Escalation-Fehler in sicherheitskritischer Software.
Leider ist Fuzzing auch relativ oberflächlich; blinde, zufällige Mutationen machen es sehr unwahrscheinlich, dass bestimmte Codepfade im getesteten Code erreicht werden, wodurch einige Schwachstellen für diese Technik unerreichbar bleiben.
Es gab zahlreiche Versuche, dieses Problem zu lösen. Einer der frühen Ansätze – von Tavis Ormandy entwickelt – ist die Korpus-Destillation. Die Methode verlässt sich auf Coverage-Signale, um eine Teilmenge interessanter Seeds aus einem riesigen, qualitativ hochwertigen Korpus von Kandidatendateien auszuwählen und diese dann mit traditionellen Mitteln zu fuzzen. Dieser Ansatz funktioniert außergewöhnlich gut, erfordert jedoch, dass ein solcher Korpus leicht verfügbar ist. Darüber hinaus liefern Block-Coverage-Messungen nur ein sehr vereinfachtes Verständnis des Programmzustands und sind auf lange Sicht weniger nützlich, um die Fuzzing-Bemühungen zu leiten.
Andere, ausgefeiltere Forschungsarbeiten konzentrierten sich auf Techniken wie Programmflussanalyse („konkolische Ausführung"), symbolische Ausführung oder statische Analyse. Alle diese Methoden sind in experimentellen Umgebungen äußerst vielversprechend, leiden in der praktischen Anwendung jedoch häufig unter Zuverlässigkeits- und Leistungsproblemen – und bieten derzeit keine brauchbare Alternative zu „dummen" Fuzzing-Techniken.
American Fuzzy Lop ist ein Brute-Force-Fuzzer, gekoppelt mit einem überaus einfachen, aber felsenfesten, instrumentierungsgesteuerten genetischen Algorithmus. Er verwendet eine modifizierte Form der Kantenabdeckung, um mühelos subtile, lokale Änderungen im Programmfluss zu erkennen.
Vereinfacht ausgedrückt lässt sich der Gesamtalgorithmus wie folgt zusammenfassen:
Lade die vom Benutzer bereitgestellten anfänglichen Testfälle in die Warteschlange,
Nimm die nächste Eingabedatei aus der Warteschlange,
Versuche, den Testfall auf die kleinste Größe zu reduzieren, die das gemessene Verhalten des Programms nicht verändert,
Mutiere die Datei wiederholt mit einer ausgewogenen und gut recherchierten Auswahl traditioneller Fuzzing-Strategien,
Wenn eine der erzeugten Mutationen zu einem neuen, von der Instrumentierung aufgezeichneten Zustandsübergang geführt hat, füge die mutierte Ausgabe als neuen Eintrag zur Warteschlange hinzu.
Weiter mit 2.