FuzzerGym: A Competitive Framework for Fuzzing and Learning

Abstract

Fuzzing是一种常用的技术,旨在通过自动制作程序输入来测试软件。目前,最成功的模糊算法强调简单,低开销的策略,能够在执行期间有效地监视程序状态。通过编译时仪器,这些方法可以访问程序状态的许多方面,包括覆盖范围,数据流和异构故障检测和分类。然而,现有方法在生成测试输入时利用盲随机变异策略。我们提出了一种不同的方法,使用这种状态信息来优化使用强化学习(RL)的变异算子。通过将OpenAI Gym与libFuzzer集成,我们能够同时利用强化学习的进步以及模糊测试来实现跨多个基准测试的更深层次的覆盖。我们的技术将LLVM Santizers提供的丰富,高效的程序监视器与深度神经网络连接起来,直接从输入数据中学习突变选择策略。我们开发的跨语言异步架构使我们能够将任何OpenAI Gym兼容的深度强化学习算法应用于任何模糊问题,同时最小化减速。

1.导言

模糊测试是一种广泛使用的测试技术,它通过反复使其执行生成的输入来自动探测软件程序。这些输入旨在通过在不同条件下运行尽可能多的代码路径来查找目标程序中的漏洞。生成这些程序输入集(称为输入语料库)的方法因分析和测试执行速度之间的权衡而变化。黑盒模糊测试技术[10],[20],[26]使用最少量的程序信息来快速生成输入,结果是它们产生最小深度的代码覆盖。白盒模糊测试[12]使用约束求解器对源代码进行详细分析,揭示程序分支的深层路径。虽然白盒模糊器可以实现高代码覆盖率,但每个生成的输入需要最大的计算成本。 Greybox技术在这两个极端之间找到平衡,强调简单的输入生成策略,能够以最小的开销有效地监视程序状态[40],[43]。在编译期间,诸如libFuzzer [24]和AFL [47]仪器程序的Greybox模糊器可以有效地监视测试期间的进度,使他们能够使用到目前为止所实现的覆盖量来动态地指导未来执行的输入生成。这些基于Coverage的Greybox Fuzzers(CGF)维护有效测试输入的语料库,在使用称为mutator的一组简单数据操作操作执行之前,这些输入被重复地随机修改。每次突变输入覆盖新的代码段时,输入都会添加到语料库中,以便可以再次选择它以进一步突变。通过以这种方式动态构建语料库,CGF可以逐步构建有用输入的存储库以指导更深入的探索。在实践中,模糊研究者之间的协作学习通过共享这些良好输入的语料间接地发生,因此未来的测试可以从针对给定程序适当地构造的输入开始。

我们观察到CGF模糊测试环是一个很好的集成自动学习的架构[32],因为测试通常执行得非常快(与测试函数一样快),编译器仪器提供丰富的程序状态[40],[43]。尽管平均24小时模糊测试运行可能会执行数十亿次突变,但试图改进此过程的研究很少,目前最先进的技术是均匀的随机选择。虽然均匀随机性与多次执行相结合可能最终会产生良好的结果,但通常的做法是定期重新启动运行,因为它们会陷入覆盖局部最小值[24]。我们建议将强化学习应用于模糊测试过程,以更智能地选择变异算子(动作),以在更短的时间内实现更深层次的代码覆盖(更高的奖励)。通过改进变异算子选择,我们的方法能够更有效地将本地搜索从现有种子驱动到有趣的新测试输入。

尽管普遍存在的“模糊测试环”(图1)与高强度学习领域(RL)中的状态 - 动作 - 奖励序列具有惊人的相似性[6],[36],但是存在阻碍其直接应用的重大挑战。对fuzzer mutator的选择。

由于可能的程序输入的巨大状态空间,这种学习过程的手动工程特征是不可行的,可能难以将这些特征推广到新程序。我们证明,与模糊测试的其他方面一样,变异算子选择可以通过深度学习技术从自动化特征工程中受益[32]。通过学习输入数据的深度表示,我们能够生成一个模型,该模型不仅可以在训练有素的程序上实现比libFuzzer更大的覆盖范围,而且可以在不进行再训练的情况下实现更广泛的其他程序。

尽管深度强化学习取得了进展,但深度RL网络(ms)的执行时间与模糊器测试的潜在简单函数(us)之间仍存在巨大差异。 为了克服这个问题,我们设计了一个用于模糊测试的异步架构,同时强化学习将这个问题视为一个实时的Atari游戏(一个在20世纪70年代后期开发的视频游戏控制台,其简单的游戏常用于基准RL算法[27])而不是离散的顺序决策问题。 通过将我们的架构与OpenAI Gym RL框架和广泛使用的CGF libFuzzer [24]集成,我们可以立即获得大型模糊基准测试库[25],用于大规模模糊测试的工具[15],[39]和前沿深度 RL算法[3],[27]。

我们的主要贡献摘要:

  • 我们表明,通过使用强化学习,我们可以训练模糊器以有效的方式选择变换器,而不会降低模糊器性能。
  • 通过使用最初为改进Atari游戏而开发的异步跳帧技术,我们的RL代理能够克服模糊器(us)和深度神经网络(ms)之间执行时间的差异[3]
  • 我们的方法能够在大多数基准测试中实现卓越的平均线覆盖率(5/4)
  • 我们表明,即使基线[24]的运行次数更多,我们的RL-Fuzzer也能够更深入地渗透到几种不同类型的软件中。

二.背景和动机

尽管他们取得了成功,灰盒符号执行往往需要大量的测试调用(和突变)来实现相对深入的代码覆盖(即使对于简单的程序,也要执行数百万次)。这主要是因为它们的成功高度依赖于符号执行随机生成输入的能力,这些输入通过各种条件检查,从而导致更深层的代码路径。一种解决方案是在许多不同的机器上同时部署许多模糊运行。大规模的模糊部署在许多大型软件公司的60多个大规模项目中发现了2000多个错误。这个过程是连续运行的[15],[39],红细胞被研究人员共享,共同改善未来的运行。

这一对语料库生成和选择的关注,也表明了目前大多数的研究。Skyfire[45]使用概率上下文敏感语法更有效地构建结构化语料库输入。Vuzzer[33]使用程序状态信息动态地选择有前途的代码路径的输入,而Learn&Fuzz[13]使用统计学习和神经网络学习如何从一组示例测试用例中构建结构化输入。最近,这些结构化输入生成和过滤的方法也扩展到了深度学习技术[13]、[29]、[32]。 

虽然为每一个被测试的程序逐步构建粒子是有用的,但仍然需要持续的模糊测试来处理主动开发的软件中的变化。尽管默认的实践是直观的,但是变化的非结构化数据(以空语料库开始模糊化)具有无偏w.r.t.的优点,即传递给被测试函数的数据类型。此外,一个从未被测试过的程序也将从这个空输入语料库状态开始。

由于变异器依赖于它们正在修改的输入,因此,考虑到它所操作的输入的结构,变异器的选择可以受益。特别是,我们表明,根据输入数据的结构做出关于变元选择的明智决策将在更短的时间内导致更大的代码覆盖率。 

a.libfuzzer突变算子

libfuzzer使用的模糊测试回路(图1)与其他变异模糊测试使用的模糊测试基本相同。执行从一个种子输入开始,选择并应用一个变元(我们的RL上下文中的一个操作),然后创建并测试一个新的输入。这个新的输入可能会导致一个有回报的结果(更多的覆盖)或没有(没有新的覆盖)。如果新的输入导致覆盖率增加,它将被添加到将来要选择的输入语料库中,否则它将被丢弃。

覆盖制导Greybox模糊测试的原理是,与其花费大量的计算来理解定义程序的复杂传递函数序列,不如快速尝试不同的输入,类似于已知的增加覆盖率的输入。通过多次重复这些随机扰动,突变模糊在某一点上会产生一个增加覆盖范围的输入,从而为将来选择进行突变的语料库添加一个新的有价值的输入(图1)。随着时间的推移,这个过程被重复(称为模糊循环),出现的是一个语料库,它覆盖了大量的代码行,而不需要理解被测试软件所期望的格式。

表一libfuzzer突变算子集
变异器 描述
EraseBytes 通过删除随机字节减小大小 
InsertByte 通过增加随机字节增加大小 
InsertRepeated
Bytes
通过添加至少3个随机字节来增加大小 
ChangeBit 随机翻转一位 
ChangeByte 用随机字节替换字节 
ShuffleBytes 随机重新排列输入字节 
ChangeASCII Integer 对ASCII的值,执行随机数学运算并覆盖输入
ChangeBinary Integer 对二进制中的值,执行随机数学运算并覆盖输入
CopyPart 返回部分输入
CrossOver  与语料库/自我的随机部分进行重组
AddWordPersist AutoDict 将部分输入替换为先前增加覆盖率的输入(整个运行)
AddWordTemp AutoDict 将部分输入替换为最近增加覆盖率的输入
AddWord FromTORC 更换最近执行比较的输入的一部分

变异器的随机性(表1)是强大的本地搜索有用输入的驱动因素,但结果是,测试通常需要重复多次以获得额外的覆盖。虽然从语料库中选择新输入总是受到前面的模糊测试步骤的影响,但是在测试运行中稍后初始语料库与其内容之间的实际关系难以预测。由于用于产生新输入的变换器的随机性质,该输入选择过程变得更加不可预测。此外,由于最成功的模糊器执行语料库蒸馏(用于将语料库减少到最小覆盖集的在线技术),因此选择输入的分布可以在任何时间以不可预测的方式改变。

不幸的是,在实践中,语料库通常是模糊测试运行的唯一最终产品。实际的测试过程基本上没有被观察到。我们打算将模糊测试的重点从语料库扩展到创建它的过程。使用我们的架构结合OpenAI-Gym和Tensorflow等现有工具,我们可以记录测试期间生成的测试输入(状态)以及导致它们的操作。我们通过了解单个程序的模糊测试中的变异算子选择,可以将这些知识转移到其他几个不相关的程序而无需额外的培训。

除了提供优化的mutator操作员选择的平台之外,还可以使用我们的RL框架来评估新mutator或mutator组的功效。 最近对更复杂和更强大的mutatorFairFuzz [22]或mutator发现的生成技术[29]的研究可以从基于RL的评估中受益,因为某些mutator可能仅在某些组合或序列中变得更有效,这一发现很难揭示 通过详尽地构建mutator集或参数化。 例如,如果长时间过去没有实现额外的覆盖,尝试突破阻塞条件(通过AddWordFromTORC运算符)可能会带来最大的回报。

B.使用LLVM进行高效的程序状态监控

在fuzzer black-box,gray-box和white-box这三个主要类别之间的一个关键区别是在测试期间发生的程序分析的程度。黑盒模糊完全忽略状态以实现最大测试吞吐量,而白盒技术专注于权重分析,以便在每次尝试时产生更大的影响。这两种方法之间的区别突出了所有模糊测试技术所固有的权衡:何时花时间和精力进行分析是否值得?我们的方法表明,通过使用编译时间检测提供的状态,可以学习如何以最小的开销更有效地模糊。

这是可以实现的,因为libFuzzer与LLVM编译器提供的Sanitizers紧密集成[21],这也是我们选择与libFuzzer集成而不是其他工具的主要原因。如表2所述,LLVM提供了五种不同类型的运行时工具,能够检测和分类程序错误以及用于动态代码覆盖率跟踪的复杂数据结构。虽然我们最初的研究工作的重点是创建一个可以实现卓越线路覆盖的模糊器,但我们框架的一个主要好处是能够使用这种丰富的Sanitizer状态灵活地定义RL奖励功能。这样可以创建针对某些类别的错误的模糊器。实现这一专业化所需要的只是创建一个针对所需结果的奖励功能。

表II LLVM SANITIZERS监控覆盖并提供故障分类和检测
Sanitizer类型 描述
线程Sanitizer  数据竞争,死锁
地址Sanitizer  UAF,缓存区溢出,泄露
内存Sanitizer  使用未初始化的内存
未定义行为Sanitizer  检测未定义的行为
覆盖Sanitizer  代码覆盖率,执行频率和调用者 - 被调用者函数关系。
图2. OpenAI Gym和LLVM-libFuzzer的异步集成

C.深度强化学习

强化学习是一个相对简单的概念,它假设一个代理位于一个环境中(模糊测试程序),对当前状态进行观察(通过LLVM)并使用这些信息来选择能够获得最大回报的动作(变异算子) (最大化所涵盖的独特代码行)。 RL已经使用了多年,但最近深度学习的突破已经在许多高度挑战的领域推动了RL性能的巨大提升[19]。 AlphaGo在复杂的连续游戏中击败了世界冠军[41],政策学习的突破教会机器人运行[17]和Tensorflow如何玩Atari [4],[16]。这些突破的原因是在RL工具集中增加了深度神经网络,可以在没有人类指导的情况下自动学习特征。虽然许多RL算法正在多个域中同时开发,但为了真正从其他域的研究中受益,有必要为基准环境和用于解决它们的RL算法提供模块化接口。幸运的是,由广泛使用的OpenAI Gym框架提供了一套用于RL的标准化,可重用的组件。

III.深入学习FUZZ

通过设计将软件测试转换为竞争性游戏的OpenAI Gym环境,我们能够使用最先进的RL技术来改进libFuzzer在其众多支持程序中的变异操作员选择[25]。虽然我们的初始实验仅使用单个学习模糊器,但我们的体系结构设计用于同时模糊(ClusterFuzz [39])和同时RL学习(如A3C [27])。

将强化学习与模糊测试相结合的最大挑战可能是模糊执行的相对速度(图2)。 Greybox突变模糊器的有效性很大程度上源于其执行速度,这在很大程度上仅受执行测试功能所需时间的限制。正如在我们的实验中发现的那样,测试可以达到每秒执行超过10万次的执行速度(每次转换需10us)。这些速度不是瞬间峰值,因为我们观察到libpng的测试运行,平均每秒执行112295次执行,持续400秒。虽然24小时模糊运行中每秒的平均测试次数通常要低得多(每秒10次执行),但这需要在24小时内进行大约10亿次测试。

结合学习和模糊测试的另一个问题是使用真实测试条件时的巨大状态空间。鉴于libFuzzer的默认最大输入大小为4096字节,即使是非常简单的mutator,如InsertByte也可以产生近2564096种不同的结果,甚至不考虑输入结构的变化。依赖于测试调用序列的更复杂操作(如AddWord- FromTempAutoDict,AddWordFromPersistAutoDict和AddWordFromTORC(表1))会导致更具爆炸性的状态空间大小,这取决于所测试软件的结构以及前面的序列模糊测试。

我们通过结合强化学习和模糊测试的新颖异步架构来描述我们处理这种复杂性的方法:

  • 我们定义了RL问题制定的基本组成部分,包括块(第III.A部分),奖励(第III.B部分)和我们有效选择行动的方法(第III.C节)
  • 利用Atari领域RL工作的灵感,我们设计了一个异步架构,用于学习如何选择增变器来增加真实模糊条件下的覆盖范围(第III.C节)
  • 我们描述了模块化架构,旨在使软件研究人员能够以最少的先验知识使用现有的RL实现。 (第四节)

A.在RL上下文中建模程序状态

为了制定解决任何顺序决策问题的方法,有必要确定如何在序列中表示给定位置,或者以适当的术语表示其状态。在可能的情况下,构造状态表示以适合被测试的程序的子集可能是有利的。例如,在[13],[45]中,通过分别利用PDF和XML文件的语法来创建复杂的语义结构。但是,对于我们提出的架构,我们直接在测试输入的字节数组表示上运行,提供了一个通用的格式,它匹配libFuzzer和我们的RL框架使用的基于神经网络的接口所期望的输入。

尽管使用与字节数组中的每个值相对应的数字序列[0-255]来按原样编码该数据是很诱人的,但是字节级方法具有实质性缺点,因为测试输入数据不一定直接编码值(例如图像中的RGB值)但也可以编码位掩码或其他非数值。因此,我们更喜欢bit-of-bits [32]技术将测试用例输入表示到我们的神经网络中。对于所有实验,我们将最大输入大小修复为libFuzzer指定的默认值(4096字节):

虽然我们的方法遵循[32]中描述的技术,但我们确实使用字节表示进行了初始实验,并且凭经验发现比特阵列技术为RL增变器选择产生了更好的结果。

B.使用RL奖励进行灵活模糊测试

使用RL的一个关键优势是能够指定奖励功能以激发被认为合乎需要的模糊行为。 在我们的例子中,模糊“高分”严格来说是最大化所涵盖的独特线条:

哪里:
Rt:奖励时间't'
covt:'t'时覆盖的唯一线数

RL奖励功能的灵活性意味着可以创建具有各种特定需求的模糊测试工具,例如快速发现错误或提高针对特定代码路径的奖励。由于我们与LLVM Sanitizer(表2)的集成,可以很容易地确定这些其他机会,无需额外的仪器即可获得额外奖励。这不仅可以发现有用的测试策略,而且可以更广泛地理解测试输入,从而得到期望的奖励响应。

c.有效地选择突变作用

虽然突变模糊包含大量具有不同随机结果的动作,但将RL应用于突变选择的最具挑战性的方面是评估神经网络所需的时间(毫秒)与执行测试程序的单个执行所需的时间(微秒)之间的差异。s)。虽然从RL学习的角度来看,将其视为一个离散的完全可观测问题(马尔可夫决策过程或MDP)是理想的,但这是我们的评估,这是不切实际的,因为它要求引信在每次测试调用之前等待RL评估。

由于执行任何测试至少都有可能达到新的覆盖范围,而不执行任何测试,因此强制模糊测试处于空闲状态几乎没有实际意义。尽管设计一个能在每个动作基础上胜过随机变异选择的RL代理并不难,但如果在两种技术的测试时间相同的情况下,有人使用这种技术比随机选择的效果差,这是很少见的。

我们注意到,通过创建街机学习环境(ALE),在Atari领域[3]之前已经解决了执行时间的这种差异。如果游戏模拟器视频帧定期采样,则可以在以更快的速度运行游戏的同时进行学习。帧跳过[3]包括让RL代理学习每k帧(而不是每一帧),并在等待新帧时重复前面的操作。这就减少了执行时间上的差异,对RL性能产生了净的积极影响。在模糊域的情况下,帧跳过对性能更为关键,因为与标准libfuzzer实现相比,执行更少的测试会使学习模糊器处于显著的劣势。如(图2)所示,只需维持先前突变动作的固定大小的圆形缓冲区,就可以以有效的方式实现这一点。

我们的体系结构的异步性质(使我们能够在模糊时帧跳过)的一个结果也意味着我们正在解决一个部分可观测的马尔可夫决策过程(POMDP),而不是一个串行离散方法将提供的完全可观测的MDP。这意味着,我们不是接收发送到模糊测试系统的每个状态输入,而是基于对真实系统状态的定期观察来学习。这种部分可观测性使得我们的问题公式与[16]中讨论的类似,后者使用一个RL代理,可以在闪烁的屏幕上玩Atari游戏。我们使用[16]中描述的相同方法来减轻这种部分可观测性,即用长短期内存(LSTM)层增强我们的网络架构,以确保我们的RL代理能够学习暂时依赖的动作。我们还注意到,通过种子过滤[32]将LSTMS应用于深度学习增强模糊化的成功作为进一步的激励。

虽然我们的异步、部分可观测公式确实使学习过程变得更具挑战性,但我们相信,权衡非常有利于我们的异步方法,并且更忠实地表示现实世界中的模糊,而我们的异步、部分可观测公式确实使学习过程更具挑战性,我们认为相信这种权衡极大地支持我们的异步方法,并且更忠实地代表了现实世界中的模糊RL问题。总之,我们的方法在以下方面不同于系列MDP RL配方:

  • 部分可观察性:我们的RL代理只异步接收测试输入的样本,以确定要选择哪个转换器。虽然我们不能观察到每一种状态,但我们表明,这些快照提供了状态的适当近似值,以通知变异器的选择。
  • 异步动作选择:由于模糊测试的速度远远超过了我们的RL网络生成动作的能力,因此我们将尽可能快地在循环缓冲区中替换最旧的选定动作。由于libfuzzer可以在不阻塞的情况下连续循环这个缓冲区,因此我们可以使用我们的框架进行测试,而不会降低测试速度。

四、深度RL模糊测试基准环境

虽然历史上以手工设计的特征为主,但我们证明,与模糊的其他方面一样,变异算子选择也可以通过深度学习技术从自动化特征工程中受益[32]。

为了实现这一点,我们主要使用了rl学习框架tensorforce[36],它为许多rl算法提供了一个易于使用的基于JSON的配置框架。由于Tensorforce能够学习任何与OpenAI兼容的问题,因此我们可以在模糊问题上使用它的任何现有特性。在我们的实验中,我们选择了深双q学习(第IV.A节),其配置参数与Tensorforce软件作者提供的Cart-Pole基准相同[35]。虽然完整的配置可以通过参考链接获得,但我们注意到在我们的配置中优先奖励(50K容量)的使用。使用最初在[38]中定义的方法,重放过去状态的动作奖励序列以加速学习。这些重放的记忆根据其对学习过程的估计值进行优先级排序。

在我们的实验中,我们选择了Deep Double-Q学习(第IV.A节),其配置参数与Tensorforce软件作者提供的Cart-Pole基准相同[35]。虽然完整的配置可以通过参考链接获得,但我们注意到在我们的配置中优先奖励(50K容量)的使用。使用最初在[38]中定义的方法,重放过去状态的动作奖励序列以加速学习。这些重放的记忆根据其对学习过程的估计值进行优先级排序。

由于我们工作的一个关键贡献是一个超出libfuzzer当前能力的实用系统,因此我们使用13个变元的完整列表(表1)作为我们的RL代理的可能操作选择。这是为了确保我们的RL代理能够解决类似于libfuzzer基准测试的问题,同时也提供了一个测试台,该测试台可以以紧急的方式提供关于哪些转换器对给定程序有用和不有用的信息。

在本节中,我们将更详细地描述应用OpenAI Gym框架进行模糊化所需的三个基本组件:

  • RL代理的执行:“学习算法用于更新权重网络实现最大的回报。(Deep Double-Q学习)(第iv.a)
  • RL网络:用于确定如何为给定状态选择动作的基础神经网络结构。(基于LSTM的W/64装置)(第IV.B节)
  • 基准环境:问题表示,是模糊测试配置和测试配置下程序的组合。这些都经过严格的版本控制,以确保对问题定义的细微更改是可跟踪和可重复的。(IV.C节)

a.Deep Double-Q Learning RL Agent for Mutator Selection 

我们使用的RL算法是基于Q学习的,这意味着它试图在没有明确模型的情况下预测各种操作的效用——在我们的例子中,变异器最有可能增加覆盖率(奖励)。该技术已应用于从电梯控制到移动机器人导航等诸多问题,在RL学习实验中被广泛应用[34]。不幸的是,Q学习无论是使用表格还是多层神经架构(如DQN)进行实例化,都会遇到随机域中动作值高估的问题。

当学习使用我们的体系结构选择用于模糊化的变异算子时,这个问题尤其普遍,因为异步性质会使状态观察和随后的奖励到达产生噪声,并且可能会有很高的延迟。

因此,我们使用一种称为双Q学习的Q学习变体进行实验,该变体使用两组网络权重来减少过度乐观的值预测。在我们的例子中,即使总训练时间相对较短(30000秒),它似乎也能有效地学习。我们按照[14]的定义定义定义双Q学习错误,这是对原始DQN实现的简单扩展,旨在最大化计算效率:

其中:

R_{t}:时间奖励'T'

\theta _{t}:时间“t”时的网络权重

 使用该算法,通过在时间步骤“t”选择最大化(argmax)下一时间步骤(rt+1)预期回报的操作“a”,对RL网络权重进行优化。

请注意,该公式还考虑了预期的未来回报,通过使用折扣因子\gamma \in \left [0,1 \right ]来确定算法相对于未来预测回报应重视即时回报的程度。在我们的研究中,我们利用了这样一个事实,即这种方法是独立开发的,在具有挑战性的Atari领域更成功,而不需要我们从头开始实施它[35]。虽然我们主要关注相对简单的RL学习配置,但培训时间有限,但我们打算将其作为未来工作中更全面基准测试的起点。

b.LSTM RL网络,用于选择带内存的Mutators 

如前所述,为了应对我们公式的部分可观测性,我们将基于多层感知器的神经网络扩展为一个能够学习潜在的长序列状态和动作的神经网络。

这一LSTM网络层[16]为以前的状态和行为(记忆)的流动建立了一条单独的路径,使人们能够记住有用的经验,而忘记那些不再有用的经验。

如图2所示,该网络架构使用位数组并生成Mutators 选择,而DDQN算法(第IV.A节)优化权重以增加回报。

C.实验设置和RL代理培训

一旦我们定义了我们的网络架构和学习算法,就有必要安排一个训练实验,以获得可能产生有效动作选择的网络权重。我们的目标是训练一种模糊测试工具,这种模糊测试工具能够通过最大化总的唯一线覆盖率来选择突变操作人员,从而获得最高的回报。在我们的研究中,我们观察到,与许多典型的RL问题不同,使用短或中等长度运行的训练模糊测试工具往往会导致RL代理能够最快地实现低悬挂水果覆盖率。为了在更长的时间内优化深层代码覆盖率,这是不可取的,因为当每个培训事件快速终止时,打破一个严格的覆盖率屏障的可能性相对较小。

有效地覆盖低挂起的代码行,同时从一个空的语料库开始,通常需要选择在较长时间内尝试创建复杂结构(addwordFromTorc、crossover、addwordFromTemp等)的那些变元(如insertbyte和insertrepeatedBytes)。

对于libjpeg,我们观察到第一个覆盖屏障(覆盖了327行)通常需要6000-9000秒的模糊(libjpeg解压功能的60-90M的测试用例)才能突破。虽然穿透这个屏障后获得的实际覆盖量可能有所不同,但这通常与模糊测试是否能够创建有效的jpeg头相对应。我们观察到,在没有经历这些突破的情况下训练一个RL代理,将导致模糊测试学习快速实现容易的覆盖,而没有能力进行深入的覆盖。

除了这些困难外,在模糊测试的配置和设置上还有很大的时间压力。虽然在性能方面的理想方法可能是将这些非常长的培训课程重复几个月,但在计算要求方面,这是不切实际的。

此外,长时间推迟引信实验的启动会大大降低框架的易用性。正如在引言[46]中雄辩地描述的,往往有紧急的时间压力来尽快开始模糊测试。正是因为这些原因,我们把训练限制在很少的时间段。对于第五节中评估的网络,我们只训练了3集,每集的长度相对较长,为10000秒。这段插曲长度足够长,可以在3集中的2集的训练中突破327线的障碍。

我们将成功实现更深层次的覆盖至少部分归因于我们观察可能突破障碍的输入(状态)模式和可能导致它们的突变的能力。在进行学习实验的同时,我们相信能够以非常短的总训练时间(约8小时(共30k秒)证明有效的学习是一个很有希望的开始。

七。有效性威胁

这项工作的主要目标是开发一个框架,将现有的模糊工具与强化学习相结合。尽管我们作出了努力,但仍有几个方面可以改进。在本节中,我们将描述其中一些对有效性的威胁,目的是进一步研究和讨论这一领域。

A.作为性能指标的独特线路覆盖率

本文的研究重点是在线覆盖率作为一种评估指标,而不是发现的故障或安全漏洞的数量。虽然行覆盖试图实现代码执行的最大宽度,但不能保证有效地导致发现错误。此外,有效地执行罕见的条件或分支[22],[44]可能对故障发现至关重要,但我们不以我们的仅覆盖度量来奖励这一点。总而言之,到达龙穴(覆盖范围)和杀死龙(发现错误或行使关键分支)是不同的。

本文中描述的奖励功能具有灵活性,可以通过在每次消毒剂(表2)检测到错误时奖励RL代理,来鼓励发现错误,而不是进行行覆盖。不幸的是,这种修改限制了可以自动检测到的故障的类别。为了实现“以故障为中心”的RL代理,还需要选择对每个发现的故障奖励多少RL算法。

B.智能型突变选择的局限性

实验的一个关键目标是确定我们是否可以通过修改突变算子选择过程来显著提高模糊性能。这是为了在简单控制实验的背景下评估RL。然而,重要的是要考虑到,仅仅改进突变选择可能不足以实现对目标程序的彻底测试。如前所述,我们在这方面设计了灵活的框架,以便于在其他相关模糊领域进行进一步的研究,如分支目标定位[33]、种子选择/筛选[32]或甚至增强正在执行的变异子行动类型[22]、[23]

c.扩大测试项目的规模和范围

我们的目标是在libfuzzer测试套件[25]提供的一组相对知名的软件测试基准上评估我们的方法。然而,对更大的一组更复杂的函数的分析将揭示我们方法的其他优点和缺点。特别是,进一步讨论被测试软件的功能或领域如何影响我们方法的有效性仍然是一个悬而未决的问题。例如,为什么我们在re2/sqlite上的性能比在boringssl上更好?

八。结论

受在具有挑战性、嘈杂的领域中强化学习的成功启发,我们表明,即使在有限的培训时间(约8小时)内,只要更有效地选择突变操作符,我们也能够显著提高代码覆盖率。我们的方法在实际条件下评估的五个基准项目中进行了演示,使用的运行次数比大多数现有的模糊研究多得多。

我们证明,通过战略选择突变,我们可以在所有测试程序中实现更深入的覆盖,即使当前最先进的随机选择有更多成功的机会(表4)。虽然这项旨在学习如何更智能地选择变异器的初步工作已经取得了成功,但与我们的体系结构在未来能够实现的目标相比,这一点显得相形见绌:将大规模模糊(lib-fuzzer)和学习(openai)结合在一个单一的多平台、多语言分布式体系结构(通过GRPC)下。通过使用异步缓冲区作为模糊和机器学习之间的协调机制,我们减轻了微秒延迟模糊预期的负担,使未来能够在不同计算约束下公平评估和比较RL方法。

九、确认

我要感谢所有帮助确定所述工作方向的审查人员。该项目由测试资源管理中心(TRMC)测试与评估/科学技术(T&E/S&T)项目资助,由美国陆军项目执行办公室(PEO Stri)负责模拟、培训和仪器仪表。合同编号W900KK-16-C-0006,坚固性内外测试(RIOT)。NAVAIR公开发布2018-165。分发声明A-批准公开发布;分发不受限制。

发布了43 篇原创文章 · 获赞 23 · 访问量 3万+

猜你喜欢

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