pip3 install frelatage
世界应得的 Python 模糊测试工具
安装 | 工作原理 | 特性 | 使用 Frelatage | 配置
Frelatage 是一个基于覆盖率的 Python 模糊测试库,可用于模糊测试 Python 代码。Frelatage 的开发灵感来自各种其他模糊测试器,包括 AFL/AFL++、Atheris 和 PythonFuzz。该项目的主要目的是利用这些模糊测试器的最佳特性,将它们整合到一个新工具中,以高效地模糊测试 Python 应用程序。
免责声明:本项目处于 alpha 阶段,仍可能导致许多意外行为。Frelatage 目前不应在生产环境中使用。
pip3 install frelatage
推荐给开发者。它会自动从 frelatage 仓库克隆主分支,并从源码安装。
# 自动克隆 Frelatage 仓库并从源码安装 Frelatage
bash <(wget -q https://raw.githubusercontent.com/Rog3rSm1th/Frelatage/main/scripts/autoinstall.sh -O -)
Frelatage 设计背后的理念是使用遗传算法生成突变,以覆盖尽可能多的代码。一个模糊测试周期的大致功能可以用下图概括:
graph TB
m1(变异 1) --> |输入| function(被模糊测试的函数)
m2(变异 2) --> |输入| function(被模糊测试的函数)
mplus(变异 ...) --> |输入| function(被模糊测试的函数)
mn(变异 n) --> |输入| function(被模糊测试的函数)
function --> generate_reports(生成报告)
generate_reports --> rank_reports(排名报告)
rank_reports --> select(选择最佳 n 个报告)
select --> |变异| nm1(变异 1) & nm2(变异 2) & nmplus(变异 ...) & nmn(变异 n)
subgraph 当前周期变异
direction LR
m1
m2
mplus
mn
end
subgraph 下一周期变异
direction LR
nm1
nm2
nmplus
nmn
end
style function fill:#5388e8,stroke:white,stroke-width:4px
Frelatage 允许通过传递文件作为输入来模糊测试函数。
import frelatage
import my_vulnerable_library
def MyFunctionFuzz(data):
my_vulnerable_library.parse(data)
input = frelatage.Input(value="initial_value")
f = frelatage.Fuzzer(MyFunctionFuzz, [[input]])
f.fuzz()
Frelatage 允许您模糊测试文件类型的输入参数。要初始化这些文件的值,您必须在输入文件夹(默认为 ./in)中创建文件。
如果我们想初始化用于模糊测试的文件的值,可以这样做:
echo "initial value" > ./in/input.txt
然后运行模糊测试器:
import frelatage
import my_vulnerable_library
def MyFunctionFuzz(data):
my_vulnerable_library.load_file(data)
input = frelatage.Input(file=True, value="input.txt")
f = frelatage.Fuzzer(MyFunctionFuzz, [[input]])
f.fuzz()
import frelatage
import my_vulnerable_library
input = frelatage.Input(file=True, value="input.txt")
@frelatage.instrument([[input]])
def MyFunctionFuzz_1(data):
my_vulnerable_library.load_file(data)
@frelatage.instrument([[input]])
def MyFunctionFuzz_1(data):
my_vulnerable_library.load_file_but_different(data)
# 以此类推
# 它将逐个模糊测试被工具化的方法
frelatage.Fuzzer.fuzz_all()
如果您需要一次将多个文件加载到语料库中(如果您使用大型语料库,这很有用),您可以使用 Frelatage 的内置函数 load_corpus。该函数返回一个输入列表。
load_corpus(directory: str, file_extensions: list) -> list[Input]
./、./images["jpeg", "gif"]、["pdf"]import frelatage
import my_vulnerable_library
def MyFunctionFuzz(data):
my_vulnerable_library.load_file(data)
my_vulnerable_library.load_file(data2)
# 加载 ./in 目录中的所有文件
corpus_1 = frelatage.load_corpus(directory="./")
# 加载 ./in/images 子目录中的所有 .gif/.jpeg 文件
corpus_2 = frelatage.load_corpus(directory="./images", file_extension=["gif", "jpeg"])
f = frelatage.Fuzzer(MyFunctionFuzz, [corpus_1, corpus_2])
f.fuzz()
您可以将一个或多个字典(位于此处)复制到专门用于字典的目录中(默认为 ./dict)。
差分模糊测试 是一种流行的软件测试技术,它通过向多个库/程序提供相同的输入并观察其行为的差异来检测错误。您可以在此处找到一个使用 Frelatage 和 json、ujson 库进行差分模糊测试的示例。
您可以在 examples 目录中找到更多模糊测试器和语料库的示例。
每个崩溃报告都保存在输出文件夹(默认为 ./out)中,文件夹命名格式为:id:<crash ID>,err:<error type>,err_pos:<error>,err_file:<error file>。
报告目录结构如下:
├── out
│ ├── id:<crash ID>,err:<error type>,err_file:<error file>,err_pos:<err_pos>
│ ├── message
│ ├── input
│ ├── 0
│ ├── <inputfile1>
│ ├── ...
│ ├── ...
每个崩溃报告包含一个 message 文件,其中包含错误信息。
每个覆盖率增加报告都保存在覆盖率文件夹(默认为 ./cov)中,文件夹命名格式为:coverage_<ID>,报告目录结构与崩溃报告目录结构相同。
传递给函数的输入在被保存到 <report_folder>/input 文件之前,会使用 pickle 模块进行序列化。因此,需要反序列化才能读取文件内容。此操作可以通过 frelatage-report 命令完成。
$ frelatage-report input
有两种方式配置 Frelatage:
| 环境变量 | 描述 | 可能的值 | 默认值 |
|---|---|---|---|
| FRELATAGE_DICTIONARY_ENABLE | 启用基于字典元素的变异 | 1 启用,0 禁用 | 1 |
| FRELATAGE_SAVE_NEW_COVERAGE | 保存新的覆盖率输入以便以后重用 | 1 启用,0 禁用 | 1 |
| FRELATAGE_TIMEOUT_DELAY | 函数返回 TimeoutError 的超时延迟(秒) | 1 - infinity | 2 |
| FRELATAGE_INPUT_FILE_TMP_DIR | 输入文件的临时存储文件夹 | 绝对路径,例如 /tmp/custom_dir | /tmp/frelatage |
| FRELATAGE_INPUT_MAX_LEN | 输入变量的最大大小(字节) | 4 - infinity | 4094 |
| FRELATAGE_MAX_THREADS | 最大同时线程数 | 8 - infinity | 8 |
| FRELATAGE_MAX_STAGES | 被模糊测试函数的最大阶段数 | 1 - infinity | 1000000 |
| FRELATAGE_MAX_CYCLES_WITHOUT_NEW_PATHS | 在未发现新路径后进入下一阶段前的最大周期数 | 10 - infinity | 5000 |
| FRELATAGE_INPUT_DIR | 包含初始输入文件的目录。需要是相对路径(相对于模糊测试文件的路径) | 相对路径,例如 ./in | ./in |
| FRELATAGE_DICTIONARY_DIR | 字典的默认目录。需要是相对路径(相对于模糊测试文件的路径) | 相对路径,例如 ./dict | ./dict |
| FRELATAGE_DEBUG_MODE | 启用调试模式(在 Frelatage 崩溃时显示错误) | 1 启用,0 禁用 | 1 |
配置示例:
export FRELATAGE_DICTIONARY_ENABLE=1 &&
export FRELATAGE_SAVE_NEW_COVERAGE=1 &&
export FRELATAGE_TIMEOUT_DELAY=2 &&
export FRELATAGE_INPUT_FILE_TMP_DIR="/tmp/frelatage" &&
export FRELATAGE_INPUT_MAX_LEN=4096 &&
export FRELATAGE_MAX_THREADS=8 &&
export FRELATAGE_MAX_STAGES=1000000 &&
export FRELATAGE_MAX_CYCLES_WITHOUT_NEW_PATHS=5000 &&
export FRELATAGE_INPUT_DIR="./in" &&
export FRELATAGE_DICTIONARY_DIR="./dict" &&
python3 fuzzer.py