From e30b2c6af6e369844c92c00a20ebdd53473a747c Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 5 Sep 2020 13:18:28 +0200 Subject: final changes for pre-3.0 --- examples/README.md | 2 +- examples/aflpp_driver/aflpp_driver.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'examples') diff --git a/examples/README.md b/examples/README.md index d28aadbe..46a92c6e 100644 --- a/examples/README.md +++ b/examples/README.md @@ -47,7 +47,7 @@ Here's a quick overview of the stuff you can find in this directory: Note that the minimize_corpus.sh tool has graduated from the examples/ directory and is now available as ../afl-cmin. The LLVM mode has likewise -graduated to ../llvm_mode/*. +graduated to ../instrumentation/*. 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, diff --git a/examples/aflpp_driver/aflpp_driver.c b/examples/aflpp_driver/aflpp_driver.c index ff5446e9..82e55fc4 100644 --- a/examples/aflpp_driver/aflpp_driver.c +++ b/examples/aflpp_driver/aflpp_driver.c @@ -27,7 +27,7 @@ EOF # Build your target with -fsanitize-coverage=trace-pc-guard using fresh clang. clang -g -fsanitize-coverage=trace-pc-guard test_fuzzer.cc -c # Build afl-llvm-rt.o.c from the AFL distribution. -clang -c -w $AFL_HOME/llvm_mode/afl-llvm-rt.o.c +clang -c -w $AFL_HOME/instrumentation/afl-llvm-rt.o.c # Build this file, link it with afl-llvm-rt.o.o and the target code. clang++ afl_driver.cpp test_fuzzer.o afl-llvm-rt.o.o # Run AFL: -- cgit 1.4.1 From f8c0182e16a6eefd5df2cb39c8fd49cce701bcca Mon Sep 17 00:00:00 2001 From: van Hauser Date: Wed, 9 Sep 2020 12:49:49 +0200 Subject: fix travis --- .travis.yml | 12 ++-- examples/analysis_scripts/queue2csv.sh | 122 +++++++++++++++++++++++++++++++++ 2 files changed, 128 insertions(+), 6 deletions(-) create mode 100755 examples/analysis_scripts/queue2csv.sh (limited to 'examples') diff --git a/.travis.yml b/.travis.yml index c82c8c26..5dc4ab39 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,18 +9,18 @@ branches: matrix: include: -# - os: linux # focal errors every run with a timeout while installing packages -# dist: focal -# env: NAME="focal-amd64" MODERN="yes" GCC="9" + - os: linux + dist: focal + env: NAME="focal-amd64" MODERN="yes" GCC="9" - os: linux dist: bionic env: NAME="bionic-amd64" MODERN="yes" GCC="7" - os: linux dist: xenial env: NAME="xenial-amd64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0" - - os: linux - dist: trusty - env: NAME="trusty-amd64" MODERN="no" GCC="4.8" +# - os: linux # disabled: fatal: unable to access 'https://git.qemu.org/git/capstone/': gnutls_handshake() failed: Handshake failed +# dist: trusty +# env: NAME="trusty-amd64" MODERN="no" GCC="4.8" - os: linux # until travis can fix this! dist: xenial arch: arm64 diff --git a/examples/analysis_scripts/queue2csv.sh b/examples/analysis_scripts/queue2csv.sh new file mode 100755 index 00000000..2528b438 --- /dev/null +++ b/examples/analysis_scripts/queue2csv.sh @@ -0,0 +1,122 @@ +#!/bin/bash + +test -z "$1" -o -z "$2" -o "$1" = "-h" -o "$1" = "-hh" -o "$1" = "--help" -o '!' -d "$1" && { + echo "Syntax: [-n] $0 out-directory file.csv [\"tools/target --opt @@\"]" + echo Option -n will suppress the CSV header. + echo If the target execution command is supplied then also edge coverage is gathered. + exit 1 +} + +function getval() { + VAL="" + if [ "$file" != "${file/$1/}" ]; then + TMP="${file/*$1:/}" + VAL="${TMP/,*/}" + fi +} + +SKIP= +if [ "$1" = "-n" ]; then + SKIP=1 + shift +fi + +test -n "$4" && { echo "Error: too many commandline options. Target command and options including @@ have to be passed within \"\"!"; exit 1; } + +test -d "$1"/queue && OUT="$1/queue" || OUT="$1" + +OK=`ls $OUT/id:000000,time:0,orig:* 2> /dev/null` +if [ -n "$OK" ]; then + LISTCMD="ls $OUT/id:"* +else + LISTCMD="ls -tr $OUT/" +fi + +ID=;SRC=;TIME=;OP=;POS=;REP=;EDGES=;EDGES_TOTAL=; +DIR="$OUT/../stats" +rm -rf "$DIR" +> "$2" || exit 1 +mkdir "$DIR" || exit 1 +> "$DIR/../edges.txt" || exit 1 + +{ + + if [ -z "$SKIP" ]; then + echo "time;\"filename\";id;src;new_cov;edges;total_edges;\"op\";pos;rep;unique_edges" + fi + + $LISTCMD | grep -v ,sync: | sed 's/.*id:/id:/g' | while read file; do + + if [ -n "$3" ]; then + + TMP=${3/@@/$OUT/$file} + + if [ "$TMP" = "$3" ]; then + + cat "$OUT/$file" | afl-showmap -o "$DIR/$file" -q -- $3 >/dev/null 2>&1 + + else + + afl-showmap -o "$DIR/$file" -q -- $TMP >/dev/null 2>&1 + + fi + + { cat "$DIR/$file" | sed 's/:.*//' ; cat "$DIR/../edges.txt" ; } | sort -nu > $DIR/../edges.txt.tmp + mv $DIR/../edges.txt.tmp $DIR/../edges.txt + EDGES=$(cat "$DIR/$file" | wc -l) + EDGES_TOTAL=$(cat "$DIR/../edges.txt" | wc -l) + + fi + + getval id; ID="$VAL" + getval src; SRC="$VAL" + getval time; TIME="$VAL" + getval op; OP="$VAL" + getval pos; POS="$VAL" + getval rep; REP="$VAL" + if [ "$file" != "${file/+cov/}" ]; then + COV=1 + else + COV="" + fi + + if [ -n "$3" -a -s "$DIR/../edges.txt" ]; then + echo "$TIME;\"$file\";$ID;$SRC;$COV;$EDGES;$EDGES_TOTAL;\"$OP\";$POS;$REP;UNIQUE$file" + else + echo "$TIME;\"$file\";$ID;$SRC;$COV;;;\"$OP\";$POS;$REP;" + fi + + done + +} | tee "$DIR/../queue.csv" > "$2" || exit 1 + +if [ -n "$3" -a -s "$DIR/../edges.txt" ]; then + + cat "$DIR/"* | sed 's/:.*//' | sort -n | uniq -c | egrep '^[ \t]*1 ' | awk '{print$2}' > $DIR/../unique.txt + + if [ -s "$DIR/../unique.txt" ]; then + + ls "$DIR/id:"* | grep -v ",sync:" |sed 's/.*\/id:/id:/g' | while read file; do + + CNT=$(sed 's/:.*//' "$DIR/$file" | tee "$DIR/../tmp.txt" | wc -l) + DIFF=$(diff -u "$DIR/../tmp.txt" "$DIR/../unique.txt" | egrep '^-[0-9]' | wc -l) + UNIQUE=$(($CNT - $DIFF)) + sed -i "s/;UNIQUE$file/;$UNIQUE/" "$DIR/../queue.csv" "$2" + + done + + rm -f "$DIR/../tmp.txt" + + else + + sed -i 's/;UNIQUE.*/;/' "$DIR/../queue.csv" "$2" + + fi + +fi + +mv "$DIR/../queue.csv" "$DIR/queue.csv" +if [ -e "$DIR/../edges.txt" ]; then mv "$DIR/../edges.txt" "$DIR/edges.txt"; fi +if [ -e "$DIR/../unique.txt" ]; then mv "$DIR/../unique.txt" "$DIR/unique.txt"; fi + +echo "Created $2" -- cgit 1.4.1 From b3b5e2509176788fac09834cf59f909de8c7df0f Mon Sep 17 00:00:00 2001 From: Tim Blazytko Date: Wed, 23 Sep 2020 01:58:11 +0200 Subject: examples: fixed path for docs (#563) --- examples/custom_mutators/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/custom_mutators/README.md b/examples/custom_mutators/README.md index a81538e6..655f7a5e 100644 --- a/examples/custom_mutators/README.md +++ b/examples/custom_mutators/README.md @@ -1,7 +1,7 @@ # Examples for the custom mutator These are example and helper files for the custom mutator feature. -See [docs/custom_mutators.md](../docs/custom_mutators.md) for more information +See [docs/custom_mutators.md](../../docs/custom_mutators.md) for more information Note that if you compile with python3.7 you must use python3 scripts, and if you use python2.7 to compile python2 scripts! -- cgit 1.4.1 From fd4a2dfec2d44879aa7b9eee76978b56a60e7912 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Thu, 8 Oct 2020 17:51:16 +0200 Subject: fix persistent_demo_new.c --- examples/persistent_demo/persistent_demo_new.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/persistent_demo/persistent_demo_new.c b/examples/persistent_demo/persistent_demo_new.c index 7f878c0c..13123d33 100644 --- a/examples/persistent_demo/persistent_demo_new.c +++ b/examples/persistent_demo/persistent_demo_new.c @@ -37,7 +37,7 @@ unsigned char fuzz_buf[1024000]; #define __AFL_FUZZ_TESTCASE_LEN fuzz_len #define __AFL_FUZZ_TESTCASE_BUF fuzz_buf #define __AFL_FUZZ_INIT() void sync(void); - #define __AFL_LOOP(x) ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ? + #define __AFL_LOOP(x) ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ? 1 : 0) #define __AFL_INIT() sync() #endif -- cgit 1.4.1 From 125f8b6ba71fba91735374b1bd07333b19aae635 Mon Sep 17 00:00:00 2001 From: van Hauser Date: Fri, 9 Oct 2020 23:23:44 +0200 Subject: -m none is the default now --- docs/Changelog.md | 1 + examples/persistent_demo/persistent_demo_new.c | 3 ++- include/config.h | 24 ++++++++---------------- src/afl-fuzz-state.c | 2 +- src/afl-fuzz.c | 4 ++-- 5 files changed, 14 insertions(+), 20 deletions(-) (limited to 'examples') diff --git a/docs/Changelog.md b/docs/Changelog.md index 0f923423..ba7028df 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -14,6 +14,7 @@ sending a mail to . - all compilers combined to afl-cc which emulates the previous ones - afl-llvm/gcc-rt.o merged into afl-compiler-rt.o - afl-fuzz + - memory limits are now disabled by default, set them with -m if required - Marcel Boehme submitted a patch that improves all AFFast schedules :) - reading testcases from -i now descends into subdirectories - allow up to 4 -x command line options diff --git a/examples/persistent_demo/persistent_demo_new.c b/examples/persistent_demo/persistent_demo_new.c index 13123d33..b8b4cda0 100644 --- a/examples/persistent_demo/persistent_demo_new.c +++ b/examples/persistent_demo/persistent_demo_new.c @@ -37,7 +37,8 @@ unsigned char fuzz_buf[1024000]; #define __AFL_FUZZ_TESTCASE_LEN fuzz_len #define __AFL_FUZZ_TESTCASE_BUF fuzz_buf #define __AFL_FUZZ_INIT() void sync(void); - #define __AFL_LOOP(x) ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ? 1 : 0) + #define __AFL_LOOP(x) \ + ((fuzz_len = read(0, fuzz_buf, sizeof(fuzz_buf))) > 0 ? 1 : 0) #define __AFL_INIT() sync() #endif diff --git a/include/config.h b/include/config.h index 3f5c5448..5df604e7 100644 --- a/include/config.h +++ b/include/config.h @@ -66,25 +66,17 @@ #define WORD_SIZE_64 1 #endif -/* Default memory limit for child process (MB): */ - -#ifndef __NetBSD__ - #ifndef WORD_SIZE_64 - #define MEM_LIMIT 50 - #else - #define MEM_LIMIT 75 - #endif /* ^!WORD_SIZE_64 */ -#else /* NetBSD's kernel needs more space for stack, see discussion for issue \ - #165 */ - #define MEM_LIMIT 250 -#endif -/* Default memory limit when running in QEMU mode (MB): */ +/* Default memory limit for child process (MB) 0 = disabled : */ + +#define MEM_LIMIT 0 + +/* Default memory limit when running in QEMU mode (MB) 0 = disabled : */ -#define MEM_LIMIT_QEMU 250 +#define MEM_LIMIT_QEMU 0 -/* Default memory limit when running in Unicorn mode (MB): */ +/* Default memory limit when running in Unicorn mode (MB) 0 = disabled : */ -#define MEM_LIMIT_UNICORN 250 +#define MEM_LIMIT_UNICORN 0 /* Number of calibration cycles per every new test case (and for test cases that show variable behavior): */ diff --git a/src/afl-fuzz-state.c b/src/afl-fuzz-state.c index 4a1e739f..a8e56e60 100644 --- a/src/afl-fuzz-state.c +++ b/src/afl-fuzz-state.c @@ -87,7 +87,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) { afl->w_end = 0.3; afl->g_max = 5000; afl->period_pilot_tmp = 5000.0; - afl->schedule = COE; /* Power schedule (default: COE) */ + afl->schedule = EXPLORE; /* Power schedule (default: EXPLORE) */ afl->havoc_max_mult = HAVOC_MAX_MULT; afl->clear_screen = 1; /* Window resized? */ diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index 8458b50f..cf0a30c9 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -90,13 +90,13 @@ static void usage(u8 *argv0, int more_help) { "Execution control settings:\n" " -p schedule - power schedules compute a seed's performance score:\n" - " -- see docs/power_schedules.md\n" " -f file - location read by the fuzzed program (default: stdin " "or @@)\n" " -t msec - timeout for each run (auto-scaled, 50-%d ms)\n" - " -m megs - memory limit for child process (%d MB)\n" + " -m megs - memory limit for child process (%d MB, 0 = no limit)\n" " -Q - use binary-only instrumentation (QEMU mode)\n" " -U - use unicorn-based instrumentation (Unicorn mode)\n" " -W - use qemu-based instrumentation with Wine (Wine " -- cgit 1.4.1 From d4b04f07904ca202586133facba5406cf10aa1be Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Thu, 29 Oct 2020 20:06:55 +0100 Subject: fix compile warning in FreeBSD --- examples/aflpp_driver/aflpp_driver.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/aflpp_driver/aflpp_driver.c b/examples/aflpp_driver/aflpp_driver.c index 82e55fc4..017aa72b 100644 --- a/examples/aflpp_driver/aflpp_driver.c +++ b/examples/aflpp_driver/aflpp_driver.c @@ -197,7 +197,7 @@ static void dup_and_close_stderr() { FILE *new_output_file = fdopen(output_fd, "w"); if (!new_output_file) abort(); if (!__sanitizer_set_report_fd) return; - __sanitizer_set_report_fd((void *)output_fd); + __sanitizer_set_report_fd((void *)(long int)output_fd); discard_output(output_fileno); } -- cgit 1.4.1 From fdc364046e8349652d857e5f5decd8a09b89831e Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Mon, 2 Nov 2020 13:56:24 +0100 Subject: doc for qemuafl --- examples/qemu_persistent_hook/read_into_rdi.c | 52 +++++++------------------ qemu_mode/README.md | 35 +++++++++++------ qemu_mode/README.persistent.md | 55 +++++++++++++++++++++++---- 3 files changed, 85 insertions(+), 57 deletions(-) (limited to 'examples') diff --git a/examples/qemu_persistent_hook/read_into_rdi.c b/examples/qemu_persistent_hook/read_into_rdi.c index bd6d3f45..15647cb4 100644 --- a/examples/qemu_persistent_hook/read_into_rdi.c +++ b/examples/qemu_persistent_hook/read_into_rdi.c @@ -1,53 +1,28 @@ -#include +#include "../../qemu_mode/qemuafl/qemuafl/api.h" + #include -#include #include +void afl_persistent_hook(struct x86_64_regs *regs, + uint64_t guest_base, + uint8_t *input_buf, + uint32_t input_buf_len) { + #define g2h(x) ((void *)((unsigned long)(x) + guest_base)) #define h2g(x) ((uint64_t)(x)-guest_base) -enum { - - R_EAX = 0, - R_ECX = 1, - R_EDX = 2, - R_EBX = 3, - R_ESP = 4, - R_EBP = 5, - R_ESI = 6, - R_EDI = 7, - R_R8 = 8, - R_R9 = 9, - R_R10 = 10, - R_R11 = 11, - R_R12 = 12, - R_R13 = 13, - R_R14 = 14, - R_R15 = 15, - - R_AL = 0, - R_CL = 1, - R_DL = 2, - R_BL = 3, - R_AH = 4, - R_CH = 5, - R_DH = 6, - R_BH = 7, - -}; - -void afl_persistent_hook(uint64_t *regs, uint64_t guest_base, - uint8_t *input_buf, uint32_t input_len) { - // In this example the register RDI is pointing to the memory location // of the target buffer, and the length of the input is in RSI. // This can be seen with a debugger, e.g. gdb (and "disass main") - printf("placing input into %p\n", regs[R_EDI]); + printf("Placing input into %p\n", regs->rdi); if (input_len > 1024) input_len = 1024; - memcpy(g2h(regs[R_EDI]), input_buf, input_len); - regs[R_ESI] = input_len; + memcpy(g2h(regs->rdi), input_buf, input_len); + regs->rsi = input_len; + +#undef g2h +#undef h2g } @@ -58,4 +33,3 @@ int afl_persistent_hook_init(void) { return 1; } - diff --git a/qemu_mode/README.md b/qemu_mode/README.md index 3cf678e4..9bbeeb19 100644 --- a/qemu_mode/README.md +++ b/qemu_mode/README.md @@ -14,12 +14,12 @@ The usual performance cost is 2-5x, which is considerably better than seen so far in experiments with tools such as DynamoRIO and PIN. The idea and much of the initial implementation comes from Andrew Griffiths. -The actual implementation on QEMU 3 (shipped with afl++) is from +The actual implementation on current QEMU (shipped as qemuafl) is from Andrea Fioraldi. Special thanks to abiondo that re-enabled TCG chaining. ## 2) How to use -The feature is implemented with a patch to QEMU 3.1.1. The simplest way +The feature is implemented with a patched QEMU. The simplest way to build it is to run ./build_qemu_support.sh. The script will download, configure, and compile the QEMU binary for you. @@ -58,7 +58,7 @@ directory. If you want to specify a different path for libraries (e.g. to run an arm64 binary on x86_64) use QEMU_LD_PREFIX. -## 3) Bonus feature #1: deferred initialization +## 3) Deferred initialization As for LLVM mode (refer to its README.md for mode details) QEMU mode supports the deferred initialization. @@ -68,7 +68,7 @@ to move the forkserver to a different part, e.g. just before the file is opened (e.g. way after command line parsing and config file loading, etc.) which can be a huge speed improvement. -## 4) Bonus feature #2: persistent mode +## 4) Persistent mode AFL++'s QEMU mode now supports also persistent mode for x86, x86_64, arm and aarch64 targets. @@ -77,7 +77,20 @@ up - but worth the effort. Please see the extra documentation for it: [README.persistent.md](README.persistent.md) -## 5) Bonus feature #3: CompareCoverage +## 5) Snapshot mode + +As an extension to persistent mode, qemuafl can snapshot and restore the memory +state and brk(). Details are in the persistent mode readme. + +The env var that enable the ready to use snapshot mode is AFL_QEMU_SNAPSHOT and +take an hex address as value that is the snpashot entrypoint. + +Snapshpot mode can work restoring all the writeable pages, tipically slower than +fork() mode but, opposed to fork(), it can scale better with multicore. +If the AFL++ Snaphsot kernel module is loaded, qemuafl will use it and, in this +case, the speed is better than fork() and also the scaling capabilities. + +## 6) CompareCoverage CompareCoverage is a sub-instrumentation with effects similar to laf-intel. @@ -98,7 +111,7 @@ on the x86, x86_64, arm and aarch64 targets. Highly recommended. -## 6) CMPLOG mode +## 7) CMPLOG mode Another new feature is CMPLOG, which is based on the redqueen project. Here all immidiates in CMP instructions are learned and put into a dynamic @@ -110,7 +123,7 @@ and aarch64. To enable it you must pass on the command line of afl-fuzz: -c /path/to/your/target -## 7) Bonus feature #4: Wine mode +## 8) Wine mode AFL++ QEMU can use Wine to fuzz WIn32 PE binaries. Use the -W flag of afl-fuzz. @@ -118,7 +131,7 @@ Note that some binaries require user interaction with the GUI and must be patche For examples look [here](https://github.com/andreafioraldi/WineAFLplusplusDEMO). -## 8) Notes on linking +## 9) Notes on linking The feature is supported only on Linux. Supporting BSD may amount to porting the changes made to linux-user/elfload.c and applying them to @@ -139,7 +152,7 @@ practice, this means two things: Setting AFL_INST_LIBS=1 can be used to circumvent the .text detection logic and instrument every basic block encountered. -## 9) Benchmarking +## 10) Benchmarking If you want to compare the performance of the QEMU instrumentation with that of afl-gcc compiled code against the same target, you need to build the @@ -154,7 +167,7 @@ Comparative measurements of execution speed or instrumentation coverage will be fairly meaningless if the optimization levels or instrumentation scopes don't match. -## 10) Gotchas, feedback, bugs +## 11) Gotchas, feedback, bugs If you need to fix up checksums or do other cleanup on mutated test cases, see examples/custom_mutators/ for a viable solution. @@ -175,7 +188,7 @@ with -march=core2, can help. Beyond that, this is an early-stage mechanism, so fields reports are welcome. You can send them to . -## 11) Alternatives: static rewriting +## 12) Alternatives: static rewriting Statically rewriting binaries just once, instead of attempting to translate them at run time, can be a faster alternative. That said, static rewriting is diff --git a/qemu_mode/README.persistent.md b/qemu_mode/README.persistent.md index b6d5d2d0..2744d172 100644 --- a/qemu_mode/README.persistent.md +++ b/qemu_mode/README.persistent.md @@ -18,11 +18,15 @@ The start of the persistent loop has to be set with AFL_QEMU_PERSISTENT_ADDR. This address can be the address of whatever instruction. Setting this address to the start of a function makes the usage simple. -If the address is however within a function, either RET or OFFSET (see below -in 2.2 and 2.3) have to be set. +If the address is however within a function, either RET, OFFSET or EXITS +(see below in 2.2, 2.3, 2.6) have to be set. This address (as well as the RET address, see below) has to be defined in hexadecimal with the 0x prefix or as a decimal value. +If both RET and EXITS are not set, QEMU will assume that START points to a +function and will patch the return address (on stack or in the link register) +to return to START (like WinAFL). + *Note:* If the target is compiled with position independant code (PIE/PIC) qemu loads these to a specific base address. For 64 bit you have to add 0x4000000000 (9 zeroes) and for 32 bit 0x40000000 @@ -41,10 +45,6 @@ The emulator will emit a jump to START when translating the instruction at RET. It is optional, and only needed if the the return should not be at the end of the function to which the START address points into, but earlier. -If it is not set, QEMU will assume that START points to a function and will -patch the return address (on stack or in the link register) to return to START -(like WinAFL). - It is defined by setting AFL_QEMU_PERSISTENT_RET, and too 0x4000000000 has to be set if the target is position independant. @@ -96,6 +96,32 @@ int main(int argc, char **argv) { If you don't save and restore the registers in x86_64, the paramteter argc will be lost at the second execution of the loop. +### 2.5) Resetting the memory state + +This option restores the memory state using the AFL++ Snapshot LKM if loaded. +Otherwise, all the writeable pages are restored. + +To enable this option, set AFL_QEMU_PERSISTENT_MEM=1. + +### 2.6) Reset on exit() + +The user can force QEMU to set the program counter to START instead of executing +the exit_group syscall and exit the program. + +The env variable is AFL_QEMU_PERSISTENT_EXITS. + +### 2.7) Snapshot + +AFL_QEMU_SNAPSHOT=address is just a shugar env variable that is equivalent to +the following set of variables: + +``` +AFL_QEMU_PERSISTENT_ADDR=address +AFL_QEMU_PERSISTENT_GPR=1 +AFL_QEMU_PERSISTENT_MEM=1 +AFL_QEMU_PERSISTENT_EXITS=1 +``` + ## 3) Optional parameters ### 3.1) Loop counter value @@ -125,10 +151,25 @@ AFL_QEMU_PERSISTENT_HOOK=/path/to/hook.so. The signature is: ```c -void afl_persistent_hook(uint64_t* regs, uint64_t guest_base); +void afl_persistent_hook(struct ARCH_regs *regs, + uint64_t guest_base, + uint8_t *input_buf, + uint32_t input_buf_len); ``` +Where ARCH is one of x86, x86_64, arm or arm64. +You have to include `path/to/qemuafl/qemuafl/api.h`. + In this hook, you can inspect and change the saved GPR state at START. +You can also initialize you data structures when QEMU loads the shared object +with: + +`int afl_persistent_hook_init(void);` + +If this reoutine returns true, the shared mem fuzzing feature of AFL++ is used +and so the input_buf variables of the hook becomes meaningful. Otherwise, +you have to read the input from a file like stdin. + An example that you can use with little modification for your target can be found here: [examples/qemu_persistent_hook](../examples/qemu_persistent_hook) -- cgit 1.4.1 From a260d34b4997d86ec158843c2362dae009e3bcf7 Mon Sep 17 00:00:00 2001 From: Andrea Fioraldi Date: Mon, 2 Nov 2020 14:15:44 +0100 Subject: persistent hook example --- README.md | 2 +- examples/qemu_persistent_hook/Makefile | 6 ++++++ examples/qemu_persistent_hook/README.md | 3 +-- examples/qemu_persistent_hook/read_into_rdi.c | 8 ++++---- qemu_mode/README.md | 23 ++++++++++++++++------- qemu_mode/build_qemu_support.sh | 2 +- 6 files changed, 29 insertions(+), 15 deletions(-) create mode 100644 examples/qemu_persistent_hook/Makefile (limited to 'examples') diff --git a/README.md b/README.md index 26a81d9d..f955aedd 100644 --- a/README.md +++ b/README.md @@ -166,7 +166,7 @@ If you want to build afl++ yourself you have many options. The easiest choice is to build and install everything: ```shell -sudo apt install build-essential libtool-bin python3-dev automake flex bison libglib2.0-dev libpixman-1-dev clang python3-setuptools llvm +sudo apt install build-essential python3-dev automake flex bison libglib2.0-dev libpixman-1-dev clang python3-setuptools llvm make distrib sudo make install ``` diff --git a/examples/qemu_persistent_hook/Makefile b/examples/qemu_persistent_hook/Makefile new file mode 100644 index 00000000..85db1b46 --- /dev/null +++ b/examples/qemu_persistent_hook/Makefile @@ -0,0 +1,6 @@ +all: + $(CC) -no-pie test.c -o test + $(CC) -fPIC -shared read_into_rdi.c -o read_into_rdi.so + +clean: + rm -rf in out test read_into_rdi.so diff --git a/examples/qemu_persistent_hook/README.md b/examples/qemu_persistent_hook/README.md index 3278b60c..3f908c22 100644 --- a/examples/qemu_persistent_hook/README.md +++ b/examples/qemu_persistent_hook/README.md @@ -3,8 +3,7 @@ Compile the test binary and the library: ``` -gcc -no-pie test.c -o test -gcc -fPIC -shared read_into_rdi.c -o read_into_rdi.so +make ``` Fuzz with: diff --git a/examples/qemu_persistent_hook/read_into_rdi.c b/examples/qemu_persistent_hook/read_into_rdi.c index 15647cb4..1977c89f 100644 --- a/examples/qemu_persistent_hook/read_into_rdi.c +++ b/examples/qemu_persistent_hook/read_into_rdi.c @@ -15,11 +15,11 @@ void afl_persistent_hook(struct x86_64_regs *regs, // of the target buffer, and the length of the input is in RSI. // This can be seen with a debugger, e.g. gdb (and "disass main") - printf("Placing input into %p\n", regs->rdi); + printf("Placing input into 0x%lx\n", regs->rdi); - if (input_len > 1024) input_len = 1024; - memcpy(g2h(regs->rdi), input_buf, input_len); - regs->rsi = input_len; + if (input_buf_len > 1024) input_buf_len = 1024; + memcpy(g2h(regs->rdi), input_buf, input_buf_len); + regs->rsi = input_buf_len; #undef g2h #undef h2g diff --git a/qemu_mode/README.md b/qemu_mode/README.md index 9bbeeb19..348f5bbc 100644 --- a/qemu_mode/README.md +++ b/qemu_mode/README.md @@ -90,7 +90,16 @@ fork() mode but, opposed to fork(), it can scale better with multicore. If the AFL++ Snaphsot kernel module is loaded, qemuafl will use it and, in this case, the speed is better than fork() and also the scaling capabilities. -## 6) CompareCoverage +## 6) Partial instrumentation + +You can tell QEMU to instrument only a part of the address space. + +Just set AFL_QEMU_INST_RANGES=A,B,C... + +The format of the iterms in the list is either a range of addresses like 0x123-0x321 +or a module name like module.so (that is mathed in the mapped object filename). + +## 7) CompareCoverage CompareCoverage is a sub-instrumentation with effects similar to laf-intel. @@ -111,7 +120,7 @@ on the x86, x86_64, arm and aarch64 targets. Highly recommended. -## 7) CMPLOG mode +## 8) CMPLOG mode Another new feature is CMPLOG, which is based on the redqueen project. Here all immidiates in CMP instructions are learned and put into a dynamic @@ -123,7 +132,7 @@ and aarch64. To enable it you must pass on the command line of afl-fuzz: -c /path/to/your/target -## 8) Wine mode +## 9) Wine mode AFL++ QEMU can use Wine to fuzz WIn32 PE binaries. Use the -W flag of afl-fuzz. @@ -131,7 +140,7 @@ Note that some binaries require user interaction with the GUI and must be patche For examples look [here](https://github.com/andreafioraldi/WineAFLplusplusDEMO). -## 9) Notes on linking +## 10) Notes on linking The feature is supported only on Linux. Supporting BSD may amount to porting the changes made to linux-user/elfload.c and applying them to @@ -152,7 +161,7 @@ practice, this means two things: Setting AFL_INST_LIBS=1 can be used to circumvent the .text detection logic and instrument every basic block encountered. -## 10) Benchmarking +## 11) Benchmarking If you want to compare the performance of the QEMU instrumentation with that of afl-gcc compiled code against the same target, you need to build the @@ -167,7 +176,7 @@ Comparative measurements of execution speed or instrumentation coverage will be fairly meaningless if the optimization levels or instrumentation scopes don't match. -## 11) Gotchas, feedback, bugs +## 12) Gotchas, feedback, bugs If you need to fix up checksums or do other cleanup on mutated test cases, see examples/custom_mutators/ for a viable solution. @@ -188,7 +197,7 @@ with -march=core2, can help. Beyond that, this is an early-stage mechanism, so fields reports are welcome. You can send them to . -## 12) Alternatives: static rewriting +## 13) Alternatives: static rewriting Statically rewriting binaries just once, instead of attempting to translate them at run time, can be a faster alternative. That said, static rewriting is diff --git a/qemu_mode/build_qemu_support.sh b/qemu_mode/build_qemu_support.sh index 9561ea34..683026bb 100755 --- a/qemu_mode/build_qemu_support.sh +++ b/qemu_mode/build_qemu_support.sh @@ -60,7 +60,7 @@ if [ ! -f "../afl-showmap" ]; then fi PREREQ_NOTFOUND= -for i in libtool wget automake autoconf sha384sum bison flex iconv patch pkg-config; do +for i in git wget sha384sum bison flex iconv patch pkg-config; do T=`command -v "$i" 2>/dev/null` -- cgit 1.4.1 From 050354a9deeece1249f3f5a8172328b4523c5b7f Mon Sep 17 00:00:00 2001 From: van Hauser Date: Mon, 2 Nov 2020 17:34:58 +0100 Subject: code-format --- examples/qemu_persistent_hook/read_into_rdi.c | 9 ++++----- instrumentation/SanitizerCoveragePCGUARD.so.cc | 22 +++++++++++++--------- 2 files changed, 17 insertions(+), 14 deletions(-) (limited to 'examples') diff --git a/examples/qemu_persistent_hook/read_into_rdi.c b/examples/qemu_persistent_hook/read_into_rdi.c index 1977c89f..f4a8ae59 100644 --- a/examples/qemu_persistent_hook/read_into_rdi.c +++ b/examples/qemu_persistent_hook/read_into_rdi.c @@ -3,11 +3,9 @@ #include #include -void afl_persistent_hook(struct x86_64_regs *regs, - uint64_t guest_base, - uint8_t *input_buf, - uint32_t input_buf_len) { - +void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base, + uint8_t *input_buf, uint32_t input_buf_len) { +\ #define g2h(x) ((void *)((unsigned long)(x) + guest_base)) #define h2g(x) ((uint64_t)(x)-guest_base) @@ -33,3 +31,4 @@ int afl_persistent_hook_init(void) { return 1; } + diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 934db3de..772a6f60 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -70,15 +70,17 @@ class ModuleSanitizerCoveragePass if (AllowlistFiles.size() > 0) Allowlist = SpecialCaseList::createOrDie(AllowlistFiles #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) - , *vfs::getRealFileSystem() + , + *vfs::getRealFileSystem() #endif - ); + ); if (BlocklistFiles.size() > 0) Blocklist = SpecialCaseList::createOrDie(BlocklistFiles #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) - , *vfs::getRealFileSystem() + , + *vfs::getRealFileSystem() #endif - ); + ); } @@ -253,7 +255,7 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) { Options.CoverageType = SanitizerCoverageOptions::SCK_Edge; // std::max(Options.CoverageType, // CLOpts.CoverageType); - Options.IndirectCalls = false; // CLOpts.IndirectCalls; + Options.IndirectCalls = false; // CLOpts.IndirectCalls; Options.TraceCmp = false; //|= ClCMPTracing; Options.TraceDiv = false; //|= ClDIVTracing; Options.TraceGep = false; //|= ClGEPTracing; @@ -379,15 +381,17 @@ class ModuleSanitizerCoverageLegacyPass : public ModulePass { if (AllowlistFiles.size() > 0) Allowlist = SpecialCaseList::createOrDie(AllowlistFiles #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) - , *vfs::getRealFileSystem() + , + *vfs::getRealFileSystem() #endif - ); + ); if (BlocklistFiles.size() > 0) Blocklist = SpecialCaseList::createOrDie(BlocklistFiles #if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0) - , *vfs::getRealFileSystem() + , + *vfs::getRealFileSystem() #endif - ); + ); initializeModuleSanitizerCoverageLegacyPassPass( *PassRegistry::getPassRegistry()); -- cgit 1.4.1 From 61fe059ba2d1cd0106c0ffa4eaf1896c7912e275 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Thu, 5 Nov 2020 21:11:31 +0100 Subject: ignore build error (unsupported platform), so top level 'make tests' can be run --- examples/aflpp_driver/GNUmakefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'examples') diff --git a/examples/aflpp_driver/GNUmakefile b/examples/aflpp_driver/GNUmakefile index 57e74be7..c1a087d7 100644 --- a/examples/aflpp_driver/GNUmakefile +++ b/examples/aflpp_driver/GNUmakefile @@ -12,7 +12,7 @@ CFLAGS := -O3 -funroll-loops -g all: libAFLDriver.a libAFLQemuDriver.a aflpp_qemu_driver_hook.so aflpp_driver.o: aflpp_driver.c - $(LLVM_BINDIR)clang -I. -I../../include $(CFLAGS) -c aflpp_driver.c + -$(LLVM_BINDIR)clang -I. -I../../include $(CFLAGS) -c aflpp_driver.c libAFLDriver.a: aflpp_driver.o ar ru libAFLDriver.a aflpp_driver.o -- cgit 1.4.1