1# How to use the persistent mode in AFL++'s QEMU mode
2
3## 1) Introduction
4
5Persistent mode lets you fuzz your target persistently between two
6addresses - without forking for every fuzzing attempt.
7This increases the speed by a factor between x2 and x5, hence it is
8very, very valuable.
9
10The persistent mode is currently only available for x86/x86_64, arm
11and aarch64 targets.
12
13## 2) How use the persistent mode
14
15### 2.1) The START address
16
17The start of the persistent loop has to be set with env var AFL_QEMU_PERSISTENT_ADDR.
18
19This address can be the address of whatever instruction.
20Setting this address to the start of a function makes the usage simple.
21If the address is however within a function, either RET, OFFSET or EXITS
22(see below in 2.2, 2.3, 2.6) have to be set.
23This address (as well as the RET address, see below) has to be defined in
24hexadecimal with the 0x prefix or as a decimal value.
25
26If both RET and EXITS are not set, QEMU will assume that START points to a
27function and will patch the return address (on stack or in the link register)
28to return to START (like WinAFL).
29
30*Note:* If the target is compiled with position independant code (PIE/PIC)
31qemu loads these to a specific base address.
32For 64 bit you have to add 0x4000000000 (9 zeroes) and for 32 bit 0x40000000
33(7 zeroes) to the address.
34On strange setups the base address set by QEMU for PIE executable may change,
35you can check it printing the process map using
36`AFL_QEMU_DEBUG_MAPS=1 afl-qemu-trace TARGET-BINARY`
37
38If this address is not valid, afl-fuzz will error during startup with the
39message that the forkserver was not found.
40
41### 2.2) The RET address
42
43The RET address is the last instruction of the persistent loop.
44The emulator will emit a jump to START when translating the instruction at RET.
45It is optional, and only needed if the return should not be
46at the end of the function to which the START address points into, but earlier.
47
48It is defined by setting AFL_QEMU_PERSISTENT_RET, and too 0x4000000000 has to
49be set if the target is position independant.
50
51### 2.3) The OFFSET
52
53This option is valid only for x86/x86_64 only, arm/aarch64 do not save the
54return address on stack.
55
56If the START address is *not* the beginning of a function, and *no* RET has
57been set (so the end of the loop will be at the end of the function but START
58will not be at the beginning of it), we need an offset from the ESP pointer
59to locate the return address to patch.
60
61The value by which the ESP pointer has to be corrected has to be set in the
62variable AFL_QEMU_PERSISTENT_RETADDR_OFFSET.
63
64Now to get this value right here is some help:
651. use gdb on the target
662. set a breakpoint to "main" (this is required for PIE/PIC binaries so the
67   addresses are set up)
683. "run" the target with a valid commandline
694. set a breakpoint to the function in which START is contained
705. set a breakpoint to your START address
716. "continue" to the function start breakpoint
726. print the ESP value with `print $esp` and take note of it
737. "continue" the target until the second breakpoint
748. again print the ESP value
759. calculate the difference between the two values - and this is the offset
76
77### 2.4) Resetting the register state
78
79It is very, very likely you need to restore the general purpose registers state
80when starting a new loop. Because of this 99% of the time you should set
81
82AFL_QEMU_PERSISTENT_GPR=1
83
84An example is when you want to use main() as persistent START:
85
86```c
87int main(int argc, char **argv) {
88
89  if (argc < 2) return 1;
90
91  // do stuff
92
93}
94```
95
96If you don't save and restore the registers in x86_64, the parameter `argc`
97will be lost at the second execution of the loop.
98
99### 2.5) Resetting the memory state
100
101This option restores the memory state using the AFL++ Snapshot LKM if loaded.
102Otherwise, all the writeable pages are restored.
103
104To enable this option, set AFL_QEMU_PERSISTENT_MEM=1.
105
106### 2.6) Reset on exit()
107
108The user can force QEMU to set the program counter to START instead of executing
109the exit_group syscall and exit the program.
110
111The env variable is AFL_QEMU_PERSISTENT_EXITS.
112
113### 2.7) Snapshot
114
115AFL_QEMU_SNAPSHOT=address is just a "syntactical sugar" env variable that is equivalent to
116the following set of variables:
117
118```
119AFL_QEMU_PERSISTENT_ADDR=address
120AFL_QEMU_PERSISTENT_GPR=1
121AFL_QEMU_PERSISTENT_MEM=1
122AFL_QEMU_PERSISTENT_EXITS=1
123```
124
125## 3) Optional parameters
126
127### 3.1) Loop counter value
128
129The more stable your loop in the target, the longer you can run it, the more
130unstable it is the lower the loop count should be. A low value would be 100,
131the maximum value should be 10000. The default is 1000.
132This value can be set with AFL_QEMU_PERSISTENT_CNT
133
134This is the same concept as in the llvm_mode persistent mode with __AFL_LOOP().
135
136### 3.2) A hook for in-memory fuzzing
137
138You can increase the speed of the persistent mode even more by bypassing all
139the reading of the fuzzing input via a file by reading directly into the
140memory address space of the target process.
141
142All this needs is that the START address has a register that can reach the
143memory buffer or that the memory buffer is at a known location. You probably need
144the value of the size of the buffer (maybe it is in a register when START is
145hit).
146
147The persistent hook will execute a function on every persistent iteration
148(at the start START) defined in a shared object specified with
149AFL_QEMU_PERSISTENT_HOOK=/path/to/hook.so.
150
151The signature is:
152
153```c
154void afl_persistent_hook(struct ARCH_regs *regs,
155                         uint64_t guest_base,
156                         uint8_t *input_buf,
157                         uint32_t input_buf_len);
158```
159
160Where ARCH is one of x86, x86_64, arm or arm64.
161You have to include `path/to/qemuafl/qemuafl/api.h`.
162
163In this hook, you can inspect and change the saved GPR state at START.
164
165You can also initialize your data structures when QEMU loads the shared object
166with:
167
168`int afl_persistent_hook_init(void);`
169
170If this routine returns true, the shared mem fuzzing feature of AFL++ is used
171and so the input_buf variables of the hook becomes meaningful. Otherwise,
172you have to read the input from a file like stdin.
173
174An example that you can use with little modification for your target can
175be found here: [utils/qemu_persistent_hook](../utils/qemu_persistent_hook)
176