一种嵌套循环结构的识别方法

文档序号:6574748阅读:357来源:国知局
专利名称:一种嵌套循环结构的识别方法
技术领域
本发明属于逆向工程和程序分析领域,具体涉及一种识别嵌套循环结构的方法,可用于 反编译、软件测试等设备中,能够有效的将程序控制流图结构化。
技术背景反编译是从可执行文件获得与源程序等效的高级代码的技术,是逆向工程领域的核心技 术之一,在不同的应用领域发挥着重要的作用。最初,反编译技术主要应用于辅助程序移植, 如将程序从第二代计算机向第三代计算机迁移;到了70年代和80年代,反编译技术开始被 用于再工程(Re-engineering),包括对遗失源码或第三方的二进制程序进行理解、文档化、 重构和修改;从90年代中后期开始,信息安全领域对反编译技术有了巨大的应用需求,比如 挖掘软件安全漏洞、分析恶意软件等工作,都对反编译技术有着很高的依赖。控制流分析是反编译中的重要研究领域,复合条件分支识别、嵌套循环识别和多路分支 (switch)识别是其中最重要的三个控制结构识别问题,也是反编译自动化的核心技术之一。 如果不能准确识别这三种控制结构,会严重制约反编译技术的发展,限制反编译技术在其它 领域的应用。本发明关注控制流分析中循环结构的识别。循环是用来实现重复指令的控制结构。在控制流图中,循环经常嵌套在其它循环内部。 这种现象产生了被称作"循环嵌套森林"的结构。尽管现代的程序使用结构化的编程方法, 但当高级语言程序被编译成了二进制程序以后,其中的循环结构常常因为内部的多层嵌套循 环的跳转指令(例如break语句,continue语句和return语句等),其单入口的结构化特性遭到 了破坏,不再符合结构化原则,即其对应的控制流图是不可规约的。如图1所示为一个典型 的不可规约循环的控制流图。图2为它所对应的"循环嵌套森林"。嵌套循环的识别是结构化程序设计语言中循环语句的编译问题的逆命题。就是如何识别二进制程序中的循环结构的范围以及它们之间的嵌套关系,从而使反编译生成的高级语言程 序结构仍然保持较好的结构化特性。如果不能准确识别循环结构的范围以及它们之间的嵌套 关系,则可能影响到反编译最终生成的源程序的语意的准确性以及结构化特性。对循环识别的研究开始于1970年,RE. Allen和J. Cocke提出了控制图的可归约性(参 见F.E. Allen. Control flow analysis. S/Gi^4iViVoric" 5(7)1:19, 1970),此后编译和反编译领域 的工作都开始关注这个问题。1997年,P. Havlak在R.E. Tarjan(参见R.E. Tarjan, Testing flow graph reducibility, Co附戸f. 5W. 9, 1974)的基础上提出了对常规控制流图的近似线性时间的算法(参见R Havlak,Nesting of reducible and irreducible loops, ^CM 7h^wa"/ows iVograw/w/wgcmd 辆簡,Vol. 19, No.4, 1997)。两年后G. Ramalingam提出了对Havlak算法的一个改进算法(参见G. Ramalingam, Identifying loops in almost linear time, ^CM rrawsacriows /V0gn3附ffH'"g丄a"gwages awd 5^^7w, Vol.21, No.2, 1999),在最差情况下近似线性时间的算法(但是在常规情况下比Havlak 算法慢)。上述方法通常基于复杂的数据结构,例如Interval/DSG,或者UNION-FIND集合,对这些 数据集合的复杂操作使得这些算法的效率很低。本发明提出了一种在二进制可执行程序中识别循环的新方法,该方法只需要对控制流图 进行一次深度优先搜索就可以准确的处理不可归约的控制流图,并且不需要复杂的数据结构。 该方法已经对Windows XP和linux下的多个典型的可执行文件进行了分析,实验表明该方法 近似线性时间,并且比Havlak的算法快2~5倍。 发明内容本发明的目的在于提供一种循环识别的方法,能够精确、高效、自动化识别循环结构。 为明确本发明的内容及方便表述,下面给出循环及相关概念的适当说明。(参见S.S. Muchnick, yWvanced Cpz7er Des/gw awe/ /mp/eOTewtoriow, Elsevier Science (USA), 1997. P. Havlak, Nesting of reducible and irreducible loops, JCM rra"sa"/ows iVogra附m/wg丄awgwages VoU9, No.4, 1997.)。控制流图(CFG):描述程序的控制流信息的连通有向图;通常用(N,E,h)表示,其中N是 程序中基本块的集合,E是这些基本块之间的有向边,h是程序的入口。强连通域(SCR): ScN节点的非空集合;给定任意q,reS,存在从q到r的路径和从r到 q的路径。当一个SCR不存在属性为SCR的父集合时,称它为最大SCR。循环包括最外层循环和内部循环。最外层循环 一个至少包含一条内部边的最大SCR。循环头节点和循环体在深度优先搜索中,访问到的第一个循环节点称作循环头节点,其余的节点称为循环体。最大外层循环嵌套在循环L中并以h为头节点的嵌套循环是在以(L-(h))为节点集合的子图的最大外层循环。重入口和重入边给定一个循环头为h的循环L和一条边〈q,r〉, qgL, reL- {h}, r称 作这个循环的重入口, 〈q,r〉称作重入边。最内层循环循环体内的一个节点n,它的最内层循环是包含n的最小循环。 最内层循环头n的最内层循环的循环头称作n的最内层循环头。循环头列表n的循环头列表包含n的最内层循环头ln,lu的最内层循环头h2, h2的最内 层循环头h3,以此类推。本发明的一种嵌套循环结构的识别方法,其步骤包括1) 对可执行文件进行反汇编,得到该可执行文件的中间代码;2) 从上述中间代码中提取控制流信息,得到控制流图;3) 深度优先遍历控制流图,得到循环结构子图,该循环结构包括 3-1)循环头节点;3-2)循环体节点,及其最内层循环头节点; 3-3)重入口节点,及其重入边;4) 标记上述节点的最内层循环头节点;5) 将上述循环结构子图识别为循环结构。 识别循环头节点的方法在于对于当前访问的节点,如其一后继节点没有被遍历,且处于深度优先生成树上从控制流图入口节点到当前访问节点的路径上,则该后继节点为循环头节 点,将该后继节点加入该当前访问节点的循环头节点列表中。识别循环体节点的方法在于对于当前访问的节点,如其一后继节点没有被遍历过,则遍 历该后继节点,如该后继节点位于一循环体内,则当前访问节点为循环体节点,将该后继节 点的最内层循环头节点加入该当前访问节点的循环头节点列表中。或对于当前访问的节点, 如其一后继节点被遍历过,且不处于深度优先生成树上从控制流图入口节点到当前访问节点 的路径上,但该后继节点位于有最内层循环头节点位于深度优先生成树上从控制流图入口节 点到当前访问节点的路径上的循环体内,则该当前访问节点为循环体节点,将该最内层循环 头节点加入该当前访问节点的循环头节点列表中。识别重入口节点的方法在于对于当前访问的节点,如其一后继节点被遍历过,且不处于 深度优先生成树上从控制流图入口节点到当前访问节点的路径上,但该后继节点位于无最内 层循环头节点位于深度优先生成树上从控制流图入口节点到当前访问节点的路径上的循环体 内,则该后继节点为重入口节点,从该当前访问节点到该后继节点的有向边为重入边。标记上述节点的最内层循环头节点的方法为对于当前访问的节点和需加入的循环头节点,将该循环头节点和它的循环头节点列表根据其在深度优先生成树上从控制流图入口节点到当前访问节点的路径上的关系加入到当前访问节点的循环头节点列表中,将该列表中每节点的最内层循环头节点标记为在该循环头节点列表中与该节点同在一循环体内且到达该节点的正向路径最短的循环头节点。上述节点为扩展后的节点,控制流图为扩展控制流图。 在反汇编获得的控制流图基础上,由如下方法获得扩展控制流图1)对于控制流图中任意两个节点6、 c,如果点6、 c满足(W-PrW(c)且W-S"cc(6),则将6和C合并为一个新的节点6',在程序控制流图中代替6、 C;重复1)中合并、替代过程,直至程序控制流图中任意两个节点都不满足1)中合并条件。本发明的效果在于可以有效判定循环结构,以及它们之间的嵌套关系,进而达到有效 结构化程序控制流图的目的。 本发明有如下优势1. 本发明方法比P. Havlak的方法和G. Ramalingam的方法更加准确,在循环结构不是严 格的嵌套关系的时候也能识别循环结构以及循环之间的嵌套关系,提高反编译后程序的结构 化程度;2. 本发明所述方法P. Havlak的方法和G. Ramalingam的方法提出的方法效率高,只需要 对程序进行一次深度优先遍历就可以识别程序中的所有循环,实验表明比P. Havlak的方法快 2~5倍;3. 本发明所述方法P. Havlak的方法和G. Ramalingam的方法易于实现,不需要使用 Interval/DSG等复杂数据结构以及多次迭代进行辅助识别。本发明所述方法完全自动化识别可执行代码中的循环结构。该方法实现简单,识别结果 准确,而且方法复杂度低,识别效率高。


图1是不可规约循环的控制图示例。图2是图1中对应的循环嵌套森林图。图3是识别循环结构的整体流程图。图4是识别循环节点控制流图。图5是识别循环节点情况示意图。图6是标记循环头节点列表工作流程图。图7是标记循环头节点列表情况示意8是循环节点识别伪代码。图9是标记循环头节点列表伪代码。
具体实施方式
本发明的循环的识别方法,其步骤可表述为1. 对可执行文件进行反汇编,得到该可执行文件的中间代码;2. 从上述中间代码中提取控制流信息,得到控制流图,进一步获得扩展控制流图 G=(N,E,h ): N是节点集合,E是边的集合,h。是控制流图入口节点;3. 深度优先遍历扩展控制流图,识别循环节点,具体包括对每个节点进行以下判断1) 该节点是否为循环头节点;2) 该节点是否在循环体内,如果是则找到它的最内层循环头节点;3) 该节点是否为重入口,如果是则找到重入边。4. 标记节点的最内层循环头节点;5. 将对应的控制流图识别为循环结构。进一步地,给定当前访问节点bo, p为在深度优先生成树上从ho到b()的当前路径。本发明可以采取以下方法,判断节点的上述三个属性1) 如果bo的某个后续节点b没有被遍历过并且b在p中,则b为循环头节点,将b加入到bo的循环头节点列表中;2) 如果bo的某个后续节点b没有被遍历过,并且遍历b后发现b在某个循环体中,则 bo在循环体内,并且将b的循环最内层循环头节点h加入到b的循环头节点列表中; 或者b被遍历过并且不在p中,但是在某个最内层循环头节点h在p中的循环体内, 则bo在循环体内,并将h加入到b的循环头列表当中。3) 如果bo的某个后续节点b被遍历过并且不在p中,若b在一个最内层循环头h不在 当前路径的一个循环体中,则b为一个循环重入口, <^山>为一条重入边。进一步地,给定当前访问节点bc和需加入的循环头节点h,使用如下方法将h加入到bo 的循环头节点列表中,以实现标记节点的最内层循环头节点-将h和它的循环头节点列表根据它们在p中的关系加入到bo的循环头节点中。将其间每 个节点的最内层循环头节点标记为在新生成的列表中与该节点同在某个循环体内,并且到达 该节点的正向路径最短的循环头节点。下面结合附图,更详细地描述本发明的具体实施方式
。 参看图3,识别循环结构的整体流程为步骤l:利用各种反汇编工具,对可执行文件反汇编处理,获得中间代码表示; 各种反汇编工具,如IDA Pro, Objdu即,可以自动完成该过程;步骤2:在中间代码基础上,提取控制流信息,进一步获得扩展控制流图;步骤3:在扩展控制流基础上,进行循环节点识别。 进一步,参看图4,进行循环节点识别的具体流程为步骤l:深度优先遍历控制流图。给定当前节点bo, p为在深度优先生成树上从ho到b() 的当前路径。步骤2:对bo的每个后续b按以下顺序进行检査1) b是一个新节点,即b没有被遍历过,如图5(A)所示。遍历b,如果遍历后发现b在 某个循环体内,将b的最内层循环头节点h加入到bo的循环头节点中;2) b被遍历过且b在p中,如图5(B)所示。标记b为循环头,并且将b加入到bo的循环 头节点列表当中;3) b被遍历过,b不在p中或者b不在某个循环体内,如图5(C)所示。则不对b进行处 理;4) b被遍历过且b不在p中,并且b在一个最内层循环头h在p中的循环体中,如图5(D)所示。将h加入到bo循环头节点列表中;5) b被遍历过且b不在p中,并且b在一个最内层循环头h不在p中的循环体中,如图 5(E)所示。将b标记为一个重入口,并且将〈bo,b〉标记为一条重入边。如果存在b在 p中的最内层循环头h2,将h2加入到bo的循环头节点列表中。步骤3:将循环头节点h加入节点b的循环头节点列表中。进一步,参看图6,将循环头节点h加入节点b的循环头节点列表的具体流程为-1) 若b等于h或者h为空,则返回;2) 令curl等于b, cur2等于h3) 当curl属于某个循环体,重复以下操作a) 令ih等于curl的最内层循环头节点,如图7所示,在第一次进入循环时ih等于HI;b) 如果ih等于cur2,循环结束;c) 如果ih在路径中的位置小于cur2在图中的位置。令curl的最内层循环头节点为 cur2, curl等于cur2, cur2等于ih。如图7所示,在算法第二次进入循环时,ih 等于H2,它在路径中的位置小于当前的cur2 (即h),因此令curl (即H1)的 最内层循环头节点为h, curl的值改变为h, cur2的值改变为H2。在图7中表现 为删除了从H1到H2的边,增加了从Hl到h的边。d) 否则,令curl等于ih。如图7所示,当算法第一次进入循环时,ih等于Hl,它在路径中的位置大于当前的ih (即h), curl的值改变为H1。4)令curl在循环体中,curl的最内层循环头节点位cur2。在图7中,循环结束时curl的当前值为H2,则令H2在循环体中,H2的最内层循环头节点为cur2当前的值即H3。在图7中表现为增加了从H2到H3的边。 在经过以上的算法后,本发明可以有效判定循环结构和它们的嵌套关系,有效结构化程序控制流图。本发明已在申请人研制的反编译工具上应用,取得了很好效果,实现了本发明的目的。
权利要求
1. 一种嵌套循环结构的识别方法,其步骤包括1)对可执行文件进行反汇编,得到该可执行文件的中间代码;2)从上述中间代码中提取控制流信息,得到控制流图;3)深度优先遍历控制流图,得到循环结构子图,该循环结构包括3-1)循环头节点;3-2)循环体节点,及其最内层循环头节点;3-3)重入口节点,及其重入边;4)标记上述节点的最内层循环头节点;5)将上述循环结构子图识别循环结构。
2. 如权利要求1所述的嵌套循环结构的识别方法,其特征在于对于当前访问的节点,如其一后继节点没有被遍历,且处于深度优先生成树上从控制流图入口节点到当前访问节点的路径 上,则该后继节点为循环头节点,将该后继节点加入该当前访问节点的循环头节点列表中。
3. 如权利要求1所述的嵌套循环结构的识别方法,其特征在于对于当前访问的节点,如其一后继节点没有被遍历过,则遍历该后继节点,如该后继节点位于一循环体内,则当前访问节 点为循环体节点,将该后继节点的最内层循环头节点加入该当前访问节点的循环头节点列表 中。
4. 如权利要求1所述的嵌套循环结构的识别方法,其特征在于对于当前访问的节点,如其一后继节点被遍历过,且不处于深度优先生成树上从控制流图入口节点到当前访问节点的路径 上,但该后继节点位于有最内层循环头节点位于深度优先生成树上从控制流图入口节点到当 前访问节点的路径上的循环体内,则该当前访问节点为循环体节点,将该最内层循环头节点 加入该当前访问节点的循环头节点列表中。
5. 如权利要求1所述的嵌套循环结构的识别方法,其特征在于对于当前访问的节点,如其一 后继节点被遍历过,且不处于深度优先生成树上从控制流图入口节点到当前访问节点的路径 上,但该后继节点位于无最内层循环头节点位于深度优先生成树上从控制流图入口节点到当 前访问节点的路径上的循环体内,则该后继节点为重入口节点,从该当前访问节点到该后继 节点的有向边为重入边。
6. 如权利要求1所述的嵌套循环结构的识别方法,其特征在于对于当前访问的节点和需加入 的循环头节点,将该循环头节点和它的循环头节点列表根据其在深度优先生成树上从控制流 图入口节点到当前访问节点的路径上的关系加入到当前访问节点的循环头节点列表中,将该 列表中每节点的最内层循环头节点标记为在该循环头节点列表中与该节点同在一循环体内且 到达该节点的正向路径最短的循环头节点。
7. 如权利要求1所述的嵌套循环结构的识别方法,其特征在于所述节点为扩展后的节点。
8. 如权利要求1所述的嵌套循环结构的识别方法,其特征在于对可执行文件通过反汇编工具 IDAPro进行反汇编。
9. 如权利要求1所述的嵌套循环结构的识别方法,其特征在于对可执行文件通过反汇编工具 Objdump进行反汇编。
全文摘要
本发明属于逆向工程和程序分析领域,具体涉及一种识别循环结构的方法对可执行文件进行反汇编,得到该可执行文件的中间代码;从上述中间代码中提取控制流信息,得到控制流图;深度优先遍历控制流图,识别循环节点;标记节点的最内层循环头节点;将对应的控制流图识别为循环结构。本发明可以有效判定循环结构,以及它们之间的嵌套关系,进而有效结构化程序控制流图。可用于反编译、软件测试等设备中。
文档编号G06F9/45GK101271397SQ20071009000
公开日2008年9月24日 申请日期2007年3月23日 优先权日2007年3月23日
发明者李佳静, 剑 毛, 伟 王, 王铁磊, 维 邹, 韬 韦 申请人:北京大学
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1