test fuzz-03-模糊测试 Atheris A Coverage-Guided, Native Python Fuzzer
拓展阅读
开源 Auto generate mock data for java test.(便于 Java 测试自动生成对象信息)
开源 Junit performance rely on junit5 and jdk8+.(java 性能测试框架。性能测试。压测。测试报告生成。)
test fuzz-01-模糊测试(Fuzz Testing)
test fuzz-02-模糊测试 JQF + Zest Semantic Fuzzing for Java
test fuzz-03-模糊测试 Atheris A Coverage-Guided, Native Python Fuzzer
test fuzz-04-模糊测试 jazzer Coverage-guided, in-process fuzzing for the JVM
test fuzz-05-模糊测试 kelinci AFL-based fuzzing for Java
test fuzz-06-模糊测试 AFL american fuzzy lop - a security-oriented fuzzer
Atheris
Atheris: 一个基于覆盖率引导的本地 Python Fuzzer
Atheris是一个基于覆盖率引导的Python模糊引擎。它支持对Python代码的模糊测试,还支持为CPython编写的本地扩展。Atheris基于libFuzzer。在模糊测试本地代码时,可以与Address Sanitizer或Undefined Behavior Sanitizer结合使用,以捕获额外的错误。
安装说明
Atheris支持Linux(32位和64位)和Mac OS X,Python版本3.6-3.10。
你可以使用pip安装预构建版本的Atheris:
pip3 install atheris
这些安装包带有内置的libFuzzer,适用于对Python代码进行模糊测试。如果你计划对本地扩展进行模糊测试,可能需要从源代码构建,以确保Atheris中的libFuzzer版本与你的Clang版本匹配。
从源代码构建
Atheris依赖于libFuzzer,该库随Clang一起分发。如果你的路径上有足够新版本的clang
,则从源代码安装就像这样简单:
# 从源代码构建最新版本
pip3 install --no-binary atheris atheris
# 从源代码构建开发代码
git clone https://github.com/google/atheris.git
cd atheris
pip3 install .
如果你没有安装clang
或者它太旧,你需要下载并构建LLVM的最新版本。请按照下面的“安装新版本的LLVM”说明进行操作。
Mac
Apple Clang不包含libFuzzer,因此你需要安装来自head的新版本的LLVM。请按照下面的“安装新版本的LLVM”说明进行操作。
安装新版本的LLVM
# 构建LLVM
git clone https://github.com/llvm/llvm-project.git
cd llvm-project
mkdir build
cd build
cmake -DLLVM_ENABLE_PROJECTS='clang;compiler-rt' -G "Unix Makefiles" ../llvm
make -j 10 # 这一步非常慢
# 安装Atheris
CLANG_BIN="$(pwd)/bin/clang" pip3 install <whatever>
使用Atheris
示例
#!/usr/bin/python3
import atheris
with atheris.instrument_imports():
import some_library
import sys
def TestOneInput(data):
some_library.parse(data)
atheris.Setup(sys.argv, TestOneInput)
atheris.Fuzz()
在对Python进行模糊测试时,如果被测试的Python代码引发未捕获的异常,Atheris将报告失败。
Python覆盖率
Atheris通过对字节码进行插桩来收集Python覆盖率信息。有三种选项可用于将此插桩添加到字节码中:
-
你可以对导入的库进行插桩:
with atheris.instrument_imports(): import foo from bar import baz
这将导致在
foo
和bar
上添加插桩,以及它们导入的任何库。 -
或者,你可以对单个函数进行插桩:
@atheris.instrument_func def my_function(foo, bar): print("instrumented")
-
或者最后,你可以对所有内容进行插桩:
atheris.instrument_all()
将其放在
atheris.Setup()
之前。这将找到解释器中当前加载的每个Python函数,并对其进行插桩。
这可能需要一些时间。
Atheris还可以插桩正则表达式检查,例如re.search
。要启用此功能,你需要添加:
atheris.enabled_hooks.add("RegEx")
在脚本调用re.compile
之前。在内部,这将导入re
模块并对必要的函数进行插桩。这是一个实验性功能。
类似地,Atheris可以插桩str方法;目前仅支持str.startswith
和str.endswith
。要启用此功能,添加
atheris.enabled_hooks.add("str")
。这是一个实验性功能。
为什么会出现“未找到任何有趣的输入”?
你可能会看到这个错误:
ERROR: no interesting inputs were found. Is the code instrumented for coverage? Exiting.
如果TestOneInput
的前两个调用未产生任何覆盖事件,你将会看到这个错误。即使你已经对一些Python代码进行了插桩,如果在这两个调用中未到达插桩点(例如,因为你有一个非平凡的TestOneInput
),这可能会发生。你可以通过在TestOneInput
上添加atheris.instrument_func
装饰器,使用atheris.instrument_all()
,或将TestOneInput
函数移到插桩的模块中来解决这个问题。
可视化Python代码覆盖率
检查哪些行已执行对于理解你的模糊测试的效果是有帮助的。Atheris与coverage.py
兼容:你可以像对待任何其他Python程序一样,使用coverage.py
模块运行你的模糊测试。以下是一个示例:
python3 -m coverage run your_fuzzer.py -atheris_runs=10000 # 运行次数
python3 -m coverage html
(cd htmlcov && python3 -m http.server 8000)
只有当你的模糊测试正常退出时,才会生成覆盖率报告。有三种情况下会正常退出:
- 你指定了
-atheris_runs=<number>
,并且已经运行了这么多次。 - 你的模糊测试通过Python异常退出。
- 你的模糊测试通过
sys.exit()
退出。
如果你的模糊测试由于本地代码崩溃或libFuzzer的-runs
标志而退出,将不会生成覆盖率报告(使用-atheris_runs
)。如果你的模糊测试通过其他方法退出,例如SIGINT(Ctrl+C),Atheris将尝试生成报告,但可能无法生成(具体取决于你的代码)。为了获得一致的报告,建议始终使用-atheris_runs=<number>
。
如果你想在运行时检查你的语料库,可以使用以下命令:
python3 -m coverage run your_fuzzer.py corpus_dir/* -atheris_runs=$(( 1 + $(ls corpus_dir | wc -l) ))
这将导致Atheris在<corpus-dir>
中的每个文件上运行,然后退出。注意:Atheris使用空数据集作为第一个输入,即使在<corpus_dir>
中没有空文件。重要的是,如果省略了-atheris_runs=$(ls corpus_dir | wc -l)
,将不会生成覆盖率报告。
使用coverage.py会显著减慢你的模糊测试,因此只在需要可视化覆盖率时使用它。
LLVM libFuzzer 是什么?
LLVM libFuzzer 是 LLVM 编译器基础设施的一部分,是一个用于模糊测试的强大引擎。模糊测试是一种自动化测试技术,它通过向程序输入注入随机或半随机的数据(称为"模糊"输入),然后监控程序的执行,以发现潜在的错误、漏洞和安全问题。
以下是 LLVM libFuzzer 的一些关键特点和工作原理:
特点:
-
基于 LLVM: libFuzzer 是 LLVM(Low Level Virtual Machine)的一部分,是 LLVM 的一种插件。因此,它可以与 LLVM 兼容,并直接集成到 LLVM 编译器中。
-
快速且高效: libFuzzer 被设计为高效执行大规模模糊测试。它使用一种称为"基于覆盖率的反馈"(coverage-guided feedback)的方法,通过监视程序的代码覆盖率来引导模糊测试的输入生成。这使得 libFuzzer 能够快速探索程序的不同执行路径。
-
无需源代码更改: libFuzzer 可以直接用于未修改的二进制程序,而无需对其源代码进行任何更改。这对于测试封闭源代码的程序或对现有代码进行快速测试非常有用。
-
支持多种语言: libFuzzer 不仅支持 C/C++,还支持其他编程语言,例如 Rust、Swift 等。这使得它成为一个通用的模糊测试工具。
-
内嵌的输入生成器: libFuzzer 包含一个内置的输入生成器,可以自动生成具有高覆盖率的输入。这减轻了用户编写自定义输入生成器的负担。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!