Fuzzing de AIDL

O fuzzer se comporta como um cliente do serviço remoto ao importar ou invocar pelo stub gerado:

Como usar a API 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;
}

Como usar a API 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 fuzz de serviços AIDL

Como mostrado no exemplo acima, fuzzService (link em inglês) é chamado no fuzzer e recebe um IBinder (serviço) e um dataProvider como parâmetros de entrada. Primeiro, ele inicializa um objeto Parcel aleatório usando provedor e chamar o método de transação no serviço remoto usando o pacote de respostas e, finalmente, obter a resposta em um pacote de resposta.

Criar e executar fuzzers

Os fuzzers são criados com cobertura por padrão.

Os limpadores a seguir são recomendados para descobrir problemas de memória. Os limpadores hwaddress só são executados na arquitetura arm:

SANITIZE_HOST=address SANITIZE_TARGET=hwaddress

Ao executar com libFuzzer, um corpus, que é um diretório, pode ser especificado no arquivo Android.bp, e você pode transmitir esse diretório para o fuzzer. Alguns fuzzers também especificam um dictionary: no arquivo Android.bp, e é possível transmiti-lo ao libFuzzer com -dict path/to/dict. Para mais opções, consulte a documentação oficial do libFuzzer.

Para executar fuzzers no dispositivo, execute adb sync data e adb shell data/fuzz/arch/name/name. Para executar os fuzzers no host, execute $ANDROID_HOST_OUT/fuzz/arch/name/name:

O sistema de build verifica se cada serviço de vinculação do AOSP tem uma entrada de fuzzer no vinculações do fuzzer de serviço. O teste de vinculação do Fuzzer verifica se todos os serviços no service_contexts têm uma fuzzer Se um fuzzer ou uma exceção não for encontrado para um novo serviço, haverá um erro de build.

Um fuzzer automático de serviço C++ pode ser escrito adicionando o seguinte (os fuzzers Java e Rust ainda não têm suporte):

  • Uma entrada cc_fuzz em Android.bp para definir o módulo fuzzer. O módulo service_fuzzer_defaults do cc_default tem dependências necessárias para fuzzService.
  • As dependências específicas do serviço precisam ser adicionadas como uma biblioteca ou como origens.
  • Um arquivo principal que constrói seu serviço e chama fuzzService

Para instruções detalhadas sobre como usar cc_fuzz, consulte a Fuzzer com o libFuzzer na documentação do Google Cloud. Para resolver o erro de build, atualize as vinculações com o novo serviço e os nomes do fuzzer. Para serviços Java ou Rust, a lista de fuzzer pode estar vazia.