Fuzzing AIDL

Il fuzzer si comporta come un client per il servizio remoto importandolo o richiamandolo 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 il fuzzing dei servizi AIDL

Come mostrato nell'esempio precedente, fuzzService viene chiamato nel fuzzer e accetta come parametri di input un IBinder (Service) e dataProvider. Innanzitutto, inizializza un oggetto Parcel casuale utilizzando il provider di dati, chiama il metodo transact sul servizio remoto utilizzando il pacco di input e infine inserisce la risposta in un pacco di risposta.

Creare ed eseguire i fuzzer

I fuzzer vengono creati con la copertura per impostazione predefinita.

Per scoprire i problemi di memoria, ti consigliamo di utilizzare i seguenti sanitizer. I sanitizer hwaddress vengono eseguiti solo sull'architettura arm:

SANITIZE_HOST=address SANITIZE_TARGET=hwaddress

Quando esegui con libFuzzer, puoi specificare un corpus, ovvero una directory, nel file Android.bp e puoi passare questa directory al fuzzer. Alcuni fuzzer specificano anche un dictionary: nel file Android.bp e puoi passarlo a libFuzzer con -dict path/to/dict. Per ulteriori 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 verifica se ogni servizio di binder AOSP ha una voce di fuzzer in binding dei fuzzer di servizio. Il test di binding 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 verifica un errore di build.

È possibile scrivere un fuzzer di servizio C++ automatico 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 richieste per fuzzService.
  • Le dipendenze specifiche del servizio devono essere aggiunte come libreria o come origini.
  • Un file principale che crea il servizio e chiama fuzzService

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