• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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# ASAN Code coverage (-C) #
48In order to make this mode work, one needs to compile the fuzzed tool (_xmllint_ here) with _-fsanitize=address -fsanitize-coverage=bb_
49
50```
51$ [honggfuzz_dir]/honggfuzz -C -f IN.corpus/ -- ./xmllint --format --nonet ___FILE___
52============================== STAT ==============================
53Iterations: 1419
54Start time: 2016-03-15 16:43:57 (16 seconds elapsed)
55Input file/dir: 'IN/'
56Fuzzed cmd: './xmllint --format --nonet ___FILE___'
57Fuzzing threads: 3
58Execs per second: 41 (avg: 88)
59Crashes: 0 (unique: 0, blacklist: 0, verified: 0)
60Timeouts: 0
61Number of dynamic files: 251
62Coverage (max):
63  - total hit #bb:  8634 (coverage 11%)
64  - total #dso:     1 (instrumented only)
65  - discovered #bb: 1 (new from input seed)
66  - crashes:        0
67============================== LOGS ==============================
68[2016-03-15T16:49:00+0100][I][2094] fuzz_sanCovFeedback():463 SanCov Update: file size (Cur): 2141, newBBs:9, counters (Cur,New): 8569/1,1666/1
69```
70
71# Compile-time instrumentation with clang/gcc (default mode) #
72
73Here you can use the following:
74  * gcc/clang `-finstrument-functions` (less-precise)
75  * clang's (>= 4.0) `-fsanitize-coverage=trace-pc-guard,indirect-calls,trace-cmp`
76    (trace-cmp adds additional comparison map to the instrumentation)
77
78_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_
79
80Two persistent modes can be used here:
81
82### LLVM-style LLVMFuzzerTestOneInput ###
83
84```c
85$ cat test.c
86#include <inttypes.h>
87#include <testlib.h>  // Our API to test
88
89extern int LLVMFuzzerTestOneInput(uint8_t **buf, size_t *len);
90
91int LLVMFuzzerTestOneInput(uint8_t *buf, size_t len) {
92  _FuncFromFuzzedLib_(buf, len);
93  return 0;
94}
95```
96
97```
98$ [honggfuzz_dir]/honggfuzz/hfuzz_cc/hfuzz-clang -c fuzzedlib.c -o fuzzedlib.o
99$ [honggfuzz_dir]/honggfuzz/hfuzz_cc/hfuzz-clang test.c fuzzedlib.o -o test
100$ [honggfuzz_dir]/honggfuzz -P -f INPUT.corpus -- ./test
101```
102
103`LLVMFuzzerInitialize(int *argc, char **argv)` is supported as well
104
105### Fetching input with HF_ITER() ###
106
107```c
108$ cat test.c
109#include <inttypes.h>
110#include <testlib.h>  // Our API to test
111
112// Get input from the fuzzer
113extern void HF_ITER(uint8_t **buf, size_t *len);
114
115int main(void) {
116  for (;;) {
117    uint8_t *buf;
118    size_t len;
119    HF_ITER(&buf, &len);
120    _FuncFromFuzzedLib_(buf, len);
121  }
122  return 0;
123}
124```
125```
126$ [honggfuzz_dir]/honggfuzz/hfuzz_cc/hfuzz-clang -c fuzzedlib.c -o fuzzedlib.o
127$ [honggfuzz_dir]/honggfuzz/hfuzz_cc/hfuzz-clang test.c fuzzedlib.o -o test
128$ [honggfuzz_dir]/honggfuzz -P -f INPUT.corpus -- ./test
129```
130
131Example:
132```
133$ [honggfuzz_dir]/honggfuzz -P -f IN.server/ -- ./persistent.server.openssl.1.0.2i.asan
134------------------------------[ honggfuzz v0.8 ]------------------------------
135      Iterations : 3,275,169 [3.28M]
136        Run Time : 2 hrs 17 min 16 sec (since: 2016-09-27 07:30:04)
137       Input Dir : 'IN.server/'
138      Fuzzed Cmd : './persistent.server.openssl.1.0.2i.asan'
139 Fuzzing Threads : 2, CPUs: 8, CPU: 759.0% (94.9%/CPU)
140   Speed (Round) : 86/sec (avg: 397)
141         Crashes : 0 (unique: 0, blacklist: 0, verified: 0)
142        Timeouts : 0 [10 sec.]
143     Corpus size : 393 (max file size: 40,000 bytes)
144        Coverage :
145       *** blocks seen:    3,545, comparison map: 204,542
146-----------------------------------[ LOGS ]-----------------------------------
147```
148
149PS. 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.
150
151# Hardware-based coverage #
152## Unique branch pair (edges) counting (--linux_perf_bts_edge) ##
153
154This 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.
155
156```
157$ [honggfuzz_dir]/honggfuzz --linux_perf_bts_edge -f IN.corpus/ -- /usr/bin/xmllint -format ___FILE___
158============================== STAT ==============================
159Iterations: 1
160Start time: 2016-02-16 18:37:08 (1 seconds elapsed)
161Input file/dir: 'IN/'
162Fuzzed cmd: '/usr/bin/xmllint -format ___FILE___'
163Fuzzing threads: 2
164Execs per second: 1 (avg: 1)
165Crashes: 0 (unique: 0, blacklist: 0, verified: 0)
166Timeouts: 0
167Number of dynamic files: 251
168Coverage (max):
169  - BTS unique edges:   2341
170============================== LOGS ==============================
171[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
172```
173
174## Unique branch points counting (--linux_perf_ipt_block) ##
175
176This 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.
177
178```
179$ [honggfuzz_dir]/honggfuzz --linux_perf_ipt_block -f IN.corpus/ -- /usr/bin/xmllint -format ___FILE___
180============================== STAT ==============================
181Iterations: 0
182Start time: 2016-02-16 18:38:45 (0 seconds elapsed)
183Input file/dir: 'IN/'
184Fuzzed cmd: '/usr/bin/xmllint -format ___FILE___'
185Fuzzing threads: 2
186Execs per second: 0 (avg: 0)
187Crashes: 0 (unique: 0, blacklist: 0, verified: 0)
188Timeouts: 0
189Number of dynamic files: 251
190Coverage (max):
191  - PT unique blocks: 243
192============================== LOGS ==============================
193```
194
195## Instruction counting (--linux_perf_instr) ##
196
197This 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.
198
199```
200$ [honggfuzz_dir]/honggfuzz --linux_perf_instr -f IN.corpus -- /usr/bin/xmllint -format ___FILE___
201============================== STAT ==============================
202Iterations: 2776
203Start time: 2016-02-16 18:40:51 (3 seconds elapsed)
204Input file/dir: 'CURRENT_BEST'
205Fuzzed cmd: '/usr/bin/xmllint -format ___FILE___'
206Fuzzing threads: 2
207Execs per second: 922 (avg: 925)
208Crashes: 0 (unique: 0, blacklist: 0, verified: 0)
209Timeouts: 0
210Number of dynamic files: 251
211Coverage (max):
212  - cpu instructions:      1369752
213============================== LOGS ==============================
214[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
215[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
216[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
217[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
218```
219
220## Branch counting (--linux_perf_branch) ##
221
222As 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.
223
224```
225$ [honggfuzz_dir]/honggfuzz --linux_perf_branch -f IN/ -F 2500 -- /usr/bin/xmllint -format ___FILE___
226============================== STAT ==============================
227Iterations: 0
228Start time: 2016-02-16 18:39:41 (0 seconds elapsed)
229Input file/dir: 'IN/'
230Fuzzed cmd: '/usr/bin/xmllint -format ___FILE___'
231Fuzzing threads: 2
232Execs per second: 0 (avg: 0)
233Crashes: 0 (unique: 0, blacklist: 0, verified: 0)
234Timeouts: 0
235Number of dynamic files: 251
236Coverage (max):
237  - cpu branches:          0
238============================== LOGS ==============================
239[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
240[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
241[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
242[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
243```
244