about summary refs log tree commit diff
path: root/README.md
diff options
context:
space:
mode:
Diffstat (limited to 'README.md')
-rw-r--r--README.md1567
1 files changed, 186 insertions, 1381 deletions
diff --git a/README.md b/README.md
index 1f1fd3b2..21724696 100644
--- a/README.md
+++ b/README.md
@@ -1,1441 +1,246 @@
 # American Fuzzy Lop plus plus (AFL++)
 
-  <img align="right" src="https://raw.githubusercontent.com/andreafioraldi/AFLplusplus-website/master/static/logo_256x256.png" alt="AFL++ Logo">
+<img align="right" src="https://raw.githubusercontent.com/andreafioraldi/AFLplusplus-website/master/static/logo_256x256.png" alt="AFL++ logo">
 
-  Release Version: [3.14c](https://github.com/AFLplusplus/AFLplusplus/releases)
+Release version: [3.14c](https://github.com/AFLplusplus/AFLplusplus/releases)
 
-  Github Version: 3.15a
+GitHub version: 3.15a
 
-  Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
-
-  AFL++ is maintained by:
-
-  * Marc "van Hauser" Heuse <mh@mh-sec.de>,
-  * Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>,
-  * Andrea Fioraldi <andreafioraldi@gmail.com> and
-  * Dominik Maier <mail@dmnk.co>.
-
-  Originally developed by Michał "lcamtuf" Zalewski.
-
-  AFL++ is a superior fork to Google's AFL - more speed, more and better
-  mutations, more and better instrumentation, custom module support, etc.
-
-  If you want to use AFL++ for your academic work, check the [papers page](https://aflplus.plus/papers/)
-  on the website. To cite our work, look at the [Cite](#cite) section.
-  For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast`
-  with `AFL_LLVM_CMPLOG=1`.
-
-## Major behaviour changes in AFL++ 3.00 onwards:
-
-With AFL++ 3.13-3.20 we introduce frida_mode (-O) to have an alternative for
-binary-only fuzzing. It is slower than Qemu mode but works on MacOS, Android,
-iOS etc.
-
-With AFL++ 3.15 we introduced the following changes from previous behaviours:
-  * Also -M main mode does not do deterministic fuzzing by default anymore
-  * afl-cmin and afl-showmap -Ci now descent into subdirectories like
-    afl-fuzz -i does (but note that afl-cmin.bash does not)
-
-With AFL++ 3.14 we introduced the following changes from previous behaviours:
-  * afl-fuzz: deterministic fuzzing it not a default for -M main anymore
-  * afl-cmin/afl-showmap -i now descends into subdirectories (afl-cmin.bash
-    however does not)
-
-With AFL++ 3.10 we introduced the following changes from previous behaviours:
-  * The '+' feature of the '-t' option now means to  auto-calculate the timeout
-    with the value given being the maximum timeout. The original meaning of
-    "skipping timeouts instead of abort" is now inherent to the -t option.
-
-With AFL++ 3.00 we introduced changes that break some previous AFL and AFL++
-behaviours and defaults:
-  * There are no llvm_mode and gcc_plugin subdirectories anymore and there is
-    only one compiler: afl-cc. All previous compilers now symlink to this one.
-    All instrumentation source code is now in the `instrumentation/` folder.
-  * The gcc_plugin was replaced with a new version submitted by AdaCore that
-    supports more features. Thank you!
-  * qemu_mode got upgraded to QEMU 5.1, but to be able to build this a current
-    ninja build tool version and python3 setuptools are required.
-    qemu_mode also got new options like snapshotting, instrumenting specific
-    shared libraries, etc. Additionally QEMU 5.1 supports more CPU targets so
-    this is really worth it.
-  * When instrumenting targets, afl-cc will not supersede optimizations anymore
-    if any were given. This allows to fuzz targets build regularly like those  
-    for debug or release versions.
-  * afl-fuzz:
-    * if neither -M or -S is specified, `-S default` is assumed, so more
-      fuzzers can easily be added later
-    * `-i` input directory option now descends into subdirectories. It also
-      does not fatal on crashes and too large files, instead it skips them
-      and uses them for splicing mutations
-    * -m none is now default, set memory limits (in MB) with e.g. -m 250
-    * deterministic fuzzing is now disabled by default (unless using -M) and
-      can be enabled with -D
-    * a caching of testcases can now be performed and can be modified by
-      editing config.h for TESTCASE_CACHE or by specifying the env variable
-      `AFL_TESTCACHE_SIZE` (in MB). Good values are between 50-500 (default: 50).
-    * -M mains do not perform trimming
-  * examples/ got renamed to utils/
-  * libtokencap/ libdislocator/ and qdbi_mode/ were moved to utils/
-  * afl-cmin/afl-cmin.bash now search first in PATH and last in AFL_PATH
-
-
-## Contents
-
-  1. [Features](#important-features-of-afl)
-  2. [How to compile and install AFL++](#building-and-installing-afl)
-  3. [How to fuzz a target](#how-to-fuzz-with-afl)
-  4. [Fuzzing binary-only targets](#fuzzing-binary-only-targets)
-  5. [Good examples and writeups of AFL++ usages](#good-examples-and-writeups)
-  6. [CI Fuzzing](#ci-fuzzing)
-  7. [Branches](#branches)
-  8. [Want to help?](#help-wanted)
-  9. [Detailed help and description of AFL++](#challenges-of-guided-fuzzing)
-
-## Important features of AFL++
-
-  AFL++ supports llvm from 3.8 up to version 13, very fast binary fuzzing with QEMU 5.1
-  with laf-intel and redqueen, frida mode, unicorn mode, gcc plugin, full *BSD,
-  Mac OS, Solaris and Android support and much, much, much more.
-
-  | Feature/Instrumentation  | afl-gcc | llvm      | gcc_plugin | frida_mode       | qemu_mode        |unicorn_mode      |
-  | -------------------------|:-------:|:---------:|:----------:|:----------------:|:----------------:|:----------------:|
-  | Threadsafe counters      |         |     x(3)  |            |                  |                  |                  |
-  | NeverZero                | x86[_64]|     x(1)  |     x      |         x        |         x        |         x        |
-  | Persistent Mode          |         |     x     |     x      | x86[_64]/arm64   | x86[_64]/arm[64] |         x        |
-  | LAF-Intel / CompCov      |         |     x     |            |                  | x86[_64]/arm[64] | x86[_64]/arm[64] |
-  | CmpLog                   |         |     x     |            | x86[_64]/arm64   | x86[_64]/arm[64] |                  |
-  | Selective Instrumentation|         |     x     |     x      |         x        |         x        |                  |
-  | Non-Colliding Coverage   |         |     x(4)  |            |                  |        (x)(5)    |                  |
-  | Ngram prev_loc Coverage  |         |     x(6)  |            |                  |                  |                  |
-  | Context Coverage         |         |     x(6)  |            |                  |                  |                  |
-  | Auto Dictionary          |         |     x(7)  |            |                  |                  |                  |
-  | Snapshot LKM Support     |         |    (x)(8) |    (x)(8)  |                  |        (x)(5)    |                  |
-  | Shared Memory Testcases  |         |     x     |     x      | x86[_64]/arm64   |         x        |         x        |
-
-  1. default for LLVM >= 9.0, env var for older version due an efficiency bug in previous llvm versions
-  2. GCC creates non-performant code, hence it is disabled in gcc_plugin
-  3. with `AFL_LLVM_THREADSAFE_INST`, disables NeverZero
-  4. with pcguard mode and LTO mode for LLVM 11 and newer
-  5. upcoming, development in the branch
-  6. not compatible with LTO instrumentation and needs at least LLVM v4.1
-  7. automatic in LTO mode with LLVM 11 and newer, an extra pass for all LLVM versions that write to a file to use with afl-fuzz' `-x`
-  8. the snapshot LKM is currently unmaintained due to too many kernel changes coming too fast :-(
-
-  Among others, the following features and patches have been integrated:
-
-  * NeverZero patch for afl-gcc, instrumentation, qemu_mode and unicorn_mode which prevents a wrapping map value to zero, increases coverage
-  * Persistent mode, deferred forkserver and in-memory fuzzing for qemu_mode
-  * Unicorn mode which allows fuzzing of binaries from completely different platforms (integration provided by domenukk)
-  * The new CmpLog instrumentation for LLVM and QEMU inspired by [Redqueen](https://www.syssec.ruhr-uni-bochum.de/media/emma/veroeffentlichungen/2018/12/17/NDSS19-Redqueen.pdf)
-  * Win32 PE binary-only fuzzing with QEMU and Wine
-  * AFLfast's power schedules by Marcel Böhme: [https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
-  * The MOpt mutator: [https://github.com/puppet-meteor/MOpt-AFL](https://github.com/puppet-meteor/MOpt-AFL)
-  * LLVM mode Ngram coverage by Adrian Herrera [https://github.com/adrianherrera/afl-ngram-pass](https://github.com/adrianherrera/afl-ngram-pass)
-  * LAF-Intel/CompCov support for instrumentation, qemu_mode and unicorn_mode (with enhanced capabilities)
-  * Radamsa and honggfuzz mutators (as custom mutators).
-  * QBDI mode to fuzz android native libraries via Quarkslab's [QBDI](https://github.com/QBDI/QBDI) framework
-  * Frida and ptrace mode to fuzz binary-only libraries, etc.
-
-  So all in all this is the best-of AFL that is out there :-)
-
-  For new versions and additional information, check out:
-  [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
-
-  To compare notes with other users or get notified about major new features,
-  send a mail to <afl-users+subscribe@googlegroups.com>.
-
-  See [docs/QuickStartGuide.md](docs/QuickStartGuide.md) if you don't have time to
-  read this file - however this is not recommended!
-
-## Branches
+Repository:
+[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
 
-  The following branches exist:
+AFL++ is maintained by:
 
-  * [stable/trunk](https://github.com/AFLplusplus/AFLplusplus/) : stable state of AFL++ - it is synced from dev from time to
-    time when we are satisfied with its stability
-  * [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev) : development state of AFL++ - bleeding edge and you might catch a
-    checkout which does not compile or has a bug. *We only accept PRs in dev!!*
-  * [release](https://github.com/AFLplusplus/AFLplusplus/tree/release) : the latest release
-  * (any other) : experimental branches to work on specific features or testing
-    new functionality or changes.
+* Marc "van Hauser" Heuse <mh@mh-sec.de>,
+* Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>,
+* Andrea Fioraldi <andreafioraldi@gmail.com> and
+* Dominik Maier <mail@dmnk.co>.
 
-  For releases, please see the [Releases](https://github.com/AFLplusplus/AFLplusplus/releases) tab.
+Originally developed by Michał "lcamtuf" Zalewski.
 
-## Help wanted
+AFL++ is a superior fork to Google's AFL - more speed, more and better
+mutations, more and better instrumentation, custom module support, etc.
 
-We have several ideas we would like to see in AFL++ to make it even better.
-However, we already work on so many things that we do not have the time for
-all the big ideas.
+You are free to copy, modify, and distribute AFL++ with attribution under the
+terms of the Apache-2.0 License. See the [LICENSE](LICENSE) for details.
 
-This can be your way to support and contribute to AFL++ - extend it to do
-something cool.
+## Getting started
 
-We have an idea list in [docs/ideas.md](docs/ideas.md).
+Here is some information to get you started:
 
-For everyone who wants to contribute (and send pull requests) please read
-[CONTRIBUTING.md](CONTRIBUTING.md) before your submit.
+* For releases, see the
+  [Releases tab](https://github.com/AFLplusplus/AFLplusplus/releases) and
+  [branches](#branches). Also take a look at the list of
+  [important changes in AFL++](docs/important_changes.md) and the list of
+  [features](docs/features.md).
+* If you want to use AFL++ for your academic work, check the
+  [papers page](https://aflplus.plus/papers/) on the website.
+* To cite our work, look at the [Cite](#cite) section.
+* For comparisons, use the fuzzbench `aflplusplus` setup, or use
+  `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. You can find the `aflplusplus`
+  default configuration on Google's
+  [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
+* To get you started with tutorials, go to
+  [docs/tutorials.md](docs/tutorials.md).
 
 ## Building and installing AFL++
 
-An easy way to install AFL++ with everything compiled is available via docker:
-You can use the [Dockerfile](Dockerfile) (which has gcc-10 and clang-11 -
-hence afl-clang-lto is available!) or just pull directly from the docker hub:
+To have AFL++ easily available with everything compiled, pull the image directly
+from the Docker Hub:
+
 ```shell
 docker pull aflplusplus/aflplusplus
 docker run -ti -v /location/of/your/target:/src aflplusplus/aflplusplus
 ```
-This image is automatically generated when a push to the stable repo happens.
-You will find your target source code in /src in the container.
-
-If you want to build AFL++ yourself you have many options.
-The easiest choice is to build and install everything:
-
-```shell
-sudo apt-get update
-sudo apt-get install -y build-essential python3-dev automake git flex bison libglib2.0-dev libpixman-1-dev python3-setuptools
-# try to install llvm 11 and install the distro default if that fails
-sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || sudo apt-get install -y lld llvm llvm-dev clang 
-sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/.* //'|sed 's/\..*//')-dev
-git clone https://github.com/AFLplusplus/AFLplusplus
-cd AFLplusplus
-make distrib
-sudo make install
-```
-It is recommended to install the newest available gcc, clang and llvm-dev
-possible in your distribution!
-
-Note that "make distrib" also builds instrumentation, qemu_mode, unicorn_mode and
-more. If you just want plain AFL++ then do "make all", however compiling and
-using at least instrumentation is highly recommended for much better results -
-hence in this case
-
-```shell
-make source-only
-```
-is what you should choose.
-
-These build targets exist:
-
-* all: just the main AFL++ binaries
-* binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap
-* source-only: everything for source code fuzzing: instrumentation, libdislocator, libtokencap
-* distrib: everything (for both binary-only and source code fuzzing)
-* man: creates simple man pages from the help option of the programs
-* install: installs everything you have compiled with the build options above
-* clean: cleans everything compiled, not downloads (unless not on a checkout)
-* deepclean: cleans everything including downloads
-* code-format: format the code, do this before you commit and send a PR please!
-* tests: runs test cases to ensure that all features are still working as they should
-* unit: perform unit tests (based on cmocka)
-* help: shows these build options
-
-[Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html) you can also build statically linked versions of the 
-AFL++ binaries by passing the STATIC=1 argument to make:
-
-```shell
-make STATIC=1
-```
-
-These build options exist:
-
-* STATIC - compile AFL++ static
-* ASAN_BUILD - compiles with memory sanitizer for debug purposes
-* DEBUG - no optimization, -ggdb3, all warnings and -Werror
-* PROFILING - compile with profiling information (gprof)
-* INTROSPECTION - compile afl-fuzz with mutation introspection
-* NO_PYTHON - disable python support
-* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
-* AFL_NO_X86 - if compiling on non-intel/amd platforms
-* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g. Debian)
-
-e.g.: `make ASAN_BUILD=1`
-
-## Good examples and writeups
-
-Here are some good writeups to show how to effectively use AFL++:
-
- * [https://aflplus.plus/docs/tutorials/libxml2_tutorial/](https://aflplus.plus/docs/tutorials/libxml2_tutorial/)
- * [https://bananamafia.dev/post/gb-fuzz/](https://bananamafia.dev/post/gb-fuzz/)
- * [https://securitylab.github.com/research/fuzzing-challenges-solutions-1](https://securitylab.github.com/research/fuzzing-challenges-solutions-1)
- * [https://securitylab.github.com/research/fuzzing-software-2](https://securitylab.github.com/research/fuzzing-software-2)
- * [https://securitylab.github.com/research/fuzzing-sockets-FTP](https://securitylab.github.com/research/fuzzing-sockets-FTP)
- * [https://securitylab.github.com/research/fuzzing-sockets-FreeRDP](https://securitylab.github.com/research/fuzzing-sockets-FreeRDP)
- * [https://securitylab.github.com/research/fuzzing-apache-1](https://securitylab.github.com/research/fuzzing-apache-1)
-
-If you do not want to follow a tutorial but rather try an exercise type of
-training then we can highly recommend the following:
- * [https://github.com/antonio-morales/Fuzzing101](https://github.com/antonio-morales/Fuzzing101)
-
-If you are interested in fuzzing structured data (where you define what the
-structure is), these links have you covered:
- * Superion for AFL++: [https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator)
- * libprotobuf for AFL++: [https://github.com/P1umer/AFLplusplus-protobuf-mutator](https://github.com/P1umer/AFLplusplus-protobuf-mutator)
- * libprotobuf raw: [https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator](https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator)
- * libprotobuf for old AFL++ API: [https://github.com/thebabush/afl-libprotobuf-mutator](https://github.com/thebabush/afl-libprotobuf-mutator)
-
-If you find other good ones, please send them to us :-)
-
-## How to fuzz with AFL++
-
-The following describes how to fuzz with a target if source code is available.
-If you have a binary-only target please skip to [#Instrumenting binary-only apps](#Instrumenting binary-only apps)
-
-Fuzzing source code is a three-step process.
-
-1. Compile the target with a special compiler that prepares the target to be
-   fuzzed efficiently. This step is called "instrumenting a target".
-2. Prepare the fuzzing by selecting and optimizing the input corpus for the
-   target.
-3. Perform the fuzzing of the target by randomly mutating input and assessing
-   if a generated input was processed in a new path in the target binary.
-
-### 1. Instrumenting that target
-
-#### a) Selecting the best AFL++ compiler for instrumenting the target
-
-AFL++ comes with a central compiler `afl-cc` that incorporates various different
-kinds of compiler targets and and instrumentation options.
-The following evaluation flow will help you to select the best possible.
-
-It is highly recommended to have the newest llvm version possible installed,
-anything below 9 is not recommended.
-
-```
-+--------------------------------+
-| clang/clang++ 11+ is available | --> use LTO mode (afl-clang-lto/afl-clang-lto++)
-+--------------------------------+     see [instrumentation/README.lto.md](instrumentation/README.lto.md)
-    |
-    | if not, or if the target fails with LTO afl-clang-lto/++
-    |
-    v
-+---------------------------------+
-| clang/clang++ 3.8+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++)
-+---------------------------------+     see [instrumentation/README.llvm.md](instrumentation/README.llvm.md)
-    |
-    | if not, or if the target fails with LLVM afl-clang-fast/++
-    |
-    v
- +--------------------------------+
- | gcc 5+ is available            | -> use GCC_PLUGIN mode (afl-gcc-fast/afl-g++-fast)
- +--------------------------------+    see [instrumentation/README.gcc_plugin.md](instrumentation/README.gcc_plugin.md) and
-                                       [instrumentation/README.instrument_list.md](instrumentation/README.instrument_list.md)
-    |
-    | if not, or if you do not have a gcc with plugin support
-    |
-    v
-   use GCC mode (afl-gcc/afl-g++) (or afl-clang/afl-clang++ for clang)
-```
-
-Clickable README links for the chosen compiler:
-
-  * [LTO mode - afl-clang-lto](instrumentation/README.lto.md)
-  * [LLVM mode - afl-clang-fast](instrumentation/README.llvm.md)
-  * [GCC_PLUGIN mode - afl-gcc-fast](instrumentation/README.gcc_plugin.md)
-  * GCC/CLANG modes (afl-gcc/afl-clang) have no README as they have no own features
-
-You can select the mode for the afl-cc compiler by:
-  1. use a symlink to afl-cc: afl-gcc, afl-g++, afl-clang, afl-clang++,
-     afl-clang-fast, afl-clang-fast++, afl-clang-lto, afl-clang-lto++,
-     afl-gcc-fast, afl-g++-fast (recommended!)
-  2. using the environment variable AFL_CC_COMPILER with MODE
-  3. passing --afl-MODE command line options to the compiler via CFLAGS/CXXFLAGS/CPPFLAGS
-
-MODE can be one of: LTO (afl-clang-lto*), LLVM (afl-clang-fast*), GCC_PLUGIN
-(afl-g*-fast) or GCC (afl-gcc/afl-g++) or CLANG(afl-clang/afl-clang++).
-
-Because no AFL specific command-line options are accepted (beside the
---afl-MODE command), the compile-time tools make fairly broad use of environment
-variables, which can be listed with `afl-cc -hh` or by reading [docs/env_variables.md](docs/env_variables.md).
-
-#### b) Selecting instrumentation options
-
-The following options are available when you instrument with LTO mode (afl-clang-fast/afl-clang-lto):
-
- * Splitting integer, string, float and switch comparisons so AFL++ can easier
-   solve these. This is an important option if you do not have a very good
-   and large input corpus. This technique is called laf-intel or COMPCOV.
-   To use this set the following environment variable before compiling the
-   target: `export AFL_LLVM_LAF_ALL=1`
-   You can read more about this in [instrumentation/README.laf-intel.md](instrumentation/README.laf-intel.md)
- * A different technique (and usually a better one than laf-intel) is to
-   instrument the target so that any compare values in the target are sent to
-   AFL++ which then tries to put these values into the fuzzing data at different
-   locations. This technique is very fast and good - if the target does not
-   transform input data before comparison. Therefore this technique is called
-   `input to state` or `redqueen`.
-   If you want to use this technique, then you have to compile the target
-   twice, once specifically with/for this mode, and pass this binary to afl-fuzz
-   via the `-c` parameter.
-   Note that you can compile also just a cmplog binary and use that for both
-   however there will be a performance penality.
-   You can read more about this in [instrumentation/README.cmplog.md](instrumentation/README.cmplog.md)
-
-If you use LTO, LLVM or GCC_PLUGIN mode (afl-clang-fast/afl-clang-lto/afl-gcc-fast)
-you have the option to selectively only instrument parts of the target that you
-are interested in:
-
- * To instrument only those parts of the target that you are interested in
-   create a file with all the filenames of the source code that should be
-   instrumented.
-   For afl-clang-lto and afl-gcc-fast - or afl-clang-fast if a mode other than
-   DEFAULT/PCGUARD is used or you have llvm > 10.0.0 - just put one
-   filename or function per line (no directory information necessary for
-   filenames9, and either set `export AFL_LLVM_ALLOWLIST=allowlist.txt` **or**
-   `export AFL_LLVM_DENYLIST=denylist.txt` - depending on if you want per
-   default to instrument unless noted (DENYLIST) or not perform instrumentation
-   unless requested (ALLOWLIST).
-   **NOTE:** During optimization functions might be inlined and then would not match!
-   See [instrumentation/README.instrument_list.md](instrumentation/README.instrument_list.md)
-
-There are many more options and modes available however these are most of the
-time less effective. See:
- * [instrumentation/README.ctx.md](instrumentation/README.ctx.md)
- * [instrumentation/README.ngram.md](instrumentation/README.ngram.md)
-
-AFL++ performs "never zero" counting in its bitmap. You can read more about this
-here:
- * [instrumentation/README.neverzero.md](instrumentation/README.neverzero.md)
-
-#### c) Sanitizers
-
-It is possible to use sanitizers when instrumenting targets for fuzzing,
-which allows you to find bugs that would not necessarily result in a crash.
-
-Note that sanitizers have a huge impact on CPU (= less executions per second)
-and RAM usage. Also you should only run one afl-fuzz instance per sanitizer type.
-This is enough because a use-after-free bug will be picked up, e.g. by
-ASAN (address sanitizer) anyway when syncing to other fuzzing instances,
-so not all fuzzing instances need to be instrumented with ASAN.
-
-The following sanitizers have built-in support in AFL++:
-  * ASAN = Address SANitizer, finds memory corruption vulnerabilities like
-    use-after-free, NULL pointer dereference, buffer overruns, etc.
-    Enabled with `export AFL_USE_ASAN=1` before compiling.
-  * MSAN = Memory SANitizer, finds read access to uninitialized memory, eg.
-    a local variable that is defined and read before it is even set.
-    Enabled with `export AFL_USE_MSAN=1` before compiling.
-  * UBSAN = Undefined Behaviour SANitizer, finds instances where - by the
-    C and C++ standards - undefined behaviour happens, e.g. adding two
-    signed integers together where the result is larger than a signed integer
-    can hold.
-    Enabled with `export AFL_USE_UBSAN=1` before compiling.
-  * CFISAN = Control Flow Integrity SANitizer, finds instances where the
-    control flow is found to be illegal. Originally this was rather to
-    prevent return oriented programming exploit chains from functioning,
-    in fuzzing this is mostly reduced to detecting type confusion
-    vulnerabilities - which is however one of the most important and dangerous
-    C++ memory corruption classes!
-    Enabled with `export AFL_USE_CFISAN=1` before compiling.
-  * LSAN = Leak SANitizer, finds memory leaks in a program. This is not really
-    a security issue, but for developers this can be very valuable.
-    Note that unlike the other sanitizers above this needs
-    `__AFL_LEAK_CHECK();` added to all areas of the target source code where you
-    find a leak check necessary!
-    Enabled with `export AFL_USE_LSAN=1` before compiling.
-
-It is possible to further modify the behaviour of the sanitizers at run-time
-by setting `ASAN_OPTIONS=...`, `LSAN_OPTIONS` etc. - the available parameters
-can be looked up in the sanitizer documentation of llvm/clang.
-afl-fuzz however requires some specific parameters important for fuzzing to be
-set. If you want to set your own, it might bail and report what it is missing.
-
-Note that some sanitizers cannot be used together, e.g. ASAN and MSAN, and
-others often cannot work together because of target weirdness, e.g. ASAN and
-CFISAN. You might need to experiment which sanitizers you can combine in a
-target (which means more instances can be run without a sanitized target,
-which is more effective).
-
-#### d) Modify the target
-
-If the target has features that make fuzzing more difficult, e.g.
-checksums, HMAC, etc. then modify the source code so that checks for these
-values are removed.
-This can even be done safely for source code used in operational products
-by eliminating these checks within these AFL specific blocks:
-
-```
-#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
-  // say that the checksum or HMAC was fine - or whatever is required
-  // to eliminate the need for the fuzzer to guess the right checksum
-  return 0;
-#endif
-```
-
-All AFL++ compilers will set this preprocessor definition automatically.
-
-#### e) Instrument the target
-
-In this step the target source code is compiled so that it can be fuzzed.
-
-Basically you have to tell the target build system that the selected AFL++
-compiler is used. Also - if possible - you should always configure the
-build system such that the target is compiled statically and not dynamically.
-How to do this is described below.
-
-The #1 rule when instrumenting a target is: avoid instrumenting shared
-libraries at all cost. You would need to set LD_LIBRARY_PATH to point to
-these, you could accidently type "make install" and install them system wide -
-so don't. Really don't.
-**Always compile libraries you want to have instrumented as static and link
-these to the target program!**
-
-Then build the target. (Usually with `make`)
-
-**NOTES**
-
-1. sometimes configure and build systems are fickle and do not like
-   stderr output (and think this means a test failure) - which is something
-   AFL++ likes to do to show statistics. It is recommended to disable AFL++
-   instrumentation reporting via `export AFL_QUIET=1`.
-
-2. sometimes configure and build systems error on warnings - these should be
-   disabled (e.g. `--disable-werror` for some configure scripts).
-
-3. in case the configure/build system complains about AFL++'s compiler and
-   aborts then set `export AFL_NOOPT=1` which will then just behave like the
-   real compiler. This option has to be unset again before building the target!
-
-##### configure
-
-For `configure` build systems this is usually done by:
-`CC=afl-clang-fast CXX=afl-clang-fast++ ./configure --disable-shared`
-
-Note that if you are using the (better) afl-clang-lto compiler you also have to
-set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as is
-described in [instrumentation/README.lto.md](instrumentation/README.lto.md).
-
-##### cmake
-
-For `cmake` build systems this is usually done by:
-`mkdir build; cd build; cmake -DCMAKE_C_COMPILER=afl-cc -DCMAKE_CXX_COMPILER=afl-c++ ..`
-
-Note that if you are using the (better) afl-clang-lto compiler you also have to
-set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as is
-described in [instrumentation/README.lto.md](instrumentation/README.lto.md).
-
-##### meson
-
-For meson you have to set the AFL++ compiler with the very first command!
-`CC=afl-cc CXX=afl-c++ meson`
-
-##### other build systems or if configure/cmake didn't work
-
-Sometimes cmake and configure do not pick up the AFL++ compiler, or the
-ranlib/ar that is needed - because this was just not foreseen by the developer
-of the target. Or they have non-standard options. Figure out if there is a 
-non-standard way to set this, otherwise set up the build normally and edit the
-generated build environment afterwards manually to point it to the right compiler
-(and/or ranlib and ar).
-
-#### f) Better instrumentation
-
-If you just fuzz a target program as-is you are wasting a great opportunity for
-much more fuzzing speed.
-
-This variant requires the usage of afl-clang-lto, afl-clang-fast or afl-gcc-fast.
-
-It is the so-called `persistent mode`, which is much, much faster but
-requires that you code a source file that is specifically calling the target
-functions that you want to fuzz, plus a few specific AFL++ functions around
-it. See [instrumentation/README.persistent_mode.md](instrumentation/README.persistent_mode.md) for details.
-
-Basically if you do not fuzz a target in persistent mode then you are just
-doing it for a hobby and not professionally :-).
-
-#### g) libfuzzer fuzzer harnesses with LLVMFuzzerTestOneInput()
-
-libfuzzer `LLVMFuzzerTestOneInput()` harnesses are the defacto standard
-for fuzzing, and they can be used with AFL++ (and honggfuzz) as well!
-Compiling them is as simple as:
-```
-afl-clang-fast++ -fsanitize=fuzzer -o harness harness.cpp targetlib.a
-```
-You can even use advanced libfuzzer features like `FuzzedDataProvider`,
-`LLVMFuzzerMutate()` etc. and they will work!
-
-The generated binary is fuzzed with afl-fuzz like any other fuzz target.
-
-Bonus: the target is already optimized for fuzzing due to persistent mode and
-shared-memory testcases and hence gives you the fastest speed possible.
-
-For more information see [utils/aflpp_driver/README.md](utils/aflpp_driver/README.md)
-
-### 2. Preparing the fuzzing campaign
-
-As you fuzz the target with mutated input, having as diverse inputs for the
-target as possible improves the efficiency a lot.
-
-#### a) Collect inputs
-
-Try to gather valid inputs for the target from wherever you can. E.g. if it is
-the PNG picture format try to find as many png files as possible, e.g. from
-reported bugs, test suites, random downloads from the internet, unit test
-case data - from all kind of PNG software.
-
-If the input format is not known, you can also modify a target program to write
-normal data it receives and processes to a file and use these.
-
-#### b) Making the input corpus unique
-
-Use the AFL++ tool `afl-cmin` to remove inputs from the corpus that do not
-produce a new path in the target.
-
-Put all files from step a) into one directory, e.g. INPUTS.
-
-If the target program is to be called by fuzzing as `bin/target -d INPUTFILE`
-the run afl-cmin like this:
-`afl-cmin -i INPUTS -o INPUTS_UNIQUE -- bin/target -d @@`
-Note that the INPUTFILE argument that the target program would read from has to be set as `@@`.
-
-If the target reads from stdin instead, just omit the `@@` as this is the
-default.
-
-This step is highly recommended!
-
-#### c) Minimizing all corpus files
-
-The shorter the input files that still traverse the same path
-within the target, the better the fuzzing will be. This minimization
-is done with `afl-tmin` however it is a long process as this has to
-be done for every file:
-
-```
-mkdir input
-cd INPUTS_UNIQUE
-for i in *; do
-  afl-tmin -i "$i" -o "../input/$i" -- bin/target -d @@
-done
-```
-
-This step can also be parallelized, e.g. with `parallel`.
-Note that this step is rather optional though.
-
-#### Done!
-
-The INPUTS_UNIQUE/ directory from step b) - or even better the directory input/ 
-if you minimized the corpus in step c) - is the resulting input corpus directory
-to be used in fuzzing! :-)
-
-### 3. Fuzzing the target
-
-In this final step we fuzz the target.
-There are not that many important options to run the target - unless you want
-to use many CPU cores/threads for the fuzzing, which will make the fuzzing much
-more useful.
-
-If you just use one CPU for fuzzing, then you are fuzzing just for fun and not
-seriously :-)
-
-#### a) Running afl-fuzz
-
-Before you do even a test run of afl-fuzz execute `sudo afl-system-config` (on
-the host if you execute afl-fuzz in a docker container). This reconfigures the
-system for optimal speed - which afl-fuzz checks and bails otherwise.
-Set `export AFL_SKIP_CPUFREQ=1` for afl-fuzz to skip this check if you cannot
-run afl-system-config with root privileges on the host for whatever reason.
-
-Note there is also `sudo afl-persistent-config` which sets additional permanent
-boot options for a much better fuzzing performance.
-
-Note that both scripts improve your fuzzing performance but also decrease your
-system protection against attacks! So set strong firewall rules and only
-expose SSH as a network service if you use these (which is highly recommended).
-
-If you have an input corpus from step 2 then specify this directory with the `-i`
-option. Otherwise create a new directory and create a file with any content
-as test data in there.
-
-If you do not want anything special, the defaults are already usually best,
-hence all you need is to specify the seed input directory with the result of
-step [2a. Collect inputs](#a-collect-inputs):
-`afl-fuzz -i input -o output -- bin/target -d @@`
-Note that the directory specified with -o will be created if it does not exist.
-
-It can be valuable to run afl-fuzz in a screen or tmux shell so you can log off,
-or afl-fuzz is not aborted if you are running it in a remote ssh session where
-the connection fails in between.
-Only do that though once you have verified that your fuzzing setup works!
-Simply run it like `screen -dmS afl-main -- afl-fuzz -M main-$HOSTNAME -i ...`
-and it will start away in a screen session. To enter this session simply type
-`screen -r afl-main`. You see - it makes sense to name the screen session
-same as the afl-fuzz -M/-S naming :-)
-For more information on screen or tmux please check their documentation.
-
-If you need to stop and re-start the fuzzing, use the same command line options
-(or even change them by selecting a different power schedule or another
-mutation mode!) and switch the input directory with a dash (`-`):
-`afl-fuzz -i - -o output -- bin/target -d @@`
-
-Memory limits are not enforced by afl-fuzz by default and the system may run
-out of memory. You can decrease the memory with the `-m` option, the value is
-in MB. If this is too small for the target, you can usually see this by
-afl-fuzz bailing with the message that it could not connect to the forkserver.
-
-Adding a dictionary is helpful. See the directory [dictionaries/](dictionaries/) if
-something is already included for your data format, and tell afl-fuzz to load
-that dictionary by adding `-x dictionaries/FORMAT.dict`. With afl-clang-lto
-you have an autodictionary generation for which you need to do nothing except
-to use afl-clang-lto as the compiler. You also have the option to generate
-a dictionary yourself, see [utils/libtokencap/README.md](utils/libtokencap/README.md).
-
-afl-fuzz has a variety of options that help to workaround target quirks like
-specific locations for the input file (`-f`), performing deterministic
-fuzzing (`-D`) and many more. Check out `afl-fuzz -h`.
-
-We highly recommend that you set a memory limit for running the target with `-m`
-which defines the maximum memory in MB. This prevents a potential
-out-of-memory problem for your system plus helps you detect missing `malloc()`
-failure handling in the target.
-Play around with various -m values until you find one that safely works for all
-your input seeds (if you have good ones and then double or quadrouple that.
-
-By default afl-fuzz never stops fuzzing. To terminate AFL++ simply press Control-C
-or send a signal SIGINT. You can limit the number of executions or approximate runtime
-in seconds with options also.
-
-When you start afl-fuzz you will see a user interface that shows what the status
-is:
-![docs/resources/screenshot.png](docs/resources/screenshot.png)
-
-All labels are explained in [docs/status_screen.md](docs/status_screen.md).
-
-#### b) Using multiple cores
-
-If you want to seriously fuzz then use as many cores/threads as possible to
-fuzz your target.
-
-On the same machine - due to the design of how AFL++ works - there is a maximum
-number of CPU cores/threads that are useful, use more and the overall performance
-degrades instead. This value depends on the target, and the limit is between 32
-and 64 cores per machine.
-
-If you have the RAM, it is highly recommended run the instances with a caching
-of the testcases. Depending on the average testcase size (and those found
-during fuzzing) and their number, a value between 50-500MB is recommended.
-You can set the cache size (in MB) by setting the environment variable `AFL_TESTCACHE_SIZE`.
-
-There should be one main fuzzer (`-M main-$HOSTNAME` option) and as many secondary
-fuzzers (eg `-S variant1`) as you have cores that you use.
-Every -M/-S entry needs a unique name (that can be whatever), however the same
--o output directory location has to be used for all instances.
-
-For every secondary fuzzer there should be a variation, e.g.:
- * one should fuzz the target that was compiled differently: with sanitizers
-   activated (`export AFL_USE_ASAN=1 ; export AFL_USE_UBSAN=1 ;
-   export AFL_USE_CFISAN=1`)
- * one or two should fuzz the target with CMPLOG/redqueen (see above), at
-   least one cmplog instance should follow transformations (`-l AT`)
- * one to three fuzzers should fuzz a target compiled with laf-intel/COMPCOV
-   (see above). Important note: If you run more than one laf-intel/COMPCOV
-   fuzzer and you want them to share their intermediate results, the main
-   fuzzer (`-M`) must be one of the them! (Although this is not really
-   recommended.)
-
-All other secondaries should be used like this:
- * A quarter to a third with the MOpt mutator enabled: `-L 0`
- * run with a different power schedule, recommended are:
-   `fast (default), explore, coe, lin, quad, exploit and rare`
-   which you can set with e.g. `-p explore`
- * a few instances should use the old queue cycling with `-Z`
-
-Also it is recommended to set `export AFL_IMPORT_FIRST=1` to load testcases
-from other fuzzers in the campaign first.
-
-If you have a large corpus, a corpus from a previous run or are fuzzing in
-a CI, then also set `export AFL_CMPLOG_ONLY_NEW=1` and `export AFL_FAST_CAL=1`.
-
-You can also use different fuzzers.
-If you are using AFL spinoffs or AFL conforming fuzzers, then just use the
-same -o directory and give it a unique `-S` name.
-Examples are:
- * [Fuzzolic](https://github.com/season-lab/fuzzolic)
- * [symcc](https://github.com/eurecom-s/symcc/)
- * [Eclipser](https://github.com/SoftSec-KAIST/Eclipser/)
- * [AFLsmart](https://github.com/aflsmart/aflsmart)
- * [FairFuzz](https://github.com/carolemieux/afl-rb)
- * [Neuzz](https://github.com/Dongdongshe/neuzz)
- * [Angora](https://github.com/AngoraFuzzer/Angora)
-
-A long list can be found at [https://github.com/Microsvuln/Awesome-AFL](https://github.com/Microsvuln/Awesome-AFL)
-
-However you can also sync AFL++ with honggfuzz, libfuzzer with `-entropic=1`, etc.
-Just show the main fuzzer (-M) with the `-F` option where the queue/work
-directory of a different fuzzer is, e.g. `-F /src/target/honggfuzz`.
-Using honggfuzz (with `-n 1` or `-n 2`) and libfuzzer in parallel is highly
-recommended!
-
-#### c) Using multiple machines for fuzzing
-
-Maybe you have more than one machine you want to fuzz the same target on.
-Simply start the `afl-fuzz` (and perhaps libfuzzer, honggfuzz, ...)
-orchestra as you like, just ensure that your have one and only one `-M`
-instance per server, and that its name is unique, hence the recommendation
-for `-M main-$HOSTNAME`.
-
-Now there are three strategies on how you can sync between the servers:
-  * never: sounds weird, but this makes every server an island and has the
-    chance the each follow different paths into the target. You can make
-    this even more interesting by even giving different seeds to each server.
-  * regularly (~4h): this ensures that all fuzzing campaigns on the servers
-    "see" the same thing. It is like fuzzing on a huge server.
-  * in intervals of 1/10th of the overall expected runtime of the fuzzing you
-    sync. This tries a bit to combine both. have some individuality of the
-    paths each campaign on a server explores, on the other hand if one
-    gets stuck where another found progress this is handed over making it
-    unstuck.
-
-The syncing process itself is very simple.
-As the `-M main-$HOSTNAME` instance syncs to all `-S` secondaries as well
-as to other fuzzers, you have to copy only this directory to the other
-machines.
-
-Lets say all servers have the `-o out` directory in /target/foo/out, and
-you created a file `servers.txt` which contains the hostnames of all
-participating servers, plus you have an ssh key deployed to all of them,
-then run:
-```bash
-for FROM in `cat servers.txt`; do
-  for TO in `cat servers.txt`; do
-    rsync -rlpogtz --rsh=ssh $FROM:/target/foo/out/main-$FROM $TO:target/foo/out/
-  done
-done
-```
-You can run this manually, per cron job - as you need it.
-There is a more complex and configurable script in `utils/distributed_fuzzing`.
-
-#### d) The status of the fuzz campaign
-
-AFL++ comes with the `afl-whatsup` script to show the status of the fuzzing
-campaign.
-
-Just supply the directory that afl-fuzz is given with the -o option and
-you will see a detailed status of every fuzzer in that campaign plus
-a summary.
-
-To have only the summary use the `-s` switch e.g.: `afl-whatsup -s out/`
-
-If you have multiple servers then use the command after a sync, or you have
-to execute this script per server.
-
-#### e) Stopping fuzzing, restarting fuzzing, adding new seeds
-
-To stop an afl-fuzz run, simply press Control-C.
-
-To restart an afl-fuzz run, just reuse the same command line but replace the
-`-i directory` with `-i -` or set `AFL_AUTORESUME=1`.
-
-If you want to add new seeds to a fuzzing campaign you can run a temporary
-fuzzing instance, e.g. when your main fuzzer is using `-o out` and the new
-seeds are in `newseeds/` directory:
-```
-AFL_BENCH_JUST_ONE=1 AFL_FAST_CAL=1 afl-fuzz -i newseeds -o out -S newseeds -- ./target
-```
-
-#### f) Checking the coverage of the fuzzing
-
-The `paths found` value is a bad indicator for checking how good the coverage is.
-
-A better indicator - if you use default llvm instrumentation with at least
-version 9 - is to use `afl-showmap` with the collect coverage option `-C` on
-the output directory:
-```
-$ afl-showmap -C -i out -o /dev/null -- ./target -params @@
-...
-[*] Using SHARED MEMORY FUZZING feature.
-[*] Target map size: 9960
-[+] Processed 7849 input files.
-[+] Captured 4331 tuples (highest value 255, total values 67130596) in '/dev/nul
-l'.
-[+] A coverage of 4331 edges were achieved out of 9960 existing (43.48%) with 7849 input files.
-```
-It is even better to check out the exact lines of code that have been reached -
-and which have not been found so far.
-
-An "easy" helper script for this is [https://github.com/vanhauser-thc/afl-cov](https://github.com/vanhauser-thc/afl-cov),
-just follow the README of that separate project.
-
-If you see that an important area or a feature has not been covered so far then
-try to find an input that is able to reach that and start a new secondary in
-that fuzzing campaign with that seed as input, let it run for a few minutes,
-then terminate it. The main node will pick it up and make it available to the
-other secondary nodes over time. Set `export AFL_NO_AFFINITY=1` or
-`export AFL_TRY_AFFINITY=1` if you have no free core.
-
-Note that in nearly all cases you can never reach full coverage. A lot of
-functionality is usually dependent on exclusive options that would need individual
-fuzzing campaigns each with one of these options set. E.g. if you fuzz a library to
-convert image formats and your target is the png to tiff API then you will not
-touch any of the other library APIs and features.
-
-#### g) How long to fuzz a target?
-
-This is a difficult question.
-Basically if no new path is found for a long time (e.g. for a day or a week)
-then you can expect that your fuzzing won't be fruitful anymore.
-However often this just means that you should switch out secondaries for
-others, e.g. custom mutator modules, sync to very different fuzzers, etc.
-
-Keep the queue/ directory (for future fuzzings of the same or similar targets)
-and use them to seed other good fuzzers like libfuzzer with the -entropic
-switch or honggfuzz.
-
-#### h) Improve the speed!
-
- * Use [persistent mode](instrumentation/README.persistent_mode.md) (x2-x20 speed increase)
- * If you do not use shmem persistent mode, use `AFL_TMPDIR` to point the input file on a tempfs location, see [docs/env_variables.md](docs/env_variables.md)
- * Linux: Improve kernel performance: modify `/etc/default/grub`, set `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then `update-grub` and `reboot` (warning: makes the system more insecure) - you can also just run `sudo afl-persistent-config`
- * Linux: Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem
- * Use your cores! [3.b) Using multiple cores/threads](#b-using-multiple-coresthreads)
- * Run `sudo afl-system-config` before starting the first afl-fuzz instance after a reboot
-
-### The End
-
-Check out the [docs/FAQ](docs/FAQ.md) if it maybe answers your question (that
-you might not even have known you had ;-) ).
-
-This is basically all you need to know to professionally run fuzzing campaigns.
-If you want to know more, the rest of this README and the tons of texts in
-[docs/](docs/) will have you covered.
-
-Note that there are also a lot of tools out there that help fuzzing with AFL++
-(some might be deprecated or unsupported):
-
-Speeding up fuzzing:
- * [libfiowrapper](https://github.com/marekzmyslowski/libfiowrapper) - if the function you want to fuzz requires loading a file, this allows using the shared memory testcase feature :-) - recommended.
-
-Minimization of test cases:
- * [afl-pytmin](https://github.com/ilsani/afl-pytmin) - a wrapper for afl-tmin that tries to speed up the process of minimization of a single test case by using many CPU cores.
- * [afl-ddmin-mod](https://github.com/MarkusTeufelberger/afl-ddmin-mod) - a variation of afl-tmin based on the ddmin algorithm. 
- * [halfempty](https://github.com/googleprojectzero/halfempty) -  is a fast utility for minimizing test cases by Tavis Ormandy based on parallelization. 
-
-Distributed execution:
- * [disfuzz-afl](https://github.com/MartijnB/disfuzz-afl) - distributed fuzzing for AFL.
- * [AFLDFF](https://github.com/quantumvm/AFLDFF) - AFL distributed fuzzing framework.
- * [afl-launch](https://github.com/bnagy/afl-launch) - a tool for the execution of many AFL instances.
- * [afl-mothership](https://github.com/afl-mothership/afl-mothership) - management and execution of many synchronized AFL fuzzers on AWS cloud.
- * [afl-in-the-cloud](https://github.com/abhisek/afl-in-the-cloud) - another script for running AFL in AWS.
-
-Deployment, management, monitoring, reporting
- * [afl-utils](https://gitlab.com/rc0r/afl-utils) - a set of utilities for automatic processing/analysis of crashes and reducing the number of test cases.
- * [afl-other-arch](https://github.com/shellphish/afl-other-arch) - is a set of patches and scripts for easily adding support for various non-x86 architectures for AFL.
- * [afl-trivia](https://github.com/bnagy/afl-trivia) - a few small scripts to simplify the management of AFL.
- * [afl-monitor](https://github.com/reflare/afl-monitor) - a script for monitoring AFL.
- * [afl-manager](https://github.com/zx1340/afl-manager) - a web server on Python for managing multi-afl.
- * [afl-remote](https://github.com/block8437/afl-remote) - a web server for the remote management of AFL instances.
- * [afl-extras](https://github.com/fekir/afl-extras) - shell scripts to parallelize afl-tmin, startup, and data collection.
-
-Crash processing
- * [afl-crash-analyzer](https://github.com/floyd-fuh/afl-crash-analyzer) - another crash analyzer for AFL.
- * [fuzzer-utils](https://github.com/ThePatrickStar/fuzzer-utils) - a set of scripts for the analysis of results.
- * [atriage](https://github.com/Ayrx/atriage) - a simple triage tool.
- * [afl-kit](https://github.com/kcwu/afl-kit) - afl-cmin on Python.
- * [AFLize](https://github.com/d33tah/aflize) - a tool that automatically generates builds of debian packages suitable for AFL.
- * [afl-fid](https://github.com/FoRTE-Research/afl-fid) - a set of tools for working with input data.
-
-## CI Fuzzing
-
-Some notes on CI Fuzzing - this fuzzing is different to normal fuzzing
-campaigns as these are much shorter runnings.
-
-1. Always:
-  * LTO has a much longer compile time which is diametrical to short fuzzing - 
-    hence use afl-clang-fast instead.
-  * If you compile with CMPLOG then you can save fuzzing time and reuse that
-    compiled target for both the -c option and the main fuzz target.
-    This will impact the speed by ~15% though.
-  * `AFL_FAST_CAL` - Enable fast calibration, this halfs the time the saturated
-     corpus needs to be loaded.
-  * `AFL_CMPLOG_ONLY_NEW` - only perform cmplog on new found paths, not the
-    initial corpus as this very likely has been done for them already.
-  * Keep the generated corpus, use afl-cmin and reuse it every time!
-
-2. Additionally randomize the AFL++ compilation options, e.g.
-  * 40% for `AFL_LLVM_CMPLOG`
-  * 10% for `AFL_LLVM_LAF_ALL`
-
-3. Also randomize the afl-fuzz runtime options, e.g.
-  * 65% for `AFL_DISABLE_TRIM`
-  * 50% use a dictionary generated by `AFL_LLVM_DICT2FILE`
-  * 40% use MOpt (`-L 0`)
-  * 40% for `AFL_EXPAND_HAVOC_NOW`
-  * 20% for old queue processing (`-Z`)
-  * for CMPLOG targets, 60% for `-l 2`, 40% for `-l 3`
-
-4. Do *not* run any `-M` modes, just running `-S` modes is better for CI fuzzing.
-   `-M` enables old queue handling etc. which is good for a fuzzing campaign but
-   not good for short CI runs.
-
-How this can look like can e.g. be seen at AFL++'s setup in Google's [oss-fuzz](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_afl)
-and [clusterfuzz](https://github.com/google/clusterfuzz/blob/master/src/python/bot/fuzzers/afl/launcher.py).
-
-## Fuzzing binary-only targets
-
-When source code is *NOT* available, AFL++ offers various support for fast,
-on-the-fly instrumentation of black-box binaries. 
-
-If you do not have to use Unicorn the following setup is recommended to use
-qemu_mode:
-  * run 1 afl-fuzz -Q instance with CMPLOG (`-c 0` + `AFL_COMPCOV_LEVEL=2`)
-  * run 1 afl-fuzz -Q instance with QASAN  (`AFL_USE_QASAN=1`)
-  * run 1 afl-fuzz -Q instance with LAF (`AFL_PRELOAD=libcmpcov.so` + `AFL_COMPCOV_LEVEL=2`)
-Alternatively you can use frida_mode, just switch `-Q` with `-O` and remove the
-LAF instance.
-
-Then run as many instances as you have cores left with either -Q mode or - better -
-use a binary rewriter like afl-dyninst, retrowrite, zafl, etc.
-
-For Qemu and Frida mode, check out the persistent mode, it gives a huge speed
-improvement if it is possible to use.
-
-### QEMU
-
-For linux programs and its libraries this is accomplished with a version of
-QEMU running in the lesser-known "user space emulation" mode.
-QEMU is a project separate from AFL, but you can conveniently build the
-feature by doing:
-```shell
-cd qemu_mode
-./build_qemu_support.sh
-```
-For additional instructions and caveats, see [qemu_mode/README.md](qemu_mode/README.md).
-If possible you should use the persistent mode, see [qemu_mode/README.persistent.md](qemu_mode/README.persistent.md).
-The mode is approximately 2-5x slower than compile-time instrumentation, and is
-less conducive to parallelization.
-
-If [afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) works for
-your binary, then you can use afl-fuzz normally and it will have twice
-the speed compared to qemu_mode (but slower than qemu persistent mode).
-Note that several other binary rewriters exist, all with their advantages and
-caveats.
-
-### Frida
-
-Frida mode is sometimes faster and sometimes slower than Qemu mode.
-It is also newer, lacks COMPCOV, but supports MacOS.
-
-```shell
-cd frida_mode
-make
-```
-For additional instructions and caveats, see [frida_mode/README.md](frida_mode/README.md).
-If possible you should use the persistent mode, see [qemu_frida/README.persistent.md](qemu_frida/README.persistent.md).
-The mode is approximately 2-5x slower than compile-time instrumentation, and is
-less conducive to parallelization.
-
-### Unicorn
-
-For non-Linux binaries you can use AFL++'s unicorn mode which can emulate
-anything you want - for the price of speed and user written scripts.
-See [unicorn_mode](unicorn_mode/README.md).
-
-It can be easily built by:
-```shell
-cd unicorn_mode
-./build_unicorn_support.sh
-```
-
-### Shared libraries
 
-If the goal is to fuzz a dynamic library then there are two options available.
-For both you need to write a small harness that loads and calls the library.
-Faster is the frida solution: [utils/afl_frida/README.md](utils/afl_frida/README.md)
+This image is automatically generated when a push to the stable repo happens
+(see [branches](#branches)). You will find your target source code in `/src` in
+the container.
 
-Another, less precise and slower option is using ptrace with debugger interrupt
-instrumentation: [utils/afl_untracer/README.md](utils/afl_untracer/README.md).
+To build AFL++ yourself, continue at [docs/INSTALL.md](docs/INSTALL.md).
 
-### More
+## Quick start: Fuzzing with AFL++
 
-A more comprehensive description of these and other options can be found in
-[docs/binaryonly_fuzzing.md](docs/binaryonly_fuzzing.md).
+*NOTE: Before you start, please read about the
+[common sense risks of fuzzing](docs/fuzzing_in_depth.md#0-common-sense-risks).*
 
-## Challenges of guided fuzzing
+This is a quick start for fuzzing targets with the source code available. To
+read about the process in detail, see
+[docs/fuzzing_in_depth.md](docs/fuzzing_in_depth.md).
 
-Fuzzing is one of the most powerful and proven strategies for identifying
-security issues in real-world software; it is responsible for the vast
-majority of remote code execution and privilege escalation bugs found to date
-in security-critical software.
+To learn about fuzzing other targets, see:
+* Binary-only targets:
+  [docs/fuzzing_binary-only_targets.md](docs/fuzzing_binary-only_targets.md)
+* Network services:
+  [docs/best_practices.md#fuzzing-a-network-service](docs/best_practices.md#fuzzing-a-network-service)
+* GUI programs:
+  [docs/best_practices.md#fuzzing-a-gui-program](docs/best_practices.md#fuzzing-a-gui-program)
 
-Unfortunately, fuzzing is also relatively shallow; blind, random mutations
-make it very unlikely to reach certain code paths in the tested code, leaving
-some vulnerabilities firmly outside the reach of this technique.
+Step-by-step quick start:
 
-There have been numerous attempts to solve this problem. One of the early
-approaches - pioneered by Tavis Ormandy - is corpus distillation. The method
-relies on coverage signals to select a subset of interesting seeds from a
-massive, high-quality corpus of candidate files, and then fuzz them by
-traditional means. The approach works exceptionally well but requires such
-a corpus to be readily available. In addition, block coverage measurements
-provide only a very simplistic understanding of the program state and are less
-useful for guiding the fuzzing effort in the long haul.
+1. Compile the program or library to be fuzzed using `afl-cc`. A common way to
+   do this would be:
 
-Other, more sophisticated research has focused on techniques such as program
-flow analysis ("concolic execution"), symbolic execution, or static analysis.
-All these methods are extremely promising in experimental settings, but tend
-to suffer from reliability and performance problems in practical uses - and
-currently do not offer a viable alternative to "dumb" fuzzing techniques.
+   ```
+   CC=/path/to/afl-cc CXX=/path/to/afl-c++ ./configure --disable-shared
+   make clean all
+   ```
 
-## Background: The afl-fuzz approach
+2. Get a small but valid input file that makes sense to the program. When
+   fuzzing verbose syntax (SQL, HTTP, etc.), create a dictionary as described in
+   [dictionaries/README.md](dictionaries/README.md), too.
 
-American Fuzzy Lop is a brute-force fuzzer coupled with an exceedingly simple
-but rock-solid instrumentation-guided genetic algorithm. It uses a modified
-form of edge coverage to effortlessly pick up subtle, local-scale changes to
-program control flow.
+3. If the program reads from stdin, run `afl-fuzz` like so:
 
-Simplifying a bit, the overall algorithm can be summed up as:
+   ```
+   ./afl-fuzz -i seeds_dir -o output_dir -- \
+   /path/to/tested/program [...program's cmdline...]
+   ```
 
-  1) Load user-supplied initial test cases into the queue,
+   To add a dictionary, add `-x /path/to/dictionary.txt` to afl-fuzz.
 
-  2) Take the next input file from the queue,
+   If the program takes input from a file, you can put `@@` in the program's
+   command line; AFL++ will put an auto-generated file name in there for you.
 
-  3) Attempt to trim the test case to the smallest size that doesn't alter
-     the measured behavior of the program,
+4. Investigate anything shown in red in the fuzzer UI by promptly consulting
+   [docs/afl-fuzz_approach.md#understanding-the-status-screen](docs/afl-fuzz_approach.md#understanding-the-status-screen).
 
-  4) Repeatedly mutate the file using a balanced and well-researched variety
-     of traditional fuzzing strategies,
+5. You will find found crashes and hangs in the subdirectories `crashes/` and
+   `hangs/` in the `-o output_dir` directory. You can replay the crashes by
+   feeding them to the target, e.g.:
 
-  5) If any of the generated mutations resulted in a new state transition
-     recorded by the instrumentation, add mutated output as a new entry in the
-     queue.
+   ```
+   cat output_dir/crashes/id:000000,* | /path/to/tested/program [...program's cmdline...]
+   ```
 
-  6) Go to 2.
+   You can generate cores or use gdb directly to follow up the crashes.
 
-The discovered test cases are also periodically culled to eliminate ones that
-have been obsoleted by newer, higher-coverage finds; and undergo several other
-instrumentation-driven effort minimization steps.
-
-As a side result of the fuzzing process, the tool creates a small,
-self-contained corpus of interesting test cases. These are extremely useful
-for seeding other, labor- or resource-intensive testing regimes - for example,
-for stress-testing browsers, office applications, graphics suites, or
-closed-source tools.
-
-The fuzzer is thoroughly tested to deliver out-of-the-box performance far
-superior to blind fuzzing or coverage-only tools.
-
-## Help: Choosing initial test cases
-
-To operate correctly, the fuzzer requires one or more starting file that
-contains a good example of the input data normally expected by the targeted
-application. There are two basic rules:
-
-  - Keep the files small. Under 1 kB is ideal, although not strictly necessary.
-    For a discussion of why size matters, see [perf_tips.md](docs/perf_tips.md).
-
-  - Use multiple test cases only if they are functionally different from
-    each other. There is no point in using fifty different vacation photos
-    to fuzz an image library.
-
-You can find many good examples of starting files in the testcases/ subdirectory
-that comes with this tool.
-
-PS. If a large corpus of data is available for screening, you may want to use
-the afl-cmin utility to identify a subset of functionally distinct files that
-exercise different code paths in the target binary.
-
-## Help: Interpreting output
-
-See the [docs/status_screen.md](docs/status_screen.md) file for information on
-how to interpret the displayed stats and monitor the health of the process. Be
-sure to consult this file especially if any UI elements are highlighted in red.
-
-The fuzzing process will continue until you press Ctrl-C. At a minimum, you want
-to allow the fuzzer to complete one queue cycle, which may take anywhere from a
-couple of hours to a week or so.
-
-There are three subdirectories created within the output directory and updated
-in real-time:
-
-  - queue/   - test cases for every distinctive execution path, plus all the
-               starting files given by the user. This is the synthesized corpus
-               mentioned in section 2.
-
-               Before using this corpus for any other purposes, you can shrink
-               it to a smaller size using the afl-cmin tool. The tool will find
-               a smaller subset of files offering equivalent edge coverage.
-
-  - crashes/ - unique test cases that cause the tested program to receive a
-               fatal signal (e.g., SIGSEGV, SIGILL, SIGABRT). The entries are 
-               grouped by the received signal.
-
-  - hangs/   - unique test cases that cause the tested program to time out. The
-               default time limit before something is classified as a hang is
-               the larger of 1 second and the value of the -t parameter.
-               The value can be fine-tuned by setting AFL_HANG_TMOUT, but this
-               is rarely necessary.
-
-Crashes and hangs are considered "unique" if the associated execution paths
-involve any state transitions not seen in previously-recorded faults. If a
-single bug can be reached in multiple ways, there will be some count inflation
-early in the process, but this should quickly taper off.
-
-The file names for crashes and hangs are correlated with the parent, non-faulting
-queue entries. This should help with debugging.
-
-When you can't reproduce a crash found by afl-fuzz, the most likely cause is
-that you are not setting the same memory limit as used by the tool. Try:
-
-```shell
-LIMIT_MB=50
-( ulimit -Sv $[LIMIT_MB << 10]; /path/to/tested_binary ... )
-```
-
-Change LIMIT_MB to match the -m parameter passed to afl-fuzz. On OpenBSD,
-also change -Sv to -Sd.
-
-Any existing output directory can be also used to resume aborted jobs; try:
-
-```shell
-./afl-fuzz -i- -o existing_output_dir [...etc...]
-```
-
-If you have gnuplot installed, you can also generate some pretty graphs for any
-active fuzzing task using afl-plot. For an example of how this looks like,
-see [http://lcamtuf.coredump.cx/afl/plot/](http://lcamtuf.coredump.cx/afl/plot/).
-
-You can also manually build and install afl-plot-ui, which is a helper utility
-for showing the graphs generated by afl-plot in a graphical window using GTK.
-You can build and install it as follows
-
-```shell
-sudo apt install libgtk-3-0 libgtk-3-dev pkg-config
-cd utils/plot_ui
-make
-cd ../../
-sudo make install
-```
-
-## Help: Crash triage
-
-The coverage-based grouping of crashes usually produces a small data set that
-can be quickly triaged manually or with a very simple GDB or Valgrind script.
-Every crash is also traceable to its parent non-crashing test case in the
-queue, making it easier to diagnose faults.
-
-Having said that, it's important to acknowledge that some fuzzing crashes can be
-difficult to quickly evaluate for exploitability without a lot of debugging and
-code analysis work. To assist with this task, afl-fuzz supports a very unique
-"crash exploration" mode enabled with the -C flag.
-
-In this mode, the fuzzer takes one or more crashing test cases as the input
-and uses its feedback-driven fuzzing strategies to very quickly enumerate all
-code paths that can be reached in the program while keeping it in the
-crashing state.
-
-Mutations that do not result in a crash are rejected; so are any changes that
-do not affect the execution path.
-
-The output is a small corpus of files that can be very rapidly examined to see
-what degree of control the attacker has over the faulting address, or whether
-it is possible to get past an initial out-of-bounds read - and see what lies
-beneath.
-
-Oh, one more thing: for test case minimization, give afl-tmin a try. The tool
-can be operated in a very simple way:
-
-```shell
-./afl-tmin -i test_case -o minimized_result -- /path/to/program [...]
-```
-
-The tool works with crashing and non-crashing test cases alike. In the crash
-mode, it will happily accept instrumented and non-instrumented binaries. In the
-non-crashing mode, the minimizer relies on standard AFL++ instrumentation to make
-the file simpler without altering the execution path.
-
-The minimizer accepts the -m, -t, -f and @@ syntax in a manner compatible with
-afl-fuzz.
-
-Another tool in AFL++ is the afl-analyze tool. It takes an input
-file, attempts to sequentially flip bytes, and observes the behavior of the
-tested program. It then color-codes the input based on which sections appear to
-be critical, and which are not; while not bulletproof, it can often offer quick
-insights into complex file formats. More info about its operation can be found
-near the end of [docs/technical_details.md](docs/technical_details.md).
-
-## Going beyond crashes
-
-Fuzzing is a wonderful and underutilized technique for discovering non-crashing
-design and implementation errors, too. Quite a few interesting bugs have been
-found by modifying the target programs to call abort() when say:
-
-  - Two bignum libraries produce different outputs when given the same
-    fuzzer-generated input,
-
-  - An image library produces different outputs when asked to decode the same
-    input image several times in a row,
-
-  - A serialization / deserialization library fails to produce stable outputs
-    when iteratively serializing and deserializing fuzzer-supplied data,
-
-  - A compression library produces an output inconsistent with the input file
-    when asked to compress and then decompress a particular blob.
-
-Implementing these or similar sanity checks usually takes very little time;
-if you are the maintainer of a particular package, you can make this code
-conditional with `#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION` (a flag also
-shared with libfuzzer and honggfuzz) or `#ifdef __AFL_COMPILER` (this one is
-just for AFL).
-
-## Common-sense risks
-
-Please keep in mind that, similarly to many other computationally-intensive
-tasks, fuzzing may put a strain on your hardware and on the OS. In particular:
-
-  - Your CPU will run hot and will need adequate cooling. In most cases, if
-    cooling is insufficient or stops working properly, CPU speeds will be
-    automatically throttled. That said, especially when fuzzing on less
-    suitable hardware (laptops, smartphones, etc), it's not entirely impossible
-    for something to blow up.
-
-  - Targeted programs may end up erratically grabbing gigabytes of memory or
-    filling up disk space with junk files. AFL++ tries to enforce basic memory
-    limits, but can't prevent each and every possible mishap. The bottom line
-    is that you shouldn't be fuzzing on systems where the prospect of data loss
-    is not an acceptable risk.
-
-  - Fuzzing involves billions of reads and writes to the filesystem. On modern
-    systems, this will be usually heavily cached, resulting in fairly modest
-    "physical" I/O - but there are many factors that may alter this equation.
-    It is your responsibility to monitor for potential trouble; with very heavy
-    I/O, the lifespan of many HDDs and SSDs may be reduced.
-
-    A good way to monitor disk I/O on Linux is the 'iostat' command:
-
-```shell
-    $ iostat -d 3 -x -k [...optional disk ID...]
-```
-
-    Using the `AFL_TMPDIR` environment variable and a RAM-disk you can have the
-    heavy writing done in RAM to prevent the aforementioned wear and tear. For
-    example the following line will run a Docker container with all this preset:
-    
-    ```shell
-    # docker run -ti --mount type=tmpfs,destination=/ramdisk -e AFL_TMPDIR=/ramdisk aflplusplus/aflplusplus
-    ```
-
-## Known limitations & areas for improvement
+## Contact
 
-Here are some of the most important caveats for AFL:
+Questions? Concerns? Bug reports?
 
-  - AFL++ detects faults by checking for the first spawned process dying due to
-    a signal (SIGSEGV, SIGABRT, etc). Programs that install custom handlers for
-    these signals may need to have the relevant code commented out. In the same
-    vein, faults in child processes spawned by the fuzzed target may evade
-    detection unless you manually add some code to catch that.
+* The contributors can be reached via
+  [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus).
+* Take a look at our [FAQ](docs/FAQ.md). If you find an interesting or important
+  question missing, submit it via
+  [https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions).
+* There is a mailing list for the AFL/AFL++ project
+  ([browse archive](https://groups.google.com/group/afl-users)). To compare
+  notes with other users or to get notified about major new features, send an
+  email to <afl-users+subscribe@googlegroups.com>.
+* Or join the [Awesome Fuzzing](https://discord.gg/gCraWct) Discord server.
 
-  - As with any other brute-force tool, the fuzzer offers limited coverage if
-    encryption, checksums, cryptographic signatures, or compression are used to
-    wholly wrap the actual data format to be tested.
+## Branches
 
-    To work around this, you can comment out the relevant checks (see
-    utils/libpng_no_checksum/ for inspiration); if this is not possible,
-    you can also write a postprocessor, one of the hooks of custom mutators.
-    See [docs/custom_mutators.md](docs/custom_mutators.md) on how to use
-    `AFL_CUSTOM_MUTATOR_LIBRARY`
+The following branches exist:
 
-  - There are some unfortunate trade-offs with ASAN and 64-bit binaries. This
-    isn't due to any specific fault of afl-fuzz.
+* [release](https://github.com/AFLplusplus/AFLplusplus/tree/release): the latest
+  release
+* [stable/trunk](https://github.com/AFLplusplus/AFLplusplus/): stable state of
+  AFL++ - it is synced from dev from time to time when we are satisfied with its
+  stability
+* [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev): development state
+  of AFL++ - bleeding edge and you might catch a checkout which does not compile
+  or has a bug. *We only accept PRs in dev!!*
+* (any other): experimental branches to work on specific features or testing new
+  functionality or changes.
 
-  - There is no direct support for fuzzing network services, background
-    daemons, or interactive apps that require UI interaction to work. You may
-    need to make simple code changes to make them behave in a more traditional
-    way. Preeny may offer a relatively simple option, too - see:
-    [https://github.com/zardus/preeny](https://github.com/zardus/preeny)
+## Help wanted
 
-    Some useful tips for modifying network-based services can be also found at:
-    [https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop](https://www.fastly.com/blog/how-to-fuzz-server-american-fuzzy-lop)
+We have several [ideas](docs/ideas.md) we would like to see in AFL++ to make it
+even better. However, we already work on so many things that we do not have the
+time for all the big ideas.
 
-  - Occasionally, sentient machines rise against their creators. If this
-    happens to you, please consult [http://lcamtuf.coredump.cx/prep/](http://lcamtuf.coredump.cx/prep/).
+This can be your way to support and contribute to AFL++ - extend it to do
+something cool.
 
-Beyond this, see INSTALL for platform-specific tips.
+For everyone who wants to contribute (and send pull requests), please read our
+[contributing guidelines](CONTRIBUTING.md) before your submit.
 
 ## Special thanks
 
 Many of the improvements to the original AFL and AFL++ wouldn't be possible
-without feedback, bug reports, or patches from:
-
-```
-  Jann Horn                             Hanno Boeck
-  Felix Groebert                        Jakub Wilk
-  Richard W. M. Jones                   Alexander Cherepanov
-  Tom Ritter                            Hovik Manucharyan
-  Sebastian Roschke                     Eberhard Mattes
-  Padraig Brady                         Ben Laurie
-  @dronesec                             Luca Barbato
-  Tobias Ospelt                         Thomas Jarosch
-  Martin Carpenter                      Mudge Zatko
-  Joe Zbiciak                           Ryan Govostes
-  Michael Rash                          William Robinet
-  Jonathan Gray                         Filipe Cabecinhas
-  Nico Weber                            Jodie Cunningham
-  Andrew Griffiths                      Parker Thompson
-  Jonathan Neuschaefer                  Tyler Nighswander
-  Ben Nagy                              Samir Aguiar
-  Aidan Thornton                        Aleksandar Nikolich
-  Sam Hakim                             Laszlo Szekeres
-  David A. Wheeler                      Turo Lamminen
-  Andreas Stieger                       Richard Godbee
-  Louis Dassy                           teor2345
-  Alex Moneger                          Dmitry Vyukov
-  Keegan McAllister                     Kostya Serebryany
-  Richo Healey                          Martijn Bogaard
-  rc0r                                  Jonathan Foote
-  Christian Holler                      Dominique Pelle
-  Jacek Wielemborek                     Leo Barnes
-  Jeremy Barnes                         Jeff Trull
-  Guillaume Endignoux                   ilovezfs
-  Daniel Godas-Lopez                    Franjo Ivancic
-  Austin Seipp                          Daniel Komaromy
-  Daniel Binderman                      Jonathan Metzman
-  Vegard Nossum                         Jan Kneschke
-  Kurt Roeckx                           Marcel Boehme
-  Van-Thuan Pham                        Abhik Roychoudhury
-  Joshua J. Drake                       Toby Hutton
-  Rene Freingruber                      Sergey Davidoff
-  Sami Liedes                           Craig Young
-  Andrzej Jackowski                     Daniel Hodson
-  Nathan Voss                           Dominik Maier
-  Andrea Biondo                         Vincent Le Garrec
-  Khaled Yakdan                         Kuang-che Wu
-  Josephine Calliotte                   Konrad Welc
-  Thomas Rooijakkers                    David Carlier
-  Ruben ten Hove                        Joey Jiao
-  fuzzah
-```
-
-Thank you!
-(For people sending pull requests - please add yourself to this list :-)
+without feedback, bug reports, or patches from our contributors.
+
+Thank you! (For people sending pull requests - please add yourself to this list
+:-)
+
+<details>
+
+  <summary>List of contributors</summary>
+
+  ```
+    Jann Horn                             Hanno Boeck
+    Felix Groebert                        Jakub Wilk
+    Richard W. M. Jones                   Alexander Cherepanov
+    Tom Ritter                            Hovik Manucharyan
+    Sebastian Roschke                     Eberhard Mattes
+    Padraig Brady                         Ben Laurie
+    @dronesec                             Luca Barbato
+    Tobias Ospelt                         Thomas Jarosch
+    Martin Carpenter                      Mudge Zatko
+    Joe Zbiciak                           Ryan Govostes
+    Michael Rash                          William Robinet
+    Jonathan Gray                         Filipe Cabecinhas
+    Nico Weber                            Jodie Cunningham
+    Andrew Griffiths                      Parker Thompson
+    Jonathan Neuschaefer                  Tyler Nighswander
+    Ben Nagy                              Samir Aguiar
+    Aidan Thornton                        Aleksandar Nikolich
+    Sam Hakim                             Laszlo Szekeres
+    David A. Wheeler                      Turo Lamminen
+    Andreas Stieger                       Richard Godbee
+    Louis Dassy                           teor2345
+    Alex Moneger                          Dmitry Vyukov
+    Keegan McAllister                     Kostya Serebryany
+    Richo Healey                          Martijn Bogaard
+    rc0r                                  Jonathan Foote
+    Christian Holler                      Dominique Pelle
+    Jacek Wielemborek                     Leo Barnes
+    Jeremy Barnes                         Jeff Trull
+    Guillaume Endignoux                   ilovezfs
+    Daniel Godas-Lopez                    Franjo Ivancic
+    Austin Seipp                          Daniel Komaromy
+    Daniel Binderman                      Jonathan Metzman
+    Vegard Nossum                         Jan Kneschke
+    Kurt Roeckx                           Marcel Boehme
+    Van-Thuan Pham                        Abhik Roychoudhury
+    Joshua J. Drake                       Toby Hutton
+    Rene Freingruber                      Sergey Davidoff
+    Sami Liedes                           Craig Young
+    Andrzej Jackowski                     Daniel Hodson
+    Nathan Voss                           Dominik Maier
+    Andrea Biondo                         Vincent Le Garrec
+    Khaled Yakdan                         Kuang-che Wu
+    Josephine Calliotte                   Konrad Welc
+    Thomas Rooijakkers                    David Carlier
+    Ruben ten Hove                        Joey Jiao
+    fuzzah
+  ```
+
+</details>
 
 ## Cite
 
-If you use AFLpluplus to compare to your work, please use either `afl-clang-lto`
-or `afl-clang-fast` with `AFL_LLVM_CMPLOG=1` for building targets and
-`afl-fuzz` with the command line option `-l 2` for fuzzing.
-The most effective setup is the `aflplusplus` default configuration on Google's [fuzzbench](https://github.com/google/fuzzbench/tree/master/fuzzers/aflplusplus).
+If you use AFL++ in scientific work, consider citing
+[our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi)
+presented at WOOT'20:
 
-If you use AFLplusplus in scientific work, consider citing [our paper](https://www.usenix.org/conference/woot20/presentation/fioraldi) presented at WOOT'20:
+    Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. “AFL++: Combining incremental steps of fuzzing research”. In 14th USENIX Workshop on Offensive Technologies (WOOT 20). USENIX Association, Aug. 2020.
 
-+ Andrea Fioraldi, Dominik Maier, Heiko Eißfeldt, and Marc Heuse. “AFL++: Combining incremental steps of fuzzing research”. In 14th USENIX Workshop on Offensive Technologies (WOOT 20). USENIX Association, Aug. 2020.
+<details>
 
-Bibtex:
-
-```bibtex
-@inproceedings {AFLplusplus-Woot20,
-	author = {Andrea Fioraldi and Dominik Maier and Heiko Ei{\ss}feldt and Marc Heuse},
-	title = {{AFL++}: Combining Incremental Steps of Fuzzing Research},
-	booktitle = {14th {USENIX} Workshop on Offensive Technologies ({WOOT} 20)},
-	year = {2020},
-	publisher = {{USENIX} Association},
-	month = aug,
-}
-```
-
-## Contact
-
-Questions? Concerns? Bug reports? The contributors can be reached via
-[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
+<summary>BibTeX</summary>
 
-There is also a mailing list for the AFL/AFL++ project; to join, send a mail to
-<afl-users+subscribe@googlegroups.com>. Or, if you prefer to browse archives
-first, try: [https://groups.google.com/group/afl-users](https://groups.google.com/group/afl-users)
+  ```bibtex
+  @inproceedings {AFLplusplus-Woot20,
+  author = {Andrea Fioraldi and Dominik Maier and Heiko Ei{\ss}feldt and Marc Heuse},
+  title = {{AFL++}: Combining Incremental Steps of Fuzzing Research},
+  booktitle = {14th {USENIX} Workshop on Offensive Technologies ({WOOT} 20)},
+  year = {2020},
+  publisher = {{USENIX} Association},
+  month = aug,
+  }
+  ```
 
+</details>
\ No newline at end of file