Fuzzing llvm

1.概述

LLVM树包括许多用于各种组件的模糊器。 它们建立在LibFuzzer之上。 要构建和运行这些模糊器,请参阅配置LLVM以构建模糊器。

2.可用的Fuzzers

2.1.clang-fuzzer

一种通用的模糊器试图将输入的汇编代码转为c++代码。这个fuzzer报告的一些错误是关于bugzilla和OSS Fuzz的跟踪器。

2.2.clang-proto-fuzzer

一个基于libprotobuf-mutator的模糊器,它编译从protobuf类生成的有效C++程序,该类描述了C++语言的一个子集。

在ignore_remaining_args = 1之后,此fuzzer接受clang命令行选项。 例如,以下命令将使用更高优化级别的模糊语句:

% bin/clang-proto-fuzzer <corpus-dir> -ignore_remaining_args=1 -O3

2.3.clang-format-fuzzer

在C ++文本片段上运行clang-format的通用模糊器。 这个fuzzer报告的一些错误是关于bugzilla和OSS Fuzz的跟踪器。

2.4.llvm-as-fuzzer

扫描二维码关注公众号,回复: 6024059 查看本文章

试图将文本解析为LLVM程序集的通用模糊器。 这个fuzzer报告的一些错误是关于bugzilla的。

2.5.llvm-dwarfdump-fuzzer

一个通用的模糊器,它将输入解释为目标文件并对它们运行llvm-dwarfdump。 这个fuzzer报告的一些错误是在OSS Fuzz的跟踪器上

2.6.llvm-demangle-fuzzer

用于各种LLVM工具的Itanium demangler的通用模糊器。 我们已经将__cxa_demangle模糊到死,为什么不要模糊LLVM的同一功能!

2.7.llvm-isel-fuzzer

结构化LLVM IR模糊器,旨在发现指令选择中的错误。

这个模糊器在ignore_remaining_args = 1之后接受标志。 标志与llc匹配,三元组是必需的。 例如,以下命令将使用全局指令选择模糊AArch64:

% bin/llvm-isel-fuzzer <corpus-dir> -ignore_remaining_args=1 -mtriple aarch64 -global-isel -O0

也可以在二进制名称本身中指定一些标志,以支持OSS Fuzz,后者在必需参数方面存在问题。 为此,您可以将llvm-isel-fuzzer复制或移动到llvm-isel-fuzzer-x-y-z,使用“ - ”将选项与二进制名称分隔开。 有效选项是体系结构名称(aarch64,x86_64),优化级别(O0,O2)或特定关键字,例如用于启用全局指令选择的gisel。 在这种模式下,同样的例子可以这样运行:

% bin/llvm-isel-fuzzer--aarch64-O0-gisel <corpus-dir>

2.8.llvm-opt-fuzzer

结构化LLVM IR模糊器,旨在发现在优化过程中的错误。

它接收优化管道并为每个模糊器输入运行它。

这个模糊器的接口几乎直接反映了llvm-isel-fuzzer。 mtriple和pass参数都是必需的。 通过以适合新传递管理器的格式指定。 您可以在Doxygen for PassBuilder :: parsePassPipeline中找到有关此格式的一些文档。

% bin/llvm-opt-fuzzer <corpus-dir> -ignore_remaining_args=1 -mtriple x86_64 -passes instcombine

与某些预定义配置中的llvm isel fuzzer参数类似,这些参数可能直接嵌入到二进制文件名中: 

% bin/llvm-opt-fuzzer--x86_64-instcombine <corpus-dir>

2.9.llvm-mc-assemble-fuzzer

一种通用的模糊器,通过将输入视为目标特定的程序集来模糊MC层的汇编程序。

请注意,此fuzzer具有不常见的命令行界面,该界面与libFuzzer的所有功能都不完全兼容。 必须在--fuzzer-args之后传递Fuzzer参数,并且任何llc标志必须使用两个破折号。 例如,要模糊AArch64汇编程序,您可以使用以下命令:

llvm-mc-fuzzer --triple=aarch64-linux-gnu --fuzzer-args -max_len=4

该计划将来可能会发生变化。

2.10.llvm-mc-disassemble-fuzzer

一种通用的模糊器,通过将输入视为已组装的二进制数据来模糊MC层的反汇编程序。

请注意,此fuzzer具有不常见的命令行界面,该界面与libFuzzer的所有功能都不完全兼容。 有关详细信息,请参阅上面有关llvm-mc-assemble-fuzzer的说明。

3.Mutators and Input Generators

模糊目标的输入是通过语料库的随机突变生成的。 LLVM中的模糊器可能需要的突变种类有几种选择。

3.1.Generic Random Fuzzing

输入变异的最基本形式是使用LibFuzzer的内置变异器。 这些只是将输入语料库视为一包比特并进行随机突变。 这种类型的模糊器有助于强调程序的表层,并且擅长测试词法分析器,解析器或二进制协议。

一些使用这种类型的mutator的in-tree模糊器是clang-fuzzer,clang-format-fuzzer,llvm-as-fuzzer,llvm-dwarfdump-fuzzer,llvm-mc-assemble-fuzzer,以及llvm-mc-disassemble-fuzzer。

3.2.Structured Fuzzing using libprotobuf-mutator

我们可以使用libprotobuf-mutator来执行结构化模糊测试并强调更深层次的程序。 这通过定义一个protobuf类来工作,该类将任意数据转换为结构上有趣的输入。 具体来说,我们使用它来处理C ++语言的一个子集并执行生成有效C ++程序的突变,以便练习比解析器错误处理更有趣的clang部分。

要构建这种模糊器,您需要安装protobuf及其依赖项,并且在使用CMake配置构建时需要指定一些额外的标志。 例如,可以通过将-DCLANG_ENABLE_PROTO_FUZZER = ON添加到配置LLVM以构建模糊器中所述的标志来启用clang-proto-fuzzer。

今天唯一使用libprotobuf-mutator的in-tree模糊器是clang-proto-fuzzer。

3.3.Structured Fuzzing of LLVM IR

对于以LLVM IR为输入的模糊器,我们还使用更直接的结构模糊测试形式。 这是通过FuzzMutate库实现的,该库已在EuroLLVM 2017中进行了讨论。

FuzzMutate库用于llvm-isel-fuzzer中的结构模糊后端。

4.Building and Running

4.1.Configuring LLVM to Build Fuzzers

只要您在启用了sanitizer覆盖的情况下构建LLVM,默认情况下将构建Fuzzers并将其链接到libFuzzer。 您通常还会启用至少一个sanitizer来更快地找到错误。 构建模糊器的最常用方法是在CMake调用中添加以下两个标志:-DLLVM_USE_SANITIZER = Address -DLLVM_USE_SANITIZE_COVERAGE = On。

note:如果在使用清理程序构建时在LLVM树中检出了compiler-rt,则需要指定-DLLVM_BUILD_RUNTIME = Off以避免在启用sanitizer的情况下自行构建清理程序。

note:如果使用BFD ld构建,则可能会遇到问题,这是许多unix系统上的默认链接器。 这些问题正在https://llvm.org/PR34636中进行跟踪。

4.2.Continuously Running and Finding Bugs

曾经有一个公共buildbot连续运行LLVM模糊器,虽然这确实发现了问题,但它没有一个非常好的方式以可操作的方式报告问题。 因此,我们正在逐步使用OSS Fuzz。

您可以浏览LLVM项目问题列表,查找LLVM在OSS Fuzz上找到的错误。 这些也邮寄到llvm-bugs邮件列表。

4.3.Utilities for Writing Fuzzers

有一些实用程序可用于在LLVM中编写模糊器。

include / llvm / FuzzMutate / FuzzerCLI.h中提供了一些用于处理命令行界面的帮助程序,包括以一致的方式解析命令行选项以及实现独立的主要功能的功能,因此可以在不构建时构建和测试模糊器libFuzzer。

还有一些处理模糊器的CMake配置,你应该使用add_llvm_fuzzer来设置模糊器目标。 此函数与add_llvm_tool等函数的工作方式类似,但它们在适当时负责链接到LibFuzzer,并且可以传递DUMMY_MAIN参数以启用独立测试。

猜你喜欢

转载自blog.csdn.net/zhang14916/article/details/89203728