Skip to content
QDucassePublic

About

Hardware-accelerated fuzzing using CoreSight

Resources

Stars

4 stars

Watchers

0 watching

Forks

Latest commit

 

History

68 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fuzzsight: Hardware-accelerated CoreSight fuzzing

Description

Fuzzsight offloads coverage-guided fuzzing's edge-tracking to hardware: instead of instrumenting the target binary, it uses the CoreSight ETM trace already built into a Zynq UltraScale+'s Cortex-A53 cores (ZCU104 here) to observe every taken/not-taken branch for free, and turns that trace into an AFL-style coverage bitmap entirely in the PL, with zero target-side overhead.

The pipeline: an existing CoreSight trace decoder (rtl/coresight-trace-decoder, forked and extended from the ETH-Zurich) demuxes/deformats/decodes the raw trace byte stream into taken/not-taken atoms; edge_extractor (rtl/fuzzsight) turns those atoms into AFL-style edge-coverage indexes, with two collision-avoiding hashing schemes selectable at runtime (STALKER and this project's own FUZZSIGHT, see rtl/fuzzsight/hash_pkg.vhd); bitmap_writer/bitmap_reader maintain the coverage bitmap in BRAM and hand it off to the PS over AXI-DMA between fuzzing iterations. rtl/stats adds decoder/edge statistics for profiling the pipeline itself.

This repo covers the RTL, the Vivado build (via the vivgit submodule in scripts/), and the userspace C "drivers" (src/) for the AXI-Lite control interfaces below. The host-side tooling lives in the separate ultrasight project.

Block designs

The following block designs/projects are available:

  • fuzzsight: historical setup, with one bitmap writer, superseeded by fuzzsight_tri
  • fuzzsight_tri: triplicated writer to handle the packet load
  • fuzzsight_tri_core3: same as fuzzsight_tri with the decoder and logic extracted from activity on core 3 rather than 0.
  • fuzzsight_stats: only the stats gathering module are present here after the decoder, no edge extraction or bitmap generation

Installation

The whole block design is defined in bd/fuzzsight_tri.tcl. Running the synthesis/implementation is done with:

$ make PROJECT=fuzzsight_tri project
$ make N_JOBS=16 PROJECT=fuzzsight_tri synth
$ make N_JOBS=16 IMPL_STRATEGY=Performance_ExplorePostRoutePhysOpt PROJECT=fuzzsight_tri impl

This generates the bitstream in build/fuzzsight/fuzzsight.bin. To generate the corresponding device tree overlay, run the command below and double-check that your addresses correspond to the ones in Vivado's address editor:

$ make PROJECT=fuzzsight_tri overlay
$ make PROJECT=fuzzsight_tri dtbo

Deploy

Once a .bin/.dtbo pair exists, stage it to the board and load it from there:

$ make PROJECT=fuzzsight_tri BOARD_DEST=/path/on/board [BOARD_HOST=user@board] deploy

This copies build/fuzzsight_tri/{fuzzsight_tri.bin,fuzzsight_tri.dtbo} and install_firmware.sh into $BOARD_DEST/fuzzsight_tri/ locally, or over ssh/scp if BOARD_HOST is set. BOARD_DEST only needs to be writable by the staging user. The actual load needs root, so it always happens by hand on the board:

$ cd /path/on/board/fuzzsight_tri
$ sh install_firmware.sh
Clearing overlay...
Copying raw bitstream (fuzzsight_tri.bin) and dt overlay (fuzzsight_tri.dtbo)...
Loading both...
Time taken to load BIN is 563.000000 Milli Seconds
BIN FILE loaded through FPGA manager successfully

install_firmware.sh clears any currently-loaded overlay (fpgautil -R), copies both files into /lib/firmware, then loads the bitstream with its overlay (fpgautil -b ... -o ...).

Before Fuzzsight can push bitmaps to the PS, the udmabuf kernel module needs to be loaded on the board (see ultrasight's udmabuf setup), bitmap_dma.h mmaps it as the DMA destination.

Usage

As soon as CoreSight is enabled (using csal), Fuzzsight fires up and writes edges in a bitmap stored in BRAM. Once the process finishes, the PS is expected to notify the bitmap reader using its AXI-Lite interface, which will read the bitmap and turn into an AXI-Stream, in turn passed to AXI-DMA.

The main logic is defined in bitmap_dma.c:

int bitmap_dma_transfer(bitmap_dma_t *h)
{
    // Trigger bitmap reader DMA
    axi_regs_write(&h->reader, BITMAP_READER_CTRL, 1);

    // Arm S2MM by writting the buffer length, triggering the transfer
    axi_regs_write(&h->dma, S2MM_BUFF_LENGTH_REGISTER, h->buf_size);

    // Wait for bitmap reader to confirm done
    while (!(axi_regs_read(&h->reader, BITMAP_READER_STATUS) & STATUS_DMA_DONE))
        ;

    // Wait for S2MM to complete
    uint32_t status;
    do {
        status = axi_regs_read(&h->dma, S2MM_STATUS_REGISTER);
    } while (!(status & STATUS_IOC_IRQ) || !(status & STATUS_IDLE));

    // Rearm S2MM for next transfer
    axi_regs_write(&h->dma, S2MM_DST_ADDRESS_REGISTER, UDMABUF_DST);
    axi_regs_write(&h->dma, S2MM_CONTROL_REGISTER, RUN_DMA | ENABLE_ALL_IRQ);

    return 0;
}

For more information on this part, look at ultrasight and its AFL++ proxy cs-proxy.c.

Interfaces / drivers

Every PL block that needs runtime control exposes a small AXI-Lite register file, and each gets a thin C "driver" header in src/, all built on the same base: axi_regs.h/axi_regs.c maps a block's physical address range through /dev/mem and provides raw axi_regs_open/_close/_read/_write/_print. Every header below is just a typed register map plus inline wrappers over these.

Header Block Base macro What it configures / reports
decoder_axi.h CoreSight trace decoder pipeline DECODER_AXI_BASE Soft reset + error-count reset (CTRL), reset-done (STATUS), frame/bytestream-gen/demux/overflow error counters, and the 64-bit trace address range filter (decoder_axi_set_range())
decoder_stats.h Decoder profiling counters (rtl/stats) DEC_STATS_BASE_ETM Enable/disable, total/idle cycles, packet and atom-packet counts with burst/gap histograms, atom-element throughput -- dec_stats_print_detailed() renders all of it
edge_extractor.h edge_extractor EDGE_EXTRACTOR_BASE Stats reset; runtime hash-mode select (edge_extractor_set_hash_mode()/_get_hash_mode() -- NONE/FUZZSIGHT/STALKER, see hash_mode_plan.md); edges-total/FIFO-overflow/freeze-drop counters
bitmap_dma.h/.c bitmap_reader_bram + AXI-DMA (S2MM) + udmabuf BITMAP_READER_BASE, DMA_BASE Bundles the reader's trigger/status AXI-Lite, the DMA's S2MM control block, and the mmap'd udmabuf destination behind one handle; bitmap_dma_transfer() drives the full reader-drains -> DMA-arms -> DMA-completes -> re-arm handshake

Every base-address macro above is a placeholder (with a build-time #pragma message warning) until overridden with your own Vivado address map -- pass it as a -D define when building whatever consumes these headers, e.g. -DEDGE_EXTRACTOR_BASE=0x80021000 (ultrasight's own copies already bake in this repo's real ZCU104 addresses instead).

About

Hardware-accelerated fuzzing using CoreSight

Resources

Stars

4 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages