作者:SungLin@知道创宇404实验室
概述
为啥叫傻瓜式fuzzing呢,可能我觉得吧,一步一步从最初始的部分去探索和研究将会很好玩,不过有时候也会很难(遇到问题的时候),但是解决每一个问题都会有小小的成就感,继续激励前行,坚持下去总会有收获的,我会把我对fuzzing的探索与研究做成一系列的paper,希望大家同样觉得很好玩,have fun。
0x00 探索与学习
在2020年的年终时候,我在知乎上对2020年的开源fuzzing做了一些总结与些许研究,一个开源的研究与项目叫FormatFuzzer[1],这个项目的出现,让我想起了aflsmart[2]的开源fuzzing项目,两者都是类似的文本结构fuzzing,和aflsmart不同的是FormatFuzzer项目还处于开发阶段,通过我对aflsmart fuzzing项目的熟悉(我用aflsmart挖了不少漏洞),我决定以Formartfuzzer为契机来做一些有意思的事情,可能我觉得有意思就行,hhhhh
0x01 Formartfuzzer
Formartfuzzer fuzzing我就不做过多介绍了,简单的来说,它就是以010 Editor众多结构模板为基础来生成与构造所需的各种结构数据,再通过对数据做一些变异算法来生成最终的畸形数据,Formartfuzzer 现在支持结构有:avi、bmp、gif、jpg、midi、mp3、mp4、pcap、png、wav、zip等,作者们还在继续编写中,既然010 Editor支持上百种结构,而这里只有10多个呢,因为010 Editor只是一个做了解析的软件,而Formartfuzzer 不仅做了解析,而且通过模板结构生成了可用的相关结构数据,所以没法直接使用010 Editor的模板,还需要做很多工作,再熟悉了Formartfuzzer 后,我决定自己修改一种模板结构,我将目标定为了ttf结构,这是一种字体结构,可以说字体结构也是相当复杂了,并且选择字体也和我最近的工作有些许联系。
0x02 ttf结构模板的修改与定义
ttf结构的描述可以参考苹果或者微软的链接,这里我们参考苹果的链接[3],ttf结构主要是以众多的table表构成,每个table表直接有相关的联系,所有的table表加起来有大概40多个,在苹果字体的描述中,以下的几个table表是必须构成字体的9个table表:
也就是说,想要生成一个可以被正常解析的字体,至少得定义以上9个table表,在010 Editor中,原始的ttf.bt大概解析了以下几个表:
生成字体必须的9个table表已经有了,但是像以上的定义是不能用的,经过我的简单研究tff的结构其实和png的结构框架是非常相似的,和png的chunk对应的是tff的table,少许不一样的是tff有个定义了所用到的table的头部,而这个头部包含了Tag、offset、length等关键结构,我将会简单介绍几个重要的table表和修改。
第一步,我将会随机生成table表,而这些table表将会包含9个重要的table表,通过其定义ReadBytes api能实现:
第二步,随机生成table表后将会获取到table表的数量和具体的table,这样就可以去生成具体的table格式,获取实际的offset、length了,其中IO操作主要有FTell()和FSeek,这样就可以随时定位到指定位置修改数值了:
第三步,定义maxp、loca、glyf:
maxp的定义很简单,基本没变
定义好maxp后,就可以获取到maxp.numGlyphs的个数了
有了Glyph的个数后,就可以定义loca表了,而loca表包含了每个Glyph的偏移offset
最后就可以定义glyf表了,tglyf结构体主要由tSimpleGlyph结构体构成,tSimpleGlyph结构体包含了tSimpleGlyphFlags和tSimpleGlyphPoints,在这里主要注意的是offset和length的计算,并且最后一定要把IO流定位到数据末尾
这里每次获取到tSimpleGlyph的长度后,得重新定位到loca表设置正确的offset,这样才能生成能够被解析的结构
之后定义好tSimpleGlyphFlags和tSimpleGlyphPoints就行了。
0x03 生成字体
上一节简单介绍了table表的定义与字体的一些结构组成,通过正确定义好了必须的9个tabel表和其他特殊的table表后,通过项目自带的ffcompile将定义好的bt模板生成cpp文件,一般情况会有很多错误,直到调试到正确为止,我自己修改好的ttf模板可以生成正确的字体了,编译的命令如下:
1、生成ttf.cpp
./ffcompile templates/ttf.bt ttf.cpp
2、生成.o文件
g++ -c -I . -std=c++17 -g -O3 -Wall tff.cpp
这里介绍生成器fuzzer.cpp主要调用了generate_file()
生成的ttf.cpp中,generate_file翻译了bt中我定义的结构主体,而这些api都可以找到,所以后面可以去优化和扩展自己的功能等。
3、编译fuzzer.cpp
g++ -c -I . -std=c++17 -g -O3 -Wall fuzzer.cpp
4、最后链接ttf和fuzzer生成ttf-fuzzer:
g++ -O3 ttf.o fuzzer.o -o ttf-fuzzer -lz
最后通过ttf-fuzzer生成字体,在macos中,打开是这样的:
好了,字体生成成功。
0x04 开启fuzzing
既然字体生成成功了,那就开始试水了噻,我打算直接fuzz macos自带的字体册/System/Applications/Font Book.app/Contents/MacOS/Font Book,我写了个简单的启动shell:
通过这个shell能直接打开生成的字体。。。。
但是这样没法检测crash,还不算fuzzing。
稍加修改后,我弄了个简单的代码如下:
这样就可以检测到crash了,虽然很简单哈哈
之后重新修改shell脚本,修改后如下:
好了,虽然很简单,但是可以跑起来了。
0x05 傻瓜fuzzing系列一
经过了200000次fuzzing,大概花了12个小时还要多,虽然没仔细统计,结果如下:
哈哈哈,牛逼哇,就这都能搞崩。
这次的fuzzing系列就到这了哈,后面我会慢慢分享我的fuzzing研究与探索,尽请期待傻瓜fuzzing系列。
0x06 参考链接
1、https://uds-se.github.io/FormatFuzzer/
2、https://github.com/aflsmart/aflsmart/https://github.com/aflsmart/aflsmart
3、https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6.html/https://developer.apple.com/fonts/TrueType-Reference-Manual/RM06/Chap6.html