使用Binary Ninja API检测潜在释放后使用漏洞的技术解析

本文详细探讨了如何利用Binary Ninja的中级中间语言(MLIL)构建数据流图,通过追踪内存分配与其他内存区域的交互关系,实现跨函数的上下文不敏感可达性分析,从而识别二进制文件中的潜在释放后使用漏洞。

释放后使用漏洞的静态检测挑战

释放后使用(Use-after-Free)是一种内存破坏条件,程序在内存被释放后仍继续引用。静态检测这类漏洞具有挑战性。本文探索了利用Binary Ninja的中级中间语言(MLIL)建立数据流图的方法,通过追踪特定内存分配与其他内存区域的交互关系,进行跨函数分析以识别潜在漏洞。

内存分配数据流图构建

数据流图由四种节点类型构成:

  • 追踪分配节点(红色):表示待追踪的内存分配
  • 函数栈帧节点(绿色):表示函数调用栈帧
  • 动态内存节点(蓝色):表示无法确定来源的SSA变量
  • 全局内存节点(黑色):表示函数内的全局变量

边表示指针存储操作,包含两个关键属性:

  • write:写入位置相对于分配基址的偏移
  • points:指针值指向的目标偏移

SSA变量与图节点的映射关系

分析从分配函数(如malloc())返回值的SSA变量开始追踪。通过Binary Ninja的get_ssa_var_definition()get_ssa_var_uses()API可以获取变量的定义位置和使用链。指针算术运算时会额外存储偏移信息。

内存加载操作转换为图边

当遇到函数外部内存加载操作时,会假设相关存储操作发生在函数外部,并据此创建图边。内存存储、赋值和加载操作共同构成了数据流图的基础构件。

数据流图信息传播

变量赋值分为三种情况处理:

  1. 直接变量赋值:简单传递源变量值
  2. 含指针算术的赋值:更新偏移信息
  3. 内存加载赋值:通过图边解析目标节点

释放后使用漏洞检测

完成数据流图构建后,分析所有被标记为"Free"的基本块,检查是否存在路径通向"Use"块。同时也会检测从一个"Free"块到另一个"Free"块的路径,以发现潜在的双重释放问题。

分配器/释放器函数的自动识别

通过分析标准函数(如malloc/free)的使用链,可以识别程序特定的包装函数。对于释放器函数,检查函数参数是否直接传递给free()等标准释放函数。

实际漏洞案例分析

工具在多个历史漏洞中成功检测出问题,包括:

  • JasPer JPEG-2000中的双重释放(CVE-2015-5221)
  • Giflib中的双重释放(CVE-2016-3177)
  • GNOME-Nettool中的释放后使用
  • OpenSLP中的跨函数双重释放(CVE-2015-5177)

结论与展望

本文介绍的方法虽然存在静态分析固有的分类误差,但为识别释放后使用漏洞提供了有效途径。未来可通过改进日志分组和增加全局内存跟踪来增强工具实用性。项目源代码已公开在uafninja仓库。

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