about summary refs log tree commit diff
path: root/docs/best_practices.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/best_practices.md')
-rw-r--r--docs/best_practices.md114
1 files changed, 75 insertions, 39 deletions
diff --git a/docs/best_practices.md b/docs/best_practices.md
index 6a406bde..e6b252f6 100644
--- a/docs/best_practices.md
+++ b/docs/best_practices.md
@@ -18,7 +18,8 @@
 
 ### Fuzzing a target with source code available
 
-To learn how to fuzz a target if source code is available, see [fuzzing_in_depth.md](fuzzing_in_depth.md).
+To learn how to fuzz a target if source code is available, see
+[fuzzing_in_depth.md](fuzzing_in_depth.md).
 
 ### Fuzzing a binary-only target
 
@@ -27,11 +28,16 @@ For a comprehensive guide, see
 
 ### Fuzzing a GUI program
 
-If the GUI program can read the fuzz data from a file (via the command line, a fixed location or via an environment variable) without needing any user interaction, then it would be suitable for fuzzing.
+If the GUI program can read the fuzz data from a file (via the command line, a
+fixed location or via an environment variable) without needing any user
+interaction, then it would be suitable for fuzzing.
 
-Otherwise, it is not possible without modifying the source code - which is a very good idea anyway as the GUI functionality is a huge CPU/time overhead for the fuzzing.
+Otherwise, it is not possible without modifying the source code - which is a
+very good idea anyway as the GUI functionality is a huge CPU/time overhead for
+the fuzzing.
 
-So create a new `main()` that just reads the test case and calls the functionality for processing the input that the GUI program is using.
+So create a new `main()` that just reads the test case and calls the
+functionality for processing the input that the GUI program is using.
 
 ### Fuzzing a network service
 
@@ -40,13 +46,16 @@ Fuzzing a network service does not work "out of the box".
 Using a network channel is inadequate for several reasons:
 - it has a slow-down of x10-20 on the fuzzing speed
 - it does not scale to fuzzing multiple instances easily,
-- instead of one initial data packet often a back-and-forth interplay of packets is needed for stateful protocols (which is totally unsupported by most coverage aware fuzzers).
+- instead of one initial data packet often a back-and-forth interplay of packets
+  is needed for stateful protocols (which is totally unsupported by most
+  coverage aware fuzzers).
 
-The established method to fuzz network services is to modify the source code
-to read from a file or stdin (fd 0) (or even faster via shared memory, combine
-this with persistent mode [instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md)
-and you have a performance gain of x10 instead of a performance loss of over
-x10 - that is a x100 difference!).
+The established method to fuzz network services is to modify the source code to
+read from a file or stdin (fd 0) (or even faster via shared memory, combine this
+with persistent mode
+[instrumentation/README.persistent_mode.md](../instrumentation/README.persistent_mode.md)
+and you have a performance gain of x10 instead of a performance loss of over x10
+- that is a x100 difference!).
 
 If modifying the source is not an option (e.g., because you only have a binary
 and perform binary fuzzing) you can also use a shared library with AFL_PRELOAD
@@ -64,13 +73,25 @@ allows you to define network state with different type of data packets.
 
 ### Improving speed
 
-1. Use [llvm_mode](../instrumentation/README.llvm.md): afl-clang-lto (llvm >= 11) or afl-clang-fast (llvm >= 9 recommended).
-2. Use [persistent mode](../instrumentation/README.persistent_mode.md) (x2-x20 speed increase).
-3. Instrument just what you are interested in, see [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md).
-4. If you do not use shmem persistent mode, use `AFL_TMPDIR` to put the input file directory on a tempfs location, see [env_variables.md](env_variables.md).
-5. Improve Linux kernel performance: modify `/etc/default/grub`, set `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then `update-grub` and `reboot` (warning: makes the system less secure).
-6. Running on an `ext2` filesystem with `noatime` mount option will be a bit faster than on any other journaling filesystem.
-7. Use your cores ([fuzzing_in_depth.md:3c) Using multiple cores](fuzzing_in_depth.md#c-using-multiple-cores))!
+1. Use [llvm_mode](../instrumentation/README.llvm.md): afl-clang-lto (llvm >=
+   11) or afl-clang-fast (llvm >= 9 recommended).
+2. Use [persistent mode](../instrumentation/README.persistent_mode.md) (x2-x20
+   speed increase).
+3. Instrument just what you are interested in, see
+   [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md).
+4. If you do not use shmem persistent mode, use `AFL_TMPDIR` to put the input
+   file directory on a tempfs location, see
+   [env_variables.md](env_variables.md).
+5. Improve Linux kernel performance: modify `/etc/default/grub`, set
+   `GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off mds=off
+   mitigations=off no_stf_barrier noibpb noibrs nopcid nopti
+   nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off
+   spec_store_bypass_disable=off spectre_v2=off stf_barrier=off"`; then
+   `update-grub` and `reboot` (warning: makes the system less secure).
+6. Running on an `ext2` filesystem with `noatime` mount option will be a bit
+   faster than on any other journaling filesystem.
+7. Use your cores
+   ([fuzzing_in_depth.md:3c) Using multiple cores](fuzzing_in_depth.md#c-using-multiple-cores))!
 
 ### Improving stability
 
@@ -78,46 +99,60 @@ For fuzzing a 100% stable target that covers all edges is the best case. A 90%
 stable target that covers all edges is, however, better than a 100% stable
 target that ignores 10% of the edges.
 
-With instability, you basically have a partial coverage loss on an edge, with ignored functions you have a full loss on that edges.
+With instability, you basically have a partial coverage loss on an edge, with
+ignored functions you have a full loss on that edges.
 
 There are functions that are unstable, but also provide value to coverage, e.g.,
 init functions that use fuzz data as input. If, however, a function that has
 nothing to do with the input data is the source of instability, e.g., checking
 jitter, or is a hash map function etc., then it should not be instrumented.
 
-To be able to exclude these functions (based on AFL++'s measured stability), the following process will allow to identify functions with variable edges.
+To be able to exclude these functions (based on AFL++'s measured stability), the
+following process will allow to identify functions with variable edges.
 
-Four steps are required to do this and it also requires quite some knowledge of coding and/or disassembly and is effectively possible only with `afl-clang-fast` `PCGUARD` and `afl-clang-lto` `LTO` instrumentation.
+Four steps are required to do this and it also requires quite some knowledge of
+coding and/or disassembly and is effectively possible only with `afl-clang-fast`
+`PCGUARD` and `afl-clang-lto` `LTO` instrumentation.
 
   1. Instrument to be able to find the responsible function(s):
 
-     a) For LTO instrumented binaries, this can be documented during compile time, just set `export AFL_LLVM_DOCUMENT_IDS=/path/to/a/file`.
-        This file will have one assigned edge ID and the corresponding function per line.
-
-     b) For PCGUARD instrumented binaries, it is much more difficult. Here you can either modify the `__sanitizer_cov_trace_pc_guard` function in `instrumentation/afl-llvm-rt.o.c` to write a backtrace to a file if the ID in `__afl_area_ptr[*guard]` is one of the unstable edge IDs.
-        (Example code is already there).
-        Then recompile and reinstall `llvm_mode` and rebuild your target.
-        Run the recompiled target with `afl-fuzz` for a while and then check the file that you wrote with the backtrace information.
-        Alternatively, you can use `gdb` to hook `__sanitizer_cov_trace_pc_guard_init` on start, check to which memory address the edge ID value is written, and set a write breakpoint to that address (`watch 0x.....`).
-
-     c) In other instrumentation types, this is not possible.
-        So just recompile with the two mentioned above.
-        This is just for identifying the functions that have unstable edges.
+     a) For LTO instrumented binaries, this can be documented during compile
+        time, just set `export AFL_LLVM_DOCUMENT_IDS=/path/to/a/file`. This file
+        will have one assigned edge ID and the corresponding function per line.
+
+     b) For PCGUARD instrumented binaries, it is much more difficult. Here you
+        can either modify the `__sanitizer_cov_trace_pc_guard` function in
+        `instrumentation/afl-llvm-rt.o.c` to write a backtrace to a file if the
+        ID in `__afl_area_ptr[*guard]` is one of the unstable edge IDs. (Example
+        code is already there). Then recompile and reinstall `llvm_mode` and
+        rebuild your target. Run the recompiled target with `afl-fuzz` for a
+        while and then check the file that you wrote with the backtrace
+        information. Alternatively, you can use `gdb` to hook
+        `__sanitizer_cov_trace_pc_guard_init` on start, check to which memory
+        address the edge ID value is written, and set a write breakpoint to that
+        address (`watch 0x.....`).
+
+     c) In other instrumentation types, this is not possible. So just recompile
+        with the two mentioned above. This is just for identifying the functions
+        that have unstable edges.
 
   2. Identify which edge ID numbers are unstable.
 
      Run the target with `export AFL_DEBUG=1` for a few minutes then terminate.
      The out/fuzzer_stats file will then show the edge IDs that were identified
-     as unstable in the `var_bytes` entry. You can match these numbers
-     directly to the data you created in the first step.
-     Now you know which functions are responsible for the instability
+     as unstable in the `var_bytes` entry. You can match these numbers directly
+     to the data you created in the first step. Now you know which functions are
+     responsible for the instability
 
   3. Create a text file with the filenames/functions
 
-     Identify which source code files contain the functions that you need to remove from instrumentation, or just specify the functions you want to skip for instrumentation.
-     Note that optimization might inline functions!
+     Identify which source code files contain the functions that you need to
+     remove from instrumentation, or just specify the functions you want to skip
+     for instrumentation. Note that optimization might inline functions!
+
+     Follow this document on how to do this:
+     [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md).
 
-     Follow this document on how to do this: [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md).
      If `PCGUARD` is used, then you need to follow this guide (needs llvm 12+!):
      [https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation](https://clang.llvm.org/docs/SanitizerCoverage.html#partially-disabling-instrumentation)
 
@@ -132,4 +167,5 @@ Four steps are required to do this and it also requires quite some knowledge of
 
      Recompile, fuzz it, be happy :)
 
-     This link explains this process for [Fuzzbench](https://github.com/google/fuzzbench/issues/677).
+     This link explains this process for
+     [Fuzzbench](https://github.com/google/fuzzbench/issues/677).
\ No newline at end of file