定向模糊测试工具Beacon基本用法
Beacon是一个定向模糊测试工具,给定行号,能够定向探索行号附近的代码区域。主要思想是采用静态分析的方法获取到与目标有关的变量的最弱前置条件(weakest precondition)的信息,并在相关位置插入断言,来提前终止模糊测试执行与目标无关的输入,提高模糊测试的吞吐量来提高效率。
关于这篇工作的具体介绍,可以参考该链接的解读:https://zhuanlan.zhihu.com/p/531371498
0. 安装
docker 拉取Beacon的镜像
docker pull yguoaz/beacon
使用方法见该链接:https://outstanding-hydrogen-2d1.notion.site/Beacon-documentation-8480ed4e7fff452a989f7e77ce749951
官方教程给出了基本的操作说明,这里打算实际复现下这个过程。
1. 分析precondition
/Beacon/precondInfer /Beacon/Test/swftophp-2017-7578.bc -target-file=/Beacon/Test/cstest.txt -join-bound=5
这个例子中:
- /Beacon/Test/swftophp-2017-7578.bc是目标程序的字节码
- /Beacon/Test/cstest.txt 是给定的行号。比如包含下面的内容
parser.c:66
给定的行号通常是漏洞的崩溃点,一般通过CVE数据库里的崩溃报告来获取。
执行上面命令后会输出三个文件:
- bbreaches_Beacon_Test_cstest.txt : 能到达目标指令的基本块集合。
- range_res.txt : 范围分析结果
- transed.bc : 转换后的字节码用于后续的处理
bb_reaches_Beacon_Test_cstest.txt内是一堆数字,下面节选了一部分,应该是LLVM IR中间层的基本块的ID。
2676
38526
27001
7456
37338
19712
38153
1958
37059
33506
2190
37077
range_res.txt是前置条件分析的结果,包含了变量的取值范围等信息。
{"fun": "outputTrailer_0x2608af8","funLoc": 7320,"instRes": [],"argRes": [],"unreachbb": [7353,7369]},{"fun": "parseSWF_DEFINEMORPHSHAPE_0x25efb78","funLoc": 32260,"instRes": [{"value": " %62 = icmp ne void (i8*, ...)* %61, null, !dbg !7087","range": "[0,0]","line": 32343}],"argRes": [],"unreachbb": [32347]}
2. 插桩
插桩过程利用上面输出的信息,
/Beacon/Ins -output=/Beacon/Test/CVE-2017-7578.bc \
-byte -blocks=/Beacon/Test/bbreaches-CVE-2017-7578.txt \
-afl -log=log.txt -load=/Beacon/Test/outputs/range_res.txt \/Beacon/Test/outputs/transed.bc
各个选项的含义:
- -output:输出插桩后的字节码文件
- -blocks:接收可达的基本块列表,就是前面生成的bb_reaches_Beacon_Test_cstest.txt
- 需要注意,默认情况下,可达性分析的结果是基于字节码的,因此需要使用-byte选项
- 如果用户自己做了源码级的可达性分析,可以用-src选项。并且提供可达的行号,形式为“文件名:行号”
- -load: 获取precondition,比如前面生成的range_res.txt
- -afl:允许AFL覆盖率追踪的插桩
- -asan选项:默认是关掉的,可能会导致功能性错误
然后将字节码编译为可执行的二进制文件,注意需要链接一些动态库。
clang /Beacon/Test/CVE-2017-7578.bc -o /Beacon/Test/CVE-2017-7578 -lm -lz /Beacon/Test/afl-llvm-rt.o
3. 开始fuzz
最后执行afl-fuzz命令
/Beacon/afl-fuzz -i /Beacon/Test/in -o /Beacon/Test/fuzz-output -m none -t 9999 -d -- /Beacon/Test/CVE-2017-7578 @@
总体流程和其他工作差不多。
4. 再来测试下Libtiff
由于镜像中没有提供生成字节码的文件,所以需要提前安装gllvm或者wllvm,这里就不再赘述。
然后准备好libtiff的目标文件,cstest.txt和libtiff种子文件夹in
放在/Beacon/libtiff_test
文件夹下
直接运行下面脚本即可,需要注意下面脚本假设gllvm放在/Beacon/
文件夹下。
cd /Beacon/libtiff_test
git clone https://gitlab.com/libtiff/libtiff.git
cd libtiff
export CC=/Beacon/gllvm/gclang
export CXX=/Beacon/gllvm/gclang++
./autogen.sh
./configure --disable-shared
make clean
make
cd tools/
/Beacon/gllvm/get-bc tiffcp
mv tiffcp.bc /Beacon/libtiff_test/
/Beacon/precondInfer /Beacon/libtiff_test/tiffcp.bc -target-file=/Beacon/libtiff_test/cstest.txt -join-bound=5
/Beacon/Ins -output=/Beacon/libtiff_test/tiffcp.ci.bc \
-byte -blocks=/Beacon/libtiff_test/bbreaches__Beacon_libtiff_test_cstest.txt \
-afl -log=log.txt -load=/Beacon/libtiff_test/range_res.txt \/Beacon/libtiff_test/transed.bcclang /Beacon/libtiff_test/tiffcp.ci.bc -o /Beacon/libtiff_test/tiffcp -lm -lz /Beacon/Test/afl-llvm-rt.o/Beacon/afl-fuzz -i /Beacon/libtiff_test/in -o /Beacon/libtiff_test/fuzz-output -m none -t 9999 -d -- /Beacon/libtiff_test/tiffcp @@
另外,如果给的是无效的target,在运行precondInfer命令时会报如下错误:
malformed target file -- exiting!