El fuzzer se comporta como un cliente para el servicio remoto importándolo o invocándolo a través del stub generado:
Uso de la API de 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;
}
Uso de la API de 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 para fuzzing de servicios AIDL
Como se muestra en el ejemplo anterior, se llama a fuzzService en el fuzzer y se toma un IBinder (Service) y dataProvider como parámetros de entrada. Primero, se inicializa un objeto Parcel aleatorio con el proveedor de datos y se llama al método transact en el servicio remoto con el paquete de entrada y, por último, se obtiene la respuesta en un paquete de respuesta.
Compila y ejecuta fuzzers
Los fuzzers se compilan con cobertura de forma predeterminada.
Se recomiendan los siguientes sanitizadores para descubrir problemas de memoria.
Los sanitizadores hwaddress solo se ejecutan en la arquitectura arm:
SANITIZE_HOST=address SANITIZE_TARGET=hwaddress
Cuando se ejecuta con libFuzzer, se puede especificar un corpus, que es un directorio, en el archivo Android.bp, y puedes pasar este directorio al fuzzer. Algunos
fuzzers también especifican un dictionary: en su archivo Android.bp, y puedes
pasarlo a libFuzzer con -dict path/to/dict. Para
obtener más opciones, consulta la
documentación oficial de libFuzzer.
Para ejecutar fuzzers en el dispositivo, ejecuta adb sync data y, luego,
adb shell data/fuzz/arch/name/name.
Para ejecutar fuzzers en el host, ejecuta
$ANDROID_HOST_OUT/fuzz/arch/name/name.
Recomienda fuzzers para servicios nuevos o existentes
El sistema de compilación verifica si cada servicio de binder de AOSP tiene una entrada de fuzzer en
las vinculaciones de fuzzer de servicio.
La prueba de vinculación de Fuzzer verifica que cada servicio en service_contexts tenga un fuzzer. Si no se encuentra un fuzzer o una excepción para un servicio nuevo, se produce un error de compilación.
Se puede escribir un fuzzer de servicio automático de C++ agregando lo siguiente (aún no se admiten los fuzzers de Java y Rust):
- Una entrada
cc_fuzzenAndroid.bppara definir el módulo de fuzzer El módulocc_defaultservice_fuzzer_defaultstiene dependencias necesarias parafuzzService. - Las dependencias específicas del servicio se deben agregar como una biblioteca o como fuentes.
- Un archivo principal que construye tu servicio y llama a
fuzzService
Para obtener instrucciones detalladas sobre el uso de cc_fuzz, consulta la
documentación de Fuzzing con libFuzzer. Para resolver el error de compilación, actualiza las vinculaciones con los nombres nuevos de servicio y fuzzer. En el caso de los servicios de Java o Rust, la lista de fuzzers puede estar vacía.