Proj EULibHarn Paper Reading: FUDGE: Fuzz Driver Generation at Scale
Abstract
任务: driver synthesis
生成c/c++代码和对应的build script,此外会自动分析driver质量
效果: 200多个生成的driver已经被用在真实测试环境中,一些在OSS-Fuzz中
效果: 150+bugs
1. Intro
本文认为生成driver的挑战: 了解codebase,了解fuzzer
本文中fuzz target和fuzz driver是相同的概念
好driver需要满足:
- 了解codebase和参数、例如图片处理时多需要给一个有基本图片格式的
- 要保证崩溃来自于bug而非driver本身的问题或者没有满足library的前置条件
- driver本身应当是确定且无后效的
本文: FUDGE
生成driver,之后只需要小幅度人工修改,基于clangMR,高度并行化
基本方法:通过一个后端pipeline处理整个google codebase,生成fuzz target candidates
- 扫描google codebase,获取 a) 目标库的使用 b) 有趣的代码片段
- 合成
- 用libfuzzer试运行,收集feedback a) code coverage b) 生成的测试大小 c) crashes结果
- 用前端展示,允许用户修改
2. Overview
整个pipeline是分布式的,每天都会运行一次,然后把结果存在数据库中。此外,是OSS-Fuzz的一部分,能可视化。
Pipeline分为三步:1. Slicing 2. Synthesis 3. Evaluation
Slicing: 扫描整个代码仓库抽取代码片段,用修改后的Clang解析,抽取调用目标库函数的序列
- 抽取调用了目标库函数的语句。这里的目标库函数来自于目标库,且接受一个buffer作为参数
- 与这些语句有操作依赖、数据依赖的语句
不应被包进去的 - 包含非目标库的复杂结构类型的
- 在函数域之外定义的符号,即使是int也被标为UnknownX
Synthesis: 使用placeholder上的变量信息做实例化,用0、1等常量或者交给fuzzer的前几个byte。因为选择的策略不同,组合起来策略更多,FUDGE选择生成不同版本。
Evaluation: 每个候选driver都会在设置好的时限中跑一遍,删掉明显API无用的driver,把可行的eval results存入数据库
User interface and workflow: 能够浏览、过滤、排名
用户可以这样完成一个workflow,这使得对fuzzing毫无了解的用户也能轻易入手
- pull目标库和对应的build file
- 用libfuzzer直接测试目标库
- 如果存在bugs,检查,修复
- check in
3. Design
尽量基于MapReduce(c++, Flume),以完成并行化操作
3.1 AST Slicing
能仅用ClangMR花几个小时扫描完整个google codebase
为了快速,不做别名分析
数据流依赖项定义为:
- 与S需要的变量定义相关
- 使用S中定义变量的控制语句
控制流依赖项定义为:
- 领导S中语句的控制语句
- 打破控制流的跳转指令如break、continue
要去除的依赖项:
- 将带有unknown types和unknown symbol的表达式换成UnknownX placeholder。
注意分析可以是跨函数的。
Q: Note that if a refered func is defined in the same translation unit, we can slice it interprocedurally
prevent from slicing out client library specfic code
获得当前dependency后(前后传播直至不变点),在LLVMfuzzerTestOneInput中重构代码
- 延迟import全局变量和常数
- 允许递归切出
- 将所有reutrn statement都改为return 0
此外,还将抽取依赖的include和build这些code snippet所需信息,作为metadata存进数据库中
由于google codebase中全部build dependency都存在Bazel中,所以可以快速提出build相关信息
3.2 Target Synthesis
{{uploading-image-784764.png(uploading...)}}
3.3 Target Evaluation
3.4 User Interface
4. Case Studies
4.1
生成14个fuzz targets
限制:无法比单元测试更难,因此无法突破UnknownX和类型转换之间的问题
4.2 OpenCV
生成2个fuzz targets,39个fixed bugs,其中12个与安全相关
这里借助catching exception这件事说明了为何要生成多个candidates并排序
4.3 HTSlib
36bugs,说明了临时文件
5. Lessons learned
Lesson 1: Choosing a suitable fuzz target (still) requires a human
Lesson 2: API call sites present good locality
对于许多 API 来说,足够多的使用都在单个单元甚至功能级别内,因而无需函数间分析。
Lesson 3: Analyzing C++ is challenging due to a long tail of language features.
C++ is a complex language, with language features spanning classes, template metaprogramming, and complex scoping rules
Lesson 4: Randomized algorithms have a good cost-value tradeoff for program synthesis.
Lesson 5: Program synthesis artifacts can be presented as code findings to developers
6. Related Work
7. Future work
- 动态执行建立driver
- 使用机器学习