一种基于简易符号执行的二进制代码漏洞挖掘方法

文档序号:6373291阅读:215来源:国知局
专利名称:一种基于简易符号执行的二进制代码漏洞挖掘方法
技术领域
本发明涉及到一种基于简易符号执行的二进制代码漏洞挖掘方法,可以检测由输入不当导致的漏洞。可适用于多平台,且只对二进制代码进行静态解释,不需要实际执行,因此较高效。使用其中一种安全属性规则成功地验证了所有近年来瑞星、超级巡警、诺顿等杀毒软件驱动程序中报的ioctrol例程中的漏洞。适用于软件测试、漏洞挖掘等领域。
背景技术
传统软件漏洞挖掘方法一般使用黑盒Fuzz测试,通过构造一组随机输入传递给程序,直到程序崩溃。这种方法较盲目,既无法获知哪些程序路径已经被执行,也无法有导 向性地构造输入,使程序可执行到未被遍历过的路径。测试过程中的大部分时间都在重复执行着同样的路径,使测试时间成本过高。源码级的测试可以帮助程序员发现很多由于代码风格或错误的语法语义引起的BUG,但存在几个缺点1)无法发现程序运行时的BUG ;2)在很多情况下,源码并不是可及的;3)需对每一类程序设计语言分别考虑。对于软件测试、漏洞挖掘等领域,往往需要考虑代码覆盖问题,尽可能多地覆盖二进制代码的执行路径,可以提高发现程序代码中BUG的可能性。然而,由于二进制代码中的分支数量非常多,使获取某一执行路径所对应的输入成为最难的研究问题之一。为解决这个问题,学术界提出了一种新的概念,符号执行,即把输入作为符号,然后通过静态解释源码的形式来收集约束,遇到分支时,同时展开两条路径,继续向下进行。符号执行的误报率极低,但是也存在一些弊端解释过程中,状态空间容易增长得非常大,效率较低。近年来,国外出现了一些基于动态执行路径,符号与具体执行混合的方法所实现的工具,如 DART、CUTE、Sage、Catchconv、Fuzzgrind 等。其中,DART 与 CUTE 同宗,它们使用同样的中间语言、插装方式及求解方法。Catchconv与Fuzzgrind为开源工具,都使用Valgrind作为其插装框架,只有微软的Sage是运行在Windows上,但未发布出来。但这些工具有一个共同的缺点,由于需要对源代码或二进制代码进行插装,由于插装代码的大量存在使运行效率较低,对于恶意软件,实际运行会带来其它危险。综上所述,本发明提出一种针对于二进制的、使用简易的符号执行挖掘漏洞的方法。在本方法中,先获取二进制代码的控制流信息,并把二进制代码翻译到一种中间语言,在该中间语言和控制流信息对某个函数进行符号执行,函数体内的分支一般不会很多,且不需要考虑循环问题,因此比传统的符号执行更加高效,通过获得表达式与输入向量间的依赖关系,根据一定的安全属性规则来判断是否漏洞。

发明内容
本发明的目的就是在克服传统的符号执行与具体执行的缺点的前提上,提供一种基于简易符号执行的二进制代码漏洞挖掘方法,它是一种快速、有效的软件漏洞挖掘方法,针对二进制代码中的函数进行符号执行,并考虑控制流从而达到代码覆盖。为达到上述目的,本发明的技术方案是这样实现的
一种基于简易符号执行的二进制代码漏洞挖掘方法,该方法包括以下步骤步骤A.实现反汇编引擎,可以提取二进制代码中的函数信息,并能分析函数内的控制流信息。步骤B.实现二进制代码翻译组件,将二进制代码转化成中间语言。步骤C.确认输入点(即函数的参数及子函数调用),对函数中调用的子函数进行建模。步骤D.根据步骤A,B, C中产生的结果进行符号执行,把输入作为符号,静态解释中间语言并更新每条指令执行的上下文,对于分支,需要保存当前上下文,遍历一条路径后,再恢复保存的上下文,继续执行下一条路径。步骤E.当执行到函数结束时,符号执行过程产生一些与输入相关的表达式集合, 根据一定的安全属性规则,简化、分析这些表达式最后判断是否有漏洞。其中,步骤A中所述的二进制代码为Windows、Linux等操作系统下的x86可执行代码。步骤A所述控制流信息是由基本块信息组成的链表,基本块信息包括Al.基本块标号(Label),表不该基本块的标识符,值唯一;A2.基本块的开始地址(Start Address);A3.基本块的结束地址(End Address);A4.基本块的入度数(In Count),表示可以到达该基本块的前驱的数量,入度数为O的基本块为本函数的第一个基本块;A5.基本块的出度数(Out Count),表示由该基本块可到达的后继的数量,该值不大于2,出度数为O的基本块为本函数的最后一个基本块;A6.基本块的前驱数组,表示到达该基本块的前驱的集合;A7.基本块的后继数组,表不由该基本块可达的后继的集合;AS.循环标志,表示该基本块是否处于循环中;其中,步骤B所述的中间语言中,包括三种存储介质Bll.临时变量,在每个基本块中临时申请,用于实现静态单赋值,为寄存器与内存间的媒介;B12.寄存器,与机器指令中的寄存器相同,读写寄存器使用中间语言中的Get和Put操作完成;B13.内存,内存地址由常量或临时变量表示,读写内存使用中间语言中的LDle和STle操作完成;步骤B中所述的中间语言由语句IRStmt组成,语句IRStmt包括B21. IMark语句,表示每个基本块的入口标志,其中包括该基本块对应机器指令的开始地址及该指令的字节数;B22. Put语句,表示把临时变量的值写入寄存器;B23. Store语句,表示把临时变量的值写入内存;B24. IRDirty语句,表示调用有副作用的函数;B25. Exit语句,表示基本块的出口;步骤B中所述的中间语言由语句IRStmt组成,语句IRStmt由表达式IRExpr组成,表达式IRExpr包括B31. Get表达式,表示从寄存器中读取值;B32. Tmp表达式,表不临时变量;B33. Binop表达式,表示二元操作;B34. Unop表达式,表不一兀操作;B35. Load表达式,表示从内存中读取值;B36. Const表达式,表示常量; B37· MuxOX 表达式,表不 if-then-else 语句;其中,步骤C所述的输入点一般指函数的参数或者从外部引入的值。在x86指令集中,参数一般表示为栈桢指针与正数偏移相加,但栈桢指针可能是ESP或者EBP,需要启发式判断。另外这种输入是从外部引入的值,如在函数内部调用ReadFile、Recv、Accept等函数时引入的外部值,在函数建模后就可以针对这些输入向量适当地引入符号。其中,步骤D所述的简易符号执行方法是在中间语言上进行,需要考虑以下几种情况Dl. Put操作,检查赋值给寄存器的临时变量是否依赖于输入;D2.赋值给临时变量时,左值需要考虑以下几种情况C21.从临时变量中读,检查该临时变量是否依赖于输入;C22.从内存中读,检查该内存中的值是否依赖于输入;C23.从寄存器中读,检查该寄存器是否依赖于输入;C24. 一元操作与二元操作,检查操作数是否依赖于输入;D3. Store操作,检查写入内存的临时变量是否依赖于输入;步骤D所述收集到路径约束为与输入相关的表达式,包括二元操作,一元操作、位移操作,有符号扩展、无符号扩展。步骤D所述的符号执行达到分支指令时,需要保存当前的上下文信息,该信息包括执行到当前指令所有寄存器、临时变量、以及内存的符号信息。然后执行一条路径,执行完成后回溯到分支处,恢复保存的上下文信息再继续执行另一条路径。其中,步骤E中所述的安全属性规则为判断该指令是否为漏洞的依据,目前,本发明成功添加三种安全属性规则来判断非法写内存模式的漏洞El.写任意值到任意地址;E2.写任意值到固定地址;E3.写固定值到任意地址;优点及功效本发明一种基于简易符号执行的二进制代码漏洞挖掘方法,它是一种快速、有效的软件漏洞挖掘方法,针对二进制代码中的函数进行符号执行,并考虑控制流从而达到代码覆盖。


图I为基于简易符号执行的二进制代码漏洞挖掘方法流程示意2为CVE-2010-1591漏洞附近的代码转化后的中间语言
具体实施例方式下面结合附图及本发明的实施对本发明的方法作进一步详细的说明。本发明的基本思想为将二进制代码转化为中间语言,然后结合上控制流信息,输入点信息、函数建模信息,在该中间语言上进行符号执行,当符号执行过程完成后,得到与输入相关的指令的中间语言语句的集合,根据一定的安全属性规则,对这些语句进行判断其是否存在漏洞。图I为基于简易符号执行的二进制代码漏洞挖掘方法流程示意图,如图I所示,该方法包括如下步骤 步骤A :将二进制代码交给反汇编引擎,解码为汇编指令,提取出汇编指令中的函数信息,再对每个函数分析,提取出该函数的控制流信息;需说明,得到函数信息后,可生成调用图,使用反向的深度遍历算法,即从调用图的叶子结点开始向上处理,这可保证在处理某函数时,它的调用子函数都已经被处理过。步骤B :实现二进制代码翻译组件将二进制代码翻译成中间语言,如图2所示;这里的中间语言与动态产生的中间语言并不相同,动态生成的中间语言,跳转指令已经得到确定,或者跳转、或者顺序执行。静态下翻译的中间语言遇到分支指令时转化为CMP-JCC语句,并不能确定是否跳转。步骤C :分析函数的输入点及对内部调用函数进行建模。根据前面所述,这里考虑了两种输入,一种为函数自身的参数,它可能是由用户指定的,表示为栈桢指针与正数偏移相加。另一种为具有副作用的函数引入的外部输入,如ReadFile、fread、accept、recv等函数,需要建立一张函数信息表描述这些函数,参数与返回值之间的映射关系,从而可以确定输入符号。步骤D :根据前述步骤产生的结果,在翻译后的中间语言上进行简易符号执行过程,之所以称之为简易的符号执行,是因为符号执行过程是在函数体内进行的,而并非针对整段二进制代码,这样就可以跳过一些没意义的函数,从而减少符号执行所用的时间。其次,该符号执行过程是一个静态解释中间语言的过程,传播描述输入的符号,对于循环,只执行一次循环后即跳出,从而避免由循环引起的状态爆炸问题。对于分支,需要保存当前的上下文信息,先执行其中一条路径,当执行完成返回后,恢复保存后的上下文信息,再继续解释另一条路径。步骤E :符号执行完成后,可得到一个与输入相关的中间语言语句的集合,根据安全属性规则进行判断是否存在漏洞。本发明中目前只添加了非法写内存漏洞模式的规则
(a)Store( Exprl (I)) = Expr2(I)-、(b)Siore(Expr, (/)) = Expnt (f[})
{c)Store{Expr^f0)) = Expr2(J)其中Store为存储函数,如Store (a) =b表示把b写入由地址a表示的内存中。Expr (X)表示关于X的表达式,I表示输入,f0表示固定值。由此可见,这三种规则的语义分别为(a)写任意值到任意地址;(b)写固定值到任意地址;(C)写任意值到固定地址。通过这三种规则即可以描述非法写内存的漏洞特征。
综上所述,基于简易的符号执行的二进制代码漏洞挖掘方法可以针对特定的函数进行分析,而不是整块二进制代码。可以处理分支,达到很高的覆盖率。在中间语言上进行静态解释,不需要实际运行程序,也可以避免机器指令的 副作用问题。此方法可以通过描述良好的安全属性规则检测二进制代码中的漏洞,漏报率与误报率都较低。
权利要求
1.一种基于简易符号执行的二进制代码漏洞挖掘方法,其特征在于该方法包括以下步骤 步骤A.实现反汇编引擎,提取二进制代码中的函数信息,并分析函数内的控制流信息; 步骤B.实现二进制代码翻译组件,将二进制代码转化成中间语言; 步骤C.确认输入点即函数的参数及子函数调用,对函数中调用的子函数进行建模;步骤D.根据步骤A,B,C中产生的结果进行符号执行,把输入作为符号,静态解释中间语言并更新每条指令执行的上下文,对于分支,需要保存当前上下文,遍历一条路径后,再恢复保存的上下文,继续执行下一条路径; 步骤E.当执行到函数结束时,符号执行过程产生一些与输入相关的表达式集合,根据 安全属性规则,简化、分析这些表达式最后判断是否有漏洞。
2.根据权利要求I所述的一种基于简易符号执行的二进制代码漏洞挖掘方法,其特征在于步骤A中所述的二进制代码为Windows、Linux操作系统下的x86可执行代码;所述控制流信息是由基本块信息组成的链表,基本块信息包括 Al.基本块标号Label,表不该基本块的标识符,值唯一; A2.基本块的开始地址Start Address ; A3.基本块的结束地址End Address ; A4.基本块的入度数In Count,表示到达该基本块的前驱的数量,入度数为O的基本块为本函数的第一个基本块; A5.基本块的出度数Out Count,表示由该基本块到达的后继的数量,该值不大于2,出度数为O的基本块为本函数的最后一个基本块; A6.基本块的如驱数组,表不到达该基本块的如驱的集合; A7.基本块的后继数组,表不由该基本块到达的后继的集合; AS.循环标志,表示该基本块是否处于循环中。
3.根据权利要求I所述的一种基于简易符号执行的二进制代码漏洞挖掘方法,其特征在于步骤B所述的中间语言中,包括三种存储介质 Bll.临时变量,在每个基本块中临时申请,用于实现静态单赋值,为寄存器与内存间的媒介; B12.寄存器,与机器指令中的寄存器相同,读写寄存器使用中间语言中的Get和Put操作完成; B13.内存,内存地址由常量或临时变量表示,读写内存使用中间语言中的LDI e和STI e操作完成; 步骤B中所述的中间语言由语句IRStmt组成,语句IRStmt包括 B21. IMark语句,表示每个基本块的入口标志,其中包括该基本块对应机器指令的开始地址及该指令的字节数; B22. Put语句,表示把临时变量的值写入寄存器; B23. Store语句,表示把临时变量的值写入内存; B24. IRDirty语句,表示调用有副作用的函数; B25. Exit语句,表示基本块的出口。
4.根据权利要求3所述的一种基于简易符号执行的二进制代码漏洞挖掘方法,其特征在于所述的语句IRStmt由表达式IRExpr组成,表达式IRExpr包括 B31. Get表达式,表示从寄存器中读取值; B32. Tmp表达式,表示临时变量; B33. Binop表达式,表示二元操作; B34. Unop表达式,表不一兀操作; B35. Load表达式,表示从内存中读取值;B36. Const表达式,表示常量; B37. MuxOX 表达式,表不 if-then-else 语句。
5.根据权利要求I所述的一种基于简易符号执行的二进制代码漏洞挖掘方法,其特征在于步骤C所述的输入点一般指函数的参数或者从外部引入的值,在x86指令集中,参数表示为栈桢指针与正数偏移相加,但栈桢指针可能是ESP或者EBP,需要启发式判断;另外这种输入是从外部引入的值,如在函数内部调用ReadFile、Recv、Accept函数时引入的外部值,在函数建模后就针对这些输入向量适当地引入符号。
6.根据权利要求I所述的一种基于简易符号执行的二进制代码漏洞挖掘方法,其特征在于步骤D所述的简易符号执行方法是在中间语言上进行,需要考虑以下几种情况 Dl. Put操作,检查赋值给寄存器的临时变量是否依赖于输入; D2.赋值给临时变量时,左值需要考虑以下几种情况 C21.从临时变量中读,检查该临时变量是否依赖于输入; C22.从内存中读,检查该内存中的值是否依赖于输入; C23.从寄存器中读,检查该寄存器是否依赖于输入; C24. 一元操作与二元操作,检查操作数是否依赖于输入; D3. Store操作,检查写入内存的临时变量是否依赖于输入; 步骤D所述收集到路径约束为与输入相关的表达式,包括二元操作,一元操作、位移操作,有符号扩展、无符号扩展; 步骤D所述的符号执行达到分支指令时,需要保存当前的上下文信息,该信息包括执行到当前指令所有寄存器、临时变量、以及内存的符号信息,然后执行一条路径,执行完成后回溯到分支处,恢复保存的上下文信息再继续执行另一条路径。
7.根据权利要求I所述的一种基于简易符号执行的二进制代码漏洞挖掘方法,其特征在于步骤E中所述的安全属性规则为判断该指令是否为漏洞的依据,目前,成功添加三种安全属性规则来判断非法写内存模式的漏洞 El.写任意值到任意地址; E2.写任意值到固定地址; E3.写固定值到任意地址。
全文摘要
本发明公开了一种基于简易符号执行的二进制代码漏洞挖掘方法,它有五大步骤;首先把二进制代码通过二进制代码翻译组件,转化为一种静态单赋值的中间语言。然后使用反汇编引擎对二进制代码进行反汇编,提取其中的控制流信息,基于该控制流信息在中间语言上进行静态的符号执行,在符号执行过程中需确认输入点,把输入向量转化为符号,并对调用函数进行建模。当符号执行过程完成后可得到依赖输入向量的中间语言的语句集合,对该集合中的语句简化后,使用安全属性规则验证后生成漏洞确认报告。
文档编号G06F11/36GK102841844SQ201210243800
公开日2012年12月26日 申请日期2012年7月13日 优先权日2012年7月13日
发明者马金鑫, 李舟军, 忽朝俭 申请人:北京航空航天大学
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1