Fuzzing AIDL

El fuzzer se comporta como un cliente para el servicio remoto importándolo/invocándolo a través del código auxiliar generado:

Usando 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;
}

Usando 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);
});

Marco para difuminar los servicios AIDL

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

Construir y ejecutar fuzzers

Los fuzzers están construidos con cobertura de forma predeterminada.

Se recomiendan los siguientes desinfectantes para descubrir problemas de memoria. Los desinfectantes hwaddress solo funcionan 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 usted puede 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, consulte la documentación oficial de libFuzzer .

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

El sistema de compilación comprueba si cada servicio de carpeta AOSP tiene una entrada de fuzzer en los enlaces de fuzzer de servicio . La prueba de enlace de Fuzzer comprueba que cada servicio en service_contexts tenga un fuzzer. Si no se encuentra un fuzzer/excepción para un nuevo servicio, hay un error de compilación.

Se puede escribir un fuzzer de servicio C++ automático agregando lo siguiente (los fuzzers de Java y Rust aún no son compatibles):

  • Una entrada cc_fuzz en Android.bp para definir el módulo fuzzer. El módulo cc_default service_fuzzer_defaults tiene dependencias necesarias para fuzzService .
  • Las dependencias específicas del servicio deben agregarse como biblioteca o como fuentes.
  • Un archivo principal que construye su servicio y llama fuzzService

Para obtener instrucciones detalladas sobre el uso cc_fuzz , consulte la documentación Fuzzing con libFuzzer . Para resolver el error de compilación, actualice los enlaces con los nuevos nombres de servicio y fuzzer. Para los servicios Java/Rust, la lista de fuzzer puede estar vacía.