kAFL/Nyx Hypercall API#
For fuzzing in kAFL/Nyx, the guest VM issues special hypercalls to bootstrap and coordinate the execution of the fuzzing harness with the fuzzer frontend.
This approach offers a minimal low-level interface that can be used to take control and start injecting inputs at any point in VM guest execution.
Essential hypercalls#
ACQUIRE / RELEASEare used to enable/disable feedback collection and generally mark the start and stop of a single execution. One initial set ofACQUIRE/RELEASEhypercalls is also used for initial handshake with the host frontend. ReachingRELEASEgenerally means the execution is done with no errors (return OK). The newer Nyx backend will automatically restore a guest snapshot on RELEASE hypercall.GET_PAYLOADis not actually getting the payload but instead telling Qemu where to write the payload. The guest must take care to allocate a sufficiently large buffer and make it page-aligned. Qemu will mmap() this buffer to make it shared with the fuzzer frontend.NEXT_PAYLOADtriggers the actual write of the next payload into the previously registered buffer. In Nyx, the first invocation will also create a snapshot before writing the payload, so our fuzzing “loop” actually always starts from this hypercall now. Thewhile()loop in our guest agent is not actually needed anymore.PRINTFsend a pointer to a C string to the host, where it will be printed or logged. Very useful for general logging/debug, forwarding sanitizer reports and exception stack dumps.PANIC,KASANare used to raise a ‘crash’ or other error event to the host. Qemu will stop Guest execution, reload the snapshot and report the crash type to the frontend.SUBMIT_PANIC,SUBMIT_KASANtell Qemu the address of existing panic or sanitizer handler functions in the guest. Qemu will overwrite the code at this address to performPANIC/KASANhypercalls so that the events are detected and fuzz inputs can be logged on the host side. Rewrite can have unexpected results in case of inlined code or if the function is a macro etc. It is often preferable and more flexible to manually place hypercalls in the corresponding error and exception handlers.
Further optional hypercalls#
RANGE_SUBMITis used to configure the IP filter range for PT tracing. This is useful when code ranges are not known at startup time or simply easier to obtain as part of agent initialization. Overrides the corresponding-ipNsetting by fuzzer frontend.SUBMIT_CR3tells Qemu to use the currently configured CR3 value as a filter for PT tracing. Useful to limit trace to a specific task/context.USER_ABORTsignals a fatal error to Qemu. Mainly useful as a kind of assert() from harness perspective (since we auto-resume on regular crash/hang).USER_SUBMIT_MODEexplicitly tells the host if the target is 32 or 64 bit code. Influences Qemu code rewrite and possibly libxdc decoder. Typically auto-detected.SET_AGENT_CONFIGtells Qemu about capabilities of the harness (agent), e.g. custom tracing options. Further options may be added by extending the handler on Qemu side.GET_HOST_CONFIGcan be used to query kAFL/Qemu configuration, e.g. size of the payload buffer.REQ_STREAM_DATAfetches a named binary buffer from the host. Qemu fetches the data from correspondingly named files in the sharedir folderDUMP_FILEcan be used to send binary buffers that will be stored as files in $WORK_DIR/dump/. Supply NULL or a valid mkstemp() template as filename to let Qemu create a unique filename for you.USER_FAST_ACQUIREthis is a combination ofNEXT_PAYLOADandACQUIREand mainly exists to save you a VM exit. Only tested for usermode fuzzing.
Untested and not fully integrated#
PRINTK_ADDR– submit the pointer of a printk()-like logging function. Qemu will rewrite this with aPRINTKhypercall which can interpret printk() args.PANIC_EXTENDED– a mix of PANIC and HPRINTF, raises a bug while also forwarding a pointer to a C string. Untested.CREATE_TMP_SNAPSHOT– create an incremental snapshot and continue fuzzing from current position. Frontend and harness have to support this.DEBUG_TMP_SNAPSHOT– debug version of incremental snapshotNESTED_*- roughly equivalent hypercalls for use with nested virtualization (when agent is a L2 guest)USER_RANGE_ADVISE,GET_ARGV– no ideaINFO,LOCK,GET_PROGRAM– deprecated