mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 19:08:08 +00:00
doc for qemuafl
This commit is contained in:
@ -1,53 +1,28 @@
|
||||
#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;
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
Reference in New Issue
Block a user