白帽故事 · 2025年4月12日

WinAFL安装与运行【记录于2022年1月】

环境

系统环境:Windows10 Pro

Visual Studio 2019(16) 必须为2019版!

所需工具 版本 下载地址
Visual Studio 2019 16 https://visualstudio.microsoft.com/zh-hans/vs/
git 2.34.1 Git – Downloads (git-scm.com)
CMake 3.22.1 Index of /files/v3.22 (cmake.org)
Dynamorio 源码 https://github.com/DynamoRIO/dynamorio
WinAFL 源码 https://github.com/ivanfratric/winafl
Strawberry Perl 任意 Strawberry Perl for Windows
IDA pro 7.0 + Lighthouse插件 /

安装步骤

Git

安装git,一路next即可,安装时记得选择自动配置环境变量,这样就可以直接在命令行中使用git

Cmake

同样一路next,记得需要勾选Add CMake to the system PATH for all users

Dynamorio

该工具主要用于动态插桩,Dynamorio最好git clone源码,然后在自己的机器上手动编译

>git clone https://github.com/DynamoRIO/dynamorio.git

Powershell走代理通道的方法:

依次输入如下两行命令$env:HTTP_PROXY="http://域名:端口"$env:HTTPS_PROXY="http://域名:端口。比如:$env:HTTP_PROXY="http://127.0.0.1:1080"即可。

Dynamorio编译(32位)

  1. 找到Visual Studio安装目录,找到vcvarsall.bat所在位置:
C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build
  1. 执行如下命令:
>vcvarsall x86
>cd dynamorio源码目录
>mkdir build32 && cd build32
>cmake -G"Visual Studio 16 2019" -A Win32 ..
>cmake --build . --config RelWithDebInfo
//也可以直接使用cmake-gui来编译

使用Cmake-gui来编译:

file

出现:

Configuring done
Generating done

即表示成功。

注1:

vcvarsall.bat,用于生成命令行编译环境:
 如果要在32位系统下生成32位代码,就执行vcvarsall x86
 如果要在32位系统下生成64位代码,就执行vcvarsall x86_amd64

 如果要在64位系统下生成32位代码,就执行vcvarsall x86
 如果要在64位系统下生成64位代码,就执行vcvarsall amd64_x86

 如果要在32位的arm平台的代码,就执行 vcvarsall x86_arm
 如果要在64位的arm平台的代码,就执行 vcvarsall amd64_arm

注2: Visual Studio 要指定于本机安装一致的版本,见下图

file

用VS打开D:\dynamorio\build32\DynamoRIO.sln项目,共有121个文件。

file

点击生成解决方案,就能一次性全部编译成功了,生成在bin32目录下:

file

编译成功的话,在build32\bin32目录下会可以看到编译出来的drrun.exe程序就表示OK了

file

Dynamorio编译(64位)

>vcvarsall amd64_x86
>cd dynamorio
>mkdir build64 && cd build64
>cmake -G"Visual Studio 16 2019" -A x64 ..
>cmake --build . --config RelWithDebInfo

编译:

file

同样用VS打开D:\dynamorio\build64\DynamoRIO.sln 项目,然后生成解决方案即可。

file

成功:

file

测试Dynamorio

检测程序会执行哪些代码块:

D:\dynamorio\build32\bin32>drrun.exe -t drcov -- D:\dynamorio\winafl\build32\bin\Release\ktest.exe input.txt

正确运行后,会在D:\dynamorio\winafl\build32\bin\Release目录下生成相应的log文件:

file

ktest.cpp的代码:

#define _CRT_SECURE_NO_DEPRECATE
#include <stdio.h>
#include <windows.h>

void fuzz(FILE* filename)
{
    char tmp[30];
    char buff[1024];

    fgets(buff, 1024, filename);    //读取文件内容 
    fclose(filename);
    strcpy(tmp, buff);      //存在栈溢出漏洞
    printf("%s\n", tmp);

}

int main(int argc, char* argv[])
{
    FILE* fp;
    fp = fopen(argv[1], "rb");
    if (fp == NULL)
    {
        printf("can not load file!\n");
        return 1;
    }
    fuzz(fp);
    return 0;
}

使用winafl.dll检测模块执行情况

注意:VS2019 编译时一定不要开优化!!!

file

>drrun.exe -c D:\dynamorio\winafl\build32\bin\Release\winafl.dll -debug -target_module ktest.exe -target_offset 0x1080 -fuzz_iterations 10 -nargs 2 -- ktest.exe input.txt
-debug              //必须为debug模式, 结束后会生成一个log文件
-target_module      //目标程序(只能有一个), 也是target_offset所在的模块
-target_offset      //目标程序偏移,相对于target_module的偏移,在method无法导出的时候使用
-fuzz_iterations    //目标程序重新启动一次内运行目标函数(即target_method)的最大迭代数
-nargs              //目标程序执行所需要的参数个数(包括目标程序本身)
-target_module      //目标函数,需要export或者调试符号(pdb)
-coverage_module    //计算覆盖率的模块,也就是目标程序会调用的模块(dll); (可以有多个)

注:要将ktest.exe和input.txt放在drrun的同目录,否则也会出现无法命中函数的情况。

成功运行后,同样会在D:\dynamorio\build32\bin32目录下生成相应的log文件:

file

但是我这里一直显示无法命中函数,偏移地址有问题,很奇怪。

经过各种尝试和调试,终于成功!(原因是VS2019在编译时一定要关闭优化,另外cmd/powershell最好使用管理员模式运行):

file

WinAFL

>cd dynamorio目录
>git clone https://github.com/googleprojectzero/winafl.git
>cd winafl
>git submodule update --init --recursive

WinAFL编译(32位)

>vcvarsall x86
>cd winafl源码目录
>mkdir build32 && cd build32
>cmake -G"Visual Studio 16 2019" -A Win32 .. -DDynamoRIO_DIR=D:\dynamorio\build32\cmake -DINTELPT=1
>cmake --build . --config Release

file

file

WinAFL编译(64位)

>cd winafl源码目录
>mkdir build64 && cd build64
>cmake -G"Visual Studio 16 2019" -A x64 .. -DDynamoRIO_DIR=D:\dynamorio\build64\cmake -DINTELPT=1
>cmake --build . --config Release

测试WinAFL

>afl-fuzz.exe  -i in -o out -D D:\dynamorio\build32\bin32 -t 20000 -- -coverage_module ntdll.dll  -fuzz_iterations 5000 -target_module ktest.exe -target_offset 0x1080 -nargs 2 -- ktest.exe  @@
-i //存放样本的目录
-o //保存输出数据,包括 crash文件、测试用例等
-D //DynamoRIO的路径 (drrun, drconfig)
-t msec //每一次样本执行的超时时间
第一个"--"分割符    //后面跟的是插桩的参数
第二个"--"分割符    //后面跟的是目标程序的参数
@@ //引用 -i 参数的中的测试用例

file

如果想要winafl在fuzz过程的界面显示彩色的话,可以在编译时:

>cmake -G"Visual Studio 16 2019" -A x64 .. -DDynamoRIO_DIR=D:\dynamorio\build64\cmake -DINTELPT=1 -DUSE_COLOR=1

运行afl-fuzz后的界面(还是彩色好看):

file

Process timing      //Fuzzer运行时长、以及距离最近发现的路径、崩溃和挂起经过了多长时间
Overall results     //Fuzzer当前状态的概述
Cycle progress      //当前Fuzz的进展
Map coverage        //目标二进制文件中的插桩代码所观察到覆盖范围的细节
Stage progress      //Fuzzer现在正在执行的文件变异策略、执行次数和执行速度
Findings in depth   //有关我们找到的执行路径,异常和挂起数量的信息
Fuzzing strategy yields //关于突变策略产生的最新行为和结果的详细信息
Path geometry       //有关Fuzzer找到的执行路径的信息
CPU load            //CPU利用率

关于覆盖率

首先是安装IDA Pro

然后是安装Lighthouse插件,安装之前,要安装好Python环境,我使用的是Python3.9:

>git clone https://github.com/gaasedelen/lighthouse.git

然后将lighthouse下plugin目录中的所有文件拷贝至IDA的plugin目录下,然后重新启动IDA pro,然后在Load File的最下方可以找到打开覆盖率日志文件。

使用drrun.exe -t drcov可以生成log日志,供IDA插件lighthouse查看覆盖率

>drrun.exe -verbose -t drcov  -- testkuhn_ok.exe

经过各种Google搜索寻找,发现新版的dynamorio生成的log日志文件,默认drcov格式为version 3.0,lighthouse无法打开!

无意中搜到一篇绿盟的文章,提到了解决方法:

解决办法有两种,一种是修改drcov.py,注释掉assert这行代码,至少DynamoRIO 9.0.1生成的.log文件就可以加载了;另一种是不改drcov.py,用WinHex修改.log的头部,把”DRCOV VERSION: 3″的3改成2。

使用了第二种方法,然后再使用IDA pro打开覆盖率日志文件,成功!

file

view-subview-Coverage Overview