mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-14 11:08:06 +00:00
persistent mode doc
This commit is contained in:
@ -29,6 +29,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
|||||||
- CmpLog instrumentation for QEMU (-c afl-fuzz command line option)
|
- CmpLog instrumentation for QEMU (-c afl-fuzz command line option)
|
||||||
- AFL_PERSISTENT_HOOK callback module for persistent QEMU
|
- AFL_PERSISTENT_HOOK callback module for persistent QEMU
|
||||||
(see examples/qemu_persistent_hook)
|
(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
|
- afl-cmin is now a sh script (invoking awk) instead of bash for portability
|
||||||
the original script is still present as afl-cmin.bash
|
the original script is still present as afl-cmin.bash
|
||||||
- afl-showmap: -i dir option now allows processing multiple inputs using the
|
- afl-showmap: -i dir option now allows processing multiple inputs using the
|
||||||
|
@ -37,8 +37,12 @@ enum {
|
|||||||
|
|
||||||
void afl_persistent_hook(uint64_t* regs, uint64_t guest_base) {
|
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]);
|
printf("reading into %p\n", regs[R_EDI]);
|
||||||
size_t r = read(0, g2h(regs[R_EDI]), 1024);
|
size_t r = read(0, g2h(regs[R_EDI]), 1024);
|
||||||
|
regs[R_EAX] = r;
|
||||||
printf("readed %ld bytes\n", r);
|
printf("readed %ld bytes\n", r);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -71,31 +71,11 @@ must be an address of a basic block.
|
|||||||
|
|
||||||
## 4) Bonus feature #2: persistent mode
|
## 4) Bonus feature #2: persistent mode
|
||||||
|
|
||||||
QEMU mode supports also persistent mode for x86 and x86_64 targets.
|
AFL++'s QEMU mode now supports also persistent mode for x86 and x86_64 targets.
|
||||||
The environment variable to enable it is AFL_QEMU_PERSISTENT_ADDR=`start addr`.
|
This increases the speed by several factors, however it is a bit of work to set
|
||||||
In this variable you must specify the address of the function that
|
up - but worth the effort.
|
||||||
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.
|
Please see the extra documentation for it: [README.persistent.md](README.persistent.md)
|
||||||
|
|
||||||
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.
|
|
||||||
|
|
||||||
## 5) Bonus feature #3: CompareCoverage
|
## 5) Bonus feature #3: CompareCoverage
|
||||||
|
|
||||||
|
99
qemu_mode/README.persistent.md
Normal file
99
qemu_mode/README.persistent.md
Normal file
@ -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
|
||||||
|
|
Reference in New Issue
Block a user