v1.4 Copyright (C) 2020 Andrea Fioraldi [email protected]
Veröffentlicht unter der Apache-Lizenz v2.0
Dieser experimentelle Fuzzer soll für API-In-Memory-Fuzzing verwendet werden.
Das Design ist stark inspiriert und basiert auf AFL/AFL++.
ATM, der Mutator, ist recht einfach, er besteht nur aus den Havoc- und Splice-Stufen der AFL.
Ich habe nur die Beispiele unter Tests/ getestet. Dies ist ein WIP-Projekt, aber es ist bekannt, dass es zumindest unter GNU/Linux x86_64 und Android x86_64 funktioniert.
Sie benötigen Frida >= 12.8.1, um dies auszuführen ( pip3 install -U frida
) und frida-tools, um das Harness zu kompilieren.
Die fuzz
-Bibliothek muss in ein benutzerdefiniertes Harness importiert und dann mit frida-compile
kompiliert werden, um den Agenten zu generieren, den frida-fuzzer
in die Ziel-App einfügt.
Der Großteil der Logik des Fuzzers liegt im Agenten.
Ein Kabelbaum hat das folgende Format:
var fuzz = require("./fuzz");var TARGET_MODULE = "test_linux64";var TARGET_FUNCTION = DebugSymbol.fromName("target_func").address;;var RET_TYPE = "void";var ARGS_TYPES = ['pointer', ' int'];var func_handle = new NativeFunction(TARGET_FUNCTION, RET_TYPE, ARGS_TYPES, { traps: 'all' });fuzz.target_module = TARGET_MODULE;var payload_mem = Memory.alloc(fuzz.config.MAX_FILE);fuzz.fuzzer_test_one_input = function (/* Uint8Array */ payload) { Memory.writeByteArray(payload_mem , Nutzlast, Nutzlastlänge); func_handle(payload_mem, payload.length);}
fuzz.fuzzer_test_one_input
ist obligatorisch. Wenn Sie fuzz.target_module
nicht angeben, wird der gesamte ausgeführte Code instrumentiert.
Sie können auch fuzz.manual_loop_start = true
setzen, um dem Fuzzer mitzuteilen, dass Sie fuzz.fuzzing_loop()
in einem Rückruf aufrufen und er es daher nicht für Sie aufrufen darf (z. B. um das Fuzzing zu starten, wenn in der Android-App auf eine Schaltfläche geklickt wird).
Der Rückruf fuzz.init_callback
kann so eingestellt werden, dass er Code ausführt, wenn der Fuzzer startbereit ist. Ein Beispiel finden Sie tests/test_java.js
.
fuzz.dictionary
ist ein klassisches Fuzzer-Wörterbuch, ein Array, in dem Sie Elemente hinzufügen können (akzeptierte Typen sind Array, ArrayBuffer, Uint8Array, String), die als zusätzliche Werte im Mutator verwendet werden. Ein Beispiel finden Sie tests/test_libxml2.js
.
frida-fuzzer
akzeptiert die folgenden Argumente:
-i ORDNER | Ordner mit anfänglichen Samen |
-o ORDNER | Ausgabeordner mit Zwischen-Seeds und Abstürzen |
-U | An USB anschließen |
-laichen | Spawnen und anhängen statt einfach anhängen |
-script-Skript | Skriptdateiname (Standard ist fuzzer-agent.js) |
Wenn Sie den Ausgabeordner nicht angeben, wird unter /tmp ein temporärer Ordner erstellt. Wenn Sie den Ordner mit dem Anfangs-Seed nicht angeben, wird ein uninformierter Seed 0000
als Start-Seed verwendet.
Wenn Sie eine lokale Anwendung fuzzen, möchten Sie möglicherweise system-config
vor frida-fuzzer
ausführen, um die Parameter Ihres Systems zu optimieren und die Dinge zu beschleunigen.
Wenn Sie ./frida-fuzzer -spawn ./tests/test_linux64
ausführen, wird auf Ihrem Terminal etwa der folgende Statusbildschirm angezeigt:
Sie können auch ganz einfach eine benutzerdefinierte Stufe in fuzz/fuzzer.js
hinzufügen und sie zur Stufenliste in fuzz/index.js
hinzufügen.
Um den Fuzzer anzupassen, bearbeiten Sie fuzz/config.js
. Die Variablen, die Sie möglicherweise ändern möchten, sind MAP_SIZE (Wenn der Code, den Sie fuzzen, klein ist, können Sie ihn reduzieren und etwas schneller werden), MAX_FILE (die maximale Größe der generierten Eingabe) und QUEUE_CACHE_MAX_SIZE (Erhöhen der Warteschlangen-Cache-Größe für mehr Geschwindigkeit, insbesondere auf Android).
Lassen Sie uns die native gemeinsam genutzte Bibliothek in der Beispiel-Android-App in tests
verzerren.
Stellen Sie sicher, dass Sie Root auf Ihrem virtuellen Gerät haben:
host$ adb root
Laden Sie den Android x86_64 frida-server von der Repo-Release-Seite herunter und kopieren Sie ihn auf das Gerät unter /data/local/tmp (verwenden Sie adb push).
Starten Sie eine Shell und führen Sie den Frida-Server aus:
device# cd /data/local/tmp device# ./frida-server
Installieren Sie nun die Test-App tests/app-debug.apk
per Drag & Drop in das Emulatorfenster.
Öffnen Sie dann die App.
Kompilieren Sie das Agent-Skript mit frida-compile:
host$ frida-compile -x tests/test_ndk_x64.js -o fuzzer-agent.js
Öffnen Sie die App im Emulator.
Fuzzen Sie die test_func
Funktion der libnative-lib.so
-Bibliothek, die mit der Test-App geliefert wird, mit dem folgenden Befehl:
host$ ./frida-fuzzer -U -o output_folder/ com.example.ndktest1
Interessante Testfälle und Abstürze werden beide im Ausgabeordner gespeichert.
Genießen.
Hallo OSS-Community, es gibt viele TODOs, wenn jemand einen Beitrag leisten möchte.
Java-Code-Fuzzing (Warten auf zusätzliche verfügbar gemachte Methoden in Frida-Java-Bridge, sollte einfach sein, fast fertig)
Spleißphase (zwei Testfälle in der Warteschlange zusammenführen und Chaos anrichten)
Unterstützen Sie Wörterbücher (und ändern Sie so auch Chaos)
Samenauswahl
Inline-Instrumentierung für arm64
Leistungsbewertung (siehe Zeitplan der AFL)
Struktureller Mutator (Mutation von Bytes basierend auf einer in JSON geschriebenen Grammatik)
CompareCoverage (Unterbefehlsprofilierung zur Umgehung von Fuzzing-Hürden)
Frida-Fuzzer in C mit Frida-Core umschreiben, um alles auf dem mobilen Gerät ausführen zu können
Wenn Sie Zweifel an einer dieser Funktionen haben, können Sie mir gerne eine DM auf Twitter senden.
Für Funktionsvorschläge gibt es den Abschnitt „Probleme“.