Rust Fuzzing wird über die libfuzzer-sys
-Kiste unterstützt, die Bindungen an die libFuzzer-Fuzzing-Engine von LLVM bietet. 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 die gleichen 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, mit dem die bedingte Kompilierung von Bibliothekscode unterstützt werden kann, um das Fuzzing zu verbessern.
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 bestimmen, ob die heap_oob
-Funktion aufgerufen werden soll. Der Aufruf führt zu einem Lesevorgang außerhalb des gültigen Bereichs. libFuzzer
ist ein abdeckungsgesteuerter Fuzzer. Er konvergiert also schnell an der problematischen Länge, da er feststellt, dass die ersten 326 Mrd. Daten nicht zu neuen Ausführungspfaden führen.
Dieses Beispiel finden Sie im Verzeichnis tools/security/fuzzing/example_rust_fuzzer/.
Ein etwas komplexeres Beispiel für einen weiteren Fuzzer, der eine rustlib
-Abhängigkeit unkenntlich macht, finden Sie unter legacy_blob_fuzzer.
Eine Anleitung zum Schreiben strukturbewusster Rust Fuzzer finden Sie im Rust Fuzz-Buch, der offiziellen Dokumentation für das Rust Fuzz-Projekt.