ex0dus-0x/fuzzable
GitHub: ex0dus-0x/fuzzable
基于静态分析的自动化框架,用于在源代码和二进制文件中识别最适合进行 fuzzing 的目标函数并生成 harness 模板。
Stars: 550 | Forks: 59
# Fuzzable
[](https://github.com/ex0dus-0x/fuzzable/actions)
[](https://badge.fury.io/py/fuzzable)
[](https://raw.githubusercontent.com/toolswatch/badges/master/arsenal/usa/2022.svg)
通过静态分析自动化发现 _Fuzzable_ 目标的框架

## 介绍
对软件进行安全评估的漏洞研究员经常会通过 AFL++ 和 libFuzzer 等强大的工具来利用覆盖率引导的 fuzzing 能力。这非常重要,因为它自动化了找 bug 的过程,并能快速揭示目标中可利用的条件。然而,当遇到庞大且复杂的代码库或闭源二进制文件时,研究人员必须煞费苦心地花时间手动审计和逆向工程它们,以确定哪些函数适合进行基于 fuzzing 的探索。
__Fuzzable__ 是一个同时支持 C/C++ 源代码和二进制文件的框架,旨在帮助漏洞研究员识别适合进行 fuzzing 的目标函数。它通过应用多种基于静态分析的启发式方法,来精准定位软件中的危险行为及其执行这些行为的函数。然后,研究人员可以利用该框架生成基础的 harness 模板,用于寻找漏洞,或将其整合到持续的 fuzzing pipeline 中,例如 Google 的 [oss-fuzz](https://github.com/google/oss-fuzz) 项目。
除了作为独立工具运行外,Fuzzable 还作为 [Binary Ninja ](https://binary.ninja) 反汇编器的插件集成,并正在开发对其他反汇编后端的支持。
请在此处[查看](https://codemuch.tech/2021/06/07/fuzzabble/)详细介绍该工具的原始博客文章,其中重点介绍了静态分析启发式方法的技术规范以及该工具的开发背景。该工具还在 [Black Hat Arsenal USA 2022](https://www.blackhat.com/us-22/arsenal/schedule/index.html#automating-fuzzable-target-discovery-with-static-analysis-26726) 上展出。
## 特性
* 支持分析 __二进制文件__(通过 [Angr](https://angr.io) 和 [Binary Ninja](https://binary.ninja))以及
__源代码__ 产物(通过 [tree-sitter](https://tree-sitter.github.io/tree-sitter/))。
* 既可以作为 __独立的 CLI 工具__ 运行,也可以作为 __Binary Ninja 插件__ 进行静态分析。
* 支持 __harness 生成__,帮助快速启动 fuzzing 活动。
## 安装
某些二进制目标可能需要进行一些清洗(例如:签名匹配,或识别内联函数),因此
__fuzzable__ 主要使用 Binary Ninja 作为反汇编后端,因为它能够有效地解决这些问题。因此,它既可以作为独立工具使用,也可以作为插件使用。
由于 Binary Ninja 并非所有人都能使用,而且在安全评估和潜在的云端扩展方面可能存在需求,因此我们也支持使用 [angr](https://github.com/angr/angr)
作为 _备用_ 后端。我预计未来还会引入其他反汇编器(优先:Ghidra)。
### 命令行(独立模式)
如果您拥有 Binary Ninja 商业版,请务必安装其 API 以进行无头(headless)独立使用:
```
$ python3 /Applications/Binary\ Ninja.app/Contents/Resources/scripts/install_api.py
```
使用 `pip` 安装:
```
$ pip install fuzzable
```
### 手动/开发构建
我们使用 [poetry](https://python-poetry.org) 进行依赖管理和构建。要进行手动构建,请使用第三方模块克隆此代码库:
```
$ git clone --recursive https://github.com/ex0dus-0x/fuzzable
```
手动安装:
```
$ cd fuzzable/
# 不使用 poetry
$ pip install .
# 使用 poetry
$ poetry install
# 使用 poetry 为开发 virtualenv
$ poetry shell
```
现在您可以开始使用该工具分析二进制文件和/或源代码了!
```
# 分析单个 shared object library 二进制文件
$ fuzzable analyze examples/binaries/libbasic.so
# 分析单个 C 源文件
$ fuzzable analyze examples/source/libbasic.c
# 分析包含多个 C/C++ 文件和头文件的 workspace
$ fuzzable analyze examples/source/source_bundle/
```
### Binary Ninja 插件
只需进入 `Binary Ninja > Manage Plugins` 并搜索,即可通过 Binary Ninja 插件市场轻松安装 __fuzzable__。以下是运行 __fuzzable__ 插件的示例,它能够精准识别适合 fuzzing 及进一步漏洞评估的目标:

## 用法
__fuzzable__ 提供了多种选项,帮助您更好地调整分析过程。未来将支持更多功能,我们也欢迎提出任何功能请求。
### 静态分析启发式方法
为了确定 fuzzability,__fuzzable__ 使用多种启发式方法来决定哪些目标最适合进行动态分析。这些启发式方法通过 [scikit-criteria](https://scikit-criteria.quatrope.org/en/latest/tutorial/quickstart.html) 库被赋予了不同的权重,该库利用 _多准则决策分析_ 来确定最佳候选目标。这些指标及其权重如下所示:
| 启发式方法 | 描述 | 权重 |
|-----------------------|-------------------------------------------------------------|--------|
| Fuzz 友好名称 | 符号名暗示了会接收文件/buffer 输入的行为 | 0.3 |
| 危险 Sink | 流向危险调用(如 memcpy)的参数 | 0.3 |
| 自然循环 | 通过支配边界(dominance frontier)检测到的循环数量 | 0.05 |
| 圈复杂度 | 基于边和节点得出的函数目标复杂度 | 0.05 |
| 覆盖深度 | 目标向下遍历的 callee 数量 | 0.3 |
许多指标在很大程度上受到了 [Vincenzo Iozzo 在 0-knowledge fuzzing 方面的开创性工作](https://resources.sei.cmu.edu/asset_files/WhitePaper/2010_019_001_53555.pdf) 的启发。
您想要分析的每一个目标都是多样的,__fuzzable__ 无法兼顾程序目标中的每一种边缘情况。因此,在分析过程中,适当地 _调整_ 这些权重可能会非常重要,以便观察不同的结果是否更符合您的使用场景。要在 CLI 中调整这些权重,只需指定 `--score-weights` 参数:
```
$ fuzzable analyze --score-weights=0.2,0.2,0.2,0.2,0.2
```
### 分析过滤
默认情况下,__fuzzable__ 会根据以下标准过滤掉部分函数目标:
* __顶层入口调用__ - 未被目标中任何其他调用调用的函数。它们是理想的入口点,具有极高的潜在覆盖率。
* __静态调用__ - _(仅限源代码)_ 标记为 `static` 且未通过头文件公开的函数。
* __导入__ - _(仅限二进制文件)_ 目标实现所使用的其他库依赖项。
要查看被 __fuzzable__ 过滤掉的调用,请设置 `--list_ignored` 标志:
```
$ fuzzable analyze --list-ignored
```
在 Binary Ninja 中,您可以在 `Settings > Fuzzable > List Ignored Calls` 中开启此设置。
如果 __fuzzable__ 错误地过滤掉了本应被分析的重要调用,建议使用 `--include-*` 参数
将它们包含在运行中:
```
# 包含所有被过滤掉的非顶层调用
$ fuzzable analyze --include-nontop
# 包含被过滤掉的特定 symbols
$ fuzzable analyze --include-sym
```
在 Binary Ninja 中,可以通过 `Settings > Fuzzable > Include non-top level calls` 和 `Symbols to Exclude` 来进行此设置。
### Harness 生成
现在您已经找到了理想的 fuzzing 候选目标,__fuzzable__ 还将帮助您生成 fuzzing harness,这些 harness 几乎可以直接准备好进行插桩和编译,以便与基于文件的 fuzzer(如 AFL++, Honggfuzz)或内存内 fuzzer(libFuzzer)配合使用。要在 CLI 中执行此操作:
```
# 从 candidate 生成 harness
$ fuzzable create-harness target --symbol-name=some_unsafe_call
# 对 harness 进行最小且必要的修改
$ vim target_some_unsafe_call_harness.cpp
# AFL-QEMU 的示例编译,这在生成的 harness 的注释中已指定
$ clang target_some_unsafe_call_harness.cpp -no-pie -o target_some_unsafe_call_harness -ldl
# 创建您的基础 seeds,理想情况下应针对输入更加格式良好
$ mkdir in/
$ echo "seed" >> in/seed
# 开始 black box fuzzing
$ afl-fuzz -Q -m none -i in/ -o out/ -- ./target_some_unsafe_call_harness
```
如果此目标是源代码库,将使用[通用源码模板](/templates/linux_source_harness.cpp)。
如果目标是二进制文件,则将使用[通用黑盒模板](/templates/linux_closed_source_harness.cpp),理想情况下,该模板可与 [AFL-QEMU](https://github.com/mirrorer/afl/blob/master/qemu_mode/README.qemu) 等 fuzzing 模拟模式配合使用。如果未直接导出符号,还会使用 [LIEF](https://lief-project.github.io) 将该二进制文件的副本创建为可供 `dlopen` 加载的共享对象(shared object)。
目前,此功能还相当基础,因为它只是简单地生成一个填充了适当参数的独立 C++ harness,而不会自动生成任何运行时行为(例如实例化和释放结构体)所需的代码。不过,为 __fuzzable__ 创建的模板依然能让您迅速进入运行状态。以下是未来我希望实现的一些极具挑战性的功能:
* 完整的 harness 合成 - 无需任何手动修改即可直接使用的 harness。
* 使用 [DeepState](https://github.com/trailofbits/deepstate) 框架从潜在的单元测试中进行合成 _(仅限源代码)_。
* 立即部署到托管的持续 fuzzing 集群中。
### 导出报告
__fuzzable__ 支持生成多种格式的报告。目前支持的格式包括 JSON、CSV 和 Markdown。如果您将其作为自动化流程的一部分使用,并希望以可序列化格式提取输出,这将非常有用。
在 CLI 中,只需传入带有相应扩展名的文件名并附带 `--export` 参数:
```
$ fuzzable analyze --export=report.json
```
在 Binary Ninja 中,请转到 `Plugins > Fuzzable > Export Fuzzability Report > ...`,选择您想要
导出的格式以及写入的路径。
## 贡献
该工具将持续开发,欢迎并感谢任何外部维护者的帮助!
* 如果您遇到功能请求或 bug,请创建一个 [issue](https://github.com/ex0dus-0x/fuzzable/issues)。
* 如果您希望提交修复和增强功能,请提交 [pull request](https://github.com/ex0dus-0x/fuzzable/pulls)。
## 许可证
Fuzzable 基于 [MIT 许可证](https://codemuch.tech/license.txt) 授权。
标签:云安全监控, 云资产清单, 逆向工具, 逆向工程, 静态分析