使用go-fuzz进行简单的fuzzing实践

go环境配置

具体参考

1
https://golang.org/doc/install

以我当时为例

1
2
3
4
5
wget https://golang.org/dl/go1.17.2.linux-amd64.tar.gz
rm -rf /usr/local/go && tar -C /usr/local -xzf go1.17.2.linux-amd64.tar.gz

# 下面的最好放到.bashrc里面(我用的Ubuntu)
export PATH=$PATH:/usr/local/go/bin:~/go/bin

其他注意事项:

go1.16以后,默认需要提供go.mod,我们可以设置环境变量GO111MODULE为auto让其自动

1
go env -w GO111MODULE=auto

例子实践

源码:

1
2
3
4
5
6
7
8
9
10
11
12
$ cat png.go 
package png

import (
"bytes"
"image/png"
)

func Fuzz(data []byte) int {
png.Decode(bytes.NewReader(data))
return 0
}

在文件目录执行go-fuzz-build,就会生成png-fuzz.zip

之后直接运行go-fuzz命令即可

1
2
3
4
5
$ go-fuzz
2021/11/03 09:21:10 workers: 1, corpus: 25 (0s ago), crashers: 0, restarts: 1/0, execs: 0 (0/sec), cover: 0, uptime: 3s
2021/11/03 09:21:13 workers: 1, corpus: 27 (2s ago), crashers: 0, restarts: 1/0, execs: 0 (0/sec), cover: 187, uptime: 6s
2021/11/03 09:21:16 workers: 1, corpus: 27 (5s ago), crashers: 0, restarts: 1/6770, execs: 40621 (4513/sec), cover: 191, uptime: 9s
2021/11/03 09:21:19 workers: 1, corpus: 27 (8s ago), crashers: 0, restarts: 1/8809, execs: 88095 (7341/sec), cover: 191, uptime: 12s

不过最好指定一下输出路径:

1
go-fuzz -workdir output

还有一种是以libfuzzer的支持

1
2
go-fuzz-build -libfuzzer -o png.a
clang -fsanitize=fuzzer png.a -o png.libfuzzer

之后把png.libfuzzer运行就可以了

1
2
3
4
5
6
7
8
9
10
$ ./png.libfuzzer 
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 4139029883
INFO: 65536 Extra Counters
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 4096 bytes
INFO: A corpus is not provided, starting from an empty corpus
#2 INITED ft: 27 corp: 1/1b exec/s: 0 rss: 29Mb
#414 NEW ft: 34 corp: 2/9b lim: 8 exec/s: 0 rss: 30Mb L: 8/8 MS: 2 InsertByte-InsertRepeatedBytes-
#262144 pulse ft: 34 corp: 2/9b lim: 2611 exec/s: 87381 rss: 35Mb
#524288 pulse ft: 34 corp: 2/9b lim: 4096 exec/s: 74898 rss: 35Mb

当然是用corpus会有更好的覆盖率,corpus可以从github.com/dvyukov/go-fuzz-corpus获取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
$ ./png.libfuzzer ./go-fuzz-corpus/png/corpus/
INFO: Running with entropic power schedule (0xFF, 100).
INFO: Seed: 4180837821
INFO: 65536 Extra Counters
INFO: 441 files found in ./go-fuzz-corpus/png/corpus/
INFO: -max_len is not provided; libFuzzer will not generate inputs larger than 294915 bytes
INFO: seed corpus: files: 441 min: 1b max: 294915b total: 4508226b rss: 29Mb
#442 INITED ft: 3197 corp: 328/2959Kb exec/s: 0 rss: 47Mb
#476 REDUCE ft: 3197 corp: 328/2959Kb lim: 294915 exec/s: 0 rss: 47Mb L: 134/294915 MS: 4 ChangeByte-ChangeBit-ShuffleBytes-EraseBytes-
#1957 REDUCE ft: 3197 corp: 328/2959Kb lim: 294915 exec/s: 0 rss: 48Mb L: 64/294915 MS: 1 EraseBytes-
#2283 REDUCE ft: 3197 corp: 328/2959Kb lim: 294915 exec/s: 0 rss: 49Mb L: 15997/294915 MS: 1 EraseBytes-
#2629 REDUCE ft: 3197 corp: 328/2959Kb lim: 294915 exec/s: 2629 rss: 49Mb L: 2182/294915 MS: 1 EraseBytes-
#5131 REDUCE ft: 3197 corp: 328/2958Kb lim: 294915 exec/s: 5131 rss: 50Mb L: 329/294915 MS: 2 CrossOver-EraseBytes-
#5372 REDUCE ft: 3197 corp: 328/2958Kb lim: 294915 exec/s: 5372 rss: 50Mb L: 48/294915 MS: 1 EraseBytes-
#5388 REDUCE ft: 3197 corp: 328/2958Kb lim: 294915 exec/s: 5388 rss: 50Mb L: 93/294915 MS: 1 EraseBytes-
#5464 NEW ft: 3198 corp: 329/2958Kb lim: 294915 exec/s: 5464 rss: 50Mb L: 75/294915 MS: 1 CopyPart-
#5695 REDUCE ft: 3198 corp: 329/2958Kb lim: 294915 exec/s: 2847 rss: 50Mb L: 31/294915 MS: 1 EraseBytes-
#7537 REDUCE ft: 3198 corp: 329/2958Kb lim: 294915 exec/s: 3768 rss: 50Mb L: 92/294915 MS: 2 ChangeBit-EraseBytes-
#7693 REDUCE ft: 3198 corp: 329/2958Kb lim: 294915 exec/s: 3846 rss: 50Mb L: 9059/294915 MS: 5 CrossOver-CrossOver-CrossOver-InsertByte-EraseBytes-
#8192 pulse ft: 3198 corp: 329/2958Kb lim: 294915 exec/s: 4096 rss: 50Mb
#8239 REDUCE ft: 3198 corp: 329/2958Kb lim: 294915 exec/s: 4119 rss: 50Mb L: 110/294915 MS: 1 EraseBytes-
#8491 REDUCE ft: 3198 corp: 329/2958Kb lim: 294915 exec/s: 4245 rss: 50Mb L: 114/294915 MS: 2 ChangeASCIIInt-EraseBytes-
#9009 REDUCE ft: 3198 corp: 329/2954Kb lim: 294915 exec/s: 4504 rss: 50Mb L: 14101/294915 MS: 3 ChangeASCIIInt-ChangeByte-EraseBytes-

假如要fuzz gif,改成下面即可,其他图片库类似

1
2
3
4
5
6
7
8
9
10
11
package gif 

import (
"bytes"
"image/gif"
)

func Fuzz(data []byte) int {
gif.Decode(bytes.NewReader(data))
return 0
}
自愿打赏专区