AIDL-Fuzzing

Der Fuzzer verhält sich als Client für den Remote-Dienst, indem er ihn über den generierten Stub importiert oder aufruft:

C++ API verwenden:

#include <fuzzbinder/libbinder_ndk_driver.h>
#include <fuzzer/FuzzedDataProvider.h>

#include <android-base/logging.h>
#include <android/binder_interface_utils.h>

using android::fuzzService;
using ndk::SharedRefBase;

extern "C" int LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
    auto binder = ndk::SharedRefBase::make<MyService>(...);

    fuzzService(binder->asBinder().get(), FuzzedDataProvider(data, size));

    return 0;
}

Rust API verwenden:

#![allow(missing_docs)]
#![no_main]
#[macro_use]
extern crate libfuzzer_sys;

use binder::{self, BinderFeatures, Interface};
use binder_random_parcel_rs::fuzz_service;

fuzz_target!(|data: &[u8]| {
    let service = BnTestService::new_binder(MyService, BinderFeatures::default());
    fuzz_service(&mut service.as_binder(), data);
});

Framework zum Fuzzing von AIDL-Diensten

Wie im Beispiel oben gezeigt, wird fuzzService im Fuzzer aufgerufen und nimmt einen IBinder (Dienst) und dataProvider als Eingabeparameter entgegen. Zuerst wird ein zufälliges Paketobjekt mit dem Datenanbieter initialisiert. Anschließend wird die Transaktionsmethode des Remote-Dienstes mit dem Eingabepaket aufgerufen und schließlich wird die Antwort in ein Antwortpaket aufgenommen.

Fuzzer erstellen und ausführen

Fuzzer werden standardmäßig mit Abdeckung erstellt.

Die folgenden Sanitizer werden empfohlen, um Speicherprobleme zu erkennen. hwaddress-Sanitizer werden nur auf arm-Architekturen ausgeführt:

SANITIZE_HOST=address SANITIZE_TARGET=hwaddress

Wenn Sie libFuzzer ausführen, kann in der Android.bp-Datei ein Corpus (ein Verzeichnis) angegeben werden, den Sie an den Fuzzer übergeben können. Einige Fuzzer geben auch eine dictionary: in ihrer Android.bp-Datei an. Sie können diese mit -dict path/to/dict an libFuzzer übergeben. Weitere Optionen finden Sie in der offiziellen libFuzzer-Dokumentation.

Wenn Sie Fuzzer auf dem Gerät ausführen möchten, führen Sie adb sync data und dann adb shell data/fuzz/arch/name/name aus. Führen Sie $ANDROID_HOST_OUT/fuzz/arch/name/name aus, um Fuzzer auf dem Host auszuführen.

Das Build-System prüft, ob jeder AOSP-Binder-Dienst einen Fuzzer-Eintrag in den Dienst-Fuzzer-Bindungen hat. Beim Fuzzer-Bindungstest wird geprüft, ob jeder Dienst in service_contexts einen Fuzzer hat. Wenn für einen neuen Dienst kein Fuzzer oder keine Ausnahme gefunden wird, liegt ein Buildfehler vor.

Ein automatischer C++-Dienst-Fuzzer kann durch Hinzufügen der folgenden Angaben geschrieben werden (Java- und Rust-Fuzzer werden noch nicht unterstützt):

  • Ein cc_fuzz-Eintrag in Android.bp zum Definieren des Fuzzer-Moduls. Das cc_default-Modul service_fuzzer_defaults hat Abhängigkeiten, die für fuzzService erforderlich sind.
  • Dienstspezifische Abhängigkeiten sollten als Bibliothek oder als Quellen hinzugefügt werden.
  • Eine Hauptdatei, in der Ihr Dienst erstellt und fuzzService aufgerufen wird

Eine ausführliche Anleitung zur Verwendung von cc_fuzz finden Sie in der Dokumentation Fuzzing mit libFuzzer. Aktualisieren Sie die Bindungen mit dem neuen Dienst und den neuen Fuzzernamen, um den Buildfehler zu beheben. Bei Java- oder Rust-Diensten kann die Fuzzerliste leer sein.