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 initialisiert sie mit dem Datenanbieter ein zufälliges Parcel-Objekt und ruft die Transaktionsmethode im Remote-Dienst mithilfe der Eingabeparzelle auf. Schließlich wird die Antwort in ein Antwortpaket hochgeladen.

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 in ihrer Android.bp-Datei einen dictionary: an. Sie können diesen 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, die Ihren Dienst erstellt und fuzzService aufruft

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.