代码改变世界

Hawkeye: Towards a Desired Directed Grey-box Fuzzer

2020-08-31 20:36  huhee  阅读(550)  评论(0编辑  收藏  举报

题目:Hawkeye: Towards a Desired Directed Grey-box Fuzzer

作者:Hongxu Chen ; Yinxing Xue∗ ; Yuekang Li ; Bihuan Chen

单位:Nanyang Technological University Singapore, Singapore Fudan University Shanghai, China

出版:CCS’18, October 15-19, 2018, Toronto, ON, Canada

目标:设计高效的定向灰盒模糊器

现有工作:

现有基于距离的DGF(代表是AFLGO)主要有以下几个方面的不足

1)target函数可以在PUT的任意位置,很多不同的trace都可以到达target;

2)因为call graph很大程度地影响了trace距离的计算(与target sites的差异),所以它需要很准确地构建;特别地,函数间的间接调用不应该被忽略。

如果上述两个问题没有解决好,基于距离的方法就会是一种阻碍,难以找到隐藏在深的函数调用序列中的漏洞。

理想的定向灰盒模糊的四种所需属性:

P1 DGF应该具有强大的基于距离的机制,来引导定向模糊测试。需要考虑能到达目标的所有trace,避免偏向某些trace。

P2 DGF应在静态分析中达到耗费(overheads)和效用(utilities)之间的平衡。

P3 DGF应优先考虑并调度可以快速到达目标的种子。

P4当种子覆盖不同的程序状态时,DGF应采用自适应的变异策略。

需要解决的两个问题:

如何进行适当的静态分析,收集DGF的必要信息?

如何对DGF中使用的动态策略进行适当调整?

方案:

对于P1,应用静态分析结果计算相邻函数距离;并且在计算函数级距离和基本块级距离时加入相邻函数距离,以模拟函数之间的关系强度。同时,在模糊测试期间,通过将静态分析结果与运行时执行信息相结合,来计算基本块跟踪距离和执行trace与目标函数覆盖相似性。

对于P2,应用基于调用图(CG)和控制流图(CFG)的分析,即函数级可达性分析,函数指针的point-to分析(间接调用)和基本块度量。

对于P3,结合基本块trace距离和覆盖函数相似性来解决功率调度问题和种子优先级排序问题。

对于P4,根据可达性分析和覆盖函数相似性应用自适应变异策略。(自适应变异策略包含种子排优先级;根据是否达到目标决定是粗粒度、细粒度变异的分配;根据是否是xml等有规则的输入确定选择何种粗粒度变异器)

方法设计:

Hawkeye的workflow主要包括两个组件:静态分析和fuzzing loop.

Static Analysis

输入: 程序源码、目标位置

输出:带有基本块距离的插桩程序

步骤:生成CG和CFG,以及基于闭包的函数指针分析。通过计算整个程序内的函数point-to集合,构建包括所有直接和间接调用的相对精确的调用图。---P2(比LLVM内置的API更精确,又不像上下文/流敏感的分析成本高)。

1-Function level distance

1)Adjacent-Function Distance Augmentation

1.1Call site occurrences CN of a certain callee for a given caller(caller中调用多少次特定callee)

1.2The number of basic blocks CB in the caller that contains at least one call site of the callee.(caller 中有几个基本块包含对callee的调用)

那么,augmented adjacent-function distance(相邻函数距离)就是

note:AFLGO中的相邻函数距离是1.
2)函数目标距离

其中R(n,Tf ) ={tf|reachable(n,tf)}.
df(n,tf)是基于从n到CG中给定目标函数tf的增广函数距离的dijkstra最短路径。

2-Basic block level distance
3-Target function trace closure

收集所有target函数tf的前驱,直到main函数。

Fuzzing Loop

输入:插桩后的二进制,初始种子,目标位置,函数级距离、目标函数trace闭包等

输出:导致程序异常行为(crash、timeout)的种子

步骤:从优先级队列选择种子;对种子应用功率调度,赋予种子能量;对种子进行自适应突变;对新生成的种子计算覆盖函数相似度以及基本块trace距离,放进对应的优先级队列。

1-Power Scheduling

基于基本块trace距离和目标函数trace相似性两个度量,决定种子的功率。

Basic Block Trace Distance.

与AFLGO的公式相同,计算执行trace的基本块目标距离累加,然后进行min-max归一化。

Covered Function Similarity.
度量执行trace在函数级别上与目标之间的相似性:依据直觉:覆盖更多函数的种子更可能变异达到目标。比较当前种子trace的函数级与目标函数trace闭包的相似性。

main-》a->c-》d

SVF:

对种子trace覆盖的函数与目标函数trace闭包之间的交集,计算其函数距离的调和平均。

然后进行归一化。

Scheduling.

为了避免像aflgo的那种对短路径的偏向,本文同时考虑了trace distance和trace similarity,计算得到种子能量.

2-Adaptive Mutation

输入:种子能量

目的:在总能量已知的情况下,分配每种类型突变的数量。

两种类型突变:

粗粒度:

(1) Mixed havoc.(混合破坏)这包括几个批量突变,即删除一大块字节,用缓冲区中的其他字节覆盖给定的块,删除某些行,多次复制某些行等等。实际的突变涉及它们的组合。

(2) Semantic mutation.当已知目标程序处理语义相关的输入文件(如javascript,xml,css等)时使用。详细说明,这遵循Skyfire,其中包括三个元突变,将另一个子树插入随机AST位置, 删除给定的AST,并用另一个AST替换给定的位置。

(3) Splice.这包括队列中两个种子之间的交叉以及随后的混合破坏。

细粒度:

只涉及几个字节级的修改,插入或删除(比如位/字节翻转,某些字节上的算术)

自适应调度:

根据种子是否到达目标,调整进行粗粒度和细粒度变异的时间分配。

粗粒度变异:

根据是否需要语义上的变异,决定是否需要semMutates,以及coarseHavoc、splice突变的时间分配。

Seed Prioritization

提供了一个三层队列,根据分数将新生成的种子附加到不同的类别中。首先挑选顶层队列(第1层)中的种子,然后是第二层(第2层),最后是较低层(第3层)。 这模仿了具有恒定时间复杂度的简化优先级队列。

优先级排序策略:

第一层队列:新生成的种子中,满足1)覆盖新的trace;或者2)与目标种子具有更大的相似性值(即功率函数值);或者3)覆盖目标函数。
第二层队列:其他新生成的种子。

第三层队列:已经变异过的种子。

评估:

Hawkeye可以到达目标站点,并且比现有的最先进的灰盒模糊器更快地重现崩溃。可以用于进行补丁测试,crash暴露和其他情况

未来工作

扩展Hawkeye以支持二进制模糊测试;结合基于覆盖的灰盒模糊,如CollAFL、Skyfire等。

与AFLGO的对比:

考虑了相邻函数的增强距离(AFLGO将相邻函数距离视为1);

加入了种子优先级排序;(AFLGO没有修改AFL的种子选择,应该是按照放入顺序选取)

功率调度不仅考虑基本块trace距离,还是考虑了函数覆盖情况;(AFLGO只考虑距离可能更倾向短的路径)

自适应的功率调度,设计选择变异类型的策略。(AFLGO使用afl的变异策略)

lava-m、cgc