h2 id=introductionIntroduction/h2
pThis article introduces VirtualBox research and explains how to build a coverage-based fuzzer, focusing on the emulated network device drivers. In the examples below, we explain how to create a harness for the non-default network device driver emPCNet/em. The example can be readily adjusted for a different network driver or even different device driver components./p
pWe are aware that there are excellent resources related to this topic - see [1], [2]. However, these cover the fuzzing process from a high-level perspective or omit some important technical details. Our goal is to present all the necessary steps and code required to instrument and debug the latest a href=https://download.virtualbox.org/virtualbox/LATEST-STABLE.TXTstable/a version of VirtualBox (6.1.30 at the time of writing). As the SVN version is out-of-sync, we download the a href=https://download.virtualbox.org/virtualboxtarball/a instead./p
pIn our setup, we use Ubuntu 20.04.3 LTS. As the VT-x/AMD-V feature is not fully supported for VirtualBox, we use a native host. When using a MacBook, the following a href=https://florisvanbreugel.wordpress.com/2018/03/23/installing-ubuntu-on-an-external-ssd-drive-on-a-macbook/guide/a enables a Linux installation to an external SSD./p
pVirtualBox uses the a href=https://www.virtualbox.org/wiki/kBuildkBuild/a framework for building. As mentioned on their page, only a few (0.5) people on our planet understand it, but editing makefiles should be straightforward. As we will see later, after commenting out hardware-specific components, thatβs indeed true./p
pemkmk/em is a kBuild alternative for the emmake/em subsystem. It allows creating debug or release builds, depending on the supplied arguments. The debug build provides a robust logging mechanism, which we will describe next./p
pNote that in this article, we will use three different builds. The remaining two release builds are for fuzzing and coverage reporting. Because they involve modifying the source code, we use a separate directory for every instance./p
h2 id=debug-buildDebug Build/h2
pThe build instructions for Linux are described a href=https://www.virtualbox.org/wiki/Linux%20build%20instructionshere/a. After installing all required dependencies, itβs enough to run the following commands:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ ./configure --disable-hardening --disable-docs
$ source ./env.sh amp;amp; kmk KBUILD_TYPE=debug
/code/pre/div/div
pIf successful, the binary code class=language-plaintext highlighter-rougeVirtualBox/code from the code class=language-plaintext highlighter-rougeout/linux.amd64/debug/bin/VirtualBox/code directory will be created. Before creating our first guest host, we have to compile and load the kernel modules:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ VERSION=6.1.30
$ vbox_dir=~/VirtualBox-$VERSION-debug/
$ (cd $vbox_dir/out/linux.amd64/debug/bin/src/vboxdrv amp;amp; sudo make amp;amp; sudo insmod vboxdrv.ko)
$ (cd $vbox_dir/out/linux.amd64/debug/bin/src/vboxnetflt amp;amp; sudo make amp;amp; sudo insmod vboxnetflt.ko)
$ (cd $vbox_dir/out/linux.amd64/debug/bin/src/vboxnetadp amp;amp; sudo make amp;amp; sudo insmod vboxnetadp.ko)
/code/pre/div/div
pVirtualBox defines the code class=language-plaintext highlighter-rougeVBOXLOGGROUP/code enum inside code class=language-plaintext highlighter-rougeinclude/VBox/log.h/code, allowing to selectively enable the logging of specific files or functionalities. Unfortunately, since the logging is intended for the debug builds, we could not enable this functionality in the release build without making many cumbersome changes./p
pUnlike the code class=language-plaintext highlighter-rougeVirtualBox/code binary, the code class=language-plaintext highlighter-rougeVBoxHeadless/code startup utility located in the same directory allows running the machines directly from the command-line interface. For illustration, we want to enable debugging for both this component and the PCNet network driver. First, we have to identify the entries of the code class=language-plaintext highlighter-rougeVBOXLOGGROUP/code. They are defined using the code class=language-plaintext highlighter-rougeLOG_GROUP_/code string near the beginning of the file we wish to trace:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ grep LOG_GROUP_ src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp src/VBox/Devices/Network/DevPCNet.cpp
src/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp:#define LOG_GROUP LOG_GROUP_GUI
src/VBox/Devices/Network/DevPCNet.cpp:#define LOG_GROUP LOG_GROUP_DEV_PCNET
/code/pre/div/div
pWe redirect the output to the terminal instead of creating log files and specify the emLog Group/em name, using the lowercased string from the grep output and without the prefix:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ export VBOX_LOG_DEST=nofile stdout
$ VBOX_LOG=+gui.e.l.f+dev_pcnet.e.l.f.l2 out/linux.amd64/debug/bin/VBoxHeadless -startvm vm-test
/code/pre/div/div
pThe VirtualBox logging facility and the meaning of all parameters are clarified a href=https://www.virtualbox.org/wiki/VBoxLogginghere/a. The output is easy to grep, and itβs crucial for understanding the internal structures./p
h2 id=afl-instrumentation-for-afl-clang-fast--afl-clang-fastAFL instrumentation for afl-clang-fast / afl-clang-fast++/h2
h3 id=installing-clangInstalling Clang/h3
pFor Ubuntu, we can follow the official a href=https://apt.llvm.org/instructions/a to install the Clang compiler. We used code class=language-plaintext highlighter-rougeclang-12/code, because building was not possible with the previous version. Alternatively, code class=language-plaintext highlighter-rougeclang-13/code is supported too. After we are done, it is useful to verify the installation and create symlinks to ensure a href=https://github.com/AFLplusplus/AFLplusplusAFLplusplus/a will not complain about missing locations:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ rehash
$ clang --version
$ clang++ --version
$ llvm-config --version
$ llvm-ar --version
$ sudo ln -sf /usr/bin/llvm-config-12 /usr/bin/llvm-config
$ sudo ln -sf /usr/bin/clang++-12 /usr/bin/clang++
$ sudo ln -sf /usr/bin/clang-12 /usr/bin/clang
$ sudo ln -sf /usr/bin/llvm-ar-12 /usr/bin/llvm-ar
/code/pre/div/div
h3 id=building-aflplusplus-aflBuilding AFLplusplus (AFL++)/h3
pOur fuzzer of choice was AFL++, although everything can be trivially reproduced with a href=https://llvm.org/docs/LibFuzzer.htmllibFuzzer/a too. Since we donβt need the black box instrumentation, itβs enough to include the code class=language-plaintext highlighter-rougesource-only/code parts:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ git clone https://github.com/AFLplusplus/AFLplusplus
$ cd AFLplusplus
# use this revision if the VirtualBox compilation fails
$ git checkout 66ca8618ea3ae1506c96a38ef41b5f04387ab560
$ make source-only
$ sudo make install
/code/pre/div/div
h3 id=applying-patchesApplying patches/h3
pTo use clang for fuzzing, itβs necessary to create a new template code class=language-plaintext highlighter-rougekBuild/tools/AFL.kmk/code by using the code class=language-plaintext highlighter-rougevbox-fuzz/AFL.kmk/code file, available on a href=https://github.com/doyensec/vbox-fuzzhttps://github.com/doyensec/vbox-fuzz/a./p
pMoreover, we have to fix multiple issues related to undefined symbols or different commentary styles. The most important change is disabling the instrumentation for Ring-0 components (code class=language-plaintext highlighter-rougeTEMPLATE_VBoxR0_TOOL/code). Otherwise itβs not possible to boot the guest machine. All these changes are included in the patch files./p
pInterestingly, when I was investigating the error message I obtained during the failed compilation, I found some recent a href=https://conference.hitb.org/hitbsecconf2021ams/materials/D2T2%20-%20Discovering%2010+%20Vulnerabilities%20in%20Virtualbox%20-%20Chen%20Nan.pdfslides/a from the HITB conference describing exactly the same issue. This was a confirmation that I was on the right track, and more people were trying the same approach. The slides also mention code class=language-plaintext highlighter-rougeVBoxHeadless,/code which was a natural choice for a harness, that we used too./p
pIf the unmodified VirtualBox is located inside the code class=language-plaintext highlighter-rouge~/VirtualBox-6.1.30-release-afl/code directory, we run these commands to apply all necessary patches:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ TO_PATCH=6.1.30
$ SRC_PATCH=6.1.30
$ cd ~/VirtualBox-$TO_PATCH-release-afl
$ patch -p1 lt; ~/vbox-fuzz/$SRC_PATCH/Config.patch
$ patch -p1 lt; ~/vbox-fuzz/$SRC_PATCH/undefined_xfree86.patch
$ patch -p1 lt; ~/vbox-fuzz/$SRC_PATCH/DevVGA-SVGA3d-glLdr.patch
$ patch -p1 lt; ~/vbox-fuzz/$SRC_PATCH/VBoxDTraceLibCWrappers.patch
$ patch -p1 lt; ~/vbox-fuzz/$SRC_PATCH/os_Linux_x86_64.patch
/code/pre/div/div
pRunning code class=language-plaintext highlighter-rougekmk/code without code class=language-plaintext highlighter-rougeKBUILD_TYPE/code yields instrumented binaries, where the device drivers are bundled inside code class=language-plaintext highlighter-rougeVBoxDD.so/code shared object. The output from code class=language-plaintext highlighter-rougenm/code confirms the presence of the instrumentation symbols:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ nm out/linux.amd64/release/bin/VBoxDD.so | egrep afl|sancov
U __afl_area_ptr
U __afl_coverage_discard
U __afl_coverage_off
U __afl_coverage_on
U __afl_coverage_skip
000000000033e124 d __afl_selective_coverage
0000000000028030 t sancov.module_ctor_trace_pc_guard
000000000033f5a0 d __start___sancov_guards
000000000036f158 d __stop___sancov_guards
/code/pre/div/div
h2 id=creating-coverage-reportsCreating Coverage Reports/h2
pFirst, we have to apply the patches for AFL, described in the previous section. After that, we copy the instrumented version and remove the earlier compiled binaries if they are present:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ VERSION=6.1.30
$ cp -r ~/VirtualBox-$VERSION-release-afl ~/VirtualBox-$VERSION-release-afl-gcov
$ cd ~/VirtualBox-$VERSION-release-afl-gcov
$ rm -rf out
/code/pre/div/div
pNow we have to edit the code class=language-plaintext highlighter-rougekBuild/tools/AFL.kmk/code template to append code class=language-plaintext highlighter-rouge-fprofile-instr-generate -fcoverage-mapping/code switches as follows:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcodeTOOL_AFL_CC ?= afl-clang-fast$(HOSTSUFF_EXE) -m64 -fprofile-instr-generate -fcoverage-mapping
TOOL_AFL_CXX ?= afl-clang-fast++$(HOSTSUFF_EXE) -m64 -fprofile-instr-generate -fcoverage-mapping
TOOL_AFL_AS ?= afl-clang-fast$(HOSTSUFF_EXE) -m64 -fprofile-instr-generate -fcoverage-mapping
TOOL_AFL_LD ?= afl-clang-fast++$(HOSTSUFF_EXE) -m64 -fprofile-instr-generate -fcoverage-mapping
/code/pre/div/div
pTo avoid duplication, we share the code class=language-plaintext highlighter-rougesrc/code and code class=language-plaintext highlighter-rougeinclude/code folders with the fuzzing build:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ rm -rf ./src
$ rm -rf ./include
$ ln -s ../VirtualBox-$VERSION-release-afl/src $PWD/src
$ ln -s ../VirtualBox-$VERSION-release-afl/include $PWD/include
/code/pre/div/div
pLastly, we expand the list of undefined symbols inside code class=language-plaintext highlighter-rougesrc/VBox/Additions/x11/undefined_xfree86/code by adding:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcodeftell
uname
strerror
mkdir
__cxa_atexit
fclose
fileno
fdopen
strrchr
fseek
fopen
ftello
prctl
strtol
getpid
mmap
getpagesize
strdup
/code/pre/div/div
pFurthermore, because this build is intended for reporting only, we disable all unnecessary features:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ ./configure --disable-hardening --disable-docs --disable-java --disable-qt
$ source ./env.sh amp;amp; kmk
/code/pre/div/div
pThe raw profile is generated by setting code class=language-plaintext highlighter-rougeLLVM_PROFILE_FILE/code. For more information, the a href=https://releases.llvm.org/12.0.0/tools/clang/docs/SourceBasedCodeCoverage.htmlClang documentation/a provides the necessary details./p
h2 id=writing-a-harnessWriting a harness/h2
h3 id=getting-pvmGetting pVM/h3
pAt this point, the VirtualBox drivers are fully instrumented, and the only remaining thing left before we start fuzzing is a harness. The PCNet device driver is defined in code class=language-plaintext highlighter-rougesrc/VBox/Devices/Network/DevPCNet.cpp/code, and it exports several functions. Our output is truncated to include only R3 components, as these are the ones we are targeting:/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=cm/**
* The device registration structure.
*//span
span class=kconst/span span class=nPDMDEVREG/span span class=ng_DevicePCNet/span span class=o=/span
span class=p{/span
span class=cm/* .u32Version = *//span span class=nPDM_DEVREG_VERSION/spanspan class=p,/span
span class=cm/* .uReserved0 = *//span span class=mi0/spanspan class=p,/span
span class=cm/* .szName = *//span span class=spcnet/spanspan class=p,/span
span class=cp#ifdef PCNET_GC_ENABLED
/span span class=cm/* .fFlags = *//span span class=nPDM_DEVREG_FLAGS_DEFAULT_BITS/span span class=o|/span span class=nPDM_DEVREG_FLAGS_RZ/span span class=o|/span span class=nPDM_DEVREG_FLAGS_NEW_STYLE/spanspan class=p,/span
span class=cp#else
/span span class=cm/* .fFlags = *//span span class=nPDM_DEVREG_FLAGS_DEFAULT_BITS/spanspan class=p,/span
span class=cp#endif
/span span class=cm/* .fClass = *//span span class=nPDM_DEVREG_CLASS_NETWORK/spanspan class=p,/span
span class=cm/* .cMaxInstances = *//span span class=o~/spanspan class=mi0U/spanspan class=p,/span
span class=cm/* .uSharedVersion = *//span span class=mi42/spanspan class=p,/span
span class=cm/* .cbInstanceShared = *//span span class=ksizeof/spanspan class=p(/spanspan class=nPCNETSTATE/spanspan class=p),/span
span class=cm/* .cbInstanceCC = *//span span class=ksizeof/spanspan class=p(/spanspan class=nPCNETSTATECC/spanspan class=p),/span
span class=cm/* .cbInstanceRC = *//span span class=ksizeof/spanspan class=p(/spanspan class=nPCNETSTATERC/spanspan class=p),/span
span class=cm/* .cMaxPciDevices = *//span span class=mi1/spanspan class=p,/span
span class=cm/* .cMaxMsixVectors = *//span span class=mi0/spanspan class=p,/span
span class=cm/* .pszDescription = *//span span class=sAMD PCnet Ethernet controller./spanspan class=se\n/spanspan class=s/spanspan class=p,/span
span class=cp#if defined(IN_RING3)
/span span class=cm/* .pszRCMod = *//span span class=sVBoxDDRC.rc/spanspan class=p,/span
span class=cm/* .pszR0Mod = *//span span class=sVBoxDDR0.r0/spanspan class=p,/span
span class=cm/* .pfnConstruct = *//span span class=npcnetR3Construct/spanspan class=p,/span
span class=cm/* .pfnDestruct = *//span span class=npcnetR3Destruct/spanspan class=p,/span
span class=cm/* .pfnRelocate = *//span span class=npcnetR3Relocate/spanspan class=p,/span
span class=cm/* .pfnMemSetup = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnPowerOn = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnReset = *//span span class=npcnetR3Reset/spanspan class=p,/span
span class=cm/* .pfnSuspend = *//span span class=npcnetR3Suspend/spanspan class=p,/span
span class=cm/* .pfnResume = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnAttach = *//span span class=npcnetR3Attach/spanspan class=p,/span
span class=cm/* .pfnDetach = *//span span class=npcnetR3Detach/spanspan class=p,/span
span class=cm/* .pfnQueryInterface = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnInitComplete = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnPowerOff = *//span span class=npcnetR3PowerOff/spanspan class=p,/span
span class=cm/* .pfnSoftReset = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnReserved0 = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnReserved1 = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnReserved2 = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnReserved3 = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnReserved4 = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnReserved5 = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnReserved6 = *//span span class=nbNULL/spanspan class=p,/span
span class=cm/* .pfnReserved7 = *//span span class=nbNULL/spanspan class=p,/span
span class=cp#elif defined(IN_RING0)
/spanspan class=c1// [ SNIP ]/span
/code/pre/div/div
pThe most interesting fields are code class=language-plaintext highlighter-rouge.pfnReset,/code which resets the driverβs state, and the code class=language-plaintext highlighter-rouge.pfnReserved/code functions. The latter ones are currently not used, but we can add our own functions and call them, by modifying the PDM (Pluggable Device Manager) header files. PDM is an abstract interface used to add new virtual devices relatively easily./p
pBut first, if we want to use the modified code class=language-plaintext highlighter-rougeVboxHeadless/code, which provides a high-level interface (a href=https://www.virtualbox.org/sdkref/annotated.htmlVirtualBox Main API/a) to the VirtualBox functionality, we need to find a way to access the code class=language-plaintext highlighter-rougepdm/code structure./p
pBy reading the source code, we can see multiple patterns where code class=language-plaintext highlighter-rougepVM/code (pointer to a VM handle) is dereferenced to traverse a linked list with all device instances:/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=c1// src/VBox/VMM/VMMR3/PDMDevice.cpp/span
span class=kfor/span span class=p(/spanspan class=nPPDMDEVINS/span span class=npDevIns/span span class=o=/span span class=npVM/spanspan class=o-gt;/spanspan class=npdm/spanspan class=p./spanspan class=ns/spanspan class=p./spanspan class=npDevInstances/spanspan class=p;/span span class=npDevIns/spanspan class=p;/span span class=npDevIns/span span class=o=/span span class=npDevIns/spanspan class=o-gt;/spanspan class=nInternal/spanspan class=p./spanspan class=ns/spanspan class=p./spanspan class=npNextR3/spanspan class=p)/span
span class=p{/span
span class=c1// [ SNIP ]/span
span class=p}/span
/code/pre/div/div
pThe VirtualBox Main API on non-Windows platforms uses Mozilla a href=https://en.wikipedia.org/wiki/XPCOMXPCOM/a. So we wanted to find out if we could leverage it to access the low-level structures. After some digging, we found out that indeed itβs possible to retrieve the VM handle via the code class=language-plaintext highlighter-rougeIMachineDebugger/code class:/p
pimg src=../../../public/images/vbox-imachinedebugger.png width=750 alt=IMachineDebugger VM align=center //p
pWith that, the following snippet of code demonstrates how to access code class=language-plaintext highlighter-rougepVM/code:/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=nLONG64/span span class=nllVM/spanspan class=p;/span
span class=nHRESULT/span span class=nhrc/span span class=o=/span span class=nmachineDebugger/spanspan class=o-gt;/spanspan class=nCOMGETTER/spanspan class=p(/spanspan class=nVM/spanspan class=p)(/spanspan class=oamp;/spanspan class=nllVM/spanspan class=p);/span
span class=nPUVM/span span class=npUVM/span span class=o=/span span class=p(/spanspan class=nPUVM/spanspan class=p)(/spanspan class=ktintptr_t/spanspan class=p)/spanspan class=nllVM/spanspan class=p;/span span class=cm/* The user mode VM handle *//span
span class=nPVM/span span class=npVM/span span class=o=/span span class=npUVM/spanspan class=o-gt;/spanspan class=npVM/spanspan class=p;/span
/code/pre/div/div
pAfter obtaining the pointer to the VM, we have to change the build scripts again, allowing code class=language-plaintext highlighter-rougeVboxHeadless/code to access internal PDM definitions from code class=language-plaintext highlighter-rougeVBoxHeadless.cpp/code./p
pWe tried to minimize the amount of changes and after some experimentation, we came up with the following steps:/p
p1) Create a new file called code class=language-plaintext highlighter-rougesrc/VBox/Frontends/Common/harness.h/code with this content:/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=cm/* without this, include/VBox/vmm/pdmtask.h does not import PDMTASKTYPE enum *//span
span class=cp#define VBOX_IN_VMM 1
/span
span class=cp#include PDMInternal.h
/span
span class=cm/* needed by machineDebugger COM VM getter *//span
span class=cp#include lt;VBox/vmm/vm.hgt;
#include lt;VBox/vmm/uvm.hgt;
/span
span class=cm/* needed by AFL *//span
span class=cp#include lt;unistd.hgt;
/span/code/pre/div/div
p2) Modify the code class=language-plaintext highlighter-rougesrc/VBox/Frontends/VBoxHeadless/VBoxHeadless.cpp/code file by adding the following code just before the event loop starts, near the end of the file:/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcode span class=nLogRel/spanspan class=p((/spanspan class=sVBoxHeadless: failed to start windows message monitor: %Rrc/spanspan class=se\n/spanspan class=s/spanspan class=p,/span span class=nirc/spanspan class=p));/span
span class=cp#endif /spanspan class=cm/* RT_OS_WINDOWS *//spanspan class=cp
/span
span class=cm/* --------------- BEGIN --------------- *//span
span class=nLONG64/span span class=nllVM/spanspan class=p;/span
span class=nHRESULT/span span class=nhrc/span span class=o=/span span class=nmachineDebugger/spanspan class=o-gt;/spanspan class=nCOMGETTER/spanspan class=p(/spanspan class=nVM/spanspan class=p)(/spanspan class=oamp;/spanspan class=nllVM/spanspan class=p);/span
span class=nPUVM/span span class=npUVM/span span class=o=/span span class=p(/spanspan class=nPUVM/spanspan class=p)(/spanspan class=ktintptr_t/spanspan class=p)/spanspan class=nllVM/spanspan class=p;/span span class=cm/* The user mode VM handle *//span
span class=nPVM/span span class=npVM/span span class=o=/span span class=npUVM/spanspan class=o-gt;/spanspan class=npVM/spanspan class=p;/span
span class=kif/span span class=p(/spanspan class=nSUCCEEDED/spanspan class=p(/spanspan class=nhrc/spanspan class=p))/span span class=p{/span
span class=nPUVM/span span class=npUVM/span span class=o=/span span class=p(/spanspan class=nPUVM/spanspan class=p)(/spanspan class=ktintptr_t/spanspan class=p)/spanspan class=nllVM/spanspan class=p;/span span class=cm/* The user mode VM handle *//span
span class=nPVM/span span class=npVM/span span class=o=/span span class=npUVM/spanspan class=o-gt;/spanspan class=npVM/spanspan class=p;/span
span class=kfor/span span class=p(/spanspan class=nPPDMDEVINS/span span class=npDevIns/span span class=o=/span span class=npVM/spanspan class=o-gt;/spanspan class=npdm/spanspan class=p./spanspan class=ns/spanspan class=p./spanspan class=npDevInstances/spanspan class=p;/span span class=npDevIns/spanspan class=p;/span span class=npDevIns/span span class=o=/span span class=npDevIns/spanspan class=o-gt;/spanspan class=nInternal/spanspan class=p./spanspan class=ns/spanspan class=p./spanspan class=npNextR3/spanspan class=p)/span span class=p{/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npDevIns/spanspan class=o-gt;/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=spcnet/spanspan class=p))/span span class=p{/span
span class=ktunsigned/span span class=ktchar/span span class=o*/spanspan class=nbuf/span span class=o=/span span class=n__AFL_FUZZ_TESTCASE_BUF/spanspan class=p;/span
span class=kwhile/span span class=p(/spanspan class=n__AFL_LOOP/spanspan class=p(/spanspan class=mi10000/spanspan class=p))/span
span class=p{/span
span class=ktint/span span class=nlen/span span class=o=/span span class=n__AFL_FUZZ_TESTCASE_LEN/spanspan class=p;/span
span class=npDevIns/spanspan class=o-gt;/spanspan class=npReg/spanspan class=o-gt;/spanspan class=npfnAFL/spanspan class=p(/spanspan class=npDevIns/spanspan class=p,/span span class=nbuf/spanspan class=p,/span span class=nlen/spanspan class=p);/span
span class=p}/span
span class=p}/span
span class=p}/span
span class=p}/span
span class=nexit/spanspan class=p(/spanspan class=mi0/spanspan class=p);/span
span class=cm/* --------------- END --------------- *//span
span class=cm/*
* Pump vbox events forever
*//span
span class=nLogRel/spanspan class=p((/spanspan class=sVBoxHeadless: starting event loop/spanspan class=se\n/spanspan class=s/spanspan class=p));/span
span class=kfor/span span class=p(;;)/span
/code/pre/div/div
pIn the same file after the code class=language-plaintext highlighter-rouge#include PasswordInput.h/code directive, add:/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=cp#include harness.h
/span/code/pre/div/div
pFinally, append code class=language-plaintext highlighter-rouge__AFL_FUZZ_INIT();/code before defining the code class=language-plaintext highlighter-rougeTrustedMain/code function:/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=n__AFL_FUZZ_INIT/spanspan class=p();/span
span class=cm/**
* Entry point.
*//span
span class=kextern/span span class=sC/span span class=nDECLEXPORT/spanspan class=p(/spanspan class=ktint/spanspan class=p)/span span class=nTrustedMain/spanspan class=p(/spanspan class=ktint/span span class=nargc/spanspan class=p,/span span class=ktchar/span span class=o**/spanspan class=nargv/spanspan class=p,/span span class=ktchar/span span class=o**/spanspan class=nenvp/spanspan class=p)/span
/code/pre/div/div
p4) Edit code class=language-plaintext highlighter-rougesrc/VBox/Frontends/VBoxHeadless/Makefile.kmk/code and change the code class=language-plaintext highlighter-rougeVBoxHeadless_DEFS/code and code class=language-plaintext highlighter-rougeVBoxHeadless_INCS/code from/p
div class=language-make highlighter-rougediv class=highlightpre class=highlightcodespan class=nvVBoxHeadless_TEMPLATE/span span class=o:=/span span class=nf$(/spanspan class=nbif/span span class=nv$(VBOX_WITH_HARDENING)/span,VBOXMAINCLIENTDLL,VBOXMAINCLIENTEXEspan class=nf)/span
span class=nvVBoxHeadless_DEFS/span span class=o+=/span span class=nf$(/spanspan class=nbif/span span class=nv$(VBOX_WITH_RECORDING)/span,VBOX_WITH_RECORDING,span class=nf)/span
span class=nvVBoxHeadless_INCS/span span class=o=/span span class=se\/span
span class=nv$(VBOX_GRAPHICS_INCS)/span span class=se\/span
../Common
/code/pre/div/div
pto/p
div class=language-make highlighter-rougediv class=highlightpre class=highlightcodespan class=nvVBoxHeadless_TEMPLATE/span span class=o:=/span span class=nf$(/spanspan class=nbif/span span class=nv$(VBOX_WITH_HARDENING)/span,VBOXMAINCLIENTDLL,VBOXMAINCLIENTEXEspan class=nf)/span
span class=nvVBoxHeadless_DEFS/span span class=o+=/span span class=nf$(/spanspan class=nbif/span span class=nv$(VBOX_WITH_RECORDING)/span,VBOX_WITH_RECORDING,span class=nf)/span span class=nv$(VMM_COMMON_DEFS)/span
span class=nvVBoxHeadless_INCS/span span class=o=/span span class=se\/span
span class=nv$(VBOX_GRAPHICS_INCS)/span span class=se\/span
../Common span class=se\/span
../../VMM/include
/code/pre/div/div
h3 id=fuzzing-with-multiple-inputsFuzzing With Multiple Inputs/h3
pFor the network drivers, there are various ways of supplying the user-controlled data by using access I/O port instructions or reading the data from the emulated device via MMIO (code class=language-plaintext highlighter-rougePDMDevHlpPhysRead/code). If this part is unclear, please refer back to [1] in references, which is probably the best available resource for explaining the attack surface. Moreover, many ports or values are restricted to a specific set, and to save some time, we want to use only these values. Therefore, after some consideration for the implementing of our fuzzing framework, we discovered a href=https://github.com/google/fuzzing/blob/master/docs/split-inputs.md#fuzzed-data-providerFuzzed Data Provider/a (later FDP)./p
pFDP is part of the LLVM and, after we pass it a buffer generated by AFL, it can leverage it to generate a restricted set of numbers, bytes, or enums. We can store the pointer to FDP inside the device driver instance and retrieve it any time we want to feed some buffer./p
pRecall that we can use the code class=language-plaintext highlighter-rougepfnReserved/code fields to implement our fuzzing helper functions. For this, itβs enough to edit code class=language-plaintext highlighter-rougeinclude/VBox/vmm/pdmdev.h/code and change the code class=language-plaintext highlighter-rougePDMDEVREGR3/code structure to conform to our prototype:/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=nDECLR3CALLBACKMEMBER/spanspan class=p(/spanspan class=ktint/spanspan class=p,/span span class=npfnAFL/spanspan class=p,/span span class=p(/spanspan class=nPPDMDEVINS/span span class=npDevIns/spanspan class=p,/span span class=ktunsigned/span span class=ktchar/span span class=o*/spanspan class=nbuf/spanspan class=p,/span span class=ktint/span span class=nlen/spanspan class=p));/span
span class=nDECLR3CALLBACKMEMBER/spanspan class=p(/spanspan class=ktvoid/span span class=o*/spanspan class=p,/span span class=npfnGetFDP/spanspan class=p,/span span class=p(/spanspan class=nPPDMDEVINS/span span class=npDevIns/spanspan class=p));/span
span class=nDECLR3CALLBACKMEMBER/spanspan class=p(/spanspan class=ktint/spanspan class=p,/span span class=npfnReserved2/spanspan class=p,/span span class=p(/spanspan class=nPPDMDEVINS/span span class=npDevIns/spanspan class=p));/span
/code/pre/div/div
pAll device drivers have a state, which we can access using convenient macro code class=language-plaintext highlighter-rougePDMDEVINS_2_DATA/code. Likewise, we can extend the state structure (in our case code class=language-plaintext highlighter-rougePCNETSTATE/code) to include the FDP header file via a pointer to FDP:/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=c1// src/VBox/Devices/Network/DevPCNet.cpp/span
span class=cp#ifdef IN_RING3
# include lt;iprt/mem.hgt;
# include lt;iprt/semaphore.hgt;
# include lt;iprt/uuid.hgt;
# include lt;fuzzer/FuzzedDataProvider.hgt; /spanspan class=cm/* Add this *//spanspan class=cp
#endif
/span
span class=c1// [ SNIP ]/span
span class=ktypedef/span span class=kstruct/span span class=nPCNETSTATE/span
span class=p{/span
span class=c1// [ SNIP ]/span
span class=cp#endif /spanspan class=cm/* VBOX_WITH_STATISTICS *//spanspan class=cp
/span span class=ktvoid/span span class=o*/span span class=nfdp/spanspan class=p;/span span class=cm/* Add this *//span
span class=p}/span span class=nPCNETSTATE/spanspan class=p;/span
span class=cm/** Pointer to a shared PCnet state structure. *//span
span class=ktypedef/span span class=nPCNETSTATE/span span class=o*/spanspan class=nPPCNETSTATE/spanspan class=p;/span
/code/pre/div/div
pTo reflect these changes, the code class=language-plaintext highlighter-rougeg_DevicePCNet/code structure has to be updated too :/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=cm/**
* The device registration structure.
*//span
span class=kconst/span span class=nPDMDEVREG/span span class=ng_DevicePCNet/span span class=o=/span
span class=p{/span
span class=c1// [[ SNIP ]]/span
span class=cm/* .pfnConstruct = *//span span class=npcnetR3Construct/spanspan class=p,/span
span class=c1// [[ SNIP ]]/span
span class=cm/* .pfnReserved0 = *//span span class=npcnetR3_AFL/spanspan class=p,/span
span class=cm/* .pfnReserved1 = *//span span class=npcnetR3_GetFDP/spanspan class=p,/span
/code/pre/div/div
pWhen adding new functions, we must be careful and include them inside R3 only parts. The easiest way is to find the R3 constructor and add new code just after that, as it already has defined the code class=language-plaintext highlighter-rougeIN_RING3/code macro for the conditional compilation./p
pAn example of the PCNet harness:/p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=kstatic/span span class=nfDECLCALLBACK/spanspan class=p(/spanspan class=ktvoid/span span class=o*/spanspan class=p)/span span class=npcnetR3_GetFDP/spanspan class=p(/spanspan class=nPPDMDEVINS/span span class=npDevIns/spanspan class=p)/span span class=p{/span
span class=nPPCNETSTATE/span span class=npThis/span span class=o=/span span class=nPDMDEVINS_2_DATA/spanspan class=p(/spanspan class=npDevIns/spanspan class=p,/span span class=nPPCNETSTATE/spanspan class=p);/span
span class=kreturn/span span class=npThis/spanspan class=o-gt;/spanspan class=nfdp/spanspan class=p;/span
span class=p}/span
span class=n__AFL_COVERAGE/spanspan class=p();/span
span class=kstatic/span span class=nfDECLCALLBACK/spanspan class=p(/spanspan class=ktint/spanspan class=p)/span span class=npcnetR3_AFL/spanspan class=p(/spanspan class=nPPDMDEVINS/span span class=npDevIns/spanspan class=p,/span span class=ktunsigned/span span class=ktchar/span span class=o*/spanspan class=nbuf/spanspan class=p,/span span class=ktint/span span class=nlen/spanspan class=p)/span
span class=p{/span
span class=kif/span span class=p(/spanspan class=nlen/span span class=ogt;/span span class=mh0x2000/spanspan class=p)/span span class=p{/span
span class=n__AFL_COVERAGE_SKIP/spanspan class=p();/span
span class=kreturn/span span class=nVINF_SUCCESS/spanspan class=p;/span
span class=p}/span
span class=kstatic/span span class=ktunsigned/span span class=ktchar/span span class=nbuf2/spanspan class=p[/spanspan class=mh0x2000/spanspan class=p];/span
span class=nmemcpy/spanspan class=p(/spanspan class=nbuf2/spanspan class=p,/span span class=nbuf/spanspan class=p,/span span class=nlen/spanspan class=p);/span
span class=nFuzzedDataProvider/span span class=nprovider/spanspan class=p(/spanspan class=nbuf2/spanspan class=p,/span span class=nlen/spanspan class=p);/span
span class=nPPCNETSTATE/span span class=npThis/span span class=o=/span span class=nPDMDEVINS_2_DATA/spanspan class=p(/spanspan class=npDevIns/spanspan class=p,/span span class=nPPCNETSTATE/spanspan class=p);/span
span class=npThis/spanspan class=o-gt;/spanspan class=nfdp/span span class=o=/span span class=oamp;/spanspan class=nprovider/spanspan class=p;/span span class=c1// Make it accessible for the other modules/span
span class=nFuzzedDataProvider/span span class=o*/spanspan class=npfdp/span span class=o=/span span class=p(/spanspan class=nFuzzedDataProvider/span span class=o*/spanspan class=p)/span span class=npDevIns/spanspan class=o-gt;/spanspan class=npReg/spanspan class=o-gt;/spanspan class=npfnGetFDP/spanspan class=p(/spanspan class=npDevIns/spanspan class=p);/span
span class=ktvoid/span span class=o*/spanspan class=npvUser/span span class=o=/span span class=nbNULL/spanspan class=p;/span
span class=ktuint32_t/span span class=nu32/spanspan class=p;/span
span class=kconst/span span class=nstd/spanspan class=o::/spanspan class=narray/spanspan class=olt;/spanspan class=ktint/spanspan class=p,/span span class=mi3/spanspan class=ogt;/span span class=nArray/span span class=o=/span span class=p{/spanspan class=mi1/spanspan class=p,/span span class=mi2/spanspan class=p,/span span class=mi4/spanspan class=p};/span
span class=ktuint16_t/span span class=noffPort/spanspan class=p;/span
span class=ktuint16_t/span span class=ncb/spanspan class=p;/span
span class=npcnetR3Reset/spanspan class=p(/spanspan class=npDevIns/spanspan class=p);/span
span class=n__AFL_COVERAGE_DISCARD/spanspan class=p();/span
span class=n__AFL_COVERAGE_ON/spanspan class=p();/span
span class=kwhile/span span class=p(/spanspan class=npfdp/spanspan class=o-gt;/spanspan class=nremaining_bytes/spanspan class=p()/span span class=ogt;/span span class=mi0/spanspan class=p)/span span class=p{/span
span class=kauto/span span class=nchoice/span span class=o=/span span class=npfdp/spanspan class=o-gt;/spanspan class=nConsumeIntegralInRange/spanspan class=p(/spanspan class=mi0/spanspan class=p,/span span class=mi3/spanspan class=p);/span
span class=noffPort/span span class=o=/span span class=npfdp/spanspan class=o-gt;/spanspan class=nConsumeIntegral/spanspan class=olt;/spanspan class=ktuint16_t/spanspan class=ogt;/spanspan class=p();/span
span class=nu32/span span class=o=/span span class=npfdp/spanspan class=o-gt;/spanspan class=nConsumeIntegral/spanspan class=olt;/spanspan class=ktuint32_t/spanspan class=ogt;/spanspan class=p();/span
span class=ncb/span span class=o=/span span class=npfdp/spanspan class=o-gt;/spanspan class=nPickValueInArray/spanspan class=p(/spanspan class=nArray/spanspan class=p);/span
span class=kswitch/span span class=p(/spanspan class=nchoice/spanspan class=p)/span span class=p{/span
span class=kcase/span span class=mi0/spanspan class=p:/span
span class=c1// pcnetIoPortWrite(PPDMDEVINS pDevIns, void *pvUser, /span
span class=c1// RTIOPORT offPort, uint32_t u32, unsigned cb)/span
span class=npcnetIoPortWrite/spanspan class=p(/spanspan class=npDevIns/spanspan class=p,/span span class=npvUser/spanspan class=p,/span span class=noffPort/spanspan class=p,/span span class=nu32/spanspan class=p,/span span class=ncb/spanspan class=p);/span
span class=kbreak/spanspan class=p;/span
span class=kcase/span span class=mi1/spanspan class=p:/span
span class=c1// pcnetIoPortAPromWrite(PPDMDEVINS pDevIns, void *pvUser, /span
span class=c1// RTIOPORT offPort, uint32_t u32, unsigned cb)/span
span class=npcnetIoPortAPromWrite/spanspan class=p(/spanspan class=npDevIns/spanspan class=p,/span span class=npvUser/spanspan class=p,/span span class=noffPort/spanspan class=p,/span span class=nu32/spanspan class=p,/span span class=ncb/spanspan class=p);/span
span class=kbreak/spanspan class=p;/span
span class=kcase/span span class=mi2/spanspan class=p:/span
span class=c1// pcnetR3MmioWrite(PPDMDEVINS pDevIns, void *pvUser,/span
span class=c1// RTGCPHYS off, void const *pv, unsigned cb)/span
span class=npcnetR3MmioWrite/spanspan class=p(/spanspan class=npDevIns/spanspan class=p,/span span class=npvUser/spanspan class=p,/span span class=noffPort/spanspan class=p,/span span class=oamp;/spanspan class=nu32/spanspan class=p,/span span class=ncb/spanspan class=p);/span
span class=kbreak/spanspan class=p;/span
span class=nldefault:/span
span class=kbreak/spanspan class=p;/span
span class=p}/span
span class=p}/span
span class=n__AFL_COVERAGE_OFF/spanspan class=p();/span
span class=npThis/spanspan class=o-gt;/spanspan class=nfdp/span span class=o=/span span class=nbNULL/spanspan class=p;/span
span class=kreturn/span span class=nVINF_SUCCESS/spanspan class=p;/span
span class=p}/span
/code/pre/div/div
h3 id=fuzzing-pdmdevhlpphysreadFuzzing PDMDevHlpPhysRead/h3
pAs the device driver calls this function multiple times, we decided to patch the wrapper instead of modifying every instance. We can do so by editing code class=language-plaintext highlighter-rougesrc/VBox/VMM/VMMR3/PDMDevHlp.cpp/code, adding the relevant FDP header, and changing the code class=language-plaintext highlighter-rougepdmR3DevHlp_PhysRead/code method to fuzz only the specific driver./p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcodespan class=cp#include dtrace/VBoxVMM.h
#include PDMInline.h
/span
span class=cp#include lt;fuzzer/FuzzedDataProvider.hgt; /spanspan class=cm/* Add this *//spanspan class=cp
/span
span class=c1// [ SNIP ]/span
span class=cm/** @interface_method_impl{PDMDEVHLPR3,pfnPhysRead} *//span
span class=kstatic/span span class=nfDECLCALLBACK/spanspan class=p(/spanspan class=ktint/spanspan class=p)/span span class=npdmR3DevHlp_PhysRead/spanspan class=p(/spanspan class=nPPDMDEVINS/span span class=npDevIns/spanspan class=p,/span span class=nRTGCPHYS/span span class=nGCPhys/spanspan class=p,/span span class=ktvoid/span span class=o*/spanspan class=npvBuf/spanspan class=p,/span span class=ktsize_t/span span class=ncbRead/spanspan class=p)/span
span class=p{/span
span class=nPDMDEV_ASSERT_DEVINS/spanspan class=p(/spanspan class=npDevIns/spanspan class=p);/span
span class=nPVM/span span class=npVM/span span class=o=/span span class=npDevIns/spanspan class=o-gt;/spanspan class=nInternal/spanspan class=p./spanspan class=ns/spanspan class=p./spanspan class=npVMR3/spanspan class=p;/span
span class=nLogFlow/spanspan class=p((/spanspan class=spdmR3DevHlp_PhysRead: caller='%s'/%d: GCPhys=%RGp pvBuf=%p cbRead=%#x/spanspan class=se\n/spanspan class=s/spanspan class=p,/span
span class=npDevIns/spanspan class=o-gt;/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=npDevIns/spanspan class=o-gt;/spanspan class=niInstance/spanspan class=p,/span span class=nGCPhys/spanspan class=p,/span span class=npvBuf/spanspan class=p,/span span class=ncbRead/spanspan class=p));/span
span class=cm/* Change this for the fuzzed driver *//span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npDevIns/spanspan class=o-gt;/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=spcnet/spanspan class=p))/span span class=p{/span
span class=nFuzzedDataProvider/span span class=o*/spanspan class=npfdp/span span class=o=/span span class=p(/spanspan class=nFuzzedDataProvider/span span class=o*/spanspan class=p)/span span class=npDevIns/spanspan class=o-gt;/spanspan class=npReg/spanspan class=o-gt;/spanspan class=npfnGetFDP/spanspan class=p(/spanspan class=npDevIns/spanspan class=p);/span
span class=kif/span span class=p(/spanspan class=npfdp/span span class=oamp;amp;/span span class=npfdp/spanspan class=o-gt;/spanspan class=nremaining_bytes/spanspan class=p()/span span class=ogt;=/span span class=ncbRead/spanspan class=p)/span span class=p{/span
span class=npfdp/spanspan class=o-gt;/spanspan class=nConsumeData/spanspan class=p(/spanspan class=npvBuf/spanspan class=p,/span span class=ncbRead/spanspan class=p);/span
span class=kreturn/span span class=nVINF_SUCCESS/spanspan class=p;/span
span class=p}/span
span class=p}/span
/code/pre/div/div
pUsing code class=language-plaintext highlighter-rougeout/linux.amd64/release/bin/VBoxNetAdpCtl/code, we can add our network adapter and start fuzzing in a href=https://github.com/AFLplusplus/AFLplusplus/blob/stable/instrumentation/README.persistent_mode.mdpersistent mode/a. However, even when we can reach more than 10k executions per second, we still have some work to do about the stability./p
h2 id=improving-stabilityImproving Stability/h2
pUnfortunately, none of these methods described a href=https://github.com/AFLplusplus/AFLplusplus/blob/stable/docs/best_practices.md#improving-stabilityhere/a worked, as we were not able to use LTO instrumentation. We guess thatβs because the device drivers module was dynamically loaded, therefore partially disabling instrumentation was not possible nor was possible to identify unstable edges. The instability is caused by not properly resetting the driverβs state, and because we are running the whole VM, there are many things under the hood which are not easy to influence, such as internal locks or VMM./p
pOne of the improvements is already contained in the harness, as we can discard the coverage before we start fuzzing and enable it only for a short fuzzing block./p
pAdditionally, we can disable the instantiation of all devices which we are not currently fuzzing. The relevant code is inside code class=language-plaintext highlighter-rougesrc/VBox/VMM/VMMR3/PDMDevice.cpp/code, implementing the init completion routine through code class=language-plaintext highlighter-rougepdmR3DevInit/code. For the PCNet driver, at least the code class=language-plaintext highlighter-rougepci/code, code class=language-plaintext highlighter-rougeVMMDev/code, and code class=language-plaintext highlighter-rougepcnet/code modules must be enabled. Therefore, we can skip the initialization for the rest./p
div class=language-c highlighter-rougediv class=highlightpre class=highlightcode span class=cm/*
*
* Instantiate the devices.
*
*//span
span class=kfor/span span class=p(/spanspan class=ni/span span class=o=/span span class=mi0/spanspan class=p;/span span class=ni/span span class=olt;/span span class=ncDevs/spanspan class=p;/span span class=ni/spanspan class=o++/spanspan class=p)/span
span class=p{/span
span class=nPDMDEVREGR3/span span class=kconst/span span class=o*/span span class=kconst/span span class=npReg/span span class=o=/span span class=npaDevs/spanspan class=p[/spanspan class=ni/spanspan class=p]./spanspan class=npDev/spanspan class=o-gt;/spanspan class=npReg/spanspan class=p;/span
span class=c1// if (!strcmp(pReg-gt;szName, pci)) {continue;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sich9pci/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=spcarch/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=spcbios/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sioapic/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=spckbd/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=spiix3ide/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=si8254/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=si8259/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=shpet/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=ssmc/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sflash/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sefi/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=smc146818/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=svga/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=c1// if (!strcmp(pReg-gt;szName, VMMDev)) {continue;}/span
span class=c1// if (!strcmp(pReg-gt;szName, pcnet)) {continue;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=se1000/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=svirtio-net/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=c1// if (!strcmp(pReg-gt;szName, IntNetIP)) {continue;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sichac97/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=ssb16/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=shda/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=susb-ohci/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sacpi/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=s8237A/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=si82078/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sserial/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=soxpcie958uart/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sparallel/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sahci/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sbuslogic/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=spcibridge/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sich9pcibridge/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=slsilogicscsi/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=slsilogicsas/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=svirtio-scsi/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=sGIMDev/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=kif/span span class=p(/spanspan class=o!/spanspan class=nstrcmp/spanspan class=p(/spanspan class=npReg/spanspan class=o-gt;/spanspan class=nszName/spanspan class=p,/span span class=slpc/spanspan class=p))/span span class=p{/spanspan class=kcontinue/spanspan class=p;}/span
span class=cm/*
* Gather a bit of config.
*//span
span class=cm/* trusted *//span
/code/pre/div/div
pThe most significant issue is that minimizing our test cases is not an option when the stability is low (the percentage depends on the drivers we fuzz). If we cannot reproduce the crash, we can at least intercept it and analyze it afterward in code class=language-plaintext highlighter-rougegdb/code./p
pWe ran AFL in debug mode as a workaround, which yields a code class=language-plaintext highlighter-rougecore/code file after every crash. Before running the fuzzer, this behavior can be enabled by:/p
div class=language-plaintext highlighter-rougediv class=highlightpre class=highlightcode$ export AFL_DEBUG=1
$ ulimit -c unlimited
/code/pre/div/div
h2 id=conclusionConclusion/h2
pWe presented one of the possible approaches to fuzzing VirtualBox device drivers. We hope it contributes to a better understanding of VirtualBox internals. For inspiration, Iβll leave you with the quote from code class=language-plaintext highlighter-rougedoc/VBox-CodingGuidelines.cpp/code:/p
precode class=language-none * (2) A really advanced hacker comes to understand the true inner workings of
* the machine - he sees through the language he's working in and glimpses
* the secret functioning of the binary code - becomes a Ba'al Shem of
* sorts. (Neal Stephenson Snow Crash)
/code/pre
h2 id=referencesReferences/h2
ul
li[1] a href=https://starlabs.sg/blog/2020/04/adventures-in-hypervisor-oracle-virtualbox-research/Pham Hong Phi, βAdventures in Hypervisor: Oracle VirtualBox Research,β Apr 2020/a/li
li[2] a href=https://conference.hitb.org/hitbsecconf2021ams/materials/D2T2%20-%20Discovering%2010+%20Vulnerabilities%20in%20Virtualbox%20-%20Chen%20Nan.pdfChenNan, βBox Escape: Discovering 10+ Vulnerabilities in VirtualBox,β HITB Security Conference, May 2021/a/li
li[3] a href=http://blog.paulch.ru/2020-07-26-hunting-for-bugs-in-virtualbox-first-take.htmlPavel Cheremushkin, βHunting for bugs in VirtualBox (First Take),β July 2020/a/li
/ul