xref: /aosp_15_r20/external/AFLplusplus/docs/FAQ.md (revision 08b48e0b10e97b33e7b60c5b6e2243bd915777f2)
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