doc for qemuafl
MODIFY
examples/qemu_persistent_hook/read_into_rdi.c
examples/qemu_persistent_hook/read_into_rdi.c
-#include <stdint.h>
+#include "../../qemu_mode/qemuafl/qemuafl/api.h"
+
#include <stdio.h>
-#include <unistd.h>
#include <string.h>
+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;
}
-

MODIFY
qemu_mode/README.md
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 <afl-users@googlegroups.com>.
-## 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

MODIFY
qemu_mode/README.persistent.md
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)

doc for qemuafl