Skip to content

Latest commit

 

History

History
131 lines (110 loc) · 8.16 KB

README.md

File metadata and controls

131 lines (110 loc) · 8.16 KB

Sloth 🦥

Sloth is a fuzzing setup that makes use of libFuzzer and QEMU’s user-mode emulation (qemu/linux-user) on x86_64/aarch64 host to emulate aarch64 Android libraries to fuzz the target Android native library.

Introduction

Sloth makes use of libFuzzer and QEMU’s user-mode emulation (qemu/linux-user) on x86_64/aarch64 host to emulate aarch64 Android libraries to fuzz the target Android native library. Internals of why and how about Sloth are available at : https://fuzzing.science/blog/Fuzzing-Android-Native-libraries-with-libFuzzer-Qemu

High level execution flow of QEMU user-mode emulation:

QEMU linux-user flow

Build Instructions

To build and launch the docker container:

export image="sloth:v1"
docker build -t $image .
docker run --rm -v `pwd`/resources/rootfs:/rootfs -v `pwd`/resources/examples:/examples -it $image bash

Check resources/examples folder to build an example android native library.

Usage:

You can copy the /system/ from a rooted Android device into resources/rootfs directory.

In the examples folder, check the signature of libQemuFuzzerTestOneInput function in jni/lib/fuzz.cpp file. This function is equivalent to LLVMFuzzerTestOneInput function that we define when creating any libFuzzer harness.

To compile the sample from examples:

cd examples/jni
ndk-build

This builds and generates libBooFuzz.so and an executable boofuzz. Copy libBooFuzz.so to rootfs/system/lib64/ and boofuzz to /rootfs/

root@b7d9fb6a454e:/examples/jni# make
root@b7d9fb6a454e:/examples/jni# cp ../libs/arm64-v8a/libBooFuzz.so /rootfs/system/lib64/
root@b7d9fb6a454e:/examples/jni# cp ../libs/arm64-v8a/boofuzz /rootfs/
root@b7d9fb6a454e:/examples/jni# 

Add your target library path that exports libQemuFuzzerTestOneInput (libBooFuzz.so in our example) to SLOTH_TARGET_LIBRARY env variable.

To start fuzzing:

root@45d7511a2802:/sloth/src# SLOTH_TARGET_LIBRARY=/rootfs/system/lib64/libBooFuzz.so ./sloth /rootfs/boofuzz test/
==== SLOTH ====
WARNING: Failed to find function "__sanitizer_acquire_crash_state".
WARNING: Failed to find function "__sanitizer_print_stack_trace".
WARNING: Failed to find function "__sanitizer_set_death_callback".
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 557648595
INFO: 65536 Extra Counters
INFO:        1 files found in test/
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: seed corpus: files: 1 min: 6b max: 6b total: 6b rss: 66Mb
#2	INITED ft: 3 corp: 1/6b exec/s: 0 rss: 66Mb
#10	REDUCE ft: 3 corp: 1/4b lim: 6 exec/s: 0 rss: 66Mb L: 4/4 MS: 3 CopyPart-CopyPart-CrossOver-
#11	REDUCE ft: 3 corp: 1/2b lim: 6 exec/s: 0 rss: 66Mb L: 2/2 MS: 1 EraseBytes-
#12	REDUCE ft: 3 corp: 1/1b lim: 6 exec/s: 0 rss: 66Mb L: 1/1 MS: 1 EraseBytes-
#4655	REDUCE ft: 5 corp: 2/37b lim: 48 exec/s: 0 rss: 66Mb L: 36/36 MS: 3 ShuffleBytes-ChangeBit-InsertRepeatedBytes-
#4676	REDUCE ft: 5 corp: 2/20b lim: 48 exec/s: 0 rss: 66Mb L: 19/19 MS: 1 EraseBytes-
#4694	REDUCE ft: 5 corp: 2/11b lim: 48 exec/s: 0 rss: 66Mb L: 10/10 MS: 3 ChangeBinInt-ChangeBinInt-EraseBytes-
#4710	REDUCE ft: 5 corp: 2/7b lim: 48 exec/s: 0 rss: 66Mb L: 6/6 MS: 1 EraseBytes-
#4736	REDUCE ft: 5 corp: 2/5b lim: 48 exec/s: 0 rss: 66Mb L: 4/4 MS: 1 EraseBytes-
#4830	REDUCE ft: 5 corp: 2/3b lim: 48 exec/s: 0 rss: 66Mb L: 2/2 MS: 4 ChangeByte-CopyPart-ChangeByte-CrossOver-
#4896	REDUCE ft: 5 corp: 2/2b lim: 48 exec/s: 0 rss: 66Mb L: 1/1 MS: 1 EraseBytes-
#36480	REDUCE ft: 7 corp: 3/4b lim: 357 exec/s: 0 rss: 66Mb L: 2/2 MS: 4 ShuffleBytes-CrossOver-ShuffleBytes-ChangeByte-
#89256	NEW    ft: 9 corp: 4/26b lim: 877 exec/s: 0 rss: 66Mb L: 22/22 MS: 1 InsertRepeatedBytes-
#89282	REDUCE ft: 9 corp: 4/21b lim: 877 exec/s: 0 rss: 66Mb L: 17/17 MS: 1 EraseBytes-
#89288	REDUCE ft: 9 corp: 4/16b lim: 877 exec/s: 0 rss: 66Mb L: 12/12 MS: 1 EraseBytes-
#89407	REDUCE ft: 9 corp: 4/14b lim: 877 exec/s: 0 rss: 66Mb L: 10/10 MS: 4 ChangeBinInt-InsertByte-ChangeBinInt-EraseBytes-
#89458	REDUCE ft: 9 corp: 4/13b lim: 877 exec/s: 0 rss: 66Mb L: 9/9 MS: 1 EraseBytes-
#89480	REDUCE ft: 9 corp: 4/11b lim: 877 exec/s: 0 rss: 66Mb L: 7/7 MS: 2 ShuffleBytes-EraseBytes-
#89496	REDUCE ft: 9 corp: 4/10b lim: 877 exec/s: 0 rss: 66Mb L: 6/6 MS: 1 EraseBytes-
#89647	REDUCE ft: 9 corp: 4/8b lim: 877 exec/s: 0 rss: 66Mb L: 4/4 MS: 1 EraseBytes-
#92983	REDUCE ft: 9 corp: 4/7b lim: 904 exec/s: 0 rss: 66Mb L: 3/3 MS: 1 EraseBytes-
#350518	REDUCE ft: 11 corp: 5/77b lim: 3458 exec/s: 350518 rss: 66Mb L: 70/70 MS: 2 ShuffleBytes-InsertRepeatedBytes-
#350594	REDUCE ft: 11 corp: 5/44b lim: 3458 exec/s: 350594 rss: 66Mb L: 37/37 MS: 1 EraseBytes-
#350611	REDUCE ft: 11 corp: 5/28b lim: 3458 exec/s: 350611 rss: 66Mb L: 21/21 MS: 2 ChangeBinInt-EraseBytes-
#350787	REDUCE ft: 11 corp: 5/26b lim: 3458 exec/s: 350787 rss: 66Mb L: 19/19 MS: 1 EraseBytes-
#350994	REDUCE ft: 11 corp: 5/22b lim: 3458 exec/s: 350994 rss: 66Mb L: 15/15 MS: 2 InsertByte-EraseBytes-
#351305	REDUCE ft: 11 corp: 5/21b lim: 3458 exec/s: 351305 rss: 66Mb L: 14/14 MS: 1 EraseBytes-
#351466	REDUCE ft: 11 corp: 5/19b lim: 3458 exec/s: 351466 rss: 66Mb L: 12/12 MS: 1 EraseBytes-
#351487	REDUCE ft: 11 corp: 5/18b lim: 3458 exec/s: 351487 rss: 66Mb L: 11/11 MS: 1 EraseBytes-
#351753	REDUCE ft: 11 corp: 5/16b lim: 3458 exec/s: 351753 rss: 66Mb L: 9/9 MS: 1 EraseBytes-
#351760	REDUCE ft: 11 corp: 5/15b lim: 3458 exec/s: 351760 rss: 66Mb L: 8/8 MS: 2 ChangeBit-EraseBytes-
#351867	REDUCE ft: 11 corp: 5/13b lim: 3458 exec/s: 351867 rss: 66Mb L: 6/6 MS: 2 ChangeBit-EraseBytes-
#352673	REDUCE ft: 11 corp: 5/12b lim: 3458 exec/s: 352673 rss: 66Mb L: 5/5 MS: 1 EraseBytes-
#524288	pulse  ft: 11 corp: 5/12b lim: 4096 exec/s: 262144 rss: 66Mb
#1048576	pulse  ft: 11 corp: 5/12b lim: 4096 exec/s: 209715 rss: 66Mb
==17== ERROR: libFuzzer: deadly signal
NOTE: libFuzzer has rudimentary signal handlers.
      Combine libFuzzer with AddressSanitizer or similar for better crash reports.
SUMMARY: libFuzzer: deadly signal
MS: 2 CMP-InsertRepeatedBytes- DE: "\x18\xd6^\x04U\x00\x00\x00"-; base unit: 4504839cf31d63eae201804d840610ae0ffcecea
0xde,0xad,0xbe,0x6f,0xef,0x18,0xd6,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0xca,0x5e,0x4,0x55,0x0,0x0,0x0,
\xde\xad\xbeo\xef\x18\xd6\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca\xca^\x04U\x00\x00\x00
artifact_prefix='./'; Test unit written to ./crash-7ac2928ac40e554032d95ebc28cdccd7ee133b1a
Base64: 3q2+b+8Y1srKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKysrKyl4EVQAAAA==

root@c4627f563a99:/rootfs/src# ls
Makefile  crash-7ac2928ac40e554032d95ebc28cdccd7ee133b1a  fuzzer  qemu  sloth  sloth.c  test

root@45d7511a2802:/sloth/src# xxd crash-7ac2928ac40e554032d95ebc28cdccd7ee133b1a 
00000000: dead be6f ef18 d6ca caca caca caca caca  ...o............
00000010: caca caca caca caca caca caca caca caca  ................
00000020: caca caca caca caca caca caca caca caca  ................
00000030: caca caca caca caca caca caca caca caca  ................
00000040: caca caca caca caca caca caca caca caca  ................
00000050: caca caca caca caca 5e04 5500 0000       ........^.U...

Happy Fuzzing :)

TODO

  • Fix signal handling in QEMU for libFuzzer to handle
  • Use QEMU as a library
  • Fuzzing support for Android JNI libraries
  • Make sure this is thread safe since I moved some variables to global.
  • Add CMP coverage
  • Add ASAN

Credits