Skip to content
KitploitKITPLOIT
ToolsBlog
Einreichen
ToolsBlog
Einreichen

Hacking-, PenTest- und Cybersicherheits-Tools für Ihr Sicherheitsarsenal!

Kitploit ist ein Verzeichnis von Hacking-, Cybersicherheits- und Pentesting-Tools. Entdecken Sie die neuesten Projekt-Updates, um Schwachstellen zu finden, Systeme zu analysieren, Tests zu automatisieren und Ihre Sicherheit zu stärken.

··Feeds·Kontakt·Datenschutz·© 2026 Kitploit

Tool-Verzeichnis

Kategorien

Alle Kategorien anzeigen
Loading categories
FormatFuzzer — Vorlagenbasierter Binärformat-Fuzzer, der gültige Testeingaben in hoher Geschwindigkeit erzeugt und parst, mit AFL++-Integration für abdeckungsgesteuertes Fuzzing. | Kitploit
Tools/GitHubGitHub/uds-se/formatfuzzer
FuzzingBinäranalyse
GitHubuds-se/formatfuzzer

FormatFuzzer

Vorlagenbasierter Binärformat-Fuzzer, der gültige Testeingaben in hoher Geschwindigkeit erzeugt und parst, mit AFL++-Integration für abdeckungsgesteuertes Fuzzing.

Repository anzeigenWebseite
44638vor 5 MonatenVon Kitploit geprüft

Beliebteste

Alle anzeigen →

Entdecken Sie die meistgenutzten Tools unserer Community.

Alle Tools erkunden

Durchsuchen Sie unsere Tool-Sammlung

Alle Tools anzeigen →
Teilen

FormatFuzzer

FormatFuzzer ist ein Framework für die hocheffiziente, qualitativ hochwertige Generierung und Analyse von Binäreingaben. Es nimmt eine Binärvorlage entgegen, die das Format einer Binäreingabe beschreibt, und generiert einen ausführbaren Code, der das angegebene Binärformat erzeugt und parst. Aus einer Binärvorlage für GIF zum Beispiel erzeugt FormatFuzzer einen GIF-Generator – auch bekannt als GIF-Fuzzer.

Die von FormatFuzzer erzeugten Generatoren sind hocheffizient und produzieren Tausende gültiger Testeingaben pro Sekunde – im krassen Gegensatz zu mutationsbasierten Fuzzern, bei denen die überwältigende Mehrheit der Eingaben ungültig ist. Die von FormatFuzzer generierten Eingaben sind unabhängig vom getesteten Programm (oder eigentlich jedem Programm), sodass Sie sie auch in Black-Box-Szenarien verwenden können. FormatFuzzer lässt sich jedoch auch in AFL++ integrieren, um gültige Eingaben zu erzeugen, die gleichzeitig auf maximale Codeabdeckung abzielen. In unseren Experimenten übertrifft dieser „Best of both Worlds"-Ansatz alle anderen Einstellungen; siehe unser Paper für Details.

Die von FormatFuzzer verwendeten Binärvorlagen stammen vom 010 Editor. Es gibt mehr als 170 Binärvorlagen, die entweder direkt für FormatFuzzer verwendet oder für dessen Nutzung angepasst werden können. Out of the Box erzeugt FormatFuzzer Formate wie AVI, BMP, GIF, JPG, MIDI, MP3, MP4, PCAP, PNG, WAV und ZIP; und wir erweitern diese Liste jede Woche weiter.

Mitwirkende sind willkommen! Besuchen Sie die FormatFuzzer-Projektseite, um Ideen und Probleme zu melden oder Pull-Requests einzureichen. Für Details zur Funktionsweise von FormatFuzzer und zu Vergleichen lesen Sie unser Paper für weitere Informationen.

Bezug

FormatFuzzer ist auf der FormatFuzzer-Projektseite verfügbar. Sie können die neueste Version von der Release-Seite herunterladen und entpacken.

Für die allerneueste Version können Sie auch das Git-Repository klonen:

root@kitploit:~
git clone https://github.com/uds-se/FormatFuzzer.git

Alle weiteren Aktionen finden im Hauptverzeichnis statt:

root@kitploit:~
cd FormatFuzzer

Voraussetzungen

Um FormatFuzzer auszuführen, benötigen Sie Folgendes:

  • Python 3
  • Einen C++-Compiler mit GNU-Bibliotheken (insbesondere getopt_long()) wie clang oder gcc
  • Die Python-Pakete py010parser, six und intervaltree
  • Eine zlib-Bibliothek (für Komprimierungsfunktionen)
  • Eine boost-Bibliothek (für Prüfsummenfunktionen)

Wenn Sie die Build- und Konfigurationsskripte (.ac- und .am-Dateien) bearbeiten möchten, benötigen Sie außerdem

  • GNU autoconf
  • GNU automake

Installieren der Anforderungen unter Linux (Debian-Pakete, mit einer Python-Virtual-Environment)

root@kitploit:~
sudo apt install git g++ make automake python3-full zlib1g-dev libboost-dev
python3 -m venv ~/fuzz
source ~/fuzz/bin/activate
pip3 install py010parser six intervaltree

Installieren der Anforderungen unter MacOS (mit Xcode & Homebrew)

root@kitploit:~
xcode-select --install
brew install python3 automake boost
pip3 install py010parser six intervaltree

Nur Python-Pakete installieren (alle Betriebssysteme)

Auf allen Systemen mit pip:

root@kitploit:~
pip install py010parser
pip install six
pip install intervaltree

Bauen

Hinweis: Alle Build-Befehle erfordern, dass Sie sich im selben Ordner wie diese README-Datei befinden. Das Bauen eines Fuzzers außerhalb dieses Ordners wird noch nicht unterstützt.

Methode 1: Verwendung des build.sh-Skripts

Es gibt ein Skript build.sh, das alle Konstruktionsschritte automatisiert. Führen Sie einfach

root@kitploit:~
./build.sh gif

aus, um einen GIF-Fuzzer zu erstellen.

Dies funktioniert für alle Dateiformate, die in templates/ bereitgestellt werden; wenn es eine Datei templates/FOO.bt gibt, dann baut ./build.sh FOO einen Fuzzer.

Methode 2: Verwendung von Make

Es gibt ein Makefile (Quelle in Makefile.am), das alle Konstruktionsschritte automatisiert. (Erfordert GNU make.) Führen Sie zuerst

root@kitploit:~
touch configure Makefile.in

dann

root@kitploit:~
./configure

und dann

root@kitploit:~
make gif-fuzzer

aus, um einen GIF-Fuzzer zu erstellen.

Dies funktioniert für alle Dateiformate, die in templates/ bereitgestellt werden; wenn es eine Datei templates/FOO.bt gibt, dann baut make FOO-fuzzer einen Fuzzer.

Methode 3: Manuelle Schritte

Falls die obige make-Methode nicht funktioniert oder Sie mehr Kontrolle wünschen, müssen Sie möglicherweise manuell vorgehen.

Schritt 1: Kompilieren von Binärvorlagendateien in C++-Code

Führen Sie den ffcompile-Compiler aus, um die Binärvorlage in C++-Code zu kompilieren. Er benötigt zwei Argumente: die .bt-Binärvorlage und eine zu generierende .cpp-C++-Datei.

root@kitploit:~
./ffcompile templates/gif.bt gif.cpp

Schritt 2: Kompilieren des C++-Codes

Verwenden Sie die folgenden Befehle, um einen Fuzzer gif-fuzzer zu erstellen. Kompilieren Sie zunächst den generischen Befehlszeilentreiber:

root@kitploit:~
g++ -c -I . -std=c++17 -g -O3 -Wall fuzzer.cpp

(-I . gibt den Speicherort der bt.h-Datei an; -std=c++17 setzt den C++-Standard.)

Kompilieren Sie dann den Binärparser/-compiler:

root@kitploit:~
g++ -c -I . -std=c++17 -g -O3 -Wall gif.cpp

Verknüpfen Sie schließlich den Binärparser/-compiler mit dem Befehlszeilentreiber, um eine ausführbare Datei zu erhalten. Wenn Sie zusätzliche Bibliotheken (wie -lz) verwenden, geben Sie diese hier ebenfalls an.

root@kitploit:~
g++ -O3 gif.o fuzzer.o -o gif-fuzzer -lz

Ausführen des Fuzzers

FormatFuzzer kann als eigenständiger Parser, Generator oder Mutator bestimmter Formate ausgeführt werden. Darüber hinaus kann es von allgemeinen Fuzzern wie AFL++ aufgerufen werden, um diese formatspezifischen Fähigkeiten in den Fuzzing-Prozess zu integrieren (siehe den folgenden Abschnitt zur AFL++-Integration).

Der generierte Fuzzer nimmt einen Befehl als erstes Argument entgegen, gefolgt von Optionen und Argumenten für diesen Befehl.

Der wichtigste Befehl ist fuzz zur Erzeugung von Ausgaben. Seine Argumente sind Dateien, die im entsprechenden Format generiert werden sollen.

Führen Sie den Generator aus als

root@kitploit:~
./gif-fuzzer fuzz output.gif

um eine zufällige Binärdatei output.gif zu erstellen, oder

root@kitploit:~
./gif-fuzzer fuzz out1.gif out2.gif out3.gif

um drei GIF-Dateien out1.gif, out2.gif und out3.gif zu erstellen.

Beachten Sie, dass die von uns bereitgestellte Vorlage gif.bt um spezielle Funktionen erweitert wurde, um die Generierung gültiger Dateien zu erleichtern. Wenn Sie eine originale .bt-Vorlagendatei ohne Anpassungen verwenden, erhalten Sie möglicherweise Warnungen während der Generierung und erstellen ungültige Dateien.

Ausführen von Parser

Sie können den Fuzzer auch als Parser für Binärdateien mit dem Befehl parse ausführen. Dies ist nützlich, wenn Sie die Genauigkeit der Binärvorlage testen oder eine Eingabe mutieren möchten (siehe „Entscheidungsdateien" unten).

Um den Parser auszuführen, verwenden Sie

root@kitploit:~
./gif-fuzzer parse input.gif

Sie sehen Fehlermeldungen, wenn input.gif nicht erfolgreich geparst werden kann.

Entscheidungsdateien

Beim Parsen können Sie auch alle Parsing-Entscheidungen (d.h. welche Parsing-Alternativen gewählt wurden) in einer Entscheidungsdatei speichern. Dies ist eine Abfolge von Bytes, die die getroffenen Entscheidungen aufzählt. Jedes Byte steht für eine einzige Parsing-Entscheidung. Ein Byte-Wert von 0 bedeutet, dass die erste Alternative gewählt wurde, ein Byte-Wert von 1 bedeutet, dass die zweite Alternative gewählt wurde, und so weiter.

Sie können eine solche Entscheidungsdatei generieren, während Sie eine Eingabe parsen:

root@kitploit:~
./gif-fuzzer parse --decisions input.dec input.gif

Hier speichert input.dec die Entscheidungen, die für das Parsen von input.gif getroffen wurden.

Sie können eine solche Entscheidungsdatei auch beim Generieren von Eingaben verwenden. Der Fuzzer trifft dann genau dieselben Entscheidungen wie beim Parsen. Der folgende Befehl generiert eine neue GIF-Datei unter Verwendung der Entscheidungen, die beim Parsen von input.gif ermittelt wurden:

root@kitploit:~
./gif-fuzzer fuzz --decisions input.dec input2.gif

Wenn alles gut funktioniert, sollten beide Dateien identisch sein:

root@kitploit:~
cmp input.gif input2.gif

Durch Mutieren einer Entscheidungsdatei (z.B. durch Ersetzen einzelner Bytes) können Sie Eingaben erstellen, die der ursprünglichen geparsten Datei ähnlich sind. Dies ist nützlich für die Schnittstelle zu spezifischen Teststrategien und Fuzzern wie AFL, bei denen Sie gif-fuzzer und ähnliche als Übersetzer von Entscheidungsdateien in Binärdateien und zurück verwenden können: AFL würde Entscheidungsdateien mutieren, und das getestete Programm würde auf den übersetzten Binärdateien ausgeführt. Im Gegensatz zur direkten Mutation von Binärdateien (wie AFL es normalerweise tun würde) hätte dies den Vorteil, dass immer gültige Eingaben vorhanden sind – und somit viel schneller Fortschritte in Richtung Codeabdeckung erzielt werden.

AFL++-Integration

Zusätzlich zu den formatspezifischen Fuzzern wie gif-fuzzer kann FormatFuzzer auch in formatspezifische Shared Libraries wie gif.so kompiliert werden (dazu führen Sie einfach ./build.sh gif oder make gif.so aus). Diese Shared Libraries können von allgemeinen Fuzzern wie AFL++ geladen werden.

Um AFL++ mit FormatFuzzer auszuführen, folgen Sie einfach den Anweisungen auf unserer modifizierten Version von AFL++. Wir unterstützen verschiedene Fuzzing-Strategien, darunter:

  • AFL+FFMut: Führt AFL++ aus und verwendet FormatFuzzer, um formatspezifische intelligente Mutationen bereitzustellen.

  • AFL+FFGen: Verwendet FormatFuzzer als formatspezifischen Generator, während AFL++ seine Entscheidungs-Seeds mutiert.

Erstellen und Anpassen von Binärvorlagen

Um Ihre eigenen .bt-Binärvorlagen zu schreiben (und damit einen hocheffizienten Fuzzer/Parser für dieses Format zu erstellen), lesen Sie den Abschnitt Introduction to Templates and Scripts aus dem 010 Editor Manual.

In vielen Fällen existiert bereits eine Vorlage für das gesuchte Format (oder ein ähnliches). Werfen Sie einen Blick in die Binärvorlagensammlung des 010 Editors, ob es etwas gibt, das Sie verwenden oder als Grundlage für Ihr Format nehmen können.

Beachten Sie, dass die im Repository bereitgestellten .bt-Dateien im Allgemeinen auf das Parsen von Dateien abzielen. Sie können auch zum Generieren von Dateien verwendet werden; aber ihnen fehlen oft genaue Informationen darüber, welche Teile der Eingabe erforderlich sind.

In diesem Abschnitt besprechen wir einige Möglichkeiten, wie Sie .bt-Dateien anpassen können, damit sie gut mit FormatFuzzer funktionieren.

Zum Beispiel zeigt für das GIF-Format die Datei templates/gif-orig.bt die originale Binärvorlage, die nur für das Parsen ausgelegt war, während die Datei templates/gif.bt eine modifizierte Version ist, die gültige GIFs generieren kann. Beim Vergleich der beiden Dateien sehen wir, dass nur eine geringe Anzahl von Änderungen erforderlich war, um dies zu erreichen.

Wenn Sie einen gif-fuzzer erstellt haben, entweder durch Ausführen von make gif-fuzzer oder durch Verwendung des ffcompile-Werkzeugs, haben Sie bereits eine C++-Datei gif.cpp erhalten, die eine Implementierung des GIF-Generators und -Parsers enthält. Dies ist nützlich, um zu sehen, wie die von Ihnen an der Binärvorlage vorgenommenen Änderungen in ausführbaren Code übersetzt werden. Weitere Details zum C++-Code finden Sie im nächsten Abschnitt.

Die GIF-Binärvorlage verwendet Lookahead-Funktionen ReadUByte() und ReadUShort(), um die Werte der nächsten Bytes in der Datei vorauszuschauen, bevor sie tatsächlich in ein Strukturfeld geparst werden. Zur Generierungszeit erlauben wir diesen Funktionen, ein zusätzliches Argument zu erhalten, das einen Satz guter bekannter Werte angibt, die für die Bytes ausgewählt werden sollen, auf die wir vorausschauen. Darüber hinaus erlauben wir auch, einen globalen Satz guter bekannter Werte anzugeben, der immer verwendet wird, wenn eine bestimmte Lookahead-Funktion wie ReadUByte() aufgerufen wird. Diese werden im Vektor ReadUByteInitValues gespeichert.

Standardmäßig versucht unser Übersetzungsverfahren ffcompile, interessante Werte zu extrahieren, die in Vergleichen gegen Lookahead-Bytes verwendet wurden, und sie als globalen Satz bekannter Werte zu verwenden. Wenn Sie

root@kitploit:~
./ffcompile templates/gif.bt gif.cpp

ausführen, zeigt eine gedruckte Nachricht die identifizierten Lookahead-Funktionen sowie die extrahierten interessanten Werte an:

root@kitploit:~
Finished creating cpp generator.

Lookahead functions found:

ReadUByte
ReadUShort

Mined interesting values:

GlobalColorTableFlag: ['1']
LocalColorTableFlag: ['1']
ReadUByte: ['0x3B', '0x2C']
ReadUShort: ['0xF921', '0xFE21', '0x0121', '0xFF21']
Signature: ['"GIF"']

Für die GIF-Generierung ist es jedoch besser, den Satz guter bekannter Werte für ReadUByte() individuell bei jedem Aufruf der Funktion anzugeben. Also definieren wir ein leeres Array (Größe 0)

root@kitploit:~
const local UBYTE ReadUByteInitValues[0];

um den Satz globaler ReadUByteInitValues zu überschreiben, und für jeden Aufruf von ReadUByte() verwenden wir ein zusätzliches Argument, um den Satz guter Werte für diese bestimmte Stelle anzugeben. Die Binärvorlagensprache ist auch mächtig genug, um diese Wahl basierend auf Laufzeitbedingungen zu treffen. Im folgenden Code zeigen wir zum Beispiel, wie die Wahl geeigneter Werte für einen ReadUByte()-Aufruf von der aktuellen GIF-Version abhängen kann, die wir generieren. Eine GIF-Version 89a erlaubt einen zusätzlichen möglichen Wert für das Byte (0x21).

root@kitploit:~
	if(GifHeader.Version == "89a")
		local UBYTE values[] = { 0x3B, 0x2C, 0x21 };
	else
		local UBYTE values[] = { 0x3B, 0x2C };

	while (ReadUByte(FTell(), values) != 0x3B) {
		...
	}

Die restlichen Änderungen, die für die GIF-Binärvorlage erforderlich sind, sind ähnlich. Beispielsweise kann für jedes Strukturfeld auch ein Satz bekannter guter Werte angegeben werden. Dies gibt zum Beispiel die korrekten Werte für das Feld Version an: 87a und 89a.

root@kitploit:~
	char	Version[3] = { {"87a"}, {"89a"} };

Verstehen des generierten C++-Codes

Zu Debugging-Zwecken sowie zum Verständnis, wie Sie geeignete Änderungen vornehmen können, um Ihre Generatoren und Parser zu verbessern, kann es nützlich sein, einige interne Funktionsweisen des generierten C++-Codes zu verstehen. Idealerweise sollten Sie in der Lage sein, die Binärvorlagendateien so zu bearbeiten, dass sie mit hoher Wahrscheinlichkeit gültige Dateien generieren können, sodass Sie den generierten C++-Code nicht bearbeiten müssten.

Der C++-Code erstellt eine Klasse für jedes struct und jede union, die in der Binärvorlage definiert sind, sowie für native Typen wie int.

Zum Konstruktionszeitpunkt, wenn eine Variable initialisiert wird, können wir einen Satz guter bekannter Werte definieren, die diese Variable annehmen kann. Beispielsweise würde der Konstruktoraufruf

root@kitploit:~
char_array_class cname(cname_element, { "IHDR", "tEXt", "PLTE", "cHRM", "sRGB", "iEXt", "zEXt", "tIME", "pHYs", "bKGD", "sBIT", "sPLT", "acTL", "fcTL", "fdAT", "IHDR", "IEND" });

17 gute Werte für die Variable cname angeben. Aber das ist oft nicht ausreichend, da die Wahl des geeigneten Chunk-Typs kontextabhängig ist. Deshalb erlauben wir auch, zur Generierungszeit einen Satz guter Werte anzugeben, wenn ein neuer Chunk generiert wird. Zum Beispiel könnte dieser Aufruf verwendet werden, um eine Instanz von chunk für den ersten Chunk zu generieren, der den Typ IHDR haben muss.

root@kitploit:~
GENERATE(chunk, ::g->chunk.generate({ "IHDR" }, false));

Beim Generieren des zweiten Chunks könnten wir diese lange Liste möglicher Chunks verwenden, die zwischen dem IHDR-Chunk und dem PLTE-Chunk vorkommen können:

root@kitploit:~
GENERATE(chunk, ::g->chunk.generate({ "iCCP", "sRGB", "sBIT", "gAMA", "cHRM", "pHYs", "sPLT", "tIME", "zTXt", "tEXt", "iTXt", "eXIf", "oFFs", "pCAL", "sCAL", "acTL", "fcTL", "fdAT", "fRAc", "gIFg", "gIFt", "gIFx", "sTER" }, true));

Der Generator wählt dann gleichmäßig einen der guten bekannten Werte für die neue Instanz aus. Wir erlauben auch die Wahl eines bösen Werts, der nicht zu den guten bekannten Werten gehört, mit einer kleinen Wahrscheinlichkeit von 1/128. Diese Funktion kann jederzeit mit der Methode set_evil_bit aktiviert oder deaktiviert werden.

Alle zufälligen Entscheidungen des Generators werden durch Aufrufen der Methode rand_int() getroffen.

root@kitploit:~
long long rand_int(unsigned long long x, std::function<long long (unsigned char*)> parse);

Wenn das Programm als Generator läuft, sampelt diese Methode eine ganze Zahl von 0 bis x-1, indem sie Bytes aus dem zufälligen Puffer liest. Wenn das Programm als Parser läuft, verwendet diese Methode die parse()-Funktion, um herauszufinden, welche zufälligen Bytes im zufälligen Puffer vorhanden sein müssen, um die Zieldatei zu generieren, und schreibt dann diese Bytes in den zufälligen Puffer. Die parse-Funktion erhält als Argument den Puffer an der aktuellen Position der Datei und muss dann den Wert zurückgeben, der vom aktuellen Aufruf von rand_int() zurückgegeben werden müsste, um diese genaue Dateikonfiguration zu generieren.

Autoren

FormatFuzzer wurde entworfen und geschrieben von Rafael Dutra <[email protected]>.

Das Konzept eines Fuzzer-Compilers wurde eingeführt von Rahul Gopinath <[email protected]> und Andreas Zeller <[email protected]>.

Urheberrecht und Lizenzen

FormatFuzzer ist urheberrechtlich geschützt © 2020, 2021 durch das CISPA Helmholtz-Zentrum für Informationssicherheit. Die folgenden Lizenzen gelten:

  • Der FormatFuzzer-Code (insbesondere aller C++-Code und Code im Zusammenhang mit seiner Generierung) unterliegt der GNU GENERAL PUBLIC LICENSE, wie in COPYING zu finden.

  • Als Ausnahme zu obigem ist der von FormatFuzzer generierte C++-Code (d.h. Fuzzer und Parser für bestimmte Formate) gemeinfrei (Public Domain).

  • Der originale pfp Code, auf dem FormatFuzzer basiert, unterliegt einer MIT-Lizenz, wie in LICENSE-pfp zu finden.

Tool herunterladen