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 la 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 esegui il fuzzing 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 fuzzer sul dispositivo, esegui adb sync data e poi adb shell data/fuzz/arch/name/name. Per eseguire fuzzer sull'host, esegui $ANDROID_HOST_OUT/fuzz/arch/name/name.

Il sistema di compilazione verifica se ogni servizio binder AOSP ha una voce fuzzer nelle associazioni di fuzzer dei servizi. Il test di associazione 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 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 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.