Skip to content

Instantly share code, notes, and snippets.

@syheliel
Last active September 7, 2022 11:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save syheliel/5f11d9c1082edb595f36c371ddbd9dad to your computer and use it in GitHub Desktop.
Save syheliel/5f11d9c1082edb595f36c371ddbd9dad to your computer and use it in GitHub Desktop.
GSoC 22 Final Report

This year I'm honored to have the chance of contributing to the well-known and amazing fuzzing framework LibAFL. This report outlines my work from the last 10 weeks and gives an overview over the state of the project.

Project Description

LibAFL is a fuzzing framework written in RUST. Fuzzing is an automatic bug detection method. During the fuzzing process, fuzzer(the fuzzing program) will feed the target with different inputs, rates and generates more valuable inputs by different techniques. LibAFL split a fuzzer into different components and provides essential parts in each component, which makes it possible to write your customized fuzzer.

The goal of this project is to make nyx fuzzer available in LibAFL. nyx is a highly optimized and coverage-guided hypervisor fuzzer that uses a fast snapshot restoration mechanism and a novel mutation engine based on affine types.

As the result of this project, I created a sub-create libafl_nyx and designed nyx_executor to support single-thread(standalone mode) or multi-threads(parallel mode) fuzzing using nyx as the backend. I also wrote two example fuzzers for libxml2 to illustrate the code usage.

design

environment setup

NYX relies on a collection of tools:

  • QEMU-NYX: a customized version of QEMU which supports: Hypervisor based snapshots, Intel-PT based tracing, and REDQUEEN style magic byte resolution
  • packer: image packer for nyx VMs
  • libnyx: rust API to build hypervisor-based snapshot fuzzers.

libnyx can be easily used as a crate dependency. For the other part, build.rs is responsible for submodule checkout, packer's initramfs build and QEMU-NYX build.

NyxHelper

Nyx has two modes:

  • In standalone mode, no VM snapshot is serialized and stored in the working directory. That might be useful if you want to run the fuzzer with only one process (meaning one VM).
  • In parallel mode, the first fuzzer process (parent) has to create the VM snapshot while all other child processes will wait for the snapshot files to appear in the working directory.

NyxHelper is responsible for NYX instance spawning in both standalone mode and parallel mode. It will first create NYX process according to the process type(ALONE in standalone and PARENT,CHILD in parallel), then it will start a dry-run to test the connection.

In parallel mode, you need to explicitly pass parent_cpu_id to distinguish PARENT from CHILD. The reason behind it is that in LibAFL's Launcher(layer to create multi-threads fuzzer), one fuzzer only communicates with other fuzzers through message passing. So specifying parent_cpu_id during creation reduces the design complexity.

NyxExecutor

struct NyxExecutor takes NyxHelper and observers as input. It provides a unified API for standalone and parallel modes. It is used for input set, program execution in VM and exception handle.

example fuzzers

nyx_libxml2_standalone and nyx_libxml2_parallel are two example fuzzers to show the usage of nyx's standalone and parallel mode. It uses cargo-make to setup the environment and has been tested on ubuntu-22.04.

documentation

For the full focumentation, you can see nyx.md

other work

During GSOC, I have also done some CI/CD and doc improvements. You can view them in Pull Request.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment