Fuzzing AIDL

Le fuzzer se comporte comme un client du service distant en l'important ou en l'appelant via le bouchon généré:

À l'aide de l'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;
}

Utiliser l'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 pour fuzzer les services AIDL

Comme indiqué dans l'exemple ci-dessus, fuzzService est appelé dans le fuzzer et reçoit un IBinder (Service) et un dataProvider comme paramètres d'entrée. Il initialise d'abord un objet Parcel aléatoire à l'aide du fournisseur de données, appelle la méthode transact sur le service distant à l'aide du parcel d'entrée, puis obtient la réponse dans un parcel de réponse.

Créer et exécuter des fuzzers

Les fuzzers sont conçus avec une couverture par défaut.

Les outils de nettoyage suivants sont recommandés pour détecter les problèmes de mémoire. Les nettoyants hwaddress ne s'exécutent que sur l'architecture arm:

SANITIZE_HOST=address SANITIZE_TARGET=hwaddress

Lors de l'exécution avec libFuzzer, un corpus, qui est un répertoire, peut être spécifié dans le fichier Android.bp. Vous pouvez transmettre ce répertoire au fuzzer. Certains outils de fuzzing spécifient également un dictionary: dans leur fichier Android.bp, et vous pouvez le transmettre à libFuzzer avec -dict path/to/dict. Pour plus d'options, consultez la documentation officielle de libFuzzer.

Pour exécuter des fuzzers sur l'appareil, exécutez adb sync data, puis adb shell data/fuzz/arch/name/name. Pour exécuter des fuzzers sur l'hôte, exécutez $ANDROID_HOST_OUT/fuzz/arch/name/name.

Le système de compilation vérifie si chaque service de liaison AOSP dispose d'une entrée de fuzzeur dans les liaisons de service de fuzzeur. Le test de liaison du fuzzeur vérifie que chaque service de service_contexts dispose d'un fuzzeur. Si aucun fuzzer ou exception n'est trouvé pour un nouveau service, une erreur de compilation se produit.

Vous pouvez écrire un fuzzeur de service C++ automatique en ajoutant ce qui suit (les fuzzeurs Java et Rust ne sont pas encore compatibles):

  • Une entrée cc_fuzz dans Android.bp pour définir le module de fuzzer. Le module cc_default service_fuzzer_defaults contient les dépendances requises pour fuzzService.
  • Les dépendances spécifiques au service doivent être ajoutées en tant que bibliothèque ou en tant que sources.
  • Un fichier principal qui crée votre service et appelle fuzzService

Pour obtenir des instructions détaillées sur l'utilisation de cc_fuzz, consultez la documentation sur le fuzzing avec libFuzzer. Pour résoudre l'erreur de compilation, mettez à jour les liaisons avec les nouveaux noms de service et de fuzzer. Pour les services Java ou Rust, la liste des fuzzers peut être vide.