发表时间: 2024-03-22 00:05:18
作者: 北京青草莓科技有限公司
浏览:
本文主要讲一下c,c++编译器对于漏洞挖掘方面的支持和探索
作为偏基础的编程语言,c,c++一直是安全漏洞的重灾区
如果关注编译器近些年来的版本变化,会发现为了配合漏洞挖掘,编译器做了相当多的支持
当然主要是clang(llvm)首先支持,随后gcc跟进
这里主要说一下和模糊测试紧密相关的几点
覆盖反馈
编译器通过在编译被测代码时插入hook函数,来告诉模糊测试工具被测代码的覆盖情况
对于用户态测试,
模糊测试工具只要实现这些hool函数,就可以得到被测代码的pc覆盖情况,这样就可以通过计算判断来实现样本进化
对于内核态测试,
情况稍微复杂一点,linux系统将pc覆盖情况通过kcov文件交给用户态,使得运行在用户态的模糊测试工具可以获得被测代码的覆盖情况,从而实现样本进化
内存hook
模糊测试的质量好坏和代码覆盖率有直接的关系
好多测试阻塞在各种各样的分支判断节点
编译器通过hook函数,将进行分支判断的魔鬼数字,魔鬼字符串,魔鬼内存hook出来
模糊测试工具只要实现这些hook函数,就能得到这些数据,从而使用他们进行数据变异,进而进入这些难以进入的分支,提升测试效率
地址消毒
下面说一下大名鼎鼎的地址消毒技术
在出现地址消毒技术之前,研发人员在分析漏洞原因的时候是很困难的
比如程序崩溃,他的直接的原因主要是访问无效内存,或者运行无效指针,而这和代码 第 一 现场的错误往往不直接相关
代码错误 第 一 现场往往是读写越界,内存释放后使用这些,从程序崩溃找到 第 一 错误现场往往需要很长的分析过程
地址消毒解决了开发人员这一烦恼,编译器通过在代码里插入一些辅助语句,在完全不影响程序运行逻辑的情况下,记录程序错误的 第 一 现场,当错误发生时将错误现场完整的呈现给开发人员
举个两个例子
1.编译器故意在编译时对有效内存两端插入无效内存, 通过影子内存,记录所有的有效内存和所有的无效内存的位置
当任何内存被读写,都会与影子内存的记录做比对,只要有无效内存被读写,就认为已经发生了读写溢出错误
2.编译器会记录所有堆内存的分配释放过程,在程序完全退出前,会扫描所有有效内存,如果已经分配还没有释放的内存的指针没有 出现在有效内存里,就认为已经发生了内存泄漏,因为程序已经没有释放这个内存的能力了
编译器与操作系统配合漏洞挖掘和模糊测试已经发展了很多年,可以看到很多大牛在基础领域为漏洞挖掘做出的努力
北京青草莓科技有限公司(模糊测试-解决方案提供商)
wanghao@cyan-strawberry.com
客服1