TODO list for AFL++

Roadmap 2.63

Makefile:

  • -march=native -Ofast -flto=full (especially for afl-fuzz)

llvm_mode:

  • using lto + opt to instrument at link time and select basic block IDs that do not result in collisions (Solution for “The far away future”, see bottom of file)

Further down the road

afl-fuzz:

  • sync_fuzzers(): only masters sync from all, slaves only sync from master (@andrea: be careful, often people run all slaves)
  • ascii_only mode for mutation output
  • setting min_len/max_len/start_offset/end_offset limits for mutation output

gcc_plugin:

  • laf-intel
  • better instrumentation (seems to be better with gcc-9+)

qemu_mode:

  • update to 4.x (probably this will be skipped :( )
  • instrim for QEMU mode via static analysis (with r2pipe? or angr?) Idea: The static analyzer outputs a map in which each edge that must be skipped is marked with 1. QEMU loads it at startup in the parent process.
  • rename qemu specific envs to AFL_QEMU (AFL_ENTRYPOINT, AFL_CODE_START/END, AFL_COMPCOV_LEVEL?)
  • add AFL_QEMU_EXITPOINT (maybe multiple?), maybe pointless as we have persistent mode
  • add/implement AFL_QEMU_INST_LIBLIST and AFL_QEMU_NOINST_PROGRAM
  • add/implement AFL_QEMU_INST_REGIONS as a list of _START/_END addresses

custom_mutators:

  • rip what Superion is doing into custom mutators for js, php, etc.
  • uniform python and custom mutators API

The far away future:

Problem: Average targets (tiff, jpeg, unrar) go through 1500 edges. At afl's default map that means ~16 collisions and ~3 wrappings.

  • Solution #1: increase map size.

    => speed loss is bad. last resort solution

    every +1 decreases fuzzing speed by ~10% and halfs the collisions birthday paradox predicts collisions at this # of edges:

    mapsizecollisions atspeed decrease
    2^163020%
    2^1742710%
    2^1860325%
    2^1985343%
    2^20120762%
    2^211706?%
    2^222412?%
    2^233411?%
    2^244823?%

    Increasing the map is an easy solution but also not a complete and efficient one.

  • Solution #2: use dynamic map size and collision free basic block IDs

    => This works and is the selected solution

    This only works in llvm_mode - obviously.

  • Solution #3: write instruction pointers to a big shared map

    => Tested and it is a dead end

    512kb/1MB shared map and the instrumented code writes the instruction pointer into the map. Map must be big enough but could be command line controlled.

    Good: complete coverage information, nothing is lost. choice of analysis impacts speed, but this can be decided by user options

    Neutral: a little bit slower but no loss of coverage

    Bad: completely changes how afl uses the map and the scheduling. Overall another very good solution, Marc Heuse/vanHauser follows this up

  • Solution #4: ???

    other ideas?