Buffer Overflow Vulnerability Prediction from x86 executables using Static Analysis and ML

题目: Buffer Overflow Vulnerability Prediction from x86 executables using Static Analysis and Machine Learning
作者: Bindu Madhavi Padmanabhuni, Hee Beng Kuan Tan
单位: School of Electrical and Electroinc Engineering, Nanyang Technological University
出版: Computer Software & Application Conference(COMPSAC), 2015


解决的问题

二进制代码的缓冲区溢出问题

所用工具

ida-pro

利用ida-pro商业反汇编器识别局部和全局变量

  • 全局变量在汇编指令中用地址进行访问
  • 局部变量在汇编指令中用栈帧偏移来进行访问
  • 将一个变量视为从已知地址(或偏移)到下一个已知地址(或偏移)

BinAnalysis(在Rose上搭建的二进制分析工具)

提供x86汇编指令的语义,使我们能够抓住帮助常量传播的机器状态,并且识别间接分支和调用,这些可以通过常量传播静态地确定。

VulMiner

作者自己实现的工具,用来从Rose的分析结果中提取下面将要提到的特征。

静态分析过程

反汇编和变量信息

包括函数边界识别和变量信息收集。

  • 利用IDA Pro来识别函数和变量信息
  • 输入BinAnalysis(在Rose上搭建的二进制分析工具),为每个函数构建AST和CFG

控制依赖

利用函数的CFG来计算过程内控制依赖。Rose提供了从CFG构建后向支配关系的API,这被用来找到直接后序支配一个结点z后序支配结点n,即所有从n开始的流向exit结点的路径都经过结点z

利用函数摘要进行数据依赖的计算

我们利用CFG和变量信息来分析容器级别的过程间数据依赖。容器级别的意思是对于容器数据的访问,我们的工具以整个容器为单位计算数据依赖。对于结构体,当struct信息能够从IDA Pro得知时,我们利用struct的偏移来识别struct中变量的边界。
Rose提供了能够仿真一个x86指令基本块执行的符号语义。每个基本块与一个符号状态相关联。符号状态表示寄存器,内存和标志位的状态。我们对CFG的仿真过程进行增强。我们也利用库函数原型对库函数的调用进行模拟。
通过分配一个新的符号值来处理符号状态的融合。对于有多个返回块的函数,所有返回块的状态融合成一个最终的返回状态。我们利用标准worklist算法来进行过程内数据依赖分析。
为提高效率,我们利用函数摘要来进行过程间分析。函数摘要是用来表示调用效果的,上下文无关的摘要。当函数被调用时,基于调用上下文和合成的函数摘要,控制和数据依赖信息被更新并传回调用函数。调用函数重新开始分析。
为生成函数摘要,函数被符号化执行来记录已知的依赖,以及收集未知的引用。在分析期间,寄存器,标志位,全局变量,参数值和动态分配的变量的定义都被收集,并且函数的最终状态通过聚集全局变量,函数参数值,动态分配变量和返回块的eax,esp等等来生成。
为应用函数摘要,首先被调用函数的摘要被重用,在被调用函数的未知引用与调用函数中对这些引用的定义之间的数据依赖被建立。我们遍历在被调用函数中生成的定义,并且更新它们在调用函数中的入口。状态信息也用类似方法更新。随后便进行调用者下一条指令的分析。

静态代码属性

文章中的一些表示方法

sink k:在二进制反汇编代码中的潜在的有漏洞的程序语句。我们将对C库函数的调用和向缓冲区/容器中写的语句视为sink。
input validation node: 在CFG中,一个谓词结点d被叫做槽k的输入验证结点,当满足以下条件:

  • k和d均是同一个普通输入变量的引用
  • k间接控制依赖于d

input dependent predicate node: CFG中一个谓词结点p被称作槽k的输入依赖谓词结点,当满足以下条件:

  • p是一个输入变量的引用,而k与这个输入变量没有直接或间接的数据依赖关系
  • k间接控制依赖于p

source: 被槽引用的变量
destination: 在槽中定义的变量

输入和源的特征描述

  • Input Count: 统计槽输入的数量
  • Inputs with Limiting: 统计有长度约束的槽输入的数量
  • Environment Dependent Input: 统计独立于环境变量的槽输入的数量
  • Is Source Null Terminated: 源是否以空的终结字符结束

槽的特征描述

不同的槽进行不同的操作,根据操作的类型,可能需要不同形式的边界检查和防御措施。

  • 操作类型:我们将操作类型分为5类
    • 复制:对于进行复制操作的C库函数的调用
    • 连接:对于进行连接操作的C库函数的调用
    • 格式化写
    • 非格式化写
    • 数组写入:其他一切形式的向容器内写入的操作
  • 防御是否有限制:标记是否使用了C库函数的安全版本

目标缓冲区的特征描述

  • 目的是否为空的非终结字符
  • 对目标是否进行多次写
  • 位置:缓冲区的位置,分为全局,局部,混合和堆
  • 源和目标大小是否相同
  • 声明:缓冲区声明,分为静态,动态并依赖于源,动态并与源独立,动态固定大小,混合

控制依赖的特征描述

描述槽结点的控制依赖特征

  • 源字符串长度:统计槽谓词的数量,即是否利用strlen检查源字符串长度
  • 源大小:统计检查源大小的次数
  • 目标字符串长度
  • 目标大小
  • 循环的终止条件是否与源相关:判断槽是否在循环之内,并且循环的终止条件与源大小相关
  • 验证:统计槽验证结点的数量
  • 输入依赖谓词:统计输入依赖的谓词数量
  • 源缓冲区谓词:统计在槽处引用的的谓词数量
  • 目标缓冲区谓词:统计在槽处定义的谓词数量

数据依赖精度特征描述

容器级别的精确度和函数摘要在数据依赖算法中带来了一些不精确性,于是我们将一些抓住了这些不确定性的属性包含到了特征集中。

  • 过程间目标缓冲区访问:目标在过程间是否被访问并写入
  • 目标写入次数:统计除了槽结点外目标被写入的次数
  • 目标缓冲区是否模糊:目标是否是模糊容器
  • 源是否模糊
  • 槽依赖的模糊容器
  • 槽依赖的非模糊容器
  • 与模糊容器相关的谓词
  • 与非模糊容器相关的谓词

实验

数据收集

数据集为MIT Lincoln Laboratories buffer overflow benchmark中的6个程序。

特征提取

利用BinAnalysis识别出槽,并进行数据依赖分析。
利用VulMiner提取特征。

模型与算法

分别利用了5种模型:朴素贝叶斯,多重感知机,逻辑回归,SMO
采用10折交叉验证

评估

评估标准

precision, recall, accuracy, false alarm…

实验结果

SMO展现出了最好的性能,达到75.9%的召回率和84.6%的精确度。

与静态的源码分析工具对比

我们将自己的实验结果与利用Splint,PolySpace,Boon,UNO等源码静态分析工具进行对比。结果显示,我们的方法的效果比这几种静态分析工具的实验效果都好。

局限性

尽管二进制程序的静态代码属性不难被收集,但数据需要一个二进制分析工具进行收集,并且需要足够多的有漏洞的数据来训练模型。我们的数据依赖IDA Pro来进行函数边界的识别,虽然有效,但并非一个简单的工作。我们的数据依赖分析引入了容器级别的精确度,与函数摘要一样,都对精确度有一定的损失。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值