honggfuzz在对输入文件进行变异前,会先创建个临时文件名(honggfuzz pid time),然后将输入数据变异后写入临时文件。
fuzz策略的实现主要集中在mangle.c中,在循环的fuzzloop函数中,会根据用户的选择的fuzz方式来调用动态fuzz或者静态fuzz的方法,但最后都是调用mangle_mangleContent来变异文件数据:
跟进mangle_mangleContent函数:
重点就在于后半部分,它会随机选择变异函数进行处理,更改的字节数也是随机的,根据用户指定的mutation变异率来定,即允许变异文件大小的百分比,变异函数列表如下:
这些函数都是在mangle_init中初始化,各函数之间也会相互调用:
把这些函数过一遍就是honggfuzz中所有的文件变异规则了,如果想实现自己的fuzzer,这些规则来扣出来用Python实现一遍,顺便把afl的规则也扣过来就更完美了,下面是我之前写office fuzzer时的半成品代码,最后偷懒直接用radamas去实现变异了:
再回到刚才的变异函数列表,我们一个个走读源码。
1、mangle_Resize函数:
用空格填充随机位置
2、mangle_Byte函数:
向随机位置写随机的uint8类型的数据
3、mangle_Bit函数:
取随机位置的数值做位翻转
4、mangle_Bytes函数:
在随机位置覆盖写2~4字节数据
5、mangle_Magic函数:
取各种边界值进行覆写,这些边界值部分跟AFL还不一样,我在自己的fuzzer里面把它们作了整合。由于边幅所限,我省略了不少边界值:
6、mangle_IncByte函数:
取随机位置的数据加1
7、mangle_DecByte函数:
取随机位置的数据减1
8、mangle_NegByte函数:
取随机位置的数据取反
9、mangle_AddSub函数:
取随机位置的1、2、4或8字节的数据长度作加减操作,操作数取 rand(0~8192)-4096
10、mangle_Dictionary函数:
变异目录名,也是随机取文件夹名称进行变异,如果有多个目录,那被变异的目录数也是随机的
11、mangle_DictionaryInsert函数:
在目录的随机位置中插入随机数据
12、mangle_MemMove函数:
取随机位置的数据拷贝随机长度的数据,里面就是调用memmove函数实现的
13、mangle_MemSet函数:
取随机位置、随机大小,用UINT8_MAX数值填充
14、mangle_Random函数:
取随机位置、随机大小的缓冲区,用随机数填充
15、mangle_CloneByte函数:
取两处随机位置的作数据交换
16、mangle_Expand函数:
文件末尾扩展随机长度的空间,用空格填充,然后在随机位置,取前面的随机长度作数据拷贝
17、mangle_Shrink函数:
删除随机长度的文件内容
18、mangle_InsertRnd函数:
在文件的随机位置插入随机长度的数据
19、mangle_ASCIIVal函数:
在随机位置覆盖32字节的随机数
总结
在Fuzzing过程中,很多变异规则是共用的,可以参考一些主源的开源软件,比如aflpeachhonggfuzzlibfuzzer,提取规则作整合,然后写个自己的fuzzing框架,在后面作针对的fuzzer时,可以直接套用。
从上面的fuzz策略可以总结出常规的变异规则:
- 随机数据替换
- 数据值增减
- 已知边界值替换
- 插入随机数据
- 删减文件内容
- 目录变异
- 数据拷贝覆盖
- ……