CaseRunner是用于大规模导向型fuzz测试的工具,具有以下几个特色功能:
-
支持多Fuzz任务调度
-
提供Tui界面
-
自动统计fuzz运行信息
建议搭配docker容器prosyslab/dafl-artifact使用
该工具使用了RabbitMQ,因此需要安装相关依赖
# 1.由于rabbitMq需要erlang语言的支持,在安装rabbitMq之前需要安装erlang
sudo apt install erlang-nox
# 2.添加公钥
wget -O- https://www.rabbitmq.com/rabbitmq-release-signing-key.asc | sudo apt-key add -
# 3.更新软件包
sudo apt update
# 4.下载RabbitMQ
sudo apt install rabbitmq-server
# 5.开启RabbitMQ
sudo systemctl start rabbitmq-server
# 如果docker中运行用 service rabbitmq-server start
# 也可以直接在命令行运行rabbitmq-server
# 1.由于rabbitMq需要erlang语言的支持,在安装rabbitMq之前需要安装erlang
sudo pacman -S erlang-nox
# 2.下载RabbitMQ
sudo pacman -S rabbitmq
# 3.开启RabbitMQ
sudo systemctl start rabbitmq-server
# 也可以直接在命令行运行rabbitmq-server &
pip3 install tqdm watchdog pika textual PyYAML
下面是swftophp-4.8-2018-7868的PoC调用栈,第一行是栈顶(即crash触发的位置)
decompile.c:398
decompile.c:1621
decompile.c:3198
decompile.c:3401
decompile.c:2740
decompile.c:3261
decompile.c:2562
decompile.c:3242
decompile.c:3423
outputscript.c:1858
outputscript.c:2079
main.c:277
main.c:350
为了能够实现覆盖率信息统计、真crash判断,除了待测试二进制程序,我们需要提供ASAN插桩的可执行程序和LLVM-Cov插桩的可执行程序。
# 编译ASAN
export CC=clang
export CXX=clang++
export CFLAGS="-fsanitize=address"
export CXXFLAGS="-fsanitize=address"
./configure
make
# 省略....
# 编译LLVM-Cov
export CC=clang
export CXX=clang++
export CFLAGS="-fprofile-instr-generate -fcoverage-mapping"
export CXXFLAGS="-fprofile-instr-generate -fcoverage-mapping"
./configure
make
参考:
# task_config.yaml
# 任务模式,有两个模式
# arrive模式下,当fuzz生成能够到达目标的种子时,CaseRunner会停止fuzz
# crash模式下,当fuzz生成真crash,CaseRunner会停止fuzz
mode: arrive
# 输出目录,CaseRunner会收集并统计fuzz运行信息保存在该目录下
output_path: /run_output/msch_test-9
# 最大同时执行的任务数
job: 4
# 任务列表
tasks:
-
# fuzzer名称
fuzzer_name: DAFL
# 任务名称
task_name: swftophp-4.8-2018-7868
# cve名称,不同cve的真crash判定规则不一样,该参数用于选择该fuzz任务的判定规则
# 想知道CaseRunner支持哪些cve,可以在运行时指定 --list-supported-cve命令行参数查看
cve_str: swftophp-4.8-2018-7868
# 待测试的可执行程序
binary_path: /benchmark/bin/DAFL/swftophp-4.8-2018-7868
# 编译了ASAN的可执行程序
# 要编译此可执行程序,需要使用clang编译,并添加 -fsanitize=address 编译选项
asan_instr_binary_path: /benchmark/bin/ASAN/swftophp-4.8-2018-7868
# 编译了LLVM-Cov的可执行程序
# 要编译此可执行程序,需要使用clang编译,并添加 -fprofile-instr-generate -fcoverage-mapping 编译选项
cov_instr_binary_path: /benchmark/bin/Cov/swftophp-4.8-2018-7868
# 被测试程序的命令行参数
args: '@@'
# fuzz时存放初始种子的目录
seed_path: /benchmark/seed/swftophp-4.8-2018-7868
# 想要复现的PoC的调用栈信息,文件具体格式请参照上述样例
target_file_path: /benchmark/target/stack-trace/swftophp-4.8/2018-7868
# 允许该fuzz任务进行的最长时间,超过该时间,CaseRunner会结束该fuzz任务
time_limit: 10800
CaseRunner提供了以下命令行参数
--help 展示帮助信息
--version -v 展示版本
--config-file -f [可选] 该参数指定了CaseRunner的任务配置文件路径。
参数默认为task_config.yaml
--list-supported-cve 打印CaseRunner支持分析的所有CVE
--debug -d [可选] 开启调试模式。若指定该参数,CaseRunner会输出调试信息。
我们使用以下命令运行CaseRunner
python3 CaseRunner.py -f task_config.yaml
该命令会开启一个tui,展示如下:
其中打印出的信息包括:
- Fuzzer -> fuzz名
- Task Name -> 任务名
- Status -> 当前状态
- Running -> 已运行时间
- Last Crash -> 上一次出现Crash种子距离现在的时间
- Last True Crash -> 上一次出现真Crash种子距离现在的时间
- Path Num -> 目前已收集到的路径数
- Crash Num -> 目前已收集到的Crash数
- True Crash Num -> 目前已收集到的真Crash数
- Max Target Depth -> 当前探索到的最大深度
- Time Limit(s) -> 运行时间上限
- First Arrive Time -> 第一次到达Crash点的时间(包含按调用栈和不按调用栈到达)
- First Arrive Time -> 第一次到达Crash点的时间
- First Arrive Seed -> 第一次到达Crash点的种子
- First Crash Time -> 第一次触发Crash的时间
- First Crash Seed -> 第一次触发Crash的种子
- First True Crash Time -> 第一次到达真Crash点的时间
- First True Crash Seed -> 第一次到达真Crash点的种子
- First Fit Stack Arrive Time -> 第一次按调用栈到达Crash点的时间
- First Fit Stack Arrive Seed -> 第一次按调用栈到达Crash点的种子
- First Not Fit Stack Arrive Time -> 第一次不按调用栈到达Crash点的时间
- First Not Fit Stack Arrive Seed -> 第一次不按调用栈到达Crash点的种子
在运行结束后,会生成以下目录下会生成
-
output:fuzz生成的output目录
-
ccdl:CaseRunner分析的缓存目录
-
statistics:fuzz运行统计结果
-
task.log:任务在运行过程中的输出日志
-
fuzz.log:fuzz的输出日志