代码覆盖率之旅:模糊测试中的关键技术解析

本文深入探讨模糊测试中的代码覆盖率概念,涵盖基本块、边和路径跟踪等核心策略,分析AFL、TinyInst等工具的实现原理,并介绍硬件辅助的Intel-PT技术,帮助读者理解覆盖率在漏洞挖掘中的关键作用。

模糊测试如穴居人第五篇:面向初学者的代码覆盖率之旅

引言

我们已在本系列前期讨论过代码覆盖率的重要性,今天将尝试理解一些基础概念、常见方法、相关工具,并了解流行模糊测试框架能够利用的技术。我们将避开晦涩策略,专注于被称为"面包黄油"的成熟主题领域。如果你是模糊测试或软件测试的新手,本文将以友好方式呈现内容。

核心定义

代码覆盖率

代码覆盖率是衡量测试、输入等覆盖程序代码程度的指标。这对模糊测试至关重要,因为它能跟踪目标程序中可触及的范围。

基本块

基本块是线性执行的代码序列,没有分支入口和出口。通过Ghidra分析示例密码检查程序,可以看到main()函数被自动分解为多个代码块。

边/分支/转换

这些术语描述基本块之间的关系。在我们的示例中,基本块001006cf与两个不同块存在关系:001006e4和00100706,具体取决于命令行参数数量的条件判断。

路径

路径是程序执行遍历的基本块列表。示例程序中有三条不同路径,用橙色、绿色和红色线标示。

插桩

插桩是为模糊测试目标提供代码覆盖率反馈数据的过程,可以是重写无源代码的编译二进制文件,也可以是在每个基本块入口地址设置断点。

仅二进制

指没有源代码的目标,只有二进制文件。这类目标在嵌入式系统、MacOS和Windows环境中更常见。

常见策略

跟踪基本块

最简单的覆盖率收集方法是跟踪给定输入到达的基本块数量。这种方法实现简单,适用于各种目标,性能表现良好。但可能限制于首次到达基本块的输入值。

跟踪边和路径

AFL及其衍生工具采用此策略,不仅关注到达的基本块,还关注块间关系。AFL使用涉及关系的块地址元组来跟踪覆盖率,并通过编译时插桩或QEMU模拟器收集数据。

比较覆盖率/比较粉碎

不仅跟踪输入在程序块/边中的进展,还试图理解测试在程序比较中的进展。通过将大型比较分解为更小的块,可以更精细地跟踪进度。AFL++的LLVM模式和TinyInst等工具实现了这一技术。

奖励领域:使用硬件获取覆盖率数据

利用实际硬件获取覆盖率数据对仅二进制目标特别有帮助。Intel-PT是新款Intel CPU提供的实用程序,可提取运行软件的控制流信息。libxdc库能够高效解码Intel-PT跟踪数据,提供完美的覆盖率信息。

结论

本文介绍了该领域的基础术语、获取有意义覆盖率数据的常见策略,以及用于提取数据的工具。流行的模糊测试框架如AFL++和honggfuzz努力使其框架尽可能灵活,适用于广泛的目标。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计