Rust-Fuzzing wird über den libfuzzer-sys
-Crate unterstützt, der Bindungen zur Fuzzing-Engine libFuzzer von LLVM bereitstellt. Weitere Informationen finden Sie im Repository libfuzzer-sys und auf der LLVM libFuzzer-Projektseite.
Das rust_fuzz
-Modul generiert einen Fuzzer-Binärcode, der beim Ausführen mit dem Fuzzing beginnt (ähnlich wie bei cc_fuzz
-Modulen). Da der Fuzzer die libFuzzer
-Fuzzing-Engine nutzt, kann es eine Reihe von Argumenten erfordern, um das Fuzzing zu steuern. Diese werden in der libFuzzer-Dokumentation aufgeführt.
rust_fuzz
-Module sind eine Erweiterung von rust_binary
-Modulen und haben daher dieselben Eigenschaften und Überlegungen. Außerdem werden viele derselben Properties und Funktionen wie in den cc_fuzz
-Modulen implementiert.
Beim Erstellen von rust_fuzz
-Modulen wird das Flag --cfg fuzzing
ausgegeben, das zur Unterstützung der bedingten Kompilierung von Bibliothekscode zur Verbesserung des Fuzzing verwendet werden kann.
Einen einfachen Rust-Fuzzer schreiben
Sie können ein Fuzz-Modul in einer Android.bp
-Builddatei mit diesem Code definieren:
rust_fuzz {
name: "example_rust_fuzzer",
srcs: ["fuzzer.rs"],
// Config for running the target on fuzzing infrastructure can be set under
// fuzz_config. This shares the same properties as cc_fuzz's fuzz_config.
fuzz_config: {
fuzz_on_haiku_device: true,
fuzz_on_haiku_host: false,
},
// Path to a corpus of sample inputs, optional. See https://llvm.org/docs/LibFuzzer.html#corpus
corpus: ["testdata/*"],
// Path to a dictionary of sample byte sequences, optional. See https://llvm.org/docs/LibFuzzer.html#dictionaries
dictionary: "example_rust_fuzzer.dict",
}
Die Datei fuzzer.rs
enthält einen einfachen Fuzzer:
fn heap_oob() {
let xs = vec![0, 1, 2, 3];
let val = unsafe { *xs.as_ptr().offset(4) };
println!("Out-of-bounds heap value: {}", val);
}
fuzz_target!(|data: &[u8]| {
let magic_number = 327;
if data.len() == magic_number {
heap_oob();
}
});
Hier definiert fuzz_target!(|data: &[u8]| { /* fuzz using data here */ });
den Fuzz-Ziel-Einstiegspunkt, der von der libFuzzer
-Engine aufgerufen wird. Das data
-Argument ist eine Bytefolge, die von der libFuzzer
-Engine bereitgestellt wird und als Eingabe manipuliert werden kann, um die Zielfunktion zu fuzzen.
In diesem Beispiel-Fuzzer wird nur die Länge der Daten geprüft, um zu ermitteln, ob die Funktion heap_oob
aufgerufen werden soll, deren Aufruf zu einem Lesefehler führt. libFuzzer
ist ein abdeckungsbasierter Fuzzer, der schnell auf die problematische Länge konvergiert, da er feststellt, dass die ersten 326 B Daten nicht zu neuen Ausführungspfaden führen.
Dieses Beispiel finden Sie im Verzeichnisbaum unter tools/security/fuzzing/example_rust_fuzzer/.
Ein etwas komplexeres Beispiel für einen anderen Fuzzer (der eine rustlib
-Abhängigkeit in einem Verzeichnis fuzzt) finden Sie unter legacy_blob_fuzzer.
Eine Anleitung zum Erstellen struktursensitiver Rust-Fuzzer finden Sie im Rust Fuzz-Buch, der offiziellen Dokumentation für das Rust Fuzz-Projekt.