winafl的使用及简单样例
前言
之前参加过学校老师的一个项目,大概就是对AFL原生版本进行的优化,但是最后项目可能达到的效果没有什么技术和速率上的优化,一些所谓的速率上的提升约束性太强,很难作为漏洞挖掘实际所使用,更偏向于学术论文发布和相关比赛而生,再加上后来个人也学习过winafl,中间也有一些坎坷和曲折(全是坎),记录下来帮助自己后续温习也帮助别人排雷(比较适合萌新,不太适合一些深入学习的同学)
简单介绍
接触不多,仅代表个人观点
个人感觉首先要明确Fuzz的局限性,Fuzz的本质理念其实就是存在一个让程序无法执行的情况,而这个情况一般是非预期产生的,有时候存在错误分支,但是没办法Fuzz其实也就是Fuzz的局限性,比如你对某个网站进行Fuzz,但是它的报错页面和正常页面一致没有任何区别,因此就无法Fuzz(软件同理)
因此需要明确就是AFL和Fuzz工具并非万能,更多时候需要魔改或者自己进行二进制调试,而我之前项目中涉及到的更多的是白盒AFL-Fuzz,区别于黑盒,白盒其实很多漏洞更多是涉及到静态分析工具,比如codesonar等工具,其实有时候会比AFL速率更快,Fuzz更多的优势在黑盒(换句话说,白盒测试一些漏洞都被人看烂了,除非特别新的而且个人审计能力突出,否则很难从白盒找到漏洞)
所以后面更多的介绍是使用winafl黑盒测试的调试和Fuzz
DynamoRIO和WinAFL的环境配置
-
环境
- windows10
- Visual Studio 2019
- cmake 3.18.0-rc2
- git
- perl
- 网上配置多为win7+vs2013 多次尝试搭建没有成功,因此换为windows10 + vs2019
-
配置
-
git perl cmake等工具默认安装即可 cmake需要安装gui版本
-
编译dynamorio源码
- 编译32位 dynamorio
32位dynamorio使用make命令行编译会报错,因此采用cmake-gui+vs2019模式
//创建fuzz文件夹,在文件夹内打开cmd git clone https://github.com/DynamoRIO/dynamorio.git cd dynamorio mkdir build32 && cd build32
打开cmake-gui进行编译,设置对应的src和build目录,configure设置当前的VS平台,我使用的是Visual Studio 16 2019
然后就一直configure,会一直报错,随便找一个对应版本的exe文件或dll文件就行,分别是ml.exe、mc.exe、uuid.lib、lib.exe,配置成功后configuring done
然后点击generate即可生成解决方案DynamoRIO.sln
直接使用VS2019打开解决方案进行编译,成功- 编译64位 dynamorio
离谱的是64位cmake-gui会丢失文件,因此直接cmake命令行模式
//everything 找到 vcvarsall vcvarsall amd64_x86 切换到64位编译环境 cd xxx mkdir build64 && cd build64 cmake -G"Visual Studio 16 2019" -A x64 .. cmake --build . --config RelWithDebInfo
即可正常编译成功
- 编译32位 dynamorio
-
编译winafl
git clone--recursive https://github.com/googleprojectzero/winafl- 编译32位 winafl
vcvarsall x86 //切换x86编译环境 cd到winafl目录 mkdir build32 && cd build32 cmake -G"Visual Studio 16 2019" -A Win32 .. -DDynamoRIO_DIR=C:\fuzz\dynamorio\build32\cmake //cmake的绝对路径 cmake --build . --config Release
- 编译64位 winafl
vcvarsall amd64_x86 cd到winafl目录 mkdir build64 && cd build64 cmake -G"Visual Studio 16 2019" -A x64 .. -DDynamoRIO_DIR=C:\fuzz\dynamorio\build64\cmake //cmake的绝对路径 cmake --build . --config Release
功能测试
- 动态插桩
drrun.exe在dynamorio/buildxx/binxx/目录下,以test_gdiplus.exe为例
drrun.exe -c winafl.dll -debug -target_module test_gdiplus.exe -target_offset x -fuzz_iterations 10 -nargs 2 -- test_gdiplus.exe input.bmp
偏移地址X随便用任意一个二进制调试工具就可以查看,最后会在执行目录下生成一个log文件,可以看到一切都正常
-
winafl-fuzz功能
afl-fuzz.exe -i in -o out -D C:\fuzz\dynamorio\build32\bin32 -t 20000 -- -coverage_module gdiplus.dll -coverage_module WindowsCodecs.dll -fuzz_iterations 5000 -target_module test_gdiplus.exe -target_offset X -nargs 2 -- test_gdiplus.exe @@
正常进行
实战测试
测试产品为某图片库,区别于正常的软件Fuzz,对库类进行Fuzz需要结合其官方使用文档对其进行相关的学习,同时结合对应的函数进行Fuzz,也就是需要自己对harness进行构造
简单介绍一下个人所接触的几种黑盒测试方法
-
正常fuzz
一般定位到对应的目标函数后直接fuzz,不做任何额外的处理,相对而言调试所消耗的时间较少,但是Fuzz速率较慢,产生新path和crash的时间间隔较长,一般为最差选项
-
构造harness
一般构造于其对应的IDA反汇编相对比较清晰,函数API调用比较明显的情况,或用于DLL等具有较多说明文档的情况,相对而言需要汇编能力较强
-
魔改程序
直接魔改,简化部分不必要且没有意义的流程
首先对此dll库进行构造harness,得到对应的执行程序,我们构造的harness主要fuzz目标为fuzz函数
进行drrun动态插桩
C:\fuzz\dynamorio\build32\bin32\drrun.exe -c winafl.dll -debug -coverage_module xx.dll -target_module test1.exe -target_method fuzz -fuzz_iterations 10 -nargs 2 -- test1.exe C:\Users\Administrator\Desktop\input.bmp
存在一个问题,就是执行结束后会存在一个弹窗,两种解决办法,手动关闭或者魔改程序直接patch掉,选择简单的办法,写个while脚本把这个弹窗关闭
python调用一下cmin精简一下输入样本
python C:\fuzz\winafl\winafl-cmin.py -i C:\Users\Administrator\Desktop\afl_testcases\ico\full\images -o C:\Users\Administrator\Desktop\afl_testcases\ico\test -t 20000 -D C:\fuzz\dynamorio\build32\bin32 -coverage_module xxx.dll -target_module test1.exe -target_method fuzz -nargs 2 -- test1.exe @@
进行fuzz跑一段时间
afl-fuzz.exe -i C:\Users\Administrator\Desktop\afl_testcases\ico\test -o imagegear\outforico -D C:\fuzz\dynamorio\build32\bin32 -t 20000 -- -coverage_module xxx.dll -target_module test1.exe -target_method fuzz -nargs 1 -- test1.exe @@
简单分析一下触发点
这里eax为我们输入样本中的可控值,但是ecx固定为0,也就是0x00000004,应该不可进一步利用,最后通过winafl我目前一共提交了8个cnvd,其中7个已过,1个还在验证中
总结
无论是AFL还是其他漏洞挖掘工具,都不能离开它本身的功能去进行魔改,为了一些所谓的项目和科研而去"水"一些所谓的论文,希望以后自己能踏实学知识,踏实做事情