Fuzzing de AIDL

El generador de fuzz se comporta como un cliente para el servicio remoto, ya que lo importa o lo invoca a través del stub generado:

Con 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 generar fuzz en servicios de AIDL

Como se muestra en el ejemplo anterior, se llama a fuzzService en el generador de fuzz y se toma un IBinder (servicio) y dataProvider como parámetros de entrada. Primero, inicializa un objeto Parcel aleatorio con el proveedor de datos y llama al método de transacción en el servicio remoto con el paquete de entrada y, por último, obtiene la respuesta en un paquete de respuesta.

Compila y ejecuta generadores de fuzz

Los generadores de fuzz se compilan con cobertura de forma predeterminada.

Se recomiendan los siguientes validadores para descubrir problemas de memoria. Los validadores 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 generador de fuzz. Algunos generadores de fuzz también especifican un dictionary: en su archivo Android.bp, y puedes pasarlo a libFuzzer con -dict path/to/dict. Para ver más opciones, consulta la documentación oficial de libFuzzer.

Para ejecutar generadores de fuzz en el dispositivo, ejecuta adb sync data y, luego, adb shell data/fuzz/arch/name/name. Para ejecutar generadores de fuzz en el host, ejecuta $ANDROID_HOST_OUT/fuzz/arch/name/name.

El sistema de compilación verifica si cada servicio de Binder de AOSP tiene una entrada de generador de fuzz en los vinculaciones de generador de fuzz de servicio. La prueba de vinculación del generador de fuzz comprueba que cada servicio en service_contexts tenga un generador de fuzz. Si no se encuentra un generador de fuzz o una excepción para un servicio nuevo, hay un error de compilación.

Para escribir un generador de fuzz automático de servicios de C++, agrega lo siguiente (aún no se admiten generadores de fuzz de Java ni Rust):

  • Una entrada cc_fuzz en Android.bp para definir el módulo de generador de fuzz. El módulo cc_default service_fuzzer_defaults tiene dependencias necesarias para fuzzService.
  • Las dependencias específicas del servicio deben agregarse como bibliotecas 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 sobre Fuzzing con libFuzzer. Para resolver el error de compilación, actualiza las vinculaciones con el nuevo servicio y los nombres del generador de fuzz. En el caso de los servicios de Java o Rust, la lista de fuzzers puede estar vacía.