本帖最后由 zhaorong 于 2021-9-11 16:42 编辑
DynamoRIO 是一个动态的动态插桩/翻译平台。
DynamoRIO 用于对程序进行动态分析 优化和翻译。DynamoRIO 可以运行在 Windows
和 Linux 操作系统上。并且支持 IA-32 和 AMD64 平台。
著名的模糊测试神器WinAFL使用DynamoRIO进行动态插桩。大家在使用WinAFL进行模糊测试时
通常使用DynamoRIO中提供的工具Dr.run来查看代码覆盖率。
一、实验环境
- Windows 7 X64
- WinAFL 1.16
- DynamoRIO-Windows-6.2.0-2
- IDA Pro 6.8(Lighthouse插件v0.6)
- Visual C++6.0
复制代码
注意:关闭360等杀毒软件 部分杀毒软件会误报。
2、验证模糊测试时的偏移量偏移
为了测试dr.run,写随测试代码 编译环境为Visual C++6.0。
- #include <stdio.h>
- #include <string.h>
- #include <stdlib.h>
- #define PASSWORD "1234567" // 默认密码
- int g_execute_count = 0; // 变量,是为了记录执行次数
- int verify_password (char *password)
- {
- printf("输入密码 = %s\n", 密码); // 用于调试
- int 认证;
- 字符缓冲区[8];
- 认证=strcmp(密码,密码);
- strcpy(缓冲区,密码);//这里溢出了!
- 返回已验证;
- }
- int main(int argc, char* argv[])
- {
- printf("g_execute_count = %d\n", g_execute_count);
- g_execute_count = g_execute_count + 1;
- int valid_flag=0;
- 字符密码[1024];
- 文件 * fp;
-
- 如果(argc!= 2)
- {
- printf("用法:%s input_file\n", argv[0]);
- 返回 1;
- }
- // argv[1]为文件名
- if(!(fp=fopen(argv[1],"rw+")))
- {
- printf("打开 %s 失败!\n\n", argv[1]);
- 退出(0);
- }
- fscanf(fp,"%s",password);
- valid_flag = verify_password(密码);
- 如果(有效标志)
- {
- printf("密码错误!\n\n");
- }
- 别的
- {
- printf("恭喜!您已通过验证!\n\n");
- }
- fclose(fp);
- 返回0;
- }
复制代码
然后将上述代码编译为推出模式32位的可执行文件readFile.exe。
在本机实验环境中
- WinAFL 路径:D:\winAFL\;DynamoRIO 的路径:D:\DynamoRIO-Windows-6.2.0-2\。
复制代码
步骤如下:
首先将编译出的readFile.exe文件和要读取的文件input.txt,复制到D:\winAFL\bin32\下
input.txt中可以输入字符串ABCDEF。
使用IDA Pro查看readFile.exe函数的地址 如图1所示 可以看到main函数地址为0x00401080。
图1主要函数地址
使用IDA Pro查看基址 可以打开基础菜单Edit->Seg->Rebase程序 如图2所示。可见地址为0x400000
则主函数偏移量偏移= 0x00401080 - 0x400000 = 0x1080。
图2 查看基址
然后构造如下所示命令行 其中target_offset为偏移量 fuzz_iterations为执行次数。
- [b]注意:[/b] target_offset为文件中的偏移量。因为readFile.exe为32位程序 所以使用bin32文
- 件夹下的drrun.exe,而不是bin64文件夹下的drrun.exe。
复制代码- D:\DynamoRIO-Windows-6.2.0-2\bin32\drrun.exe -c winafl.dll -debug -target_module readFil
- e.exe -target_offset 0x1080 -fuzz_iterations 5 -nargs 2 -- readFile.exe input.txt
复制代码
然后切换到D:\winAFL\bin32\目录下。执行上述命令 执行结果如图3所示。
(因为g_execute_count为单位变量,可以记录执行次数)可以看出我们设置的偏移量0x1080是正确的。
图3 drrun执行截图
D:\winAFL\bin32目录下生成afl.readFile.exe.01016.0000.proc.log之类的日志文件。日志文件如下所示。
- 模块加载,readFile.exe
- 模块加载,drx.dll
- 模块加载,drreg.dll
- 模块加载,drwrap.dll
- 模块加载,winafl.dll
- 模块加载,drmgr.dll
- 模块加载,dynamorio.dll
- 模块加载,KERNELBASE.dll
- 模块加载,KERNEL32.dll中
- 模块加载,NTDLL.DLL
- 在pre_fuzz_handler
- 在OpenFileA,读input.txt中
- 在OpenFileW,读input.txt中
- 在post_fuzz_handler
- 在pre_fuzz_handler
- 在OpenFileA,读input.txt中
- 在OpenFileW,读input.txt中
- 在post_fuzz_handler
- 在pre_fuzz_handler
- 在OpenFileA ,
- 在 OpenFileW 中读取 input.txt ,
- 在 post_fuzz_handler 中读取 input.txt
- 在 pre_fuzz_handler
- 在 OpenFileA 中,读取 input.txt
- 在 OpenFileW 中,
- 在 post_fuzz_handler 中读取 input.txt在 pre_fuzz_handler
- 在
- OpenFileA 中,读取 input.txt
- 在 OpenFileW 中,读取 input.txt
- 在 post_fuzz_handler 中的
- 一切似乎都在正常运行。
- 覆盖图如下:
- ...
复制代码
可以看到很多行开始都是模块加载 也就是说参数coverage_module和target_module指定
的模块必须出现在这里。
如果-target_offset设置不正确 查看日志文件中 警告提示如下。
- ...
- 在 OpenFileA 中,读取 input.txt
- 在 OpenFileW 中,读取 input.txt
- 警告:从未调用过目标函数。target_offset 不正确?
- 覆盖图如下:
- ...
复制代码
3、生成代码覆盖文件
切换到 D:\DynamoRIO-Windows-6.2.0-2\bin32目录下 执行如下命令。
- D:\DynamoRIO-Windows-6.2.0-2\bin32>drrun.exe -t drcov -- ..\..\winafl\bin
- 32\readFile.exe ..\..\winafl\bin32\input.txt
复制代码
图4 drrun执行截图
在D:\DynamoRIO-Windows-6.2.0-2\bin32目录下 生成drcov.readFile.exe.12800.0000.proc.log类似文件。
使用IDA Pro加载上述代码生成的readFile.exe文件IDA Pro已经安装Lighthouse插件v0.6 待文件加载完成后。
打开IDA Pro菜单File -> Load File -> Code coverage file...加载drcov.readFile.exe.12800.0000.proc.log
文件如图5所示。 Lighthouse 插件将不同覆盖率的函数变化不同。
图5函数视角的代码覆盖率
题6所示 可以看到某个函数中的基本块是否能覆盖到。
图6某个函数的基本块覆盖
在模糊测试中 如果要测试的函数覆盖率 则可进行数据下一步操作。既专业输入集。 |