2 - kAFL workflow#
This section focuses on setting up a development workflow for virtualizing our target with QEMU/KVM and interfacing it with kAFL.
A streamlined workflow enables rapid iterations while adjusting the harness and obtaining feedback from the fuzzing campaign.
Concepts introduced:
kAFL QEMU inputs parameter:
linux-user agent.sh workflow: for a simple yet effective setup targeting Linux userspace and drivers.
kAFL
sharedir
parameter: enables efficient file-based guest-host communication on top of kAFL hypercalls.
Virtualizing our target#
QEMU Image#
Traditional QEMU/KVM virtualization would necessitate creating a complete, bootable QEMU image.
Although feasible, this approach presents several practical challenges:
Download and install a fresh Ubuntu image, or equivalent
Download our kafl target into the VM
Compile it, and configure it to load during the boot sequence.
Export the image and use it as kAFL
qemu_image
parameter
(venv) $ kafl fuzz --image /path/to/ubuntu-target.qcow2
Repeat steps
3-4
on each iteration of the harness or target update
Updating the target in this workflow is cumbersome and may require the VM to be booted or its image restored from a snapshot.
Additionally, you must set up a communication channel with the VM. Several options are available for this, including:
Simple SSH server
Note
The Windows driver example target demonstrates how to combine Packer, Vagrant, and Ansible with WinRM channel to provide a convenient setup.
Direct Kernel Boot and initrd#
Open source kernel and firmware targets can often be booted using QEMUโs Direct Linux Boot feature.
This approach is often more efficient than bootng a full-VM image and easier to customize and script.
(venv) $ kafl fuzz --kernel /path/to/linux/arch/x86/boot/bzImage --initrd /path/to/initrd.cpio.gz
Initrd and agent.sh
workflow#
The approach outlined here relies on crafting a custom initrd that boots into a minimal BusyBox root filesystem.
Weโll utilize kAFLโs sharedir
feature as an expedient communication channel between the host and guest.
This solution is implemented in the ๐ scripts/gen_initrd.sh
.
gen_initrd.sh
#
vmcall
#
The ๐ vmcall
binary is a utility that implements most of the hypercall interface, serving as a convenient tool within the guest environment.
$ echo "Hello from vmcall" | vmcall hcat
$ vmcall hget -x -o /fuzz file.txt
$ vmcall hpush -o "modules" /proc/modules
agent.sh
#
To streamline the development workflow and eliminate the need to recompile the initrd for every target update, loader.sh
downloads an agent.sh
script from the exposed sharedir
, using vmcall
.
The agent.sh scriptโs role is multifaceted. It downloads the dvkm.ko
kernel module, loads it, and then initiates the fuzzing process.
Summary#
With this workflow, we have a flexible setup, ideal to gather feedback, build our harness and make quick iterations !
DVKM workflow setup#
The ๐ linux-user/dvkm
directory structure is organized as follows:
$ ls -l
๐ Damn_Vulnerable_Kernel_Module
๐๏ธ kafl.yaml
๐๏ธ Makefile
๐ sharedir
$ ls -l sharedir
๐๏ธ agent.sh
โก๏ธ dvkm.ko -> ../Damn_Vulnerable_Kernel_Module/dvkm.ko
โก๏ธ fuzz_dvkm -> ../Damn_Vulnerable_Kernel_Module/test_dvkm
$ ls -l Damn_Vulnerable_Kernel_Module/
๐๏ธ dvkm.c
๐๏ธ LICENSE
๐๏ธ Makefile
๐๏ธ Module.symvers
๐๏ธ README.md
๐๏ธ test_dvkm.c
To set up the required dependencies, navigate to the kAFL directory and execute make deploy
:
$ cd kAFL
(venv) $ make deploy -- --tags examples,examples-linux-dvkm
Now, switch to the ๐ linux-user/dvkm
directory to compile the target and its dependencies:
$ cd kafl/examples/linux-user/dvkm
make
You have successfully compiled:
the custom initrd
the Linux kernel with kAFL modifications
the dvkm module
the kafl-agent implemented in
test_dvkm.c
In the next part, we will focus on how to implement a kAFL harness, and look at the implementation details of DVKM !