about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAndrea Fioraldi <andreafioraldi@gmail.com>2020-02-08 18:07:39 +0100
committerAndrea Fioraldi <andreafioraldi@gmail.com>2020-02-08 18:07:39 +0100
commite6685436d8c8e5a346b3aa10b9d28098c1ca2dd7 (patch)
tree62e8b70a8210da308620b71fab193f71bfef2a8a
parent5fa4f47baec7e3dc78e685f9f8a44bf34c3eba53 (diff)
parenta93e11b79702eece7bda93bc8646c0bb9c2b0b64 (diff)
downloadafl++-e6685436d8c8e5a346b3aa10b9d28098c1ca2dd7.tar.gz
Merge branch 'master' of github.com:vanhauser-thc/AFLplusplus
l---------ChangeLog.md1
-rw-r--r--Makefile6
-rw-r--r--docs/Changelog.md (renamed from docs/ChangeLog.md)10
-rw-r--r--examples/qemu_persistent_hook/read_into_rdi.c4
-rw-r--r--libdislocator/libdislocator.so.c2
-rw-r--r--qemu_mode/README.md30
-rw-r--r--qemu_mode/README.persistent.md99
-rwxr-xr-xtest/test.sh6
8 files changed, 123 insertions, 35 deletions
diff --git a/ChangeLog.md b/ChangeLog.md
deleted file mode 120000
index 84ffa672..00000000
--- a/ChangeLog.md
+++ /dev/null
@@ -1 +0,0 @@
-docs/ChangeLog.md
\ No newline at end of file
diff --git a/Makefile b/Makefile
index 70eac6b9..5af8444a 100644
--- a/Makefile
+++ b/Makefile
@@ -51,7 +51,9 @@ endif
 ifneq "$(shell uname -m)" "x86_64"
  ifneq "$(shell uname -m)" "i386"
   ifneq "$(shell uname -m)" "amd64"
+   ifneq "$(shell uname -m)" "i86pc"
 	AFL_NO_X86=1
+   endif
   endif
  endif
 endif
@@ -109,10 +111,12 @@ endif
 
 ifneq "$(findstring FreeBSD, $(shell uname))" ""
   CFLAGS += -pthread
+  LDFLAGS  += -lpthread
 endif
 
 ifneq "$(findstring NetBSD, $(shell uname))" ""
   CFLAGS += -pthread
+  LDFLAGS  += -lpthread
 endif
 
 ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
@@ -423,7 +427,7 @@ endif
 
 	install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
 	ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
-	install -m 644 docs/*.md docs/ChangeLog $${DESTDIR}$(DOC_PATH)
+	install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
 	cp -r testcases/ $${DESTDIR}$(MISC_PATH)
 	cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
 
diff --git a/docs/ChangeLog.md b/docs/Changelog.md
index ad0b9e88..f2c39e65 100644
--- a/docs/ChangeLog.md
+++ b/docs/Changelog.md
@@ -1,4 +1,4 @@
-# ChangeLog
+# Changelog
 
   This is the list of all noteworthy changes made in every public release of
   the tool. See README for the general instruction manual.
@@ -25,9 +25,11 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
        instrumentation. compile normally and set AFL_LLVM_USE_TRACE_PC :)
      - LLVM 11 is supported
      - CmpLog instrumentation using SanCov (see llvm_mode/README.cmplog)
-  - CmpLog instrumentation for QEMU
-  - AFL_PERSISTENT_HOOK callback module for persistent QEMU
-    (see examples/qemu_persistent_hook)
+  - qemu_mode:
+     - CmpLog instrumentation for QEMU (-c afl-fuzz command line option)
+     - AFL_PERSISTENT_HOOK callback module for persistent QEMU
+       (see examples/qemu_persistent_hook)
+     - added qemu_mode/README.persistent.md documentation
   - afl-cmin is now a sh script (invoking awk) instead of bash for portability
     the original script is still present as afl-cmin.bash
   - afl-showmap: -i dir option now allows processing multiple inputs using the
diff --git a/examples/qemu_persistent_hook/read_into_rdi.c b/examples/qemu_persistent_hook/read_into_rdi.c
index fd4c9000..3994e790 100644
--- a/examples/qemu_persistent_hook/read_into_rdi.c
+++ b/examples/qemu_persistent_hook/read_into_rdi.c
@@ -37,8 +37,12 @@ enum {
 
 void afl_persistent_hook(uint64_t* regs, uint64_t guest_base) {
 
+  // In this example the register RDI is pointing to the memory location
+  // of the target buffer, and the length of the input is in RAX.
+
   printf("reading into %p\n", regs[R_EDI]);
   size_t r = read(0, g2h(regs[R_EDI]), 1024);
+  regs[R_EAX] = r;
   printf("readed %ld bytes\n", r);
 
 }
diff --git a/libdislocator/libdislocator.so.c b/libdislocator/libdislocator.so.c
index a426c387..98f16358 100644
--- a/libdislocator/libdislocator.so.c
+++ b/libdislocator/libdislocator.so.c
@@ -64,7 +64,7 @@
 #include "config.h"
 #include "types.h"
 
-#if __STDC_VERSION__ < 201112L
+#if __STDC_VERSION__ < 201112L || defined __FreeBSD__
 // use this hack if not C11
 typedef struct {
 
diff --git a/qemu_mode/README.md b/qemu_mode/README.md
index ccfd50e3..95b75e9c 100644
--- a/qemu_mode/README.md
+++ b/qemu_mode/README.md
@@ -71,31 +71,11 @@ must be an address of a basic block.
 
 ## 4) Bonus feature #2: persistent mode
 
-QEMU mode supports also persistent mode for x86 and x86_64 targets.
-The environment variable to enable it is AFL_QEMU_PERSISTENT_ADDR=`start addr`.
-In this variable you must specify the address of the function that
-has to be the body of the persistent loop.
-The code in this function must be stateless like in the LLVM persistent mode.
-The return address on stack is patched like in WinAFL in order to repeat the
-execution of such function.
-Another modality to execute the persistent loop is to specify also the
-AFL_QEMU_PERSISTENT_RET=`end addr` env variable.
-With this variable assigned, instead of patching the return address, the
-specified instruction is transformed to a jump towards `start addr`.
-Note that the format of the addresses in such variables is hex.
-
-Note that the base address of PIE binaries in QEMU user mode is 0x4000000000.
-
-With the env variable AFL_QEMU_PERSISTENT_GPR you can tell QEMU to save the
-original value of general purpose registers and restore them in each cycle.
-This allows to use as persistent loop functions that make use of arguments on 
-x86_64.
-
-With AFL_QEMU_PERSISTENT_RETADDR_OFFSET you can specify the offset from the
-stack pointer in which QEMU can find the return address when `start addr` is
-hitted.
-
-Use this mode with caution, probably it will not work at the first shot.
+AFL++'s QEMU mode now supports also persistent mode for x86 and x86_64 targets.
+This increases the speed by several factors, however it is a bit of work to set
+up - but worth the effort.
+
+Please see the extra documentation for it: [README.persistent.md](README.persistent.md)
 
 ## 5) Bonus feature #3: CompareCoverage
 
diff --git a/qemu_mode/README.persistent.md b/qemu_mode/README.persistent.md
new file mode 100644
index 00000000..6dba5a00
--- /dev/null
+++ b/qemu_mode/README.persistent.md
@@ -0,0 +1,99 @@
+# How to use the persistent mode in AFL++'s QEMU mode
+
+## 1) Introduction
+
+Persistent mode let you fuzz your target persistently between to
+addresses - without forking for every fuzzing attempt.
+This increases the speed by a factor between x2 and x5, hence it is
+very, very valuable.
+
+The persistent mode is currently only available for x86/x86_64 targets.
+
+
+## 2) How use the persistent mode
+
+### 2.1) The START address
+
+The start of the persistent mode has to be set with AFL_QEMU_PERSISTENT_ADDR.
+
+This address must be at the start of a function or the starting address of
+basic block. This (as well as the RET address, see below) has to be defined
+in hexadecimal with the 0x prefix.
+
+If the target is compiled with position independant code (PIE/PIC), you must
+add 0x4000000000 to that address, because qemu loads to this base address.
+
+If this address is not valid, afl-fuzz will error during startup with the
+message that the forkserver was not found.
+
+
+### 2.2) the RET address
+
+The RET address 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.
+
+It is defined by setting AFL_QEMU_PERSISTENT_RET, and too 0x4000000000 has to
+be set if the target is position independant.
+
+
+### 2.3) the OFFSET
+
+If the START address is *not* the beginning of a function, and *no* RET has
+been set (so the end of the loop will be at the end of the function), the
+ESP pointer very likely has to be reset correctly.
+
+The value by which the ESP pointer has to be corrected has to set in the
+variable AFL_QEMU_PERSISTENT_RETADDR_OFFSET
+
+Now to get this value right here some help:
+1. use gdb on the target 
+2. set a breakpoint to your START address
+3. set a breakpoint to the end of the same function
+4. "run" the target with a valid commandline
+5. at the first breakpoint print the ESP value with
+```
+print $esp
+```
+6. "continue" the target until the second breakpoint
+7. again print the ESP value
+8. calculate the difference between the two values - and this is the offset
+
+
+### 2.4) resetting the register state
+
+It is very, very likely you need to reste the register state when starting
+a new loop. Because of this you 99% of the time should set
+
+AFL_QEMU_PERSISTENT_GPR=1
+
+
+## 3) optional parameters
+
+### 3.1) loop counter value
+
+The more stable your loop in the target, the longer you can run it, the more
+unstable it is the lower the loop count should be. A low value would be 100,
+the maximum value should be 10000. The default is 1000.
+This value can be set with AFL_QEMU_PERSISTENT_CNT
+
+This is the same concept as in the llvm_mode persistent mode with __AFL_LOOP().
+
+
+### 3.2) a hook for in-memory fuzzing
+
+You can increase the speed of the persistent mode even more by bypassing all
+the reading of the fuzzing input via a file by reading directly into the
+memory address space of the target process.
+
+All this needs is that the START address has a register pointing to the
+memory buffer, and another register holding the value of the read length
+(or pointing to the memory where that value is held).
+
+If the target reads from an input file you have to supply an input file
+that is of least of the size that your fuzzing input will be (and do not
+supply @@).
+
+An example that you can use with little modification for your target can
+be found here: [examples/qemu_persistent_hook](../examples/qemu_persistent_hook)
+This shared library is specified via AFL_QEMU_PERSISTENT_HOOK
+
diff --git a/test/test.sh b/test/test.sh
index 1709468e..db197cf2 100755
--- a/test/test.sh
+++ b/test/test.sh
@@ -75,7 +75,7 @@ $ECHO "${RESET}${GREY}[*] starting afl++ test framework ..."
 test -z "$SYS" && $ECHO "$YELLOW[-] uname -m did not succeed"
 
 $ECHO "$BLUE[*] Testing: ${AFL_GCC}, afl-showmap, afl-fuzz, afl-cmin and afl-tmin"
-test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" && {
+test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" && {
  test -e ../${AFL_GCC} -a -e ../afl-showmap -a -e ../afl-fuzz && {
   ../${AFL_GCC} -o test-instr.plain ../test-instr.c > /dev/null 2>&1
   AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c > /dev/null 2>&1
@@ -263,7 +263,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
       $ECHO "$RED[!] afl-fuzz is not working correctly with llvm_mode"
       CODE=1
     }
-    test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" || {
+    test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" || {
       echo 000000000000000000000000 > in/in2
       echo 111 > in/in3
       mkdir -p in2
@@ -583,7 +583,7 @@ test -e ../afl-qemu-trace && {
       }
       rm -f errors
 
-      test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" && {
+      test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" && {
         $ECHO "$GREY[*] running afl-fuzz for persistent qemu_mode, this will take approx 10 seconds"
         {
           export AFL_QEMU_PERSISTENT_ADDR=`expr 0x4$(nm test-instr | grep "T main" | awk '{print $1}' | sed 's/^.......//')`