Page 28 - 《软件学报》2024年第6期
P. 28
2604 软件学报 2024 年第 35 卷第 6 期
• 有待进一步大规模测试. 目前 DBI-Go 在真实世界开源项目上的测试尚未发现问题, 只在 18 个仓库上进行
了测试, 覆盖面不足. 未来期望能够进行更大规模的测试, 以期找出开源仓库中的问题, 帮助改善 Go 语言软件的
内存安全性, 提升其可靠性.
6 相关工作
6.1 动态二进制分析
动态二进制分析框架, 如 Pin [21] 、Valgrind [42] 、DynamoRIO [43] , 可以用于插桩任意指令来执行动态分析. 这些
工具为研究者们的分析带来了很大的便利. Amitabha 等人 [44] 研究了如何有效地插桩 x86 机器码中的内存访问以
支持软件事务内存和分析. Patil 等人 [45] 基于 Pin 设计了 Pinplay, 一个基于执行捕获和确定性重放的并行程序分析
框架. Zhong 等人 [17] 基于 DynamoRIO 设计了一个动态二进制工具, 用于检测 Go 中的并发问题.
基于动态二进制分析的漏洞检测包括前面提到的并发漏洞分析、污点分析 [46] 、逆向工程 [47] 和执行重
放 [48] 等.
, 用于检测数据竞争的
6.2 内存漏洞检测
目前已有的内存相关的漏洞检测工作主要是针对 C/C++这种具有弱静态类型系统的编程语言来进行的, 因为
强制类型转换、任意指针的存在使得悬空引用、边界溢出等内存漏洞更容易发生, Song 等人于 2013 年 [30] 通过系
统性地建立内存损坏的一般模型, 揭示了 C/C++容易遭受内存漏洞的主要原因. 现有的内存漏洞检测工作依赖于
静态程序分析或动态程序分析来进行.
静态检测: 分析程序 (源) 代码, 并生成对于所有可能的代码执行都是保守正确的结果. 静态检测的一部分工
作基于形式化验证: Clarke 等人提出了一种使用有界模型检查 (BMC) 对 ANSI-C 程序进行形式化验证的工具 [49]
来检测内存问题. 更多的静态检测工作则是基于符号执行: CUTE [50] 通过结合符号执行和具体执行, 将内存图作为
输入来执行自动化测试; EXE [51] 是利用符号执行来自动生成导致实际代码崩溃的输入, 进行快速的错误定位;
Klee [52] 则是通过符号执行来自动生成测试.
动态检测: 通过分析单个程序的执行, 并输出仅对单个运行有效的精确分析结果. 消毒器 (sanitizer)——静态
插入运行时监视器, 并在运行时进行检测——是动态检测工具的典型代表. Serebryany 等人在 2012 年提出了
AddressSanitizer (ASAN) [28] , 它通过插桩应用程序中的内存访问操作, 在运行时建模影子内存, 从而能识别缓冲区
溢出、悬垂指针、内存泄漏等内存漏洞. 由于它能够在不牺牲完备性的情况下实现了检测效率, AddressSanitizer
已经被集成到许多常用的编译工具链中, 包括针对 C/C++的编译器 GCC、LLVM, 以及 Go 语言编译器. 但 ASAN
目前在 Go 编译器中的使用场景受限, 仅能检测 Go 语言中和 C 语言进行交互的相关代码上的内存错误 [53] , 对于
纯 Go 语言代码尚不支持. ASAN 与 DBI-Go 的相同点在于二者都是基于插桩, ASAN 是在编译时插桩, DBI-Go 是
基于动态二进制插桩. 区别在于 ASAN 的设计目的是检测诸如缓冲区溢出之类的通用的内存漏洞, 不能检测 Go
中违反 Go 逃逸不变式的 store; 且其所能检测的内存漏洞只有在被触发时才能发现 (如内存被释放、指针被解引
用时), 此时 Go 程序可能已经崩溃. 而 DBI-Go 则是针对 Go 语言专门设计, 利用 Go 的逃逸不变式这一独特特性,
可以在内存隐患发生的第一现场就报错 (比如将栈地址存入堆时). 因此即使 ASAN 可以支持纯 Go 的代码, 其也
无法代替 DBI-Go. 类似地, 还有许多使用类似方式进行针对其他问题检测的漏洞检测工具, 如用于检测未初始化
内存的使用情况的 MemorySanitizer [54] ThreadSanitizer [55] , 利用动态内存检查来检测对象有
效性的 EffectiveSan [56] 等. Song 等人 [29] 则是在 2019 年对 Sanitizing 这种技术进行了对比总结, 描述了不同的
Sanitizer 工具的性能和可扩展性. 此外, 还有部分工作通过修改运行时系统来实现运行时检测, 如 DieHard [57] 、
SoftBound [58] .
6.3 Go 的漏洞检测
目前针对 Go 的漏洞检测已有许多工作. Lange 等人 [19] 为 Go 中的消息传递机制进行建模, 为 Go 的消息传递
机制提出了一个验证框架. Lauinger 等人 [33] 提出了 go-safer, 一种全新的静态分析工具, 用来识别 Go 源代码中对