El fuzzer se comporta como un cliente para el servicio remoto, ya que lo importa o lo invoca a través del stub generado:
Usa 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 realizar fuzzing de servicios AIDL
Como se muestra en el ejemplo anterior, se llama a fuzzService en el fuzzer y se ingresan un IBinder (servicio) y un dataProvider como parámetros de entrada. Primero, inicializa un objeto Parcel aleatorio con el proveedor de datos y llama al método transact en el servicio remoto con el objeto Parcel de entrada y, por último, obtiene la respuesta en un objeto Parcel 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 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 pasar esto 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 del AOSP tiene una entrada de fuzzing en las vinculaciones del fuzzer de servicios.
La prueba de vinculación del 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.
Para escribir un fuzzer de servicio automático en C++, agrega lo siguiente (aún no se admiten los fuzzers de Java y Rust):
- Una entrada
cc_fuzz
enAndroid.bp
para definir el módulo de fuzzing. El módulocc_default
service_fuzzer_defaults
tiene 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 with libFuzzer. Para resolver el error de compilación, actualiza las vinculaciones con los nombres nuevos del servicio y del fuzzer. En el caso de los servicios de Java o Rust, la lista de fuzzers puede estar vacía.