Le fuzzer se comporte comme un client pour le service distant en l'important ou en l'appelant via le stub généré :
Utilisation 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;
}
Utilisation de 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 le fuzzing des services AIDL
Comme illustré dans l'exemple ci-dessus, fuzzService est appelé dans le fuzzer et prend 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 créés avec une couverture par défaut.
Les sanitizers suivants sont recommandés pour détecter les problèmes de mémoire.
Les sanitizers 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, et vous pouvez transmettre ce répertoire au fuzzer. Certains
fuzzers spécifient également un dictionary: dans leur Android.bp file, que vous pouvez
transmettre à libFuzzer avec -dict path/to/dict. Pour
plus d'options, consultez la
documentation officielle de libFuzzer.
Pour exécuter des fuzzers sur un appareil, exécutez adb sync data puis
adb shell data/fuzz/arch/name/name.
Pour exécuter des fuzzers sur un hôte, exécutez
$ANDROID_HOST_OUT/fuzz/arch/name/name.
Recommander des fuzzers pour les services nouveaux ou existants
Le système de compilation vérifie si chaque service de binder AOSP comporte une entrée de fuzzer dans les
liaisons de fuzzer de service.
Le test de liaison de fuzzer vérifie que chaque service dans service_contexts dispose d'un fuzzer. Si aucun fuzzer ni aucune exception n'est trouvé pour un nouveau service, une erreur de compilation se produit.
Un fuzzer de service C++ automatique peut être écrit en ajoutant les éléments suivants (les fuzzers Java et Rust ne sont pas encore compatibles) :
- Une entrée
cc_fuzzdansAndroid.bppour définir le module de fuzzer. Le modulecc_defaultservice_fuzzer_defaultscomporte les dépendances requises pourfuzzService. - 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 construit votre service et appelle
fuzzService
Pour obtenir des instructions détaillées sur l'utilisation de cc_fuzz, consultez la
documentation
Fuzzing with 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.