This is a fuzzer that uses libprotobuf-mutator to fuzz the NFC module on an Android device. This can be used on supported Google phones such as Pixel3 and Pixel4. It has been tested on Pixel3a. Currently the NFC forum type 2 tag is implemented.
DISCLAIMER: As using the fuzzer requires OEM unlocking of the device and flashing custom OS. There is a chance of data loss or bricking the device (which may require factory restore). It is recommended that a dedicated research device is used for the purpose and any consequences is at the user's own risk. The author is not liable for any data loss, damage to devices or compromised in security when following these steps. Fuzzing corpus is also considered as trusted input and the author is not liable for any security compromise resulting from using untrusted corpus and would not consider memory corruption bugs in corpus parsing code security bugs. The fuzzer is offer on an AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON- INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
The idea is to modify nfc system library, libnfc-nci.so to create fuzz harnesses and feed it with inputs generated by libprotobuf-mutator. As I do not seem to be able to fuzz with libprotobuf-mutator as a standalone library, the fuzzer needs to include a local copy of the source code of libprotobuf-mutator and compile it together. The directories src
and port
under tools
are the same directories from libprotobuf-mutator. These correspond to commit 9eaf063
of libprotobuf-mutator in the aosp source tree. The reason for using a cached version is that newer versions seem to have introduced some changes which causes the following failure when fuzzing:
/usr/local/google/buildbot/src/android/llvm-toolchain/out/llvm-project/compiler-rt/lib/fuzzer/FuzzerMutate.cpp:510: size_t fuzzer::MutationDispatcher::MutateImpl(uint8_t *, size_t, size_t, Vector<fuzzer::MutationDispatcher::Mutator> &): assertion "MaxSize > 0" failed
First follow the instructions here to obtain a copy of the aosp and initialize it with the master branch.
mkdir AOSP_ROOT
cd AOSP_ROOT
repo init -u https://android.googlesource.com/platform/manifest
repo sync -qc -j$(nproc)
Then obtain the proprietary binaries for your device following instructions here, under the "Obtain proprietary binary" section.
Next set up the build environment and select the product and variant (See instructions here):
cd AOSP_ROOT
source build/envsetup.sh
lunch <product_name>-<build_variant>
For example, environment for a Pixel3a will be
cd AOSP_ROOT
source build/envsetup.sh
lunch aosp_sargo-userdebug
For fuzzing, it is not necessary to build the entire aosp, which will save time and disk space.
In order to compile the protobuf for fuzzing, aprotoc
needs to be built:
make -j($nproc) aprotoc
After that, run the patch.sh
script in this repository's root directory with the aosp root directory as argument, to patch the nfc library code, and to include the fuzzers in the system/nfc
directory (The patch should merges cleanly with commit @cfccaaf
for system/nfc
and commit @6645f5c
for external/protobuf
in the aosp source tree):
./patch.sh AOSP_ROOT
at this point, a directory called tools
will be copied to the system/nfc
directory in the AOSP checkout. This directory contains the fuzzers, as well as tools for generating coverage and debugging.
Then compile the protobuf definitions for fuzzing:
./generate_proto.sh AOSP_ROOT
Following the build instructions from here to build the fuzzer. The available targets can be found in the tools/Android.bp
, with targets of type cc_fuzz
. For example, to build the t2t_detect_fuzzer
, run:
SANITIZE_TARGET=address make -j$(nproc) t2t_detect_fuzzer
To run the fuzzer on device, the Android flash tool can be used. This is a very convenient web service that flashes the latest master build on a device. This avoids the need to build the entire aosp locally. Note that to use the service, OEM needs to be unlock and may also wipe all the user data, so it is recommended to use a dedicated research device for such purpose. These are tested on Android master branch with build number 6331282.
To use the Android flash tool, adb
and fastboot
needs to be installed. These can either be built from the aosp checkout, or install via apt:
make -j($nproc) adb
make -j($nproc) fastboot
Note also that fastboot
also requires extra configurations, see here for some details.
After that, the fuzzer can be copied to the device for fuzzing:
adb root
adb sync data
If adb sync data
failed, the same can be achieved by just copying the data/fuzz
directory in the out/target/product/<product_name>
directory:
adb push AOSP_ROOT/out/target/product/<product_name>/data/fuzz /data
This is now ready for fuzzing on the device:
adb shell
sargo:/ # ASAN_OPTIONS=detect_container_overflow=0 /data/fuzz/arm64/t2t_detect_fuzzer/t2t_detect_fuzzer /data/fuzz/arm64/t2t_detect_fuzzer/corpus
The detect_container_overflow
option may be required as protobuf is not compiled with asan and will cause container_overflow
FP when fuzzing.