Fuzzer zachowuje się jak klient usługi zdalnej, importując ją lub wywołując za pomocą wygenerowanego stuba:
Korzystanie z interfejsu 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;
}
Korzystanie z interfejsu 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);
});
Framework do fuzzingu usług AIDL
Jak widać w przykładzie powyżej, w fuzzerze wywoływana jest funkcja fuzzService, która przyjmuje jako parametry wejściowe IBinder (Service) i dataProvider. Najpierw inicjuje losowy obiekt Parcel za pomocą dostawcy danych i wywołuje metodę transact w usłudze zdalnej, używając wejściowego pakietu, a na koniec pobiera odpowiedź do pakietu odpowiedzi.
Tworzenie i uruchamianie narzędzi do testowania fuzzingowego
Fuzzery są domyślnie tworzone z uwzględnieniem pokrycia.
Do wykrywania problemów z pamięcią zalecamy te narzędzia:
hwaddress
narzędzia do czyszczenia działają tylko w architekturze arm
:
SANITIZE_HOST=address SANITIZE_TARGET=hwaddress
Podczas uruchamiania z parametrem libFuzzer
w pliku Android.bp
można określić korpus, czyli katalog, który można przekazać do fuzzera. Niektóre narzędzia do testowania fuzzingowego określają też dictionary:
w pliku Android.bp
, a możesz przekazać to do libFuzzer za pomocą -dict path/to/dict
. Więcej opcji znajdziesz w oficjalnej dokumentacji libFuzzer.
Aby uruchomić narzędzia fuzzingowe na urządzeniu, uruchom polecenie adb sync data
, a potem
adb shell data/fuzz/arch/name/name
.
Aby uruchomić narzędzia fuzzing na hoście, uruchom polecenie
$ANDROID_HOST_OUT/fuzz/arch/name/name
.
Rekomendowanie narzędzi fuzzingowych w przypadku nowych i istniejących usług
System kompilacji sprawdza, czy każdy binder AOSP ma wpis fuzzera w powiązaniach fuzzerów usług.
Test wiązania Fuzzera sprawdza, czy każda usługa w service_contexts
ma fuzzer. Jeśli w przypadku nowej usługi nie zostanie znaleziony fuzzer ani wyjątek, wystąpi błąd kompilacji.
Automatyczny fuzzer usług C++ można utworzyć, dodając te elementy (fuzzery Java i Rust nie są jeszcze obsługiwane):
- Wpis
cc_fuzz
wAndroid.bp
, aby zdefiniować moduł fuzzera. Modułcc_default
service_fuzzer_defaults
ma zależności wymagane w przypadkufuzzService
. - Zależności specyficzne dla usługi należy dodać jako bibliotekę lub źródła.
- główny plik, który tworzy usługę i wywołuje
fuzzService
;
Szczegółowe instrukcje korzystania z cc_fuzz
znajdziesz w dokumentacji Fuzzing with libFuzzer. Aby rozwiązać błąd kompilacji, zaktualizuj powiązania, podając nowe nazwy usługi i fuzzera. W przypadku usług w językach Java lub Rust lista fuzzera może być pusta.