1# Frequently asked questions (FAQ) 2 3If you find an interesting or important question missing, submit it via 4[https://github.com/AFLplusplus/AFLplusplus/discussions](https://github.com/AFLplusplus/AFLplusplus/discussions). 5 6## General 7 8<details> 9 <summary id="what-is-the-difference-between-afl-and-aflplusplus">What is the difference between AFL and AFL++?</summary><p> 10 11 AFL++ is a superior fork to Google's AFL - more speed, more and better 12 mutations, more and better instrumentation, custom module support, etc. 13 14 American Fuzzy Lop (AFL) was developed by Michał "lcamtuf" Zalewski starting 15 in 2013/2014, and when he left Google end of 2017 he stopped developing it. 16 17 At the end of 2019, the Google fuzzing team took over maintenance of AFL, 18 however, it is only accepting PRs from the community and is not developing 19 enhancements anymore. 20 21 In the second quarter of 2019, 1 1/2 years later, when no further development 22 of AFL had happened and it became clear there would none be coming, AFL++ was 23 born, where initially community patches were collected and applied for bug 24 fixes and enhancements. Then from various AFL spin-offs - mostly academic 25 research - features were integrated. This already resulted in a much advanced 26 AFL. 27 28 Until the end of 2019, the AFL++ team had grown to four active developers 29 which then implemented their own research and features, making it now by far 30 the most flexible and feature rich guided fuzzer available as open source. And 31 in independent fuzzing benchmarks it is one of the best fuzzers available, 32 e.g., 33 [Fuzzbench Report](https://www.fuzzbench.com/reports/2020-08-03/index.html). 34</p></details> 35 36<details> 37 <summary id="is-afl-a-whitebox-graybox-or-blackbox-fuzzer">Is AFL++ a whitebox, graybox, or blackbox fuzzer?</summary><p> 38 39 The definition of the terms whitebox, graybox, and blackbox fuzzing varies 40 from one source to another. For example, "graybox fuzzing" could mean 41 binary-only or source code fuzzing, or something completely different. 42 Therefore, we try to avoid them. 43 44 [The Fuzzing Book](https://www.fuzzingbook.org/html/GreyboxFuzzer.html#AFL:-An-Effective-Greybox-Fuzzer) 45 describes the original AFL to be a graybox fuzzer. In that sense, AFL++ is 46 also a graybox fuzzer. 47</p></details> 48 49<details> 50 <summary id="where-can-i-find-tutorials">Where can I find tutorials?</summary><p> 51 52 We compiled a list of tutorials and exercises, see 53 [tutorials.md](tutorials.md). 54</p></details> 55 56<details> 57 <summary id="what-is-an-edge">What is an "edge"?</summary><p> 58 59 A program contains `functions`, `functions` contain the compiled machine code. 60 The compiled machine code in a `function` can be in a single or many `basic 61 blocks`. A `basic block` is the **largest possible number of subsequent machine 62 code instructions** that has **exactly one entry point** (which can be be entered by 63 multiple other basic blocks) and runs linearly **without branching or jumping to 64 other addresses** (except at the end). 65 66 ``` 67 function() { 68 A: 69 some 70 code 71 B: 72 if (x) goto C; else goto D; 73 C: 74 some code 75 goto E 76 D: 77 some code 78 goto B 79 E: 80 return 81 } 82 ``` 83 84 Every code block between two jump locations is a `basic block`. 85 86 An `edge` is then the unique relationship between two directly connected 87 `basic blocks` (from the code example above): 88 89 ``` 90 Block A 91 | 92 v 93 Block B <------+ 94 / \ | 95 v v | 96 Block C Block D --+ 97 \ 98 v 99 Block E 100 ``` 101 102 Every line between two blocks is an `edge`. Note that a few basic block loop 103 to itself, this too would be an edge. 104</p></details> 105 106<details> 107 <summary id="should-you-ever-stop-afl-fuzz-minimize-the-corpus-and-restart">Should you ever stop afl-fuzz, minimize the corpus and restart?</summary><p> 108 109 To stop afl-fuzz, minimize it's corpus and restart you would usually do: 110 111 ``` 112 Control-C # to terminate afl-fuzz 113 $ afl-cmin -T nproc -i out/default/queue -o minimized_queue -- ./target 114 $ AFL_FAST_CAL=1 AFL_CMPLOG_ONLY_NEW=1 afl-fuzz -i minimized_queue -o out2 [other options] -- ./target 115 ``` 116 117 If this improves fuzzing or not is debated and no consensus has been reached 118 or in-depth analysis been performed. 119 120 On the pro side: 121 * The queue/corpus is reduced (up to 20%) by removing intermediate paths 122 that are maybe not needed anymore. 123 124 On the con side: 125 * Fuzzing time is lost for the time the fuzzing is stopped, minimized and 126 restarted. 127 128 The the big question: 129 * Does a minimized queue/corpus improve finding new coverage or does it 130 hinder it? 131 132 The AFL++ team's own limited analysis seem to to show that keeping 133 intermediate paths help to find more coverage, at least for afl-fuzz. 134 135 For honggfuzz in comparison it is a good idea to restart it from time to 136 time if you have other fuzzers (e.g: AFL++) running in parallel to sync 137 the finds of other fuzzers to honggfuzz as it has no syncing feature like 138 AFL++ or libfuzzer. 139 140</p></details> 141 142## Targets 143 144<details> 145 <summary id="how-can-i-fuzz-a-binary-only-target">How can I fuzz a binary-only target?</summary><p> 146 147 AFL++ is a great fuzzer if you have the source code available. 148 149 However, if there is only the binary program and no source code available, 150 then the standard non-instrumented mode is not effective. 151 152 To learn how these binaries can be fuzzed, read 153 [fuzzing_binary-only_targets.md](fuzzing_binary-only_targets.md). 154</p></details> 155 156<details> 157 <summary id="how-can-i-fuzz-a-network-service">How can I fuzz a network service?</summary><p> 158 159 The short answer is - you cannot, at least not "out of the box". 160 161 For more information on fuzzing network services, see 162 [best_practices.md#fuzzing-a-network-service](best_practices.md#fuzzing-a-network-service). 163</p></details> 164 165<details> 166 <summary id="how-can-i-fuzz-a-gui-program">How can I fuzz a GUI program?</summary><p> 167 168 Not all GUI programs are suitable for fuzzing. If the GUI program can read the 169 fuzz data from a file without needing any user interaction, then it would be 170 suitable for fuzzing. 171 172 For more information on fuzzing GUI programs, see 173 [best_practices.md#fuzzing-a-gui-program](best_practices.md#fuzzing-a-gui-program). 174</p></details> 175 176## Performance 177 178<details> 179 <summary id="what-makes-a-good-performance">What makes a good performance?</summary><p> 180 181 Good performance generally means "making the fuzzing results better". This can 182 be influenced by various factors, for example, speed (finding lots of paths 183 quickly) or thoroughness (working with decreased speed, but finding better 184 mutations). 185</p></details> 186 187<details> 188 <summary id="how-can-i-improve-the-fuzzing-speed">How can I improve the fuzzing speed?</summary><p> 189 190 There are a few things you can do to improve the fuzzing speed, see 191 [best_practices.md#improving-speed](best_practices.md#improving-speed). 192</p></details> 193 194<details> 195 <summary id="why-is-my-stability-below-100percent">Why is my stability below 100%?</summary><p> 196 197 Stability is measured by how many percent of the edges in the target are 198 "stable". Sending the same input again and again should take the exact same 199 path through the target every time. If that is the case, the stability is 200 100%. 201 202 If, however, randomness happens, e.g., a thread reading other external data, 203 reaction to timing, etc., then in some of the re-executions with the same data 204 the edge coverage result will be different across runs. Those edges that 205 change are then flagged "unstable". 206 207 The more "unstable" edges there are, the harder it is for AFL++ to identify 208 valid new paths. 209 210 If you fuzz in persistent mode (`AFL_LOOP` or `LLVMFuzzerTestOneInput()` 211 harnesses, a large number of unstable edges can mean that the target keeps 212 internal state and therefore it is possible that crashes cannot be replayed. 213 In such a case do either **not** fuzz in persistent mode (remove `AFL_LOOP()` 214 from your harness or call `LLVMFuzzerTestOneInput()` harnesses with `@@`), 215 or set a low `AFL_LOOP` value, e.g. 100, and enable `AFL_PERSISTENT_RECORD` 216 in `config.h` with the same value. 217 218 A value above 90% is usually fine and a value above 80% is also still ok, and 219 even a value above 20% can still result in successful finds of bugs. However, 220 it is recommended that for values below 90% or 80% you should take 221 countermeasures to improve stability. 222 223 For more information on stability and how to improve the stability value, see 224 [best_practices.md#improving-stability](best_practices.md#improving-stability). 225</p></details> 226 227<details> 228 <summary id="what-are-power-schedules">What are power schedules?</summary><p> 229 230 Not every item in our queue/corpus is the same, some are more interesting, 231 others provide little value. 232 A power schedule measures how "interesting" a value is, and depending on 233 the calculated value spends more or less time mutating it. 234 235 AFL++ comes with several power schedules, initially ported from 236 [AFLFast](https://github.com/mboehme/aflfast), however, modified to be more 237 effective and several more modes added. 238 239 The most effective modes are `-p fast` (default) and `-p explore`. 240 241 If you fuzz with several parallel afl-fuzz instances, then it is beneficial 242 to assign a different schedule to each instance, however the majority should 243 be `fast` and `explore`. 244 245 It does not make sense to explain the details of the calculation and 246 reasoning behind all of the schedules. If you are interested, read the source 247 code and the AFLFast paper. 248</p></details> 249 250## Troubleshooting 251 252<details> 253 <summary id="fatal-forkserver-is-already-up-but-an-instrumented-dlopen-library-loaded-afterwards">FATAL: forkserver is already up but an instrumented dlopen library loaded afterwards</summary><p> 254 255 It can happen that you see this error on startup when fuzzing a target: 256 257 ``` 258 [-] FATAL: forkserver is already up, but an instrumented dlopen() library 259 loaded afterwards. You must AFL_PRELOAD such libraries to be able 260 to fuzz them or LD_PRELOAD to run outside of afl-fuzz. 261 To ignore this set AFL_IGNORE_PROBLEMS=1. 262 ``` 263 264 As the error describes, a dlopen() call is happening in the target that is 265 loading an instrumented library after the forkserver is already in place. This 266 is a problem for afl-fuzz because when the forkserver is started, we must know 267 the map size already and it can't be changed later. 268 269 The best solution is to simply set `AFL_PRELOAD=foo.so` to the libraries that 270 are dlopen'ed (e.g., use `strace` to see which), or to set a manual forkserver 271 after the final dlopen(). 272 273 If this is not a viable option, you can set `AFL_IGNORE_PROBLEMS=1` but then 274 the existing map will be used also for the newly loaded libraries, which 275 allows it to work, however, the efficiency of the fuzzing will be partially 276 degraded. Note that there is additionally `AFL_IGNORE_PROBLEMS_COVERAGE` to 277 additionally tell AFL++ to ignore any coverage from the late loaded libaries. 278</p></details> 279 280<details> 281 <summary id="i-got-a-weird-compile-error-from-clang">I got a weird compile error from clang.</summary><p> 282 283 If you see this kind of error when trying to instrument a target with 284 afl-cc/afl-clang-fast/afl-clang-lto: 285 286 ``` 287 /prg/tmp/llvm-project/build/bin/clang-13: symbol lookup error: /usr/local/bin/../lib/afl//cmplog-instructions-pass.so: undefined symbol: _ZNK4llvm8TypeSizecvmEv 288 clang-13: error: unable to execute command: No such file or directory 289 clang-13: error: clang frontend command failed due to signal (use -v to see invocation) 290 clang version 13.0.0 (https://github.com/llvm/llvm-project 1d7cf550721c51030144f3cd295c5789d51c4aad) 291 Target: x86_64-unknown-linux-gnu 292 Thread model: posix 293 InstalledDir: /prg/tmp/llvm-project/build/bin 294 clang-13: note: diagnostic msg: 295 ******************** 296 ``` 297 298 Then this means that your OS updated the clang installation from an upgrade 299 package and because of that the AFL++ llvm plugins do not match anymore. 300 301 Solution: `git pull ; make clean install` of AFL++. 302</p></details> 303 304<details> 305 <summary id="afl-map-size-warning">AFL++ map size warning.</summary><p> 306 307 When you run a large instrumented program stand-alone or via afl-showmap 308 you might see a warning like the following: 309 310 ``` 311 Warning: AFL++ tools might need to set AFL_MAP_SIZE to 223723 to be able to run this instrumented program if this crashes! 312 ``` 313 314 Depending how the target works it might also crash afterwards. 315 316 Solution: just do an `export AFL_MAP_SIZE=(the value in the warning)`. 317</p></details> 318 319<details> 320 <summary id="linker-errors">Linker errors.</summary><p> 321 322 If you compile C++ harnesses and see `undefined reference` errors for 323 variables named `__afl_...`, e.g.: 324 325 ``` 326 /usr/bin/ld: /tmp/test-d3085f.o: in function `foo::test()': 327 test.cpp:(.text._ZN3fooL4testEv[_ZN3fooL4testEv]+0x35): undefined reference to `foo::__afl_connected' 328 clang: error: linker command failed with exit code 1 (use -v to see invocation) 329 ``` 330 331 Then you use AFL++ macros like `__AFL_LOOP` within a namespace and this 332 will not work. 333 334 Solution: Move that harness portion to the global namespace, e.g. before: 335 ``` 336 #include <cstdio> 337 namespace foo { 338 static void test() { 339 while(__AFL_LOOP(1000)) { 340 foo::function(); 341 } 342 } 343 } 344 345 int main(int argc, char** argv) { 346 foo::test(); 347 return 0; 348 } 349 ``` 350 after: 351 ``` 352 #include <cstdio> 353 static void mytest() { 354 while(__AFL_LOOP(1000)) { 355 foo::function(); 356 } 357 } 358 namespace foo { 359 static void test() { 360 mytest(); 361 } 362 } 363 int main(int argc, char** argv) { 364 foo::test(); 365 return 0; 366 } 367 ``` 368</p></details> 369