The fuzzer behaves as a client for the remote service by importing/invoking it through the generated stub:
Using 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;
}
Using 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);
});
Using Java API:
import com.code_intelligence.jazzer.api.FuzzedDataProvider;
import randomparcel.FuzzBinder;
public class ServiceFuzzer {
static {
// Initialize fuzzService and JNI dependencies
FuzzBinder.init();
}
public static void fuzzerTestOneInput(FuzzedDataProvider data) {
TestService service = new TestService();
FuzzBinder.fuzzService(service, data.consumeRemainingAsBytes());
}
}
For build setup, refer to Java Binder Service Fuzzer.
Framework to fuzz AIDL services
As shown in the example above, fuzzService is called in the fuzzer and takes in an IBinder (Service) and dataProvider as input parameters. It first initializes a random Parcel object using the data provider and call the transact method on the remote service by using the input parcel, and finally get the reply into a reply parcel.
Recommending fuzzers for new/existing services
The build system checks whether every AOSP binder service has a fuzzer entry in
service fuzzer bindings.
The Fuzzer binding test checks that every service in service_contexts
has a
fuzzer. If a fuzzer/exception isn't found for a new service, there's a build
error.
An automatic C++ service fuzzer can be written by adding the following (Java and Rust fuzzers are not yet supported):
* a `cc_fuzz` entry in `Android.bp` to define the fuzzer module. `cc_default` module `service_fuzzer_defaults` has dependencies required for `fuzzService`. Service specific dependencies should be added as a library or as sources.
* a main file that constructs your service and calls `fuzzService`
For detailed instructions on using cc_fuzz
, see the
Fuzzing with libFuzzer
documentation. To resolve build error, update bindings with the new service and
fuzzer names. For Java/Rust services, the fuzzer list can be empty.