本文是对于模糊测试方面的小总结,计划三篇;第一篇概述;第二篇afl;第三篇Winafl。非大部头书,只提取关键信息。
本篇为第三篇:winafl,本篇中的内容大量引用Hardik Shah的公开演讲。
本篇的主要内容如下:
- Winafl是什么
- 使用DynamoRIO返回覆盖率信息
- 模糊策略
- 开始使用Winafl
- 动手:使用VisualStudio编译示例C程序
- 动手:找到Fuzz函数的偏移量
- 动手:在调试模式下运行Winafl,检查一切正常
- 动手:开始使用WinAFL
- 动手:分析崩溃并找到根本原因
- 开搞真实的商业应用程序
- 动手:编写一个线束/测试程序来读取/解析MDB文件
- 动手:分析MDB文件
- 动手:用WinAFL模糊它
- CVE-2018-8423和CVE-2019-0576分析
- 总结
Winafl是什么?
- 在FUzz的闭源代码程序所面临许多挑战
- 无源码,仅有dll和exes
- 比如:Gdi32.dll,gdiplus.dll, msrd3x40.dll
- 无源码,仅有dll和exes
- Winafl
- Windows版本的afl(American Fuzzy Lop)
- 由 Ivan Fratric 所维护
- 使用 DynamoRIO(drrun.exe)来插桩和收集覆盖率
- afl-fuzz.exe与充当drrun.exe客户端的winafl.dll进行通信
- 信息流:afl-fuzz.exe <——> winafl.dll <——> drrun.exe
- 需要写一种叫harness的程序
- 它能从处理文件解析的DLL中调用函数
- harness应该有一个函数,它接受文件名作为输入,打开它,然后进行进一步的处理
- winafl将在内存模糊中使用这个函数
- 一个简单的实例
使用DynamoRIO返回覆盖率信息
afl-fuzz.exe是负责在linux上实现模糊测试的过程主进程
winafl.dll是一个客户端dll,它负责处理从dynamorio, pre_fuzz,
post_fuzz之类传递过来的信息
两者都通过IPC(Inter-Process Communication进程间通讯)进行通信
注册各种事件的回调,比如基本块、模块的加载和卸载等
- 检查其模块是否为目标模块,然后使用符号/地址来搜索模糊函数
- 调用pre_fuzz处理程序以保存程序此时的状态
- 执行函数并监控崩溃情况,不断更新覆盖率map
- 调用post_fuzz处理程序并恢复状态
- 一直循环到迭代次数
模糊策略
- bitflip,按位翻转,1变为0,0变为1
- 1/1,2/1,4/1,8/8 ….32/8
- Byte Flip ,按字节反转
- arithmetic,整数加/减算术运算
- havoc,中文意思是“大破坏”,此阶段会对原文件进行大量变异
- dictionary,把自动生成或用户提供的token替换/插入到原文件中
- interest,把一些特殊内容替换到原文件中
- splice,中文意思是“绞接”,此阶段会将两个文件拼接起来得到一个新的文件
该部分内容可参考官方文档: https://github.com/googleprojectzero/winafl/blob/master/afl_docs/technical_details.txt
开始使用Winafl
动手:让我们使用WinAFL
- 编译
- 使用 visual studio 编译目标二进制程序或者使用官方预编译好的二进制程序
- 开启Page Heap堆页
- 开启:gflags /p /enable readfile.exe
- 验证:gflags /p
- 对函数fuzz
- 查找处理器图像函数的偏移量
- 用 WinDBG
- x ReadFile!ProcessImage
- 查找处理器图像函数的偏移量
- 确保程序得到DynamoRIO信息正确:
- C:\fuzzingwork\DynamoRIO-Windows-7.1.0-1\bin32\drrun.exe -c winafl.dll -debug -target_module readfile.exe -target_offset 0x10a0 -fuzz_iterations 10 -nargs 1 – readfile.exe 1.img
- Drrun.exe -> DynamoRIO 二进制程序
- -c winafl.dll -> 用于与drrun通讯的客户端程序
- -debug -> Winafl将生成调试日志
- -target_module -> 你想要插桩&测量代码覆盖率的目标模块
- -target_offset -> 在内存模糊中的你要fuzz的函数的偏移
- -fuzz_iterations -> 你想要循环的次数
- -nargs -> 参数的数量
- C:\fuzzingwork\DynamoRIO-Windows-7.1.0-1\bin32\drrun.exe -c winafl.dll -debug -target_module readfile.exe -target_offset 0x10a0 -fuzz_iterations 10 -nargs 1 – readfile.exe 1.img
动手:运行WinAFL开始Fuzzing
- 命令行格式:
AFL-FUZZ.EXE AFL_ARGS – INSTRUMENTATION_OPTIONS – PROGRAM_NAME @@
- afl-fuzz.exe参数
- -M – Master模式
- -S – Slave模式
- -i -> 输入目录
- -o -> 输出目录
- -D -> DynamoRIO bin32/64 目录路径
- -t -> 超时时间
- DynamoRIO的参数
- -coverage_module -> 需要进行检测的dll/exe的名称
- -target_module -> harness里可执行文件的名称。
- -target_method or –target_offset -> 处理输入文件的偏移量或者函数名称。
- -call_convention – -函数调用约定,比如 thiscall,stdcall,cdecl,fastcall等
- 程序参数,后面跟着@@
动手:WinAFL状态屏幕
详细情况说明可看官方文档: https://github.com/google/AFL/blob/master/docs/status_screen.txt
动手:分析崩溃并找到根本原因
- 使用Visual Studio
- 调试源代码,运行崩溃文件,并跟踪执行流程,查找根本原因。
- 使用windbg
- 使用崩溃文件调试可执行文件并查找根本原因
开搞真实的商业应用程序
对MDB文件进行fuzz
Fuzz MDB 文件的harness
- 使用CDao数据库对象
- 打开MDB文件
- 关闭它
- 解析代码在msrd3x40.dll中
- db.open将从这个dll中调用函数
- 如果文件结构不正确,我们的程序将崩溃
- 这个harness导致了13个CVE
开始fuzz
- 编译这个c文件
- 从谷歌收集一些MDB文件
- 用winafl来fuzz它
CVE-2018-8423和CVE-2019-0576分析
CVE-2018-8423
- 这是一个OOB写入的漏洞
- 在处理MDB文件时出现的漏洞
- MDB文件是由MSAccess使用的数据库文件
- 包含数据库结构,如表、索引、索引
- 它有旧的和专有的文件格式,好在多年来许多人收集了不少样例
- Ref: http://jabakobob.net/mdb/
- 遵循页面结构
- 第一页,表定义页,数据页,OLE字段。表中的属性
- 这使它成为一个容易的模糊目标
- PoC Availble : https://github.com/thezdi/PoC/tree/master/ZDI-18-1075
- 包含两个文件-> Group1 [MDB file], poc.js [js file]
- McAfee的分析报告:https://www.mcafee.com/blogs/other-blogs/mcafee-labs/jet-database-engine-flaw-may-lead-to-exploitation-analyzing-cve-2018-8423/
- 所以它被修复了,是吗?
CVE-2019-0576
- 不,又发现了另一个问题!!cve-2019-0576
- Ref: https://www.mcafee.com/blogs/other-blogs/mcafee-labs/analyzing-and-identifying-issues-with-the-microsoft-patch-for-cve-2018-8423/
- 它最终是如何解决的?
在Windows下如何追踪分类Crash?
- 人工手动一个个分析崩溃是非常困难的
- 可以使用python + winappdbg 简单自动化
- 编写自己的工具?
- 使用bugid
总结
- 模糊测试有助于全面理解软件安全
- 帮助编写更好的代码
- 可以帮助找到使用正常测试找不到的问题
- 帮助保护软件的安全
- 软件开发生命周期的一部分
- 需要大量的艰苦的工作
- 会面临各种零碎的问题,任何小问题都会导致不工作
- 花费无数小时去分析和解决这些问题
- 期望供应商进行后续跟进
- 结果被拒绝
- 但最终,这是值得的☺