about summary refs log tree commit diff
path: root/qemu_mode
diff options
context:
space:
mode:
Diffstat (limited to 'qemu_mode')
-rw-r--r--qemu_mode/README.md30
-rw-r--r--qemu_mode/README.persistent.md99
2 files changed, 104 insertions, 25 deletions
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
+