aboutsummaryrefslogtreecommitdiff
path: root/experimental
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2019-05-28 16:40:24 +0200
committervan Hauser <vh@thc.org>2019-05-28 16:40:24 +0200
commitf367728c4435670caf2e9cc5acad257e7766cc65 (patch)
tree5a4f587630b161f32a548f5c196032e2566741e2 /experimental
parent1b3d018d35d9091bda28e38e066a99491f2415b5 (diff)
downloadafl++-f367728c4435670caf2e9cc5acad257e7766cc65.tar.gz
afl++ 2.52c initial commit
Diffstat (limited to 'experimental')
-rw-r--r--experimental/README.experiments38
-rw-r--r--experimental/argv_fuzzing/argv-fuzz-inl.h80
-rwxr-xr-xexperimental/asan_cgroups/limit_memory.sh157
-rw-r--r--experimental/bash_shellshock/shellshock-fuzz.diff59
-rw-r--r--experimental/canvas_harness/canvas_harness.html170
-rwxr-xr-xexperimental/clang_asm_normalize/as75
-rwxr-xr-xexperimental/crash_triage/triage_crashes.sh115
-rwxr-xr-xexperimental/distributed_fuzzing/sync_script.sh93
-rw-r--r--experimental/libpng_no_checksum/libpng-nocrc.patch15
-rw-r--r--experimental/persistent_demo/persistent_demo.c89
-rw-r--r--experimental/post_library/post_library.so.c119
-rw-r--r--experimental/post_library/post_library_png.so.c113
12 files changed, 1123 insertions, 0 deletions
diff --git a/experimental/README.experiments b/experimental/README.experiments
new file mode 100644
index 00000000..af9739bd
--- /dev/null
+++ b/experimental/README.experiments
@@ -0,0 +1,38 @@
+Here's a quick overview of the stuff you can find in this directory:
+
+ - argv_fuzzing - a simple wrapper to allow cmdline to be fuzzed
+ (e.g., to test setuid programs).
+
+ - asan_cgroups - a contributed script to simplify fuzzing ASAN
+ binaries with robust memory limits on Linux.
+
+ - bash_shellshock - a simple hack used to find a bunch of
+ post-Shellshock bugs in bash.
+
+ - canvas_harness - a test harness used to find browser bugs with a
+ corpus generated using simple image parsing
+ binaries & afl-fuzz.
+
+ - clang_asm_normalize - a script that makes it easy to instrument
+ hand-written assembly, provided that you have clang.
+
+ - crash_triage - a very rudimentary example of how to annotate crashes
+ with additional gdb metadata.
+
+ - distributed_fuzzing - a sample script for synchronizing fuzzer instances
+ across multiple machines (see parallel_fuzzing.txt).
+
+ - libpng_no_checksum - a sample patch for removing CRC checks in libpng.
+
+ - persistent_demo - an example of how to use the LLVM persistent process
+ mode to speed up certain fuzzing jobs.
+
+ - post_library - an example of how to build postprocessors for AFL.
+
+Note that the minimize_corpus.sh tool has graduated from the experimental/
+directory and is now available as ../afl-cmin. The LLVM mode has likewise
+graduated to ../llvm_mode/*.
+
+Most of the tools in this directory are meant chiefly as examples that need to
+be tweaked for your specific needs. They come with some basic documentation,
+but are not necessarily production-grade.
diff --git a/experimental/argv_fuzzing/argv-fuzz-inl.h b/experimental/argv_fuzzing/argv-fuzz-inl.h
new file mode 100644
index 00000000..b042d38c
--- /dev/null
+++ b/experimental/argv_fuzzing/argv-fuzz-inl.h
@@ -0,0 +1,80 @@
+/*
+ american fuzzy lop - sample argv fuzzing wrapper
+ ------------------------------------------------
+
+ Written by Michal Zalewski <lcamtuf@google.com>
+
+ Copyright 2015 Google Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ This file shows a simple way to fuzz command-line parameters with stock
+ afl-fuzz. To use, add:
+
+ #include "/path/to/argv-fuzz-inl.h"
+
+ ...to the file containing main(), ideally placing it after all the
+ standard includes. Next, put AFL_INIT_ARGV(); near the very beginning of
+ main().
+
+ This will cause the program to read NUL-delimited input from stdin and
+ put it in argv[]. Two subsequent NULs terminate the array. Empty
+ params are encoded as a lone 0x02. Lone 0x02 can't be generated, but
+ that shouldn't matter in real life.
+
+ If you would like to always preserve argv[0], use this instead:
+ AFL_INIT_SET0("prog_name");
+
+*/
+
+#ifndef _HAVE_ARGV_FUZZ_INL
+#define _HAVE_ARGV_FUZZ_INL
+
+#include <unistd.h>
+
+#define AFL_INIT_ARGV() do { argv = afl_init_argv(&argc); } while (0)
+
+#define AFL_INIT_SET0(_p) do { \
+ argv = afl_init_argv(&argc); \
+ argv[0] = (_p); \
+ if (!argc) argc = 1; \
+ } while (0)
+
+#define MAX_CMDLINE_LEN 100000
+#define MAX_CMDLINE_PAR 1000
+
+static char** afl_init_argv(int* argc) {
+
+ static char in_buf[MAX_CMDLINE_LEN];
+ static char* ret[MAX_CMDLINE_PAR];
+
+ char* ptr = in_buf;
+ int rc = 0;
+
+ if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0);
+
+ while (*ptr) {
+
+ ret[rc] = ptr;
+ if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++;
+ rc++;
+
+ while (*ptr) ptr++;
+ ptr++;
+
+ }
+
+ *argc = rc;
+
+ return ret;
+
+}
+
+#undef MAX_CMDLINE_LEN
+#undef MAX_CMDLINE_PAR
+
+#endif /* !_HAVE_ARGV_FUZZ_INL */
diff --git a/experimental/asan_cgroups/limit_memory.sh b/experimental/asan_cgroups/limit_memory.sh
new file mode 100755
index 00000000..b0c77d15
--- /dev/null
+++ b/experimental/asan_cgroups/limit_memory.sh
@@ -0,0 +1,157 @@
+#!/usr/bin/env bash
+#
+# american fuzzy lop - limit memory using cgroups
+# -----------------------------------------------
+#
+# Written by Samir Khakimov <samir.hakim@nyu.edu> and
+# David A. Wheeler <dwheeler@ida.org>
+#
+# Edits to bring the script in line with afl-cmin and other companion scripts
+# by Michal Zalewski <lcamtuf@google.com>. All bugs are my fault.
+#
+# Copyright 2015 Institute for Defense Analyses.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# This tool allows the amount of actual memory allocated to a program
+# to be limited on Linux systems using cgroups, instead of the traditional
+# setrlimit() API. This helps avoid the address space problems discussed in
+# docs/notes_for_asan.txt.
+#
+# Important: the limit covers *both* afl-fuzz and the fuzzed binary. In some
+# hopefully rare circumstances, afl-fuzz could be killed before the fuzzed
+# task.
+#
+
+echo "cgroup tool for afl-fuzz by <samir.hakim@nyu.edu> and <dwheeler@ida.org>"
+echo
+
+unset NEW_USER
+MEM_LIMIT="50"
+
+while getopts "+u:m:" opt; do
+
+ case "$opt" in
+
+ "u")
+ NEW_USER="$OPTARG"
+ ;;
+
+ "m")
+ MEM_LIMIT="$[OPTARG]"
+ ;;
+
+ "?")
+ exit 1
+ ;;
+
+ esac
+
+done
+
+if [ "$MEM_LIMIT" -lt "5" ]; then
+ echo "[-] Error: malformed or dangerously low value of -m." 1>&2
+ exit 1
+fi
+
+shift $((OPTIND-1))
+
+TARGET_BIN="$1"
+
+if [ "$TARGET_BIN" = "" -o "$NEW_USER" = "" ]; then
+
+ cat 1>&2 <<_EOF_
+Usage: $0 [ options ] -- /path/to/afl-fuzz [ ...afl options... ]
+
+Required parameters:
+
+ -u user - run the fuzzer as a specific user after setting up limits
+
+Optional parameters:
+
+ -m megs - set memory limit to a specified value ($MEM_LIMIT MB)
+
+This tool configures cgroups-based memory limits for a fuzzing job to simplify
+the task of fuzzing ASAN or MSAN binaries. You would normally want to use it in
+conjunction with '-m none' passed to the afl-fuzz binary itself, say:
+
+ $0 -u joe ./afl-fuzz -i input -o output -m none /path/to/target
+
+_EOF_
+
+ exit 1
+
+fi
+
+# Basic sanity checks
+
+if [ ! "`uname -s`" = "Linux" ]; then
+ echo "[-] Error: this tool does not support non-Linux systems." 1>&2
+ exit 1
+fi
+
+if [ ! "`id -u`" = "0" ]; then
+ echo "[-] Error: you need to run this script as root (sorry!)." 1>&2
+ exit 1
+fi
+
+if ! type cgcreate 2>/dev/null 1>&2; then
+
+ echo "[-] Error: you need to install cgroup tools first." 1>&2
+
+ if type apt-get 2>/dev/null 1>&2; then
+ echo " (Perhaps 'apt-get install cgroup-bin' will work.)" 1>&2
+ elif type yum 2>/dev/null 1>&2; then
+ echo " (Perhaps 'yum install libcgroup-tools' will work.)" 1>&2
+ fi
+
+ exit 1
+
+fi
+
+if ! id -u "$NEW_USER" 2>/dev/null 1>&2; then
+ echo "[-] Error: user '$NEW_USER' does not seem to exist." 1>&2
+ exit 1
+fi
+
+# Create a new cgroup path if necessary... We used PID-keyed groups to keep
+# parallel afl-fuzz tasks separate from each other.
+
+CID="afl-$NEW_USER-$$"
+
+CPATH="/sys/fs/cgroup/memory/$CID"
+
+if [ ! -d "$CPATH" ]; then
+
+ cgcreate -a "$NEW_USER" -g memory:"$CID" || exit 1
+
+fi
+
+# Set the appropriate limit...
+
+if [ -f "$CPATH/memory.memsw.limit_in_bytes" ]; then
+
+ echo "${MEM_LIMIT}M" > "$CPATH/memory.limit_in_bytes" 2>/dev/null
+ echo "${MEM_LIMIT}M" > "$CPATH/memory.memsw.limit_in_bytes" || exit 1
+ echo "${MEM_LIMIT}M" > "$CPATH/memory.limit_in_bytes" || exit 1
+
+elif grep -qE 'partition|file' /proc/swaps; then
+
+ echo "[-] Error: your system requires swap to be disabled first (swapoff -a)." 1>&2
+ exit 1
+
+else
+
+ echo "${MEM_LIMIT}M" > "$CPATH/memory.limit_in_bytes" || exit 1
+
+fi
+
+# All right. At this point, we can just run the command.
+
+cgexec -g "memory:$CID" su -c "$*" "$NEW_USER"
+
+cgdelete -g "memory:$CID"
diff --git a/experimental/bash_shellshock/shellshock-fuzz.diff b/experimental/bash_shellshock/shellshock-fuzz.diff
new file mode 100644
index 00000000..3fa05bf8
--- /dev/null
+++ b/experimental/bash_shellshock/shellshock-fuzz.diff
@@ -0,0 +1,59 @@
+This patch shows a very simple way to find post-Shellshock bugs in bash, as
+discussed here:
+
+ http://lcamtuf.blogspot.com/2014/10/bash-bug-how-we-finally-cracked.html
+
+In essence, it shows a way to fuzz environmental variables. Instructions:
+
+1) Download bash 4.3, apply this patch, compile with:
+
+ CC=/path/to/afl-gcc ./configure
+ make clean all
+
+ Note that the harness puts the fuzzed output in $TEST_VARIABLE. With
+ Florian's Shellshock patch (bash43-028), this is no longer passed down
+ to the parser.
+
+2) Create and cd to an empty directory, put the compiled bash binary in
+ there, and run these commands:
+
+ mkdir in_dir
+ echo -n '() { a() { a; }; : >b; }' >in_dir/script.txt
+
+3) Run the fuzzer with:
+
+ /path/to/afl-fuzz -d -i in_dir -o out_dir ./bash -c :
+
+ The -d parameter is advisable only if the tested shell is fairly slow
+ or if you are in a hurry; will cover more ground faster, but
+ less systematically.
+
+4) Watch for crashes in out_dir/crashes/. Also watch for any new files
+ created in cwd if you're interested in non-crash RCEs (files will be
+ created whenever the shell executes "foo>bar" or something like
+ that). You can correlate their creation date with new entries in
+ out_dir/queue/.
+
+ You can also modify the bash binary to directly check for more subtle
+ fault conditions, or use the synthesized entries in out_dir/queue/
+ as a seed for other, possibly slower or more involved testing regimes.
+
+ Expect several hours to get decent coverage.
+
+--- bash-4.3/shell.c.orig 2014-01-14 14:04:32.000000000 +0100
++++ bash-4.3/shell.c 2015-04-30 05:56:46.000000000 +0200
+@@ -371,6 +371,14 @@
+ env = environ;
+ #endif /* __OPENNT */
+
++ {
++
++ static char val[1024 * 16];
++ read(0, val, sizeof(val) - 1);
++ setenv("TEST_VARIABLE", val, 1);
++
++ }
++
+ USE_VAR(argc);
+ USE_VAR(argv);
+ USE_VAR(env);
diff --git a/experimental/canvas_harness/canvas_harness.html b/experimental/canvas_harness/canvas_harness.html
new file mode 100644
index 00000000..19293667
--- /dev/null
+++ b/experimental/canvas_harness/canvas_harness.html
@@ -0,0 +1,170 @@
+<html>
+<!--
+
+ american fuzzy lop - <canvas> harness
+ -------------------------------------
+
+ Written and maintained by Michal Zalewski <lcamtuf@google.com>
+
+ Copyright 2013, 2014 Google Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ A simple harness for going through afl-generated test cases, rendering them in
+ the browser environment, and discovering the use of uninitialized memory and
+ similar bugs. This code led to the discovery of a fair number of library and
+ browser security bugs!
+
+ The url_list[] array is a placeholder; for this to work properly, it needs to
+ be initialized with web-reachable paths to individual test cases. This can
+ be done manually or with a simple script.
+
+-->
+
+<body onload="set_images()">
+
+<div id="status"></div>
+
+<div id="image_div"></div>
+
+<canvas height=64 width=64 id=cvs></canvas>
+
+<h2>Results</h2>
+
+<ul id="output"></ul>
+
+<script>
+
+var c = document.getElementById('cvs');
+var ctx = c.getContext('2d');
+
+var url_list = [
+ "images/id:000000,[...].jpg",
+ "images/id:000001,[...].jpg",
+ /* ... */
+ null
+];
+
+var USE_IMAGES = 50;
+var cur_image = 0;
+
+if (location.hash) cur_image = parseInt(location.hash.substr(1));
+
+var loaded = 0;
+var image_obj = [];
+
+var msie_cleanup;
+
+function check_results() {
+
+ var uniques = [];
+
+ clearTimeout(msie_cleanup);
+
+ ctx.clearRect(0, 0, 64, 64);
+
+ uniques.push(image_obj[0].imgdata);
+
+ for (var i = 1; i < USE_IMAGES; i++) {
+
+ if (!image_obj[i].imgdata) continue;
+
+ if (image_obj[0].imgdata != image_obj[i].imgdata) {
+
+ for (var j = 1; j < uniques.length; j++)
+ if (uniques[j] == image_obj[i].imgdata) break;
+
+ if (j == uniques.length) uniques.push(image_obj[i].imgdata);
+
+
+ }
+
+ }
+
+ if (uniques.length > 1) {
+
+ var str = '<li> Image ' + url_list[cur_image] + ' has ' + uniques.length + ' variants: ';
+
+ for (var i = 0; i < uniques.length; i++)
+ str += '<img src="' + uniques[i] + '">';
+
+ document.getElementById('output').innerHTML += str;
+
+ }
+
+ cur_image++;
+ set_images();
+}
+
+
+function count_image() {
+
+ if (!this.complete || this.counted) return;
+
+ this.counted = true;
+
+ loaded++;
+
+ ctx.clearRect(0, 0, 64, 64);
+
+ try {
+ ctx.drawImage(this, 0, 0, 64, 64);
+ } catch (e) { }
+
+ this.imgdata = c.toDataURL();
+
+ if (loaded == USE_IMAGES) check_results();
+}
+
+
+function set_images() {
+
+ loaded = 0;
+
+ document.getElementById('status').innerHTML = 'Now processing ' + cur_image + '...';
+ location.hash = '#' + cur_image;
+
+ if (url_list[cur_image] == null) {
+ alert('Done!');
+ return;
+ }
+
+ restart_images();
+
+ msie_cleanup = setTimeout(check_results, 5000);
+
+ for (var i = 0; i < USE_IMAGES; i++)
+ image_obj[i].src = url_list[cur_image] + '?' + Math.random();
+
+}
+
+
+function restart_images() {
+
+ for (var i = 0; i < USE_IMAGES; i++)
+ if (image_obj[i]) image_obj[i].counted = true;
+
+ document.getElementById('image_div').innerHTML = '';
+ image_obj = [];
+
+ for (var i = 0; i < USE_IMAGES; i++) {
+
+ image_obj[i] = new Image();
+ image_obj[i].height = 64;
+ image_obj[i].width = 64;
+ image_obj[i].onerror = count_image;
+ image_obj[i].onload = count_image;
+
+ document.getElementById('image_div').appendChild(image_obj[i]);
+
+ }
+
+}
+
+</script>
+
+<iframe src='http://www.cnn.com/'></iframe>
diff --git a/experimental/clang_asm_normalize/as b/experimental/clang_asm_normalize/as
new file mode 100755
index 00000000..4ee07e69
--- /dev/null
+++ b/experimental/clang_asm_normalize/as
@@ -0,0 +1,75 @@
+#!/bin/sh
+#
+# american fuzzy lop - clang assembly normalizer
+# ----------------------------------------------
+#
+# Written and maintained by Michal Zalewski <lcamtuf@google.com>
+# The idea for this wrapper comes from Ryan Govostes.
+#
+# Copyright 2013, 2014 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# This 'as' wrapper should allow you to instrument unruly, hand-written
+# assembly with afl-as.
+#
+# Usage:
+#
+# export AFL_REAL_PATH=/path/to/directory/with/afl-as/
+# AFL_PATH=/path/to/this/directory/ make clean all
+
+if [ "$#" -lt "2" ]; then
+ echo "[-] Error: this utility can't be called directly." 1>&2
+ exit 1
+fi
+
+if [ "$AFL_REAL_PATH" = "" ]; then
+ echo "[-] Error: AFL_REAL_PATH not set!" 1>&2
+ exit 1
+fi
+
+if [ ! -x "$AFL_REAL_PATH/afl-as" ]; then
+ echo "[-] Error: AFL_REAL_PATH does not contain the 'afl-as' binary." 1>&2
+ exit 1
+fi
+
+unset __AFL_AS_CMDLINE __AFL_FNAME
+
+while [ ! "$#" = "0" ]; do
+
+ if [ "$#" = "1" ]; then
+ __AFL_FNAME="$1"
+ else
+ __AFL_AS_CMDLINE="${__AFL_AS_CMDLINE} $1"
+ fi
+
+ shift
+
+done
+
+test "$TMPDIR" = "" && TMPDIR=/tmp
+
+TMPFILE=`mktemp $TMPDIR/.afl-XXXXXXXXXX.s`
+
+test "$TMPFILE" = "" && exit 1
+
+clang -cc1as -filetype asm -output-asm-variant 0 "${__AFL_FNAME}" >"$TMPFILE"
+
+ERR="$?"
+
+if [ ! "$ERR" = "0" ]; then
+ rm -f "$TMPFILE"
+ exit $ERR
+fi
+
+"$AFL_REAL_PATH/afl-as" ${__AFL_AS_CMDLINE} "$TMPFILE"
+
+ERR="$?"
+
+rm -f "$TMPFILE"
+
+exit "$ERR"
diff --git a/experimental/crash_triage/triage_crashes.sh b/experimental/crash_triage/triage_crashes.sh
new file mode 100755
index 00000000..5894a4d6
--- /dev/null
+++ b/experimental/crash_triage/triage_crashes.sh
@@ -0,0 +1,115 @@
+#!/bin/sh
+#
+# american fuzzy lop - crash triage utility
+# -----------------------------------------
+#
+# Written and maintained by Michal Zalewski <lcamtuf@google.com>
+#
+# Copyright 2013, 2014, 2017 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Note that this assumes that the targeted application reads from stdin
+# and requires no other cmdline parameters. Modify as needed if this is
+# not the case.
+#
+# Note that on OpenBSD, you may need to install a newer version of gdb
+# (e.g., from ports). You can set GDB=/some/path to point to it if
+# necessary.
+#
+
+echo "crash triage utility for afl-fuzz by <lcamtuf@google.com>"
+echo
+
+ulimit -v 100000 2>/dev/null
+ulimit -d 100000 2>/dev/null
+
+if [ "$#" -lt "2" ]; then
+ echo "Usage: $0 /path/to/afl_output_dir /path/to/tested_binary [...target params...]" 1>&2
+ echo 1>&2
+ exit 1
+fi
+
+DIR="$1"
+BIN="$2"
+shift
+shift
+
+if [ "$AFL_ALLOW_TMP" = "" ]; then
+
+ echo "$DIR" | grep -qE '^(/var)?/tmp/'
+ T1="$?"
+
+ echo "$BIN" | grep -qE '^(/var)?/tmp/'
+ T2="$?"
+
+ if [ "$T1" = "0" -o "$T2" = "0" ]; then
+ echo "[-] Error: do not use shared /tmp or /var/tmp directories with this script." 1>&2
+ exit 1
+ fi
+
+fi
+
+if
+ [ "$GDB" = "" ]; then
+ GDB=gdb
+fi
+
+if [ ! -f "$BIN" -o ! -x "$BIN" ]; then
+ echo "[-] Error: binary '$2' not found or is not executable." 1>&2
+ exit 1
+fi
+
+if [ ! -d "$DIR/queue" ]; then
+ echo "[-] Error: directory '$1' not found or not created by afl-fuzz." 1>&2
+ exit 1
+fi
+
+CCOUNT=$((`ls -- "$DIR/crashes" 2>/dev/null | wc -l`))
+
+if [ "$CCOUNT" = "0" ]; then
+ echo "No crashes recorded in the target directory - nothing to be done."
+ exit 0
+fi
+
+echo
+
+for crash in $DIR/crashes/id:*; do
+
+ id=`basename -- "$crash" | cut -d, -f1 | cut -d: -f2`
+ sig=`basename -- "$crash" | cut -d, -f2 | cut -d: -f2`
+
+ # Grab the args, converting @@ to $crash
+
+ use_args=""
+ use_stdio=1
+
+ for a in $@; do
+
+ if [ "$a" = "@@" ] ; then
+ args="$use_args $crash"
+ unset use_stdio
+ else
+ args="$use_args $a"
+ fi
+
+ done
+
+ # Strip the trailing space
+ use_args="${use_args# }"
+
+ echo "+++ ID $id, SIGNAL $sig +++"
+ echo
+
+ if [ "$use_stdio" = "1" ]; then
+ $GDB --batch -q --ex "r $use_args <$crash" --ex 'back' --ex 'disass $pc, $pc+16' --ex 'info reg' --ex 'quit' "$BIN" 0</dev/null
+ else
+ $GDB --batch -q --ex "r $use_args" --ex 'back' --ex 'disass $pc, $pc+16' --ex 'info reg' --ex 'quit' "$BIN" 0</dev/null
+ fi
+ echo
+
+done
diff --git a/experimental/distributed_fuzzing/sync_script.sh b/experimental/distributed_fuzzing/sync_script.sh
new file mode 100755
index 00000000..2d5e0635
--- /dev/null
+++ b/experimental/distributed_fuzzing/sync_script.sh
@@ -0,0 +1,93 @@
+#!/bin/sh
+#
+# american fuzzy lop - fuzzer synchronization tool
+# ------------------------------------------------
+#
+# Written and maintained by Michal Zalewski <lcamtuf@google.com>
+#
+# Copyright 2014 Google Inc. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at:
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# To make this script work:
+#
+# - Edit FUZZ_HOSTS, FUZZ_DOMAIN, FUZZ_USER, and SYNC_DIR to reflect your
+# environment.
+#
+# - Make sure that the system you are running this on can log into FUZZ_HOSTS
+# without a password (authorized_keys or otherwise).
+#
+# - Make sure that every fuzzer is running with -o pointing to SYNC_DIR and -S
+# that consists of its local host name, followed by an underscore, and then
+# by some host-local fuzzer ID.
+#
+
+# Hosts to synchronize the data across.
+FUZZ_HOSTS='host1 host2 host3 host4'
+
+# Domain for all hosts
+FUZZ_DOMAIN='example.com'
+
+# Remote user for SSH
+FUZZ_USER=bob
+
+# Directory to synchronize
+SYNC_DIR='/home/bob/sync_dir'
+
+# Interval (seconds) between sync attempts
+SYNC_INTERVAL=$((30 * 60))
+
+if [ "$AFL_ALLOW_TMP" = "" ]; then
+
+ if [ "$PWD" = "/tmp" -o "$PWD" = "/var/tmp" ]; then
+ echo "[-] Error: do not use shared /tmp or /var/tmp directories with this script." 1>&2
+ exit 1
+ fi
+
+fi
+
+rm -rf .sync_tmp 2>/dev/null
+mkdir .sync_tmp || exit 1
+
+while :; do
+
+ # Pull data in...
+
+ for host in $FUZZ_HOSTS; do
+
+ echo "[*] Retrieving data from ${host}.${FUZZ_DOMAIN}..."
+
+ ssh -o 'passwordauthentication no' ${FUZZ_USER}@${host}.$FUZZ_DOMAIN \
+ "cd '$SYNC_DIR' && tar -czf - ${host}_*/[qf]*" >".sync_tmp/${host}.tgz"
+
+ done
+
+ # Distribute data. For large fleets, see tips in the docs/ directory.
+
+ for dst_host in $FUZZ_HOSTS; do
+
+ echo "[*] Distributing data to ${dst_host}.${FUZZ_DOMAIN}..."
+
+ for src_host in $FUZZ_HOSTS; do
+
+ test "$src_host" = "$dst_host" && continue
+
+ echo " Sending fuzzer data from ${src_host}.${FUZZ_DOMAIN}..."
+
+ ssh -o 'passwordauthentication no' ${FUZZ_USER}@$dst_host \
+ "cd '$SYNC_DIR' && tar -xkzf -" <".sync_tmp/${src_host}.tgz"
+
+ done
+
+ done
+
+ echo "[+] Done. Sleeping for $SYNC_INTERVAL seconds (Ctrl-C to quit)."
+
+ sleep $SYNC_INTERVAL
+
+done
+
diff --git a/experimental/libpng_no_checksum/libpng-nocrc.patch b/experimental/libpng_no_checksum/libpng-nocrc.patch
new file mode 100644
index 00000000..0a3793a0
--- /dev/null
+++ b/experimental/libpng_no_checksum/libpng-nocrc.patch
@@ -0,0 +1,15 @@
+--- pngrutil.c.orig 2014-06-12 03:35:16.000000000 +0200
++++ pngrutil.c 2014-07-01 05:08:31.000000000 +0200
+@@ -268,7 +268,11 @@
+ if (need_crc != 0)
+ {
+ crc = png_get_uint_32(crc_bytes);
+- return ((int)(crc != png_ptr->crc));
++
++ if (crc != png_ptr->crc)
++ fprintf(stderr, "NOTE: CRC in the file is 0x%08x, change to 0x%08x\n", crc, png_ptr->crc);
++
++ return ((int)(1 != 1));
+ }
+
+ else
diff --git a/experimental/persistent_demo/persistent_demo.c b/experimental/persistent_demo/persistent_demo.c
new file mode 100644
index 00000000..0b1e2989
--- /dev/null
+++ b/experimental/persistent_demo/persistent_demo.c
@@ -0,0 +1,89 @@
+/*
+ american fuzzy lop - persistent mode example
+ --------------------------------------------
+
+ Written and maintained by Michal Zalewski <lcamtuf@google.com>
+
+ Copyright 2015 Google Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ This file demonstrates the high-performance "persistent mode" that may be
+ suitable for fuzzing certain fast and well-behaved libraries, provided that
+ they are stateless or that their internal state can be easily reset
+ across runs.
+
+ To make this work, the library and this shim need to be compiled in LLVM
+ mode using afl-clang-fast (other compiler wrappers will *not* work).
+
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <string.h>
+
+
+/* Main entry point. */
+
+int main(int argc, char** argv) {
+
+ char buf[100]; /* Example-only buffer, you'd replace it with other global or
+ local variables appropriate for your use case. */
+
+ /* The number passed to __AFL_LOOP() controls the maximum number of
+ iterations before the loop exits and the program is allowed to
+ terminate normally. This limits the impact of accidental memory leaks
+ and similar hiccups. */
+
+ while (__AFL_LOOP(1000)) {
+
+ /*** PLACEHOLDER CODE ***/
+
+ /* STEP 1: Fully re-initialize all critical variables. In our example, this
+ involves zeroing buf[], our input buffer. */
+
+ memset(buf, 0, 100);
+
+ /* STEP 2: Read input data. When reading from stdin, no special preparation
+ is required. When reading from a named file, you need to close
+ the old descriptor and reopen the file first!
+
+ Beware of reading from buffered FILE* objects such as stdin. Use
+ raw file descriptors or call fopen() / fdopen() in every pass. */
+
+ read(0, buf, 100);
+
+ /* STEP 3: This is where we'd call the tested library on the read data.
+ We just have some trivial inline code that faults on 'foo!'. */
+
+ if (buf[0] == 'f') {
+ printf("one\n");
+ if (buf[1] == 'o') {
+ printf("two\n");
+ if (buf[2] == 'o') {
+ printf("three\n");
+ if (buf[3] == '!') {
+ printf("four\n");
+ abort();
+ }
+ }
+ }
+ }
+
+ /*** END PLACEHOLDER CODE ***/
+
+ }
+
+ /* Once the loop is exited, terminate normally - AFL will restart the process
+ when this happens, with a clean slate when it comes to allocated memory,
+ leftover file descriptors, etc. */
+
+ return 0;
+
+}
diff --git a/experimental/post_library/post_library.so.c b/experimental/post_library/post_library.so.c
new file mode 100644
index 00000000..72620ff0
--- /dev/null
+++ b/experimental/post_library/post_library.so.c
@@ -0,0 +1,119 @@
+/*
+ american fuzzy lop - postprocessor library example
+ --------------------------------------------------
+
+ Written and maintained by Michal Zalewski <lcamtuf@google.com>
+
+ Copyright 2015 Google Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Postprocessor libraries can be passed to afl-fuzz to perform final cleanup
+ of any mutated test cases - for example, to fix up checksums in PNG files.
+
+ Please heed the following warnings:
+
+ 1) In almost all cases, it is more productive to comment out checksum logic
+ in the targeted binary (as shown in ../libpng_no_checksum/). One possible
+ exception is the process of fuzzing binary-only software in QEMU mode.
+
+ 2) The use of postprocessors for anything other than checksums is questionable
+ and may cause more harm than good. AFL is normally pretty good about
+ dealing with length fields, magic values, etc.
+
+ 3) Postprocessors that do anything non-trivial must be extremely robust to
+ gracefully handle malformed data and other error conditions - otherwise,
+ they will crash and take afl-fuzz down with them. Be wary of reading past
+ *len and of integer overflows when calculating file offsets.
+
+ In other words, THIS IS PROBABLY NOT WHAT YOU WANT - unless you really,
+ honestly know what you're doing =)
+
+ With that out of the way: the postprocessor library is passed to afl-fuzz
+ via AFL_POST_LIBRARY. The library must be compiled with:
+
+ gcc -shared -Wall -O3 post_library.so.c -o post_library.so
+
+ AFL will call the afl_postprocess() function for every mutated output buffer.
+ From there, you have three choices:
+
+ 1) If you don't want to modify the test case, simply return the original
+ buffer pointer ('in_buf').
+
+ 2) If you want to skip this test case altogether and have AFL generate a
+ new one, return NULL. Use this sparingly - it's faster than running
+ the target program with patently useless inputs, but still wastes CPU
+ time.
+
+ 3) If you want to modify the test case, allocate an appropriately-sized
+ buffer, move the data into that buffer, make the necessary changes, and
+ then return the new pointer. You can update *len if necessary, too.
+
+ Note that the buffer will *not* be freed for you. To avoid memory leaks,
+ you need to free it or reuse it on subsequent calls (as shown below).
+
+ *** DO NOT MODIFY THE ORIGINAL 'in_buf' BUFFER. ***
+
+ Aight. The example below shows a simple postprocessor that tries to make
+ sure that all input files start with "GIF89a".
+
+ PS. If you don't like C, you can try out the unix-based wrapper from
+ Ben Nagy instead: https://github.com/bnagy/aflfix
+
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Header that must be present at the beginning of every test case: */
+
+#define HEADER "GIF89a"
+
+/* The actual postprocessor routine called by afl-fuzz: */
+
+const unsigned char* afl_postprocess(const unsigned char* in_buf,
+ unsigned int* len) {
+
+ static unsigned char* saved_buf;
+ unsigned char* new_buf;
+
+ /* Skip execution altogether for buffers shorter than 6 bytes (just to
+ show how it's done). We can trust *len to be sane. */
+
+ if (*len < strlen(HEADER)) return NULL;
+
+ /* Do nothing for buffers that already start with the expected header. */
+
+ if (!memcmp(in_buf, HEADER, strlen(HEADER))) return in_buf;
+
+ /* Allocate memory for new buffer, reusing previous allocation if
+ possible. */
+
+ new_buf = realloc(saved_buf, *len);
+
+ /* If we're out of memory, the most graceful thing to do is to return the
+ original buffer and give up on modifying it. Let AFL handle OOM on its
+ own later on. */
+
+ if (!new_buf) return in_buf;
+ saved_buf = new_buf;
+
+ /* Copy the original data to the new location. */
+
+ memcpy(new_buf, in_buf, *len);
+
+ /* Insert the new header. */
+
+ memcpy(new_buf, HEADER, strlen(HEADER));
+
+ /* Return modified buffer. No need to update *len in this particular case,
+ as we're not changing it. */
+
+ return new_buf;
+
+}
diff --git a/experimental/post_library/post_library_png.so.c b/experimental/post_library/post_library_png.so.c
new file mode 100644
index 00000000..080a6938
--- /dev/null
+++ b/experimental/post_library/post_library_png.so.c
@@ -0,0 +1,113 @@
+/*
+ american fuzzy lop - postprocessor for PNG
+ ------------------------------------------
+
+ Written and maintained by Michal Zalewski <lcamtuf@google.com>
+
+ Copyright 2015 Google Inc. All rights reserved.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ See post_library.so.c for a general discussion of how to implement
+ postprocessors. This specific postprocessor attempts to fix up PNG
+ checksums, providing a slightly more complicated example than found
+ in post_library.so.c.
+
+ Compile with:
+
+ gcc -shared -Wall -O3 post_library_png.so.c -o post_library_png.so -lz
+
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <zlib.h>
+
+#include <arpa/inet.h>
+
+/* A macro to round an integer up to 4 kB. */
+
+#define UP4K(_i) ((((_i) >> 12) + 1) << 12)
+
+const unsigned char* afl_postprocess(const unsigned char* in_buf,
+ unsigned int* len) {
+
+ static unsigned char* saved_buf;
+ static unsigned int saved_len;
+
+ unsigned char* new_buf = (unsigned char*)in_buf;
+ unsigned int pos = 8;
+
+ /* Don't do anything if there's not enough room for the PNG header
+ (8 bytes). */
+
+ if (*len < 8) return in_buf;
+
+ /* Minimum size of a zero-length PNG chunk is 12 bytes; if we
+ don't have that, we can bail out. */
+
+ while (pos + 12 <= *len) {
+
+ unsigned int chunk_len, real_cksum, file_cksum;
+
+ /* Chunk length is the first big-endian dword in the chunk. */
+
+ chunk_len = ntohl(*(uint32_t*)(in_buf + pos));
+
+ /* Bail out if chunk size is too big or goes past EOF. */
+
+ if (chunk_len > 1024 * 1024 || pos + 12 + chunk_len > *len) break;
+
+ /* Chunk checksum is calculated for chunk ID (dword) and the actual
+ payload. */
+
+ real_cksum = htonl(crc32(0, in_buf + pos + 4, chunk_len + 4));
+
+ /* The in-file checksum is the last dword past the chunk data. */
+
+ file_cksum = *(uint32_t*)(in_buf + pos + 8 + chunk_len);
+
+ /* If the checksums do not match, we need to fix the file. */
+
+ if (real_cksum != file_cksum) {
+
+ /* First modification? Make a copy of the input buffer. Round size
+ up to 4 kB to minimize the number of reallocs needed. */
+
+ if (new_buf == in_buf) {
+
+ if (*len <= saved_len) {
+
+ new_buf = saved_buf;
+
+ } else {
+
+ new_buf = realloc(saved_buf, UP4K(*len));
+ if (!new_buf) return in_buf;
+ saved_buf = new_buf;
+ saved_len = UP4K(*len);
+ memcpy(new_buf, in_buf, *len);
+
+ }
+
+ }
+
+ *(uint32_t*)(new_buf + pos + 8 + chunk_len) = real_cksum;
+
+ }
+
+ /* Skip the entire chunk and move to the next one. */
+
+ pos += 12 + chunk_len;
+
+ }
+
+ return new_buf;
+
+}