Awesome
HIAFuzz
Hybrid Interface Aware Fuzz for Android Kernel Drivers
This tool is for recovering ioctl interfaces in kernel drivers, which is used in kernel fuzzing.
Tested on
Ubuntu 16.04 LTS
There are two main components of HIAFuzz
: Interface Recovery and Fuzzing Engine
1. Interface Recovery
The interface recovery mechanism is based on gdb analysis on kernel image vmlinux.
1.1 Setup
This tool depends on pygdbmi, which is used for parsing gdb machine interface output with Python.
pip3 install pygdbmi
1.2 Build the Kernel
To run the Interface Recovery components on kernel drivers, we need to first compile the kernel with -g3 option. The following command can be used to replace all -g option to -g3.
for f in `find . -name Makefile`; do sed -i "s/-g /-g3 /g" $f;done
for f in `find . -name Makefile`; do sed -i "s/-g$/-g3/g" $f; done
Then normal steps are taken to build the kernel. Ex:
make defconfig
make -j8 O=out ARCH=arm64
After vmlinux builded, the debug information is in the .debug section. The option -j8 makes 8 threads working in parallel, and in few minutes the kernel will be build.
1.3 Running
Use the following command to run this tool.
python3 gdbioctl.py -h
usage: gdbioctl.py [-h] [-v VMLINUX] [-f DEVICE_IOCTL_FILE]
optional arguments:
-h, --help show this help message and exit
-v VMLINUX Path of the vmlinux image. The recovered ioctls are
stored in this folder.
-f DEVICE_IOCTL_FILE The file that conations ioctl and corresponding device
file names, like /dev/alarm alarm_ioctl.
For example, to analyze the vmlinux of kindle HDX 3rd, we need kindle7_device_ioctl.txt. Use the command
python3 gdbioctl.py -v /path/to/kindle/vmlinux -f /path/to/kindle7_device_ioctl.txt
After a few minutes the recovered interface are in the folder that -v option set.
2. Post Processing
The recovered interfaces are described in text. They should be parsed in to structured xml document. Use the scripts in post_processing to do this job.
cd HIAFuzz/post_processing
$ python run_all.py -h
usage: run_all.py [-h] -f F -o O [-n {manual,auto,hybrid}] [-m M]
run_all options
optional arguments:
-h, --help show this help message and exit
-f F Filename of the ioctl analysis output OR the entire
output directory created by the system
-o O Output directory to store the results. If this
directory does not exist it will be created
-n {manual,auto,hybrid}
Specify devname options. You can choose manual
(specify every name manually), auto (skip anything
that we don't identify a name for), or hybrid (if we
detected a name, we use it, else we ask the user)
-m M Enable multi-device output most ioctls only have one
applicable device node, but some may have multiple. (0
to disable)
python run_all.py -f /path/to/ioctl_finder_out -o output -n auto -m 0
The structured xml documents are in output directory.
3. Fuzzing
The fuzzing tool is Mango Fuzz from difuze.
3.1 Mango Fuzz
MangoFuzz is a simple prototype fuzzer and is based off of Peach (specifically MozPeach).
It's not a particularly sophisticated fuzzer but it does find bugs. It was also built to be easily expandable. There are 2 components to this fuzzer, the fuzz engine and the executor. The executor can be found here, and the fuzz engine can be found here.
3.2 Executor
The executor runs on the phone, listening for data that the fuzz engine will send to it.
Simply compile it for your phones architecture, adb push /data/local/tmp/
it on to the phone, and execute with the port you want it to listen on!
3.3 Fuzz Engine
Note that before the fuzz engine can communicate with the phone, you'll need to use ADB to set up port forwarding e.g. adb forward tcp:2022 tcp:2022
Interfacing with MangoFuzz is fairly simple. You'll want an Engine
object and a Parser
object, which you'll feed your engine into.
From here, you parse jpits with your Parser, and then run the Engine. Easy!
We've provided some simple run scripts to get you started.
To run against specific drivers you can use runner.py
on one of the ioctl folders in the output directory (created by our post processing scripts).
e.g. ./runner.py -f honor8/out/chb -num 1000
. This tells MangoFuzz to run for 1000 iterations against all ioctl command value pairs pertaining to the chb
ioctl/driver.
If instead we want to run against an entire device (phone), you can use dev_runner.py
. e.g. ./dev_runner.py -f honor8/out -num 100
.
This will continue looping over the driver files, randomly switching between them for 100 iterations each.
4. Example
Now, we will show an example from the point where you have kernel sources to the point of getting Interface Recovery results. Download and extract the kernel source of Huawei Mate 9 kernel from MHA-NG_EMUI5.0_opensource.tar.gz from Huawei Open Source Release Center. Lets say you extracted the above file in a folder called: ~/Code_Opensource
4.1 Build the kernel
Use the command to replace -g to -g3.
cd ~/Code_Opensource/kernel
for f in `find . -name Makefile`; do sed -i "s/-g /-g3 /g" $f; done
for f in `find . -name Makefile`; do sed -i "s/-g$/-g3/g" $f; done
#export PATH=$PATH:$(android platform directory you download)/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin
export PATH=$PATH:/workspace/aosp/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin/aarch64-linux-android-gcc
export CROSS_COMPILE=aarch64-linux-android-
mkdir ../out
make ARCH=arm64 O=../out merge_hi3660_defconfig
make ARCH=arm64 O=../out -j8
After a few minutes, the vmlinux of Mate 9 is generated in ../out/.
4.2 Running
Use mate9_device_ioctl.txt provided by this project as input.
python3 gdbioctl.py -v ~/Code_Opensource/out/vmlinux -f ../DriversDevices/mate9_device_ioctl.txt
Tow folders are created in ~/Code_Opensource/out/ called ioctl_finder_out and ioctl_preprocessed_out. All interface recovered are located in ioctl_finder_out and related struct, union, type def and etc. are in ioctl_preprocessed_out.
Use post processing scripts to generated structured document.
cd HIAFuzz/post_processing
python run_all -f ~/Code_Opensource/out/ioctl_finder_out -o xml_output -n auto -m 0
The structured document are in HIAFuzz/post_processing/xml_output. Then:
cd ../MangoFuzz
$ python runner.py -h
usage: runner.py [-h] -f F [-j J] [-seed SEED] [-num NUM] [-a A] [-port PORT]
MangoFuzz options
optional arguments:
-h, --help show this help message and exit
-f F Filename of the jpit, or driver directory containing jpits
-j J Juicer type. Default is TCP
-seed SEED Seed. Default will be time
-num NUM Number of tests to run (if limited). Default is to simply keep
running.
-a A Address to send the data to. Default is localhost
-port PORT Port to send the data to. Default is 2022
You should run the executor in target device and run this script on host.