The Fantastic Beasts Framework is a collection of tools for fuzzing the Android OS.
The main, and for now only, tool is called Chizpurfle, a gray-box fuzzer designed to run on actual devices, with a focus on testing vendor-specific system services of Android OS. It was presented at the IEEE ISSRE 2017 conference, and received the best research paper award.
If you want to mention Chizpurfle in a research paper, please cite the following reference:
@inproceedings{iannillo2017chizpurfle,
title={Chizpurfle: A gray-box {Android} fuzzer for vendor service customizations},
author={Iannillo, Antonio Ken and Natella, Roberto and Cotroneo, Domenico and Nita-Rotaru, Cristina},
booktitle={Software Reliability Engineering (ISSRE), 2017 IEEE 28th International Symposium on},
pages={1--11},
year={2017},
organization={IEEE}
}
The framework includes scripts for initializing a fuzzing campaign, by creating the configuration files used by Chizpurfle.
Chizpurfle is a gray-box fuzzer that targets the Binder interfaces of Android system services. It includes an instrumentation module that traces the running service, and provides fine-grained coverage info.
Chizpufle uses a genetic algorithm for generating inputs, and for evolving inputs over time based on coverage info from previous executions. The tool also provide a black-box fuzzing mode (blind random inputs). For more information about the design of the tool, please see check out our research paper.
The tool does not require to recompile the source code of the Android OS. Therefore, it can be adopted for testing any vendor (proprietary, closed-source) customization of the Android OS.
Chizpurfle runs on rooted devices. There is no need to modify the original Android OS.
It supports Android versions 6 and 7, and can target Java-implemented Android services.
Once you cloned the project, you need to attach your Android device to the workstation, and to activate debug options on the device.
To build and install chizpurfle, run:
cd fantastic_beasts
bunzip2 ./chizpurfle/libs/frida-core/libfrida-core.a.bz2
./gradlew installAppProcess
This installs all the necessary files on your device. To check it, run:
adb shell
ls /data/local/tmp
> chizpurfle
> chizpurfle.jar
> chizpurfle.shell
> cli.jar
> libstalker-server.so
> libchizpurfle-native.so
Chizpurfle needs a service/process map file, which depends on the target device.
This file maps each Android system service running in the device with the name of the hosting process.
Some known maps are in chizpurfle/config
project folder.
If your device is not present in this folder, you should create your own map file.
First and former, you must install FRIDA both on your workstation (client) and device (server).
Run the frida server as root, and then kill the Zygote process (forcing a re-inizialization of system services).
adb shell
su
cd /data/local/tmp
./frida-server &
ps | grep zygote
>root 570 1 2132104 78644 poll_sched 7496f24b94 S zygote64
>root 571 1 1568616 67888 poll_sched 00ed08f664 S zygote
kill -9 570 571
As soon as you killed zygote, run:
python init_scripts/create_service_pid_map.py
(Substitute line 81 and 85 with you device id, obtained by adb devices
)
Finally, when the python script ends, save the ps command output.
adb shell
su
ps >> /data/local/tmp/ps.out
chmod 666 /data/local/tmp/ps.out
exit
adb pull /data/local/tmp/ps.out
Now, you should have both service_pid.map and ps.out files. Thus, run:
bash init_scripts/create_process_service_map.sh ps.out service_pid.map
This returns the service_process_name.map file for your device.
Once you have the map file, you have to push it on the device. Run:
cp <map_file> service_process_name.map
adb push service_process_name.map /data/local/tmp
adb shell
su
chmod 666 /data/local/tmp/service_process_name.map
If you want a full model of your device service interfaces, run:
adb shell
su
cd /data/local/tmp
./chizpurfle -e
chmod 666 all_services_interfaces_in_binder.json
exit
adb pull /data/local/tmp/all_services_interfaces_in_binder.json
all_services_interfaces_in_binder.json
is a json file that provides all the service interfaces of your devices.
Chizpurfle entry-point is /data/local/tmp/chizpufle
, and should be executed as root user.
All the output from chizpurfle is not printed on the standard output, but it is instead written on /data/local/tmp/chizpufle.shell
.
To print the help from chizpurfle, run:
adb shell
su
cd /data/local/tmp
./chizpurfle -h
cat chizpurfle.shell
>usage: chizpurfle
> -bb,--black-box uses a blackbox approach
> -e,--extract Extract the model from the smartphone
> -f1,--blocks-counter-fitness-evaluator uses the blocks counter fitness evaluator (default)
> -f2,--branch-execution-fitness-evaluator uses the blocks branch execution evaluator
> -f3,--coarse-branch-hit-fitness-evaluator uses the blocks coarse branch hit evaluator
> -h,--help show help
> -n,--max-generation <arg> the number of generations the populations should pass through (default is 20)
> -process,--process-name <arg> the name of the process to trace
> -s1,--fitness-proportionate-selection uses a fitness proportionate selection algorithm (default)
> -s2,--ranking-selection uses a ranking selection algorithm
> -s3,--tournament-selection uses a tournament selection algorithm
> -service,--service-name <arg> the name of the service under test
>
>Thank you for feeding me!
To test a service with default fitness evaluator and default selection algorithm, run:
adb shell
su
cd /data/local/tmp
./chizpurfle -service <SERVICE_NAME>
To test a service with black-box fuzzing, run instead:
adb shell
su
cd /data/local/tmp
./chizpurfle -bb -n 200 -service <SERVICE_NAME>
The max-generation argument becomes the number of the iterations of the fuzzer.
If you want to trace a process different from the one specified in the service_process_name.map, run:
adb shell
su
cd /data/local/tmp
./chizpurfle -service <SERVICE_NAME> -process <PROCESS_NAME>