动态程序分析的问题 - Trail of Bits博客
开发者可以使用诸如AddressSanitizer和Valgrind等工具,在运行代码时检测未初始化内存访问、内存泄漏或释放后使用内存等问题。尽管这些优秀工具可用,内存错误仍然存在,仍会发布给用户,并在实际环境中被利用。
当今大多数错误查找工具都是动态的:它们在程序运行时识别错误。这很好,因为所有程序都有庞大的测试套件来执行每一行代码……对吗?错了。大型测试套件是例外而非规则。测试套件确实有助于发现和减少错误,但错误仍然会漏网。
也许解决方案是付费让专业人士审计代码。更多眼睛查看代码是好事™,但根本问题仍然存在。专家头脑中运行的分析仍然是“动态的”:思考每一条代码路径并不可行。
因此,动态分析可能会遗漏错误,因为它们无法检查所有可能的程序路径。那么,什么可以检查所有可能的程序路径?
在数百万行代码中查找释放后使用
我们使用静态分析来分析数百万行代码,而无需运行代码。这种称为数据流跟踪的分析技术使我们能够分析和总结关于所有可能程序路径的属性。这解决了前述因未执行某些程序路径而遗漏错误的问题。
一个能查看一切的分析实际上如何工作?下面我们描述我们开发并定期使用的实际全程序静态分析工具PointsTo的1-2-3步骤。该工具在大型代码库中查找并报告潜在的释放后使用错误。
步骤1:转换为LLVM位码
PointsTo操作程序的LLVM位码表示。我们选择LLVM位码,因为它是执行程序分析的便捷中间表示。不出所料,我们分析流程的第一阶段是将程序的源代码转换为LLVM位码数据库。我们使用名为CompInfo的内部工具生成这些数据库。一个类似功能的开源替代工具是whole-program-llvm。
步骤2:创建数据流图
PointsTo背后的关键思想是分析指向已分配对象的指针如何在程序中流动。我们关心的是指针的赋值和复制、指针解引用以及指针的释放。这些指针操作使用数据流图表示。
过程中最有趣的步骤是将分配和释放转换为特殊赋值的原因和方法。“原因”是这种转换让我们重新利用现有程序分析来查找从FREE定义到指针解引用的路径。方法更为微妙:PointsTo如何知道应将“new A”更改为ALLOC,将“delete a”更改为FREE?
想象一个假设的嵌入式系统,程序内存匮乏,因此自然选择是使用名为ration_memory的自定义内存分配器。我们创建了一种Python建模语言,向PointsTo提供关于高级函数行为的信息。我们的建模脚本告诉PointsTo“new A”返回一个新对象,因此我们可以用它来对ration_memory说同样的话。
插曲:隐藏数据流
从源代码到数据流图的转换看起来很简单,但那是因为我们开始的源代码很简单。它没有函数调用,更重要的是,没有函数指针或方法调用!如果下面的callback是函数指针会发生什么?如果callback释放了x会发生什么?
|
|
这是PointsTo的秘方和同名来源:我们执行上下文和路径敏感的指针分析,告诉我们哪些函数指针指向哪些函数以及何时指向。总之,我们可以生成一个错误报告,跟踪x通过callback并再次返回。
步骤3:结局
是时候报告潜在错误供专家分析了。PointsTo搜索数据流图,查找从赋值到FREE再到解引用的流。这些流被转换为源代码行的程序切片,显示执行需要遵循的路径以产生释放后使用。以下是一个真实错误的程序切片示例:
(此处原文未提供具体示例代码,故保留描述)
当向编译器人员描述这个系统时,通常的第一个问题是:但是误报呢?如果我们收到关于释放后使用的报告,但它不是呢?这就是编译器分析和漏洞分析的优先级分歧之处。
编译器分析中的误报可能会引入错误,因此编译器通常是保守的。也就是说,它们用误报换取漏报。它们可能会错过一些优化机会,因为它们无法证明某些事情,但至少程序会被正确编译咳嗽。
对于漏洞分析,这是一个糟糕的交易。漏洞分析中的误报是不方便的,但当需要查看数百万行代码时,它们只是沧海一粟。然而,漏报是不可接受的。漏报是被遗漏并可能进入生产环境的错误。一个总能找到错误并有时警告你可疑但正确代码的工具是一项投资,可以在代码审计期间节省时间和金钱。
总结
分析程序中的错误是困难的。应遵循行业最佳实践,如拥有广泛的测试套件。开发者应定期通过动态分析工具运行程序,以摘取低垂的果实。但更重要的是,开发者应理解测试套件和动态分析不是万能药。错误有一个讨厌的习惯,隐藏在很少执行的代码路径后面。这就是为什么需要查看所有路径。这就是我们制作PointsTo的原因。
PointsTo是最近Empire Hacking(纽约双月聚会)的讨论话题。我在那里的演讲包括更多关于PointsTo设计和实现的信息,对于好奇的读者,幻灯片和视频在下面重现。我们希望未来发布更多来自Empire Hacking的视频。
PointsTo最初为Cyber Fast Track制作,我们要感谢DARPA资助我们的工作。Trail of Bits的顾问使用PointsTo和其他内部工具进行应用程序安全审查。如果您有兴趣对代码进行详细审计,并得到PointsTo和我们的CRS等工具的支持,请联系我们。
如果您喜欢这篇文章,请分享: Twitter LinkedIn GitHub Mastodon Hacker News
页面内容 在数百万行代码中查找释放后使用 步骤1:转换为LLVM位码 步骤2:创建数据流图 步骤3:结局 总结 近期文章 非传统创新者奖学金 在你的PajaMAS中劫持多代理系统 我们构建了MCP一直需要的安全层 在废弃硬件中利用零日漏洞 Inside EthCC[8]:成为智能合约审计师 © 2025 Trail of Bits. 使用Hugo和Mainroad主题生成。