Go Around and Back to Learn Directed Fuzzing on My PoC Transformation Journey
TyeYeah Lv4

There is surely a gap between vulnerability detection and vulnerability exploitation, while in the field of vulnerability detection, the differences still persist between statically detecting vulns and dynamically trigger to confirm their existence.

Here provides several reproducible methods for PoC migration based on directed fuzzing.

The Milestone: AFLGO

When we talk about directed fuzzing, it always starts from AFLGo: Directed Greybox Fuzzing, a fairly famous and reliable work based on afl.

It is not hard to build the project, but there are some limitations for the installation environment, including running on Ubuntu 20.04 and compiling with LLVM-11.

After building AFLGo, to run directed fuzzing on a real target, you must ensure that ① you can control the entire compilation process (compiler and flags/options) and ② instrument the target source code.

Only if the distance calculation during the first compilation attempt (the second compilation performs the final instrumentation) is successfully conducted can directed fuzzing be performed successfully.

TransferFuzz

A state-of-the-art work is TransferFuzz, which is built on SelectFuzz and SelectFuzz‘s Docker image (its image names anonymous4paper/transferfuzz).

Summarize It

This work targets migrating the PoC from one binary to another binary that reuses exactly the same components or functions (e.g., cxxfilt and objdump, both from the binutils repository).

TransferFuzz uses Nested Simulated Annealing to guide fuzzing along the target trace, function by function, with the help of a state machine model.

It then employs Key Bytes Guided Mutation, which means it uses specific key bytes for mutation, such as unique sequences of consecutively accessed memory bytes observed when the PoC runs on the basic binary.

Therefore, from an engineering implementation perspective, it is a directed greybox fuzzing method with a customized seed power scheduling strategy and a customized fuzzing dictionary.

Run It

Since TransferFuzz is based on SelectFuzz, and SelectFuzz relies on the original version of AFLGo (the older version of AFLGo is a modification of afl-v2.52b and requires LLVM-4, while the newer version of AFLGo is based on afl-v2.57b and uses LLVM-11), the pre-compiled libDFUZZPASS.so must be built with LLVM-4 to successfully compile the entire fuzzer project.

However, compiling the compiler-rt component of LLVM-4 is problematic on Ubuntu 20.04, making it difficult to set it up from source. Therefore, we opt to deploy it using Docker.

To make the Docker container more convenient to use, we can install the VSCode Server in it and connect to it using the VSCode Remote-SSH extension. However, the TransferFuzz container is based on Ubuntu 16.04, which is too old to support the VSCode Server (starting with VSCode release 1.99 (March 2025), the prebuilt servers distributed by VSCode are only compatible with Linux distributions that are based on glibc 2.28 or later. These include for example, Debian 10, RHEL 8, or Ubuntu 20.04.).

  • Solution 1: downgrade VSCode to v1.85
  • Solution 2: refer to official doc about Can I run VS Code Server on older Linux distributions?
    • build crosstool-NG:
      1
      2
      3
      4
      $ sudo apt-get install -y gcc g++ gperf bison flex texinfo help2man make libncurses5-dev python3-dev autoconf automake libtool libtool-bin gawk wget bzip2 xz-utils unzip patch rsync meson ninja-build
      $ wget http://crosstool-ng.org/download/crosstool-ng/crosstool-ng-1.26.0.tar.bz2
      $ tar -xjf crosstool-ng-1.26.0.tar.bz2 && cd crosstool-ng-1.26.0
      $ ./configure && make && sudo make install
    • build sysroot with crosstool-NG
      1
      2
      3
      4
      5
      $ mkdir toolchain-dir && cd toolchain-dir
      $ wget https://github.com/microsoft/vscode-linux-build-agent/raw/refs/heads/main/x86_64-gcc-8.5.0-glibc-2.28.config
      $ mv x86_64-gcc-8.5.0-glibc-2.28.config .config
      $ ct-ng menuconfig # in `menuconfig`, set `Operating System` -> `Version of linux` to match your Linux kernel version, check it using `uname -a`. Save and Exit.
      $ ct-ng build
    • download patchelf
      1
      2
      $ wget https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0-x86_64.tar.gz
      $ sudo tar -zxf patchelf-0.18.0-x86_64.tar.gz -C /
    • test patchelf
      1
      2
      3
      4
      5
      $ gcc hello_world.c
      $ ./a.out
      $ patchelf --set-interpreter /path/to/toolchain-dir/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2 --set-rpath /path/to/toolchain-dir/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib64 a.out
      $ ./a.out
      $ ldd a.out
    • set env vars, put the following lines to the “head” of ~/.bashrc
      1
      2
      3
      export VSCODE_SERVER_CUSTOM_GLIBC_LINKER=/path/to/toolchain-dir/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib/ld-linux-x86-64.so.2
      export VSCODE_SERVER_CUSTOM_GLIBC_PATH=/path/to/toolchain-dir/x86_64-linux-gnu/x86_64-linux-gnu/sysroot/lib64
      export VSCODE_SERVER_PATCHELF_PATH=/bin/patchelf

After that, you can inspect /transferfuzz/scripts/evaluation/ for a quick start.
A formal usage process is detailed in the README - Full process, and the fuzzing process requires not only the standard inputs needed by AFLGo but also additional artifacts, such as function traces /transferfuzz/scripts/fuzz_functrace/cve-xxxx-xxxx.txt and fuzz dictionaries /transferfuzz/scripts/fuzz_dict/cve-xxxx-xxxx.txt.

ChainFuzz

Another SOTA work is available at Artifact for Paper “ChainFuzz: Exploiting Upstream Vulnerabilities in Open-Source Supply Chains”.

Summarize It

This work targets a more complex scenario, which is the real-world vulnerability propagation from an upstream software to a distinct downstream software, and they are always from different projects.

The core assumption is also that the same vulnerable functions are reused and already identified, while the functionalities of the two binaries and the paths to the target functions are changed a lot.

ChainFuzz workflow can be divided into 2 parts. First is Cross-layer Differential Directed Fuzzing, which identifies waypoints (functions connecting upstream functionalities and downstream code logic) and does fuzzing to explore and exploit, finally generating PoCs. The second part is Bottom-up Proof-of-Concept Generation, which reverses the synthesis of the exploit path to solve long supply chain conditions.

This aims to handle a more realistic and practical scenario than TransferFuzz, while the data cannot be reproduced currently as in TransferFuzz, since the PoCs are of large size and hard to fetch using LFS.

Run It

The code and dataset are both publicly available, while we were unable to reproduce the crashes reported in the original PoCs.

The implementation is based on a newer version of AFLGo (built on afl-2.57b and LLVM-11) along with Rust components, making it relatively straightforward to build on modern operating systems.

The setup remains somewhat complex (noob alert! send help!), and this part is still a work in progress … no guarantees it’ll actually work.

Others

VulScope: an approach to assessing the under-reported vulnerable versions for a reported vulnerability. (across versions, based on trace comparision)
SyzBridge: a research project that adapts Linux upstream PoCs to downstream distributions. (fixing env for Linux kernel bug reproduction)
OctoPoCs: generates PoC automatically for propagated vulnerability in cloned software. (combine guiding input with crash primitive)

Powered by Hexo & Theme Keep
Total words 137k
$li-margin-bottom = 0.8rem $post-tool-button-width = 2.5rem .post-tools-container { padding-top var(--component-gap) .tools-list { li { position relative box-sizing border-box width $post-tool-button-width height $post-tool-button-width margin-bottom $li-margin-bottom color var(--text-color-3) font-size 1.2rem background var(--background-color-1) border-radius 50% box-shadow 2px 2px 5px var(--shadow-color) cursor pointer &:hover { box-shadow 2px 2px 8px var(--shadow-hover-color) } i { color var(--text-color-3) } &:hover { color var(--background-color-1) background var(--primary-color) i { color var(--background-color-1) } } &:last-child { margin-bottom 0 } &.toggle-show-toc { display none } &.go-to-comments { .post-comments-count { position absolute top 0 right -1rem display none align-items center justify-content center box-sizing border-box min-width 1.1rem height 1.1rem padding 0 0.2rem color var(--badge-color) font-size 12px background var(--badge-background-color) border-radius 0.4rem +keep-tablet() { display none !important } } } } } }