AIDL-Fuzzing

Der Fuzzer verhält sich wie ein 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 verwendet einen IBinder (Service) und einen DataProvider als Eingabeparameter. Zuerst wird ein zufälliges Parcel-Objekt mit dem Datenanbieter initialisiert und die Methode „transact“ für den Remote-Dienst mit dem Eingabe-Parcel aufgerufen. Schließlich wird die Antwort in ein Antwort-Parcel abgerufen.

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 der arm-Architektur ausgeführt:

SANITIZE_HOST=address SANITIZE_TARGET=hwaddress

Bei der Ausführung mit libFuzzer kann ein Korpus, der ein Verzeichnis ist, in der Datei Android.bp angegeben werden. Sie können dieses Verzeichnis an den Fuzzer übergeben. Einige Fuzzer geben auch ein dictionary: in ihrer Android.bp-Datei an. Sie können dies 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 service fuzzer bindings hat. Beim Fuzzer-Binding-Test 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 Build-Fehler vor.

Ein automatischer C++-Service-Fuzzer kann durch Hinzufügen des Folgenden geschrieben werden (Java- und Rust-Fuzzer werden noch nicht unterstützt):

  • Ein cc_fuzz-Eintrag in Android.bp zum Definieren des Fuzzer-Moduls. Das Modul cc_default 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 with libFuzzer. Aktualisieren Sie die Bindungen mit den neuen Dienst- und Fuzzer-Namen, um den Build-Fehler zu beheben. Bei Java- oder Rust-Diensten kann die Fuzzer-Liste leer sein.