Фаззер ведет себя как клиент удаленного сервиса, импортируя или вызывая его через сгенерированный заглушку:
Использование C++ API:
#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;
}
Использование Rust API:
#![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);
});
Фреймворк для фаззинга сервисов AIDL
Как показано в примере выше, fuzzService вызывается в фаззере и принимает IBinder (Service) и dataProvider в качестве входных параметров. Сначала он инициализирует случайный объект Parcel, используя поставщика данных, а затем вызывает метод transact для удаленного сервиса, используя входной объект Parcel, и, наконец, получает ответ в объект Parcel ответа.
Как создавать и запускать фаззеры
По умолчанию фаззеры создаются с покрытием.
Для обнаружения проблем с памятью рекомендуется использовать следующие санитайзеры.
Санитайзеры hwaddress работают только на архитектуре arm:
SANITIZE_HOST=address SANITIZE_TARGET=hwaddress
При работе с libFuzzer корпус, представляющий собой каталог, можно указать в файле Android.bp и передать этот каталог фаззеру. Некоторые фаззеры также указывают dictionary: в файле Android.bp. Вы можете передать это значение в libFuzzer с помощью -dict path/to/dict. Дополнительные параметры можно найти в официальной документации по libFuzzer.
Чтобы запустить фаззеры на устройстве, выполните команду adb sync data, а затем adb shell data/fuzz/arch/name/name.
Чтобы запустить фаззеры на хосте, выполните команду
$ANDROID_HOST_OUT/fuzz/arch/name/name.
Рекомендовать фаззеры для новых или существующих сервисов.
Система сборки проверяет, есть ли у каждого сервиса связывания AOSP запись о фазере в файле service fuzzer bindings.
Тест привязки фаззера проверяет, есть ли фаззер у каждого сервиса в service_contexts. Если для нового сервиса не найден фаззер или исключение, возникает ошибка сборки.
Автоматический фаззер для сервиса C++ можно написать, добавив следующий код (фаззеры для Java и Rust пока не поддерживаются):
- Запись
cc_fuzzвAndroid.bpдля определения модуля фаззера. Модульservice_fuzzer_defaults(cc_default) содержит зависимости, необходимые дляfuzzService. - Зависимости, относящиеся к сервису, следует добавлять как библиотеку или как источники.
- Основной файл, который создает сервис и вызывает
fuzzService.
Подробные инструкции по использованию cc_fuzz приведены в документации по фаззингу с помощью libFuzzer. Чтобы устранить ошибку сборки, обновите привязки, указав новые названия сервиса и фаззера. Для сервисов на Java или Rust список фаззеров может быть пустым.