AFLplusplus/Grammar-Mutator
GitHub: AFLplusplus/Grammar-Mutator
AFL++ 的语法感知扩展插件,利用树状结构变异解决传统模糊测试难以处理高度结构化输入(如代码、JSON)的痛点。
Stars: 271 | Forks: 23
# Grammar Mutator - AFL++

一个基于语法的自定义变异器,用于 AFL++ 以处理高度结构化的输入。
- 开发者:[Shengtuo Hu (h1994st)](https://github.com/h1994st)
- 导师:[Marc Heuse](https://github.com/vanhauser-thc),[Andrea Fioraldi](https://github.com/andreafioraldi)
## 概述
我们开发了一个语法变异器来增强 AFL++,使其能够处理高度结构化的输入,例如 JSON、Ruby 等。
该语法变异器利用了 [F1 fuzzer](https://github.com/vrthra/F1) 和 [Nautilus](https://github.com/nautilus-fuzz/nautilus) 的思想进行测试用例生成和变异。
总之,本仓库包括:
- 基于树的变异:规则变异、随机变异、随机递归变异、拼接变异
- 基于树的修剪:子树修剪、递归修剪
- 一个 ANTLR4 shim,用于在运行时解析模糊测试测试用例
- 关于如何构建语法变异器、指定自定义语法以及使用语法变异器的文档
- 用于单元测试的全面测试用例
- 示例语法文件和一个用于转换 nautilus python 语法文件的脚本
有关基于树的变异、修剪和基于语法的模糊测试的更多详细信息,请参阅 [Nautilus 论文](https://www.syssec.ruhr-uni-bochum.de/media/emma/veroeffentlichungen/2018/12/17/NDSS19-Nautilus.pdf)。
关于使用 AFL++ Grammar Mutator 对 Apache 进行模糊测试的一篇报告可以在这里找到:
[https://securitylab.github.com/research/fuzzing-apache-1](https://securitylab.github.com/research/fuzzing-apache-1)
## 入门指南
### 前置条件
在开始之前,应安装以下工具/包:
```
sudo apt install valgrind uuid-dev default-jre python3
wget https://www.antlr.org/download/antlr-4.8-complete.jar
sudo cp -f antlr-4.8-complete.jar /usr/local/lib
```
如果您没有将 JAR 文件留在 Grammar-Mutator 目录中,或者没有将其复制到 /usr/local/lib,则必须通过 make 命令中的 ANTLR_JAR_LOCATION=... 指定其位置。
请注意,语法变异器基于 AFL++ 中最新的自定义变异器 API,因此请使用 [AFL++](https://github.com/AFLplusplus/AFLplusplus/tree/dev) 最新的 `dev` 或 `stable` 分支。
```
git clone https://github.com/AFLplusplus/AFLplusplus.git
cd AFLplusplus
make distrib
sudo make install
```
### 构建 Grammar Mutator
接下来您需要构建语法变异器。
要指定语法文件,例如 Ruby,您可以使用 `GRAMMAR_FILE` 环境变量。
`grammars` 目录中有几个语法文件,例如 `json.json`、`ruby.json` 和 `http.json`。
有关输入语法文件的更多详细信息,请参阅 [customizing-grammars.md](doc/customizing-grammars.md)。
请注意,我们欢迎提交包含新语法的 Pull Request!:-)
```
make GRAMMAR_FILE=grammars/ruby.json
```
请注意,共享库和语法生成器的名称基于指定的语法文件,因此您可以生成多个语法。
语法名称部分取自文件名,并在下划线、连字符或点之后截断所有内容,因此 `ruby.json` 将生成 `ruby`,进而创建 `grammar_generator-ruby` 和 `libgrammarmutator-ruby.so`。
您可以通过设置 `GRAMMAR_FILENAME=yourname` 作为 make 选项来指定您自己的命名。
现在,您应该能在根目录下看到两个符号文件 `libgrammarmutator-ruby.so` 和 `grammar_generator-ruby`。
这两个文件实际上位于 `src` 目录中。
如果您想 Fork 该项目并修复错误或为项目做出贡献,可以查看 [building-grammar-mutator.md](doc/building-grammar-mutator.md) 以获取完整的构建说明。
### 插桩模糊测试目标
您可以参考 [sample-fuzzing-targets.md](doc/sample-fuzzing-targets.md) 来构建示例模糊测试目标。
### 种子
在模糊测试真实程序之前,您需要准备输入模糊测试种子。您可以:
- 为给定的语法生成种子
- 使用现有的种子
#### 使用现有种子
您可以将自己的模糊测试种子提供给 fuzzer,这些种子不需要与您的输入语法文件匹配。
假设语法变异器是使用 `grammars/ruby.json` 构建的,这是一个简化的 Ruby 语法,并未涵盖所有 Ruby 语法。
在这种情况下,肯定会出现解析错误。
对于任何解析错误,语法变异器不会终止,而是将错误部分保存为树中的终端节点,这样我们就不会丢失原始测试用例的太多信息。
例如,要使用 `mruby` 项目的测试用例作为输入模糊测试种子,只需在运行 fuzzer 时将 `-i mruby/test/t` 传递给 afl-fuzz(如果已通过 `git clone https://github.com/mruby/mruby.git` 在当前目录中检出)。
#### 使用生成的种子
`grammar_generator` 可用于生成输入模糊测试种子和相应的树文件,遵循您在编译语法变异器时指定的语法文件(即 `GRAMMAR_FILE`)。
您可以控制生成的种子数量和相应树的最大大小。
通常,树的大小越大,相应的输入种子就越复杂。
```
# 用法
# ./grammar_generator-$GRAMMAR []
# # 是可选的
# 例如:
./grammar_generator-ruby 100 1000 ./seeds ./trees
```
然后将名为 `trees` 的文件夹以该确切名称复制到您将与 afl-fuzz 一起使用的输出目录(例如 `-o out -S default`):
```
mkdir -p out/default
cp -r trees out/default
```
请注意,如果您使用多个 fuzzer(-M/-S 同步模式),则必须对所有 fuzzer 实例执行此操作,例如,当 fuzzer 实例命名为 fuzzer1 到 fuzzer8 时:
```
for i in 1 2 3 4 5 6 7 8; do
mkdir -p out/fuzzer$i
cp -r trees out/fuzzer$i/
done
```
### 使用 Grammar Mutator 对目标进行模糊测试!
让我们开始运行 fuzzer。
以下示例命令使用 Ruby 语法(来自 `grammars/ruby.json`),其中 `mruby` 项目已克隆到根 `Grammar-Mutator` 目录。
`afl-fuzz` 中子进程的默认内存限制为 `75M`。
这对于某些测试用例可能不够,因此建议通过添加选项 `-m 128` 将其增加到 `128M`。
```
export AFL_CUSTOM_MUTATOR_LIBRARY=./libgrammarmutator-ruby.so
export AFL_CUSTOM_MUTATOR_ONLY=1
afl-fuzz -m 128 -i seeds -o out -- /path/to/target @@
```
您可能会注意到,fuzzer 在模糊测试开始时会卡住一段时间。
卡住的一个原因是我们选择了较大的 `max_size`(即 1000),这导致测试用例的大小较大,从而增加了加载时间。
另一个原因是语法变异器中解析操作的成本很高。
由于输入种子是字符串格式,语法变异器首先需要将它们解析为树表示形式,这是非常耗时的。
传递给 `grammar_generator-$GRAMMAR` 的大 `max_size` 确实有助于我们生成深度嵌套的树,但它进一步增加了解析开销。
### 更改默认配置
除了确定性规则变异外,用户可以通过设置相关的环境变量来更改以下三种类型变异的默认数量:
- `RANDOM_MUTATION_STEPS`:随机变异的数量
- `RANDOM_RECURSIVE_MUTATION_STEPS`:随机递归变异的数量
- `SPLICING_MUTATION_STEPS`:拼接变异的数量
默认情况下,这三种变异的数量各为 1000。如果需要,请按如下方式自行增加。:)
```
export RANDOM_MUTATION_STEPS=10000
export RANDOM_RECURSIVE_MUTATION_STEPS=10000
export SPLICING_MUTATION_STEPS=10000
export AFL_CUSTOM_MUTATOR_LIBRARY=./libgrammarmutator-ruby.so
export AFL_CUSTOM_MUTATOR_ONLY=1
afl-fuzz -m 128 -i seeds -o out -- /path/to/target @@
```
## 联系方式与贡献
我们欢迎任何问题和贡献!随时开放 Issue 或提交 Pull Request!
标签:AFL++, ANTLR4, API密钥检测, C/C++, F1 Fuzzer, Fuzzing, Git, Grammar Mutator, JSON, Nautilus, TLS抓取, 事务性I/O, 代码安全, 变异算法, 文件格式解析, 树形变异, 测试工具, 漏洞枚举, 灰盒测试, 结构化输入, 网络安全, 语法生成, 软件安全, 输入验证, 逆向工具, 隐私保护