# Ubuntu host fuzzing qumu Debian
###### tags: `USB`
## Reference
https://github.com/google/syzkaller/blob/master/docs/linux/setup_ubuntu-host_qemu-vm_x86-64-kernel.md
## Testing Environment
* host machine: Virtualbox (6.1.19) with Ubuntu 20.04
* if using virtualbox for host, need the version of 6.1.19 (since this version support nested virtualization)
* target machine: Debian with ***mainline linux kernel*** (to enable raw gadget, kcov)
## Compiler
* gcc (only gcc 6.1.0 or later support code-coverage)
## Linux Kernel
1. get kernel source code `git clone git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git $KERNEL`
2. generate default config
```
cd $KERNEL
make CC="$GCC/bin/gcc" defconfig
make CC="$GCC/bin/gcc" kvm_guest.config
```
3. Enable kernel config options
* enable features
* coverage collection
```
CONFIG_KCOV=y
CONFIG_KCOV_INSTRUMENT_ALL=y
CONFIG_KCOV_ENABLE_COMPARISONS=y
CONFIG_DEBUG_FS=y
```
* detect memory leak
```
CONFIG_DEBUG_KMEMLEAK=y
```
* show code coverage in web interface
```
CONFIG_DEBUG_INFO=y
```
* show enable syscall and kernel bitness
```
CONFIG_KALLSYMS=y
CONFIG_KALLSYMS_ALL=y
```
* config for creating Debian image
```
CONFIG_CONFIGFS_FS=y
CONFIG_SECURITYFS=y
```
* enable usb fuzzing
* enable CONFIG_USB_RAW_GADGET
* enable CONFIG_USB_DUMMY_HCD
### enable CONFIG_USB_RAW_GADGET
* use below instruction if you could not find CONFIG_USB_RAW_GADGET
```
make menuconfig
# path of usb raw gadget inside menuconfig screen
Device Driver -> USB support -> USB Gadget Support ->
USB Gadget precomposed configurations -> USB Raw Gadget
```
* enable CONFIG_USB_DUMMY_HCD
* the reason of using USB Raw Gadget
* USB raw gadget do not check the packet
* for more information, please see [here](https://www.kernel.org/doc/html/latest/usb/raw-gadget.html)
4. regenerate config `make CC="$GCC/bin/gcc" olddefconfig`
6. build kernel `make CC="$GCC/bin/gcc" -j64
7. check build successful or not
```bash=
$ ls $KERNEL/vmlinux
$KERNEL/vmlinux
$ ls $KERNEL/arch/x86/boot/bzImage
$KERNEL/arch/x86/boot/bzImage
```
## Image
1. install debootstrap `sudo apt-get install debootstrap`
2. create a Debian Stretch Linux image with the minimal set of required packages
```
cd $IMAGE/
wget https://raw.githubusercontent.com/google/syzkaller/master/tools/create-image.sh -O create-image.sh
chmod +x create-image.sh
./create-image.sh
```
3. check the result by `ls $IMAGE/stretch.img`
## VM or Physical device
* could also done on physical device (android device, Odroid C2 boards)
* VM image needs to include networking support (since the fuzzing process communicate with outsisde world)
* run the ssh server in vm (since fuzzer connect with vm through ssh)
### qemu setup
1. install qemu `sudo apt-get install qemu-system-x86`
2. Make sure the kernel boots and sshd starts:
```
qemu-system-x86_64 \
-m 2G \
-smp 2 \
-kernel $KERNEL/arch/x86/boot/bzImage \
-append "console=ttyS0 root=/dev/sda earlyprintk=serial net.ifnames=0" \
-drive file=$IMAGE/stretch.img,format=raw \
-net user,host=10.0.2.10,hostfwd=tcp:127.0.0.1:10021-:22 \
-net nic,model=e1000 \
-enable-kvm \
-nographic \
-pidfile vm.pid \
2>&1 | tee vm.log
```
* -m: assign 2 gigabytes of memory
* -smp 2 assign 2 cpu to the vm
* -kernel: kerenl image
* -append cmdline: as kernel commmand line
* -drive: drive image
* -net: initialized network interface
* -pidfile [file]: write `pid` to [file]
* `2 > &1`: redirect from stderr to stdout
3. ssh to qemu machine to check whether the instance is successfully boot `ssh -i $IMAGE/stretch.id_rsa -p 10021 -o "StrictHostKeyChecking no" root@localhost`
4. kill the qemu instance `kill $(cat vm.pid)`
### bugs on qemu setup (for virtualbox)
when executing the above command in command line, you might encounter this problem `qemu-system-x86_64: failed to initialized KVM: No such file or directory`
* solution: enable nested virtualization
* check whether your cpu enable virtualization
```
$ egrep -c "(svm|vmx)" /proc/cpuinfo
```
* `2` should be listed when the virtualization is enabled
* how to enable nested virtualization: go to `Setting --> System --> Processor` and check the option `Enable Nested VT-x/AMD-V`
* if your virtualbox version is incorrect, you may crash after execute the command
* required virtual box version (6.1.19)
* see how to update virtualbox in [here](https://www.nakivo.com/blog/how-to-update-virtualbox/)
## Syzkaller
1. install `go`
```
wget https://dl.google.com/go/go1.14.2.linux-amd64.tar.gz
tar -xf go1.14.2.linux-amd64.tar.gz
mv go goroot
mkdir gopath
export GOPATH=`pwd`/gopath
export GOROOT=`pwd`/goroot
export PATH=$GOPATH/bin:$PATH
export PATH=$GOROOT/bin:$PATH
```
2. download and build syzkaller
```bash=
go get -u -d github.com/google/syzkaller/prog
cd gopath/src/github.com/google/syzkaller/
make
```
* all build should be in $syzkaller/bin
3. write config file
```
{
"target": "linux/amd64",
"http": "127.0.0.1:56741",
"workdir": "$GOPATH/src/github.com/google/syzkaller/workdir",
"kernel_obj": "$KERNEL",
"image": "$KERNEL/image/stretch.img",
"sshkey": "$KERNEL/image/stretch.id_rsa",
"syzkaller": "$GOPATH/src/github.com/google/syzkaller",
"enable_syscalls": ["syz_usb_connect", "syz_usb_disconnect", "syz_usb_control_io", "syz_usb_ep_write", "syz_usb_ep_read"],
"procs": 4,
"type": "qemu",
"vm": {
"count": 4,
"kernel": "$KERNEL/arch/x86/boot/bzImage",
"cpu": 2,
"mem": 2048,
"cmdline": "dummy_hcd.num=4"
}
}
```
* $KERNEL means your self-compiled linux kernel
4. run the syzkaller by `$GOPATH/syz-manger -config=usb.cfg`