Mobile Security: Harnessing AFL++ for Fuzz Testing

In today’s blog, I’ll show you how to set up AFL++ for fuzzing native libraries (JNI) on Android. This can help uncover new bugs, thereby increasing the attack surface.

AFL++ (American Fuzzy Lop Plus Plus)

AFL++ (American Fuzzy Lop Plus Plus) is an advanced and enhanced version of the original AFL (American Fuzzy Lop) fuzzer. Fuzzing is a software testing technique that involves providing invalid, unexpected, or random data as inputs to a computer program to find bugs and vulnerabilities.

Imagine a program you rely on daily. It could be anything from your web browser to a complex banking application. Unfortunately, even the most well-written software can harbor vulnerabilities. This is where AFL++ comes in – a powerful tool that helps uncover these hidden bugs before they cause problems.

Installation AFL ++

To embark on your fuzzing adventure with AFL++, you’ll need a suitable environment. While Kali Linux is a popular choice, any Linux distribution should work just fine. Here’s a step-by-step guide to get you started:

cd /opt
git clone
git submodule update --init --recursive
cd ..
git clone
cd AFLplusplus
make distrib
sudo make install

To work in an Android environment, we need to download the NDK from this link. I selected version 21. After downloading, unzip the file and save it to the desktop.

Before moving forward, we need to modify a couple of AFL files.

First, navigate to /opt/AFLplusplus/qemu_mode/qemuafl/linux-user/main.c and comment out the signal_init(); line.

Next, open /opt/AFLplusplus/qemu_mode/ and comment out all lines containing the git command.

Now we can compile the tool to work with the aarch64 architecture.

cd /opt/AFLplusplus
sudo CPU_TARGET=aarch64 ./


For our demo, we will create a dummy library in C, simulating that it was extracted from an APK and utilized through JNI (Java Native Interface). The code for this library is as follows (we will name the file libhello.c).


void  sayHello(char name[]){
    char buffer[10] ;
    printf("Hello %s",buffer);

Afterwards, we will also create the harness program that will be utilized by AFL. the harness code that interfaces with AFL++ and your target program. This code will be responsible for reading inputs from AFL++, feeding them to the target program, and capturing the program’s output.


extern void  sayHello(char name[]);

int main(int argc, char const *argv[])
    char buffer[70000];
    FILE *fp = fopen(argv[1], "rw");

    return 0;

The next step is to compile the two file

/home/kali/Desktop/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang libhello.c -o  -shared -fPIC

/home/kali/Desktop/android-ndk-r21e/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android21-clang harness.c -o harness -lhello -L.

Then, we need to configure some variables to ensure that AFL operates correctly.

export QEMU_LD_PREFIX=/opt/qiling/examples/rootfs/arm64_android                  
export QEMU_SET_ENV=LD_LIBRARY_PATH=/home/kali/Desktop/tutorial
mkdir input
echo "AAAA" > input/input.txt

Before to execute the fuzzer we can check if everything it works in the proper way:

AFL_INST_LIBS=1 /opt/AFLplusplus/afl-qemu-trace ./harness input/input.txt

Finally we can execute our fuzzer:

AFL_INST_LIBS=1 /opt/AFLplusplus/afl-fuzz -Q -i input/ -o output  ./harness @@

Within a few seconds, the fuzzer has already crashed the program, and we can locate the results in the output folder. Of course, this is just a demonstration, but a fuzzer could require weeks to uncover something of interest. Additionally, a security engineer needs to conduct a thorough reverse engineering analysis to identify the most suitable functions to fuzz. Functions such as Memcpy and strcpy are among those worth considering. If you enjoyed this blog, please show your support by sharing or giving it a like. If you’d like to read more blogs like this, don’t hesitate to let me know!