Fuzzing AIDL

Il fuzzer si comporta come un client per il servizio remoto importandolo o invocandolo tramite lo stub generato:

Utilizzo dell'API C++:

#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;
}

Utilizzo dell'API Rust:

#![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 per eseguire fuzz dei servizi AIDL

Come mostrato nell'esempio precedente, fuzzService viene chiamato nel fuzzer e riceve un IBinder (servizio) e dataProvider come parametri di input. Innanzitutto, inizializza un oggetto Parcel casuale utilizzando il fornitore di dati e chiama il metodo transact sul servizio remoto utilizzando il pacchetto di input, per poi ricevere la risposta in un pacchetto di risposta.

Crea ed esegui fuzzer

I fuzzer vengono creati con copertura per impostazione predefinita.

Per rilevare i problemi di memoria, sono consigliati i seguenti programmi di sanificazione. I sanitazzari hwaddress vengono eseguiti solo sull'architettura arm:

SANITIZE_HOST=address SANITIZE_TARGET=hwaddress

Quando viene eseguito con libFuzzer, nel file Android.bp può essere specificato un corpus, ovvero una directory, che puoi passare al fuzzer. Alcuni fuzzer specificano anche un dictionary: nel file Android.bp e puoi trasmetterlo a libFuzzer con -dict path/to/dict. Per altre opzioni, consulta la documentazione ufficiale di libFuzzer.

Per eseguire i fuzzer sul dispositivo, esegui adb sync data e poi adb shell data/fuzz/arch/name/name. Per eseguire i fuzzer sull'host, esegui $ANDROID_HOST_OUT/fuzz/arch/name/name.

Il sistema di compilazione controlla se ogni servizio binder AOSP ha una voce del fuzzer nelle associazioni del fuzzer del servizio. Il test di associazione del fuzzer verifica che ogni servizio in service_contexts abbia un fuzzer. Se non viene trovato un fuzzer o un'eccezione per un nuovo servizio, si è verificato un errore di compilazione.

È possibile scrivere un fuzzer automatico per i servizi C++ aggiungendo quanto segue (i fuzzer Java e Rust non sono ancora supportati):

  • Una voce cc_fuzz in Android.bp per definire il modulo del fuzzer. Il modulo cc_default service_fuzzer_defaults ha le dipendenze necessarie per fuzzService.
  • Le dipendenze specifiche del servizio devono essere aggiunte come librerie o come origini.
  • Un file principale che crea il servizio e chiama fuzzService

Per istruzioni dettagliate sull'utilizzo di cc_fuzz, consulta la documentazione su Fuzzing con libFuzzer. Per risolvere l'errore di compilazione, aggiorna le associazioni con i nuovi nomi del servizio e del fuzzer. Per i servizi Java o Rust, l'elenco dei fuzzer può essere vuoto.