test fuzz-03-模糊测试 Atheris A Coverage-Guided, Native Python Fuzzer

发布时间:2024年01月09日

拓展阅读

开源 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

test fuzz-07-模糊测试 libfuzzer

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
    

    这将导致在foobar上添加插桩,以及它们导入的任何库。

  • 或者,你可以对单个函数进行插桩:

    @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.startswithstr.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 的一些关键特点和工作原理:

特点:

  1. 基于 LLVM: libFuzzer 是 LLVM(Low Level Virtual Machine)的一部分,是 LLVM 的一种插件。因此,它可以与 LLVM 兼容,并直接集成到 LLVM 编译器中。

  2. 快速且高效: libFuzzer 被设计为高效执行大规模模糊测试。它使用一种称为"基于覆盖率的反馈"(coverage-guided feedback)的方法,通过监视程序的代码覆盖率来引导模糊测试的输入生成。这使得 libFuzzer 能够快速探索程序的不同执行路径。

  3. 无需源代码更改: libFuzzer 可以直接用于未修改的二进制程序,而无需对其源代码进行任何更改。这对于测试封闭源代码的程序或对现有代码进行快速测试非常有用。

  4. 支持多种语言: libFuzzer 不仅支持 C/C++,还支持其他编程语言,例如 Rust、Swift 等。这使得它成为一个通用的模糊测试工具。

  5. 内嵌的输入生成器: libFuzzer 包含一个内置的输入生成器,可以自动生成具有高覆盖率的输入。这减轻了用户编写自定义输入生成器的负担。

在这里插入图片描述

文章来源:https://blog.csdn.net/ryo1060732496/article/details/135473434
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。