mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-15 11:28: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 <stdio.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <string.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 g2h(x) ((void *)((unsigned long)(x) + guest_base))
|
||||||
#define h2g(x) ((uint64_t)(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
|
// 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.
|
// 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")
|
// 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;
|
if (input_len > 1024) input_len = 1024;
|
||||||
memcpy(g2h(regs[R_EDI]), input_buf, input_len);
|
memcpy(g2h(regs->rdi), input_buf, input_len);
|
||||||
regs[R_ESI] = input_len;
|
regs->rsi = input_len;
|
||||||
|
|
||||||
|
#undef g2h
|
||||||
|
#undef h2g
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -58,4 +33,3 @@ int afl_persistent_hook_init(void) {
|
|||||||
return 1;
|
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.
|
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 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.
|
Andrea Fioraldi. Special thanks to abiondo that re-enabled TCG chaining.
|
||||||
|
|
||||||
## 2) How to use
|
## 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,
|
to build it is to run ./build_qemu_support.sh. The script will download,
|
||||||
configure, and compile the QEMU binary for you.
|
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
|
If you want to specify a different path for libraries (e.g. to run an arm64
|
||||||
binary on x86_64) use QEMU_LD_PREFIX.
|
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
|
As for LLVM mode (refer to its README.md for mode details) QEMU mode supports
|
||||||
the deferred initialization.
|
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.)
|
opened (e.g. way after command line parsing and config file loading, etc.)
|
||||||
which can be a huge speed improvement.
|
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
|
AFL++'s QEMU mode now supports also persistent mode for x86, x86_64, arm
|
||||||
and aarch64 targets.
|
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)
|
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.
|
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.
|
Highly recommended.
|
||||||
|
|
||||||
## 6) CMPLOG mode
|
## 7) CMPLOG mode
|
||||||
|
|
||||||
Another new feature is CMPLOG, which is based on the redqueen project.
|
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
|
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:
|
To enable it you must pass on the command line of afl-fuzz:
|
||||||
-c /path/to/your/target
|
-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.
|
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).
|
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 feature is supported only on Linux. Supporting BSD may amount to porting
|
||||||
the changes made to linux-user/elfload.c and applying them to
|
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
|
Setting AFL_INST_LIBS=1 can be used to circumvent the .text detection logic
|
||||||
and instrument every basic block encountered.
|
and instrument every basic block encountered.
|
||||||
|
|
||||||
## 9) Benchmarking
|
## 10) Benchmarking
|
||||||
|
|
||||||
If you want to compare the performance of the QEMU instrumentation with that of
|
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
|
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
|
fairly meaningless if the optimization levels or instrumentation scopes don't
|
||||||
match.
|
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
|
If you need to fix up checksums or do other cleanup on mutated test cases, see
|
||||||
examples/custom_mutators/ for a viable solution.
|
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.
|
Beyond that, this is an early-stage mechanism, so fields reports are welcome.
|
||||||
You can send them to <afl-users@googlegroups.com>.
|
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
|
Statically rewriting binaries just once, instead of attempting to translate
|
||||||
them at run time, can be a faster alternative. That said, static rewriting is
|
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.
|
This address can be the address of whatever instruction.
|
||||||
Setting this address to the start of a function makes the usage simple.
|
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
|
If the address is however within a function, either RET, OFFSET or EXITS
|
||||||
in 2.2 and 2.3) have to be set.
|
(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
|
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.
|
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)
|
*Note:* If the target is compiled with position independant code (PIE/PIC)
|
||||||
qemu loads these to a specific base address.
|
qemu loads these to a specific base address.
|
||||||
For 64 bit you have to add 0x4000000000 (9 zeroes) and for 32 bit 0x40000000
|
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
|
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.
|
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
|
It is defined by setting AFL_QEMU_PERSISTENT_RET, and too 0x4000000000 has to
|
||||||
be set if the target is position independant.
|
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
|
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.
|
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) Optional parameters
|
||||||
|
|
||||||
### 3.1) Loop counter value
|
### 3.1) Loop counter value
|
||||||
@ -125,10 +151,25 @@ AFL_QEMU_PERSISTENT_HOOK=/path/to/hook.so.
|
|||||||
The signature is:
|
The signature is:
|
||||||
|
|
||||||
```c
|
```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.
|
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
|
An example that you can use with little modification for your target can
|
||||||
be found here: [examples/qemu_persistent_hook](../examples/qemu_persistent_hook)
|
be found here: [examples/qemu_persistent_hook](../examples/qemu_persistent_hook)
|
||||||
|
Reference in New Issue
Block a user