1# Feedback-driven fuzzing # 2 3Honggfuzz is capable of performing feedback-guided (code coverage driven) fuzzing. It can utilize the following sources of data: 4 * (Linux) Hardware-based counters (instructions, branches) 5 * (Linux) Intel BTS code coverage (kernel >= 4.2) 6 * (Linux) Intel PT code coverage (kernel >= 4.2) 7 * Sanitzer-coverage instrumentation (`-fsanitize-coverage=bb`) 8 * Compile-time instrumentation (`-finstrument-functions` or `-fsanitize-coverage=trace-pc[-guard],indirect-calls,trace-cmp` or both) 9 10Developers should provide the initial file corpus which will be gradually improved upon. It can even comprise of a single 1-byte initial file, and honggfuzz will try to generate better inputs starting from there. 11 12--- 13# Requirements for software-based coverage-guided fuzzing # 14 * `-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp` - Clang >= 4.0 15 * `-fsanitize-coverage=bb` - Clang >= 3.7 16 * `-finstrument-functions` - GCC or Clang 17 * [older, slower variant] `-fsanitize-coverage=trace-pc,indirect-calls` - Clang >= 3.9 18 19_Note_: The _-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp_ set of flags will be automatically added to clang's command-line switches when using [hfuzz-clang](https://github.com/google/honggfuzz/tree/master/hfuzz_cc) binary. 20 21``` 22$ [honggfuzz_dir]/honggfuzz/hfuzz_cc/hfuzz-clang terminal-test.c -o terminal-test 23``` 24 25--- 26# Requirements for hardware-based counter-based fuzzing # 27 * GNU/Linux OS 28 * Relatively modern Linux kernel (4.2 should suffice) 29 * CPU which is supported by the [perf subsystem](https://perf.wiki.kernel.org/index.php/Main_Page) for hardware-assisted instruction and branch counting 30 31--- 32# Requirements for hardware-based coverage-feedback fuzzing (Intel) # 33 * CPU supporting [BTS (Branch Trace Store)](https://software.intel.com/en-us/forums/topic/277868?language=en) for hardware assisted unique pc and edges (branch pairs) counting. Currently it's available only in some newer Intel CPUs (unfortunately no AMD support for now) 34 * CPU supporting [Intel PT (Processor Tracing)](https://software.intel.com/en-us/blogs/2013/09/18/processor-tracing) for hardware assisted unique edge (branch pairs) counting. Currently it's available only in some newer Intel CPUs (since Broadwell architecture) 35 * GNU/Linux OS with a supported CPU; Intel Core 2 for BTS, Intel Broadwell for Intel PT 36 * Intel's [ibipt library](http://packages.ubuntu.com/yakkety/libipt1) for Intel PT 37 * Linux kernel >= v4.2 for perf AUXTRACE 38 39--- 40# Fuzzing strategy # 41The implemented strategy is trying to identify files which add new code coverage (or increased instruction/branch counters). Then those inputs are added (dynamically stored in memory) corpus, and reused during following fuzzing rounds 42 43There are 2 phases of feedback-driven the fuzzing: 44 * Honggfuzz goes through each file in the initial corpus directory (-f). It adds files which hit new code coverage to the dynamic input corpus (as well as saving them on the disk, using *COVERAGE_DATA.PID.pid.RND.time.rnd* pattern 45 * Honggfuzz choses randomly files from the dynamic input corpus (in-memory), mutates them, and runs a new fuzzing round (round in persistent mode, exec in non-persistent mode). If the newly created file induces new code path (extends code coverage), it gets added to the dynamic input corpus 46 47# Compile-time instrumentation with clang/gcc (default mode) # 48 49Here you can use the following: 50 * gcc/clang `-finstrument-functions` (less-precise) 51 * clang's (>= 4.0) `-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp` 52 (trace-cmp adds additional comparison map to the instrumentation) 53 54_Note_: The _-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp_ set of flags will be automatically added to clang's command-line switches when using [hfuzz-clang](https://github.com/google/honggfuzz/tree/master/hfuzz_cc) binary. The [hfuzz-clang](https://github.com/google/honggfuzz/tree/master/hfuzz_cc) binary will also link your code with _libhfuzz.a_ 55 56Two persistent modes can be used here: 57 58### LLVM-style LLVMFuzzerTestOneInput ### 59 60```c 61$ cat test.c 62#include <inttypes.h> 63#include <testlib.h> // Our API to test 64 65extern int LLVMFuzzerTestOneInput(uint8_t **buf, size_t *len); 66 67int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) { 68 _FuncFromFuzzedLib_(buf, len); 69 return 0; 70} 71``` 72 73``` 74$ [honggfuzz_dir]/honggfuzz/hfuzz_cc/hfuzz-clang -c fuzzedlib.c -o fuzzedlib.o 75$ [honggfuzz_dir]/honggfuzz/hfuzz_cc/hfuzz-clang test.c fuzzedlib.o -o test 76$ [honggfuzz_dir]/honggfuzz -P -f INPUT.corpus -- ./test 77``` 78 79`LLVMFuzzerInitialize(int *argc, char **argv)` is supported as well 80 81### Fetching input with HF_ITER() ### 82 83```c 84$ cat test.c 85#include <inttypes.h> 86#include <testlib.h> // Our API to test 87 88// Get input from the fuzzer 89extern void HF_ITER(uint8_t **buf, size_t *len); 90 91int main(void) { 92 for (;;) { 93 uint8_t *buf; 94 size_t len; 95 HF_ITER(&buf, &len); 96 _FuncFromFuzzedLib_(buf, len); 97 } 98 return 0; 99} 100``` 101``` 102$ [honggfuzz_dir]/honggfuzz/hfuzz_cc/hfuzz-clang -c fuzzedlib.c -o fuzzedlib.o 103$ [honggfuzz_dir]/honggfuzz/hfuzz_cc/hfuzz-clang test.c fuzzedlib.o -o test 104$ [honggfuzz_dir]/honggfuzz -P -f INPUT.corpus -- ./test 105``` 106 107Example: 108``` 109$ [honggfuzz_dir]/honggfuzz -P -f IN.server/ -- ./persistent.server.openssl.1.0.2i.asan 110------------------------------[ honggfuzz v0.8 ]------------------------------ 111 Iterations : 3,275,169 [3.28M] 112 Run Time : 2 hrs 17 min 16 sec (since: 2016-09-27 07:30:04) 113 Input Dir : 'IN.server/' 114 Fuzzed Cmd : './persistent.server.openssl.1.0.2i.asan' 115 Fuzzing Threads : 2, CPUs: 8, CPU: 759.0% (94.9%/CPU) 116 Speed (Round) : 86/sec (avg: 397) 117 Crashes : 0 (unique: 0, blacklist: 0, verified: 0) 118 Timeouts : 0 [10 sec.] 119 Corpus size : 393 (max file size: 40,000 bytes) 120 Coverage : 121 *** blocks seen: 3,545, comparison map: 204,542 122-----------------------------------[ LOGS ]----------------------------------- 123``` 124 125PS. You can also use a non-persistent mode here (without the __-P__ flag), in which case you need to read data either from a file passed at command-line (`___FILE___`), or from the standard input (e.g. with `read(0, buf, sizeof(buf))`. The compile-time instrumentation will still work in such case. 126 127# Hardware-based coverage # 128## Unique branch pair (edges) counting (--linux_perf_bts_edge) ## 129 130This mode will take into consideration pairs (tuples) of jumps, recording unique from-to jump pairs. The data is taken from the Intel BTS CPU registers. 131 132``` 133$ [honggfuzz_dir]/honggfuzz --linux_perf_bts_edge -f IN.corpus/ -- /usr/bin/xmllint -format ___FILE___ 134============================== STAT ============================== 135Iterations: 1 136Start time: 2016-02-16 18:37:08 (1 seconds elapsed) 137Input file/dir: 'IN/' 138Fuzzed cmd: '/usr/bin/xmllint -format ___FILE___' 139Fuzzing threads: 2 140Execs per second: 1 (avg: 1) 141Crashes: 0 (unique: 0, blacklist: 0, verified: 0) 142Timeouts: 0 143Number of dynamic files: 251 144Coverage (max): 145 - BTS unique edges: 2341 146============================== LOGS ============================== 147[2016-02-16T18:37:09+0100][I][14944] fuzz_perfFeedback():420 New: (Size New,Old): 257,257, Perf (Cur,New): 0/0/0/0/0/0,0/0/0/2341/0/0 148``` 149 150## Unique branch points counting (--linux_perf_ipt_block) ## 151 152This mode will utilize Interl's PT (Process Trace) subsystem, which should be way faster than BTS (Branch Trace Store), but will currently produce less precise results. 153 154``` 155$ [honggfuzz_dir]/honggfuzz --linux_perf_ipt_block -f IN.corpus/ -- /usr/bin/xmllint -format ___FILE___ 156============================== STAT ============================== 157Iterations: 0 158Start time: 2016-02-16 18:38:45 (0 seconds elapsed) 159Input file/dir: 'IN/' 160Fuzzed cmd: '/usr/bin/xmllint -format ___FILE___' 161Fuzzing threads: 2 162Execs per second: 0 (avg: 0) 163Crashes: 0 (unique: 0, blacklist: 0, verified: 0) 164Timeouts: 0 165Number of dynamic files: 251 166Coverage (max): 167 - PT unique blocks: 243 168============================== LOGS ============================== 169``` 170 171## Instruction counting (--linux_perf_instr) ## 172 173This mode tries to maximize the number of instructions taken during each process iteration. The counters will be taken from the Linux perf subsystems. Intel, AMD and even other CPU architectures are supported for this mode. 174 175``` 176$ [honggfuzz_dir]/honggfuzz --linux_perf_instr -f IN.corpus -- /usr/bin/xmllint -format ___FILE___ 177============================== STAT ============================== 178Iterations: 2776 179Start time: 2016-02-16 18:40:51 (3 seconds elapsed) 180Input file/dir: 'CURRENT_BEST' 181Fuzzed cmd: '/usr/bin/xmllint -format ___FILE___' 182Fuzzing threads: 2 183Execs per second: 922 (avg: 925) 184Crashes: 0 (unique: 0, blacklist: 0, verified: 0) 185Timeouts: 0 186Number of dynamic files: 251 187Coverage (max): 188 - cpu instructions: 1369752 189============================== LOGS ============================== 190[2016-02-16T18:40:54+0100][I][17406] fuzz_perfFeedback():420 New: (Size New,Old): 2497,2496, Perf (Cur,New): 1369752/0/0/0/0/0,1371747/0/0/0/0/0 191[2016-02-16T18:40:54+0100][I][17406] fuzz_perfFeedback():420 New: (Size New,Old): 2497,2497, Perf (Cur,New): 1371747/0/0/0/0/0,1372273/0/0/0/0/0 192[2016-02-16T18:40:54+0100][I][17406] fuzz_perfFeedback():420 New: (Size New,Old): 2497,2497, Perf (Cur,New): 1372273/0/0/0/0/0,1372390/0/0/0/0/0 193[2016-02-16T18:40:54+0100][I][17406] fuzz_perfFeedback():420 New: (Size New,Old): 2497,2497, Perf (Cur,New): 1372390/0/0/0/0/0,1372793/0/0/0/0/0 194``` 195 196## Branch counting (--linux_perf_branch) ## 197 198As above, it will try to maximize the number of branches taken by CPU on behalf of the fuzzed process (here: djpeg.static) while performing each fuzzing iteration. Intel, AMD and even other CPU architectures are supported for this mode. 199 200``` 201$ [honggfuzz_dir]/honggfuzz --linux_perf_branch -f IN/ -F 2500 -- /usr/bin/xmllint -format ___FILE___ 202============================== STAT ============================== 203Iterations: 0 204Start time: 2016-02-16 18:39:41 (0 seconds elapsed) 205Input file/dir: 'IN/' 206Fuzzed cmd: '/usr/bin/xmllint -format ___FILE___' 207Fuzzing threads: 2 208Execs per second: 0 (avg: 0) 209Crashes: 0 (unique: 0, blacklist: 0, verified: 0) 210Timeouts: 0 211Number of dynamic files: 251 212Coverage (max): 213 - cpu branches: 0 214============================== LOGS ============================== 215[2016-02-16T18:39:41+0100][I][16738] fuzz_perfFeedback():420 New: (Size New,Old): 2500,2500, Perf (Cur,New): 0/0/0/0/0/0,0/258259/0/0/0/0 216[2016-02-16T18:39:41+0100][I][16738] fuzz_perfFeedback():420 New: (Size New,Old): 2500,2500, Perf (Cur,New): 0/258259/0/0/0/0,0/258260/0/0/0/0 217[2016-02-16T18:39:41+0100][I][16738] fuzz_perfFeedback():420 New: (Size New,Old): 2500,2500, Perf (Cur,New): 0/258260/0/0/0/0,0/258261/0/0/0/0 218[2016-02-16T18:39:41+0100][I][16738] fuzz_perfFeedback():420 New: (Size New,Old): 2500,2500, Perf (Cur,New): 0/258261/0/0/0/0,0/258263/0/0/0/0 219``` 220