golang

go-fuzz随机测试工具快速上手

最近在使用go-fuzz工具进行模糊化测试,记录一下使用过程和理解。

安装

先确认本机有基础的golang环境,在此基础上,运行下列命令下载代码包

$ go get -u github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build

完成上述下载源码包后已经可以开始fuzz操作了,官方的go-fuzz-corpus仓库提供了很多的示例可以参考,对fuzz不熟悉可以执行下列操作进行熟悉。

$ go get -d github.com/dvyukov/go-fuzz-corpus
$ cd $GOPATH/src/github.com/dvyukov/go-fuzz-corpus
$ cd png
$ go-fuzz-build

上述是进入一个png示例库,执行go-fuzz-build生成对应的zip文件。文件生成完成后就可以直接执行go-fuzz操作,不过建议先执行go-fuzz -h查看具体命令行参数,限制下cpu之类的,防止机器cpu拉满,风扇转的飞起。

$ go-fuzz

项目组织

上一节中有看到png库里的示例,或者其他示例,目录下一般有gen文件夹与corpus文件夹,以及一个fuzz.go文件。
corpus文件夹里用来收集输入语料库,可以放入初始语料,例如单元测试时的测试用例,也可以使用gen中写程序来生成。
gen文件夹中写个main.go文件,主要用来生成语料库,示例可以看示例库的文件,写完后执行。

$ go run main.go -out ../corpus/

执行fuzz

go-fuzz执行需要一个函数来作为入口,即:

func Fuzz(data []byte) int

示例,本文用iprange库进行测试。

package iprange

func Fuzz(data []byte)int{
    _,err := ParseList(string(data))
    if err != nil{
    return 0
    }
    return 1
}

返回的int,有三种,1代表会提高此类输入的优先级,-1代表此类输入不会加入语料,0就是其他情况。

run起来后,注意,go-fuzz是无限循环,所以需要自己手动停止,如果产生了crash,那么在当前目录下的crashers会有三个输出文件,一个无后缀,一个后缀为.output,一个后缀为.quoted

$ ls 
17ee301be06245aa20945bc3ff3c4838abe13b52
17ee301be06245aa20945bc3ff3c4838abe13b52.output
17ee301be06245aa20945bc3ff3c4838abe13b52.quted

分别查看下三个文件内容:

$ cat 17ee301be06245aa20945bc3ff3c4838abe13b52
0.0.0.0/40%

上述可见是导致crash的输入内容。

$ cat 17ee301be06245aa20945bc3ff3c4838abe13b52.output
panic: runtime error: index out of range [3] with length 0

goroutine 1 [running]:
encoding/binary.bigEndian.Uint32(...)
    /usr/local/go/src/encoding/binary/binary.go:112
_/***/iprange.(*ipParserImpl).Parse(0xc000093200, 0x11301e0, 0xc000115400, 
...
exit status 2%

output文件是详细的错误追踪记录。

$ cat 17ee301be06245aa20945bc3ff3c4838abe13b52.quoted
    "0.0.0.0/40"

quoted文件也是倒置crash的输入内容。

Leave a Reply

Your email address will not be published.

five + eight =