aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
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/^.......//')`