[Syzkaller I]Get start
Syzkaller is the start-of-the-art kernel fuzzer.
Syzkaller takes in a collection of syscall descriptions provided by human experts as template , which provide the fuzzer awareness of the type and arguments of syscalls to be called and dependencies between syscalls . Then the fuzzer randomly generates test cases based on the template , start a kernel to run the test cases , meanwhile monitor the kernel state and collect crash reports.
0x0 TL;DR
This post will take a look at the Syzkaller environment setup , and I will provide an ez demo to report a heap overflow in a kernel module. Hopefully my time consuming debugging process can help you . Let’s go.
0x1 setup
0.enable cpu feature kvm
inspect the cpuinfo to make sure cpu support the kvm feature
- for intel:
1 | cat /proc/cpuinfo | grep "vmx" |
- for AMD:
1 | cat /proc/cpuinfo | grep "svm" |
1.setup golang environment
Golang version is 1.23.4 up to that time.
1 | wget https://go.dev/dl/go1.23.4.linux-amd64.tar.gz |
add Gopath to environment
1 | export GOROOT=/path/to/go |
run go version
to check Golang environment
2.build Syzkaller
ensure your golang environment
1 | git clone https://github.com/google/syzkaller/ |
3.compile Linux kernel
take Linux 5.14 for example
1 | wget https://mirrors.edge.kernel.org/pub/linux/kernel/v5.x/linux-5.14.tar.xz |
then append the following CONFIGS to .config
1 | CONFIG_KCOV=y |
more configs :
https://github.com/google/syzkaller/blob/master/docs/linux/kernel_configs.md
the compile the kernel
1 | make -j `nproc` |
this will take for a while when you get a bootable kernel image .
1 | file ./arch/x86/boot/bzImage |
4.build virtual hard disk
to build a disk image with MBR and basic file system
1 | cd /path/to/syzkaller |
this will take for a while when you get bullseye.img as the disk image and two ssh key file
bullseye is the release name of Debian up to that time.
5.build QEMU
1 | apt install qemu-system |
6.run the kernel
1 | qemu-system-x86_64 \ |
Login as root without password
errors :
1 network backend 'user' is not compiled into this binarycheck this post :
https://stackoverflow.com/questions/75641274/network-backend-user-is-not-compiled-into-this-binary
then make sure ssh is avaliable
1 | ssh -i ./image/bullseye.id_rsa -p 10021 -o "StrictHostKeyChecking no" root@localhost |
7.start SyzKaller
1 | cd /path/to/syzkaller |
and edit a config file saved as default.cfg
1 | { |
run Syzkaller by:
1 | ./bin/syz-manager -config=./default.cfg -debug |
meanwhile explorer 127.0.0.1:56741 to get a view of the current fuzzing state
0x2 demo
take a kernel heap overflow for example.
1.build a vulnability kernel module
this module contains a heap overflow in function proc_write, and we will compile it directly into the kernel
up to 4096 bytes can be written to a narrow 512 Byte slab object in cache kmalloc-512
1 |
|
save as linux-5.14/drivers/char/testxy.c
then append following to
linux-5.14/drivers/char/Kconfig
1 | config TESTXY_MODULE |
then append following to
linux-5.14/drivers/char/Makefile
1 | obj-$(CONFIG_TESTXY_MODULE) += testxy.o |
reconfig the kernel with
make menuconfig
we can find the module @Device Drivers/dustball’s vulnability module
*
means compile into the kernel, chosen
M
means compile as independent module
recompile the kernel
1 | make -j `nproc` |
rerun the kernel and check the module loaded
1 | ls /proc/test1 |
2.provide syscall descriptions
2.1 save the following syscall descriptions as
/syzkaller/sys/linux/proc_testxy.txt
1 | include <linux/fs.h> |
more syzlang :
https://github.com/google/syzkaller/blob/master/docs/syscall_descriptions_syntax.md
2.2 extract necessary information like syscall numbers and macro values using syz-extract
1 | cd /path/to/syzkaller |
check syzkaller/sys/linux/proc.testxy.txt.const
when finished
2.3 generate syzkaller-awareness datastructure in golang
1 | cd /path/to/syzkaller |
check syzkaller/executor/syscalls.h
to find read$testxy
when finished
2.4 rebuild Syzkaller
1 | make generate |
3.start Syzkaller
edit a test.cfg file
1 | { |
then run Syzkaller by
1 | cd syzkaller |
visit http://127.0.0.1:56741/ and wait for crash reports