AIDL-Fuzzing

Der Fuzzer verhält sich wie ein Client für den Remote-Dienst, indem er über den generierten Stub importiert oder aufgerufen wird:

Mit der C++ API:

#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 für Fuzz-AIDL-Dienste

Wie im obigen Beispiel gezeigt, wird fuzzService im Fuzzer aufgerufen und akzeptiert einen IBinder (Service) und dataProvider als Eingabeparameter. Zuerst wird mit dem Datenanbieter ein zufälliges Parcel-Objekt initialisiert und die Transaktionsmethode im Remote-Dienst mithilfe der Eingabeparzelle aufgerufen. Anschließend wird die Antwort in ein Antwortpaket übertragen.

Fuzzer erstellen und ausführen

Fuzzer werden standardmäßig mit Abdeckung erstellt.

Die folgenden Desinfektionsmittel werden empfohlen, um Speicherprobleme zu erkennen. hwaddress-Sanitizers werden nur in der arm-Architektur ausgeführt:

SANITIZE_HOST=address SANITIZE_TARGET=hwaddress

Bei der Ausführung mit libFuzzer kann in der Datei Android.bp ein Korpus angegeben werden, bei dem es sich um ein Verzeichnis handelt. Sie können dieses Verzeichnis dann an den Fuzzer übergeben. Einige Fuzzer geben auch eine dictionary: in ihrer Android.bp-Datei an, die Sie mit -dict path/to/dict an libFuzzer übergeben können. Weitere Optionen finden Sie in der offiziellen libFuzzer-Dokumentation.

Wenn Sie Fuzzers 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 Fuzzers auf dem Host auszuführen.

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

Sie können einen automatischen C++-Service-Fuzzer schreiben, indem Sie Folgendes hinzufügen (Java- und Rost-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 zu Fuzzing mit libFuzzer. Aktualisieren Sie die Bindungen mit dem neuen Dienst- und Fuzzer-Namen, um Build-Fehler zu beheben. Bei Java- oder Rust-Diensten kann die Fuzzer-Liste leer sein.