El fuzzer se comporta como un cliente del servicio remoto; para ello, lo importa o invoca a través del stub generado:
Si usas 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;
}
Con 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 de AIDL
Como se muestra en el ejemplo anterior, se llama a fuzzService en el fuzzer y toma un IBinder (Service) y dataProvider como parámetros de entrada. Primero, inicializa un objeto Parcel aleatorio con el proveedor de datos, llama al método de transacción en el servicio remoto mediante la parcela de entrada y, por último, obtiene la respuesta en un paquete de respuesta.
Crea y ejecuta fuzzers
Los fuzzers se crean con cobertura de forma predeterminada.
Se recomienda usar los siguientes limpiadores para detectar problemas de memoria.
Los limpiadores de 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 conocer 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 del AOSP tiene una entrada de fuzzer en las vinculaciones de fuzzer del servicio.
La prueba de vinculación de fuzzer verifica que todos los servicios en service_contexts
tengan un fuzzer. Si no se encuentra un fuzzer o una excepción para un servicio nuevo, se produce un error de compilación.
Para escribir un fuzzer automático de servicio de C++, agrega lo siguiente (los fuzzers de Java y Rust aún no son compatibles):
- Una entrada
cc_fuzz
enAndroid.bp
para definir el módulo del fuzzer El móduloservice_fuzzer_defaults
decc_default
tiene dependencias necesarias parafuzzService
. - Las dependencias específicas del servicio deben agregarse 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 Cómo realizar una prueba de Fuzz con libFuzzer. Para resolver el error de compilación, actualiza las vinculaciones con el servicio nuevo y los nombres de fuzzer. Para los servicios de Java o Rust, la lista del fuzzer puede estar vacía.