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:
配置示例:
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
import frelatage
def myfunction(input1_string, input2_int):
pass
input1 = frelatage.Input(value="initial_value")
input2 = frelatage.Input(value=2)
f = frelatage.Fuzzer(
# 要模糊测试的方法
method=myfunction,
# 语料库
corpus=[[input1], [input2]],
# 线程数
threads_count=8,
# 会被视为异常的类型
exceptions_whitelist=(OSError),
# 不会被视为异常的类型
exceptions_blacklist=(),
# 错误报告存储目录
output_directory="./out",
# 覆盖率增加报告存储目录
coverage_directory="./cov",
# 启用或禁用静默模式
silent=False,
# 启用或禁用无限模糊测试
infinite_fuzz=False
)
f.fuzz()
请记住,与许多其他计算密集型任务类似,模糊测试可能会对您的硬件和操作系统造成压力。具体而言:
您的 CPU 会运行高温,需要足够的冷却。在大多数情况下,如果冷却不足或停止正常工作,CPU 速度会自动降低。但特别是在不太适合的硬件(笔记本电脑、智能手机等)上进行模糊测试时,发生故障并非完全不可能。
目标程序可能会不稳定地占用数 GB 内存或用垃圾文件填满磁盘空间。Frelatage 会尝试执行基本的内存限制,但无法防止每一种可能的事故。底线是,您不应该在数据丢失风险不可接受的系统上进行模糊测试。
模糊测试涉及数十亿次的文件系统读写。在现代系统上,这通常会被高度缓存,导致相当适度的“物理” I/O —— 但有许多因素可能会改变这一状况。您有责任监控潜在问题;在非常高的 I/O 情况下,许多 HDD 和 SSD 的寿命可能会缩短。
在 Linux 上监控磁盘 I/O 的一个好方法是使用 'iostat' 命令:
$ iostat -d 3 -x -k [...可选的磁盘 ID...]
我是 Rog3rSm1th,21 岁,法国计算机与网络安全爱好者。我喜欢开发工具(OSINT、模糊测试……)和参加 CTF/战争游戏。要了解更多关于我和我的项目,请点击此处。
➜ 如果您想雇佣我开发您的项目(编程、网络安全等),请通过 [email protected] 联系我,我们将一起评估您的需求。
对于任何建议、意见、错误报告,或者如果您使用 Frelatage 发现了错误,可以通过 [email protected] 或 Twitter @Rog3rSm1th 联系我。
| 环境变量 | 描述 | 可能的值 | 默认值 |
|---|
| 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 |