傻瓜式 fuzzing 系列一

robots

 

作者: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

(完)