APP下载

基于逆向工程的扩展OpenC++静态分析方法研究

2010-10-17汤发俊

湖南工业职业技术学院学报 2010年6期
关键词:编译器逆向静态

汤发俊

(无锡商业职业技术学院,江苏 无锡 214063)

基于逆向工程的扩展OpenC++静态分析方法研究

汤发俊

(无锡商业职业技术学院,江苏 无锡 214063)

文章提出了一种基于逆向工程项目的扩展OpenC++静态分析方法。探讨了抽取静态信息的OpenC++扩展策略,容错解析技术和嵌套定义类、结构体的识别与处理等方面的问题,介绍了采用 XML文件进行静态信息的存储方法。

逆向工程;开放编译器;静态分析

一、引言

静态信息是生成静态模型和获取动态信息的依据,从某种程度上看是进行逆向工程的基础,在逆向工程中占据着非常重要的地位。静态信息主要是通过对目标系统源码直接进行静态分析来提取的,实现方法主要有两种:

1.直接进行词法和语法分析。通过词法分析可以得到程序信息的多种有用表示,通过语法分析可以得到两类表示:分析树 (parse tree)和抽象语法树 AST(abstract syntax tree)。其中,分析树只是指导分析过程,是比较原始的结果。分析树显示了程序语句的分解过程,包含和程序的实际含义无关的信息。去除分析树的无关信息后得到AST,AST只包含和程序实际内容相关的细节,是更复杂的程序分析工具的基础。

2.基于开放编译器进行分析。借助于开放编译器提供的便利,使用相应的接口获取静态信息。这种方法的优点在于:由于开放编译器通过元对象协议 (MOP)把编译过程对用户开放,用户可以通过元对象协议提供的接口,有选择性的获取所需的静态信息,而不必在如何进行语法分析、如何构造语法树这样的细节上花费太多的精力。但这种方案所能获取的静态信息量要小于前一方案。虽然元对象协议向用户提供了可干预编译过程的接口,但它同时也限制了用户对底层的分析树或语法树可执行的操作范围。另外,一个元对象协议所提供接口的完备与否也会影程序员响对底层分析树或语法树的操纵力度。

在本逆向工程项目中,静态分析的职能主要有以下几点:一是获取生成静态模型 (如类图)所需信息;二是辅助确定软件触发器的植入位置,为动态信息的获取提供支持;三是为部分模型 (如状态图、类图等)的高层抽象提供支持。为此本文主要阐述基于逆向工程的扩展 OpenC++静态分析方法。

一、抽取静态信息的OpenC++扩展策略

OpenC++提供了静态分析支持,但是通过MOP接口获取静态信息有诸多的限制,获取的信息不全面,而且 OpenC++没有提供保存信息的MOP。为了抽取和保存比较全面的信息,需要对OpenC++进行一些扩展。

OpenC++在对源代码进行分析之后会生成分析树,从分析树可以获取全面的静态信息,所以对 OpenC++的扩展主要是在分析树 Translate过程中添加获取和保存静态信息的功能。主要实现方法是:为 OpenC++的 Class类中添加三个新的成员方 法 SaveStaticInfo () 、SaveStaticInfoO fMethod () 、SaveStaticInfoOfAttribute()。其中 SaveStaticInfo()方法用于获取和保存目标系统源代码中的静态信息,它在 Class::TranslateClass()中被调用。TranslateClass()主要负责类定义的转换,面向对象程序中的每个类都会通过调用它进行转换。在 SaveStaticInfo()中会调用 SaveStaticInfoO fMethod ()、SaveStaticInfoOfAttribute()获取类的成员方法和数据成员,然后通过调用 CXMLParser类操纵 XML解析器完成静态信息的永久保存。

图 1示的是抽取静态信息的 OpenC++分析流程,其中的虚线框中为扩展的功能。

获取函数返回值的类型。OpenC++提供了 TypeInfo元对象,用于表示类型。利用 TypeInfo元对象构造一个变量定义表达式,然后删除表达式中的变量名,就可以得到准确的类型。

类型识别方法。OpenC++的 Parser类成员方法 rClassSpec (…)会在解析过程中能够识别当前分析的是结构、联合、类或模板,通过在这里设一个全局 int类型变量保存当前解析的类型,用于后续的静态分析。

图1 抽取静态信息的OpenC++分析流程

二、容错解析技术

OpenC++是按标准编译器进行词法分析和语法分析,所以对于含有完整的类、函数、变量、宏等定义的目标程序, OpenC++可以准确的完成处理和分析,但如果缺少部分定义,那么在解析过程中可能会出现丢失信息,或导致信息错误,或异常退出等情况。

为了减少干扰性信息、避免海量信息的产生,会在预处理时隔离一些系统类、系统函数、系统变量、系统宏等的定义头文件,OpenC++在解析这类程序时将会出现语法错误,其默认处理方法是当错误达到预定义数量时中断退出,未达到这一数量时会记住本次出错位置,然后继续分析,在分析完后退出整个编译过程,不进行后续处理,分析的最终结果是失败。这种处理策略对于编译器而言是合理的,但对于程序静态分析工具而言则并不合理,其根本的原因在于,编译器解析程序的前提是不知目标系统的语法是否正确,在解析的过程中才进行检查,而静态分析工具则假定分析的目标系统在语法上是正确的。

目前国际上有几种解决解析过程中出现无法识别信息或语法错误等情况的技术,如Fuzzy Parsing[1],Island Grammars[2],Skeleton Grammars,Error Recovery等。图 2显示了上述几种技术对程序源码的解析深度。

图2 几种技术对程序源码的解析深度

通过对上述相关技术的研究,针对程序静态分析的需要,本文提出了两种可行的实现方法:一是当遇到无法识别的元素时,跳出解析的程序段,将这个程序段的信息忽略,例如对于函数而言,如果函数中含有无法识别的信息时,直接跳到函数定义结束符“}”处;二是当遇到解析错误时忽略出错语句,从后续语句继续解析,对于C++而言是指跳到“;”处继续解析。这两种方法各有利弊,第一种方法在遇到无法识别的代码时会将相关信息整段丢失,会损失较多的信息;第二种方法丢失信息较前一种少,但它提高了解析的复杂度。在本文提出的静态解析方法中,根据获取信息的粒度,结合使用了上述两种方法。

三、嵌套定义类、结构体的识别与处理

前文提到,类型信息是在 OpenC++的 Parser::rClassSpec ()方法获取,并保存到一个全局变量中,在 SaveStaticInfo()保存静态信息时,将其一并保存,以备后续静态模型抽象和软件触发器植入之用。这种处理方法存在一些不足。出现这种问题的原因可以从 OpenC++分析的过程看出:OpenC++在解析代码时首先用 Parse类的 rProgram()方法读取一个代码段,然后对代码段进行分析,并在分析过程中生成分析树。如果在代码段的分析过程中遇到内部定义的类、结构体、联合体等的定义时会将其做为一个子段进行分析,分析过程是一个深度优先的过程。分析完此程序段后,OpenC++会对此段代码生成的分析树进行 Translate()操作。Translate()操作的调用是对树的一个后序遍历过程,也就是说,最后生成的类、结构体或联合体的子树会首先进行 Translate。如果使用一个 int变量记录类型,则只能记录最后分析的一个定义体类型。那么可不可以使用一个 int数组进行记录呢?其实也是不行的,因为记录的类型和定义体无法对应。图 3展示了使用一个全局变量记录类型的错误示例。

图3 使用一个全局变量记录类型的错误

结合前面的叙述,本文提出一种方法弥补了上述缺陷。该方法如下:

(1)使用 STL的map进行类名、结构名和其类型 ID的成对保存,定义如下:

std::map<std::string,int>g_map;其中 string类型用于保存类名或结构名,int类型用于保存 string对应的类型 ID。

(2)在 Parser类的 rClassSpec(…)成员方法中识别类型,当遇到一个解析段时,保存 <类或结构名,类型 ID>数据对。

(3)在进行 TranslateClass()时通过查询类名、结构名获取其对应的类型 ID。

(4)OpenC++分析完一个 C++源码后清空 map,准备对下一个源码进行分析。

这种方法的好处是:类或结构体的嵌套定义层数和数量没有限制;可以准确、高效的进行类型保存和查询。

四、静态信息的存储

本逆向工程项目的目标系统以面向对象系统为主,获取的静态信息主要用于系统的静态模型抽象,并为动态信息的获取和过滤提供依据。这就决定了获取的静态信息主要以类为主,包括类、结构、联合、全局函数、系统API以及为获取系统的动态信息提供支持的一些其它信息,例如函数的调用、类的实例化、对类成员的操作 (如成员方法的调用、成员变量的修改)等。对于类、结构体、全局函数等静态信息,主要用于静态模型抽取,这类信息需要物理保存,以备后续模块抽象之用。而系统API以及其它一些信息则主要用于软件触发器的植入定位,不做他用,所以这些信息只需在系统静态分析和软件触发器植入时临时存储。

图4 静态信息文件的XML Schema

静态信息的存储需要满足以下几点:有利于信息的格式化;应具有跨平台性,因为本逆向工程项目的目标系统基于W indows、Unix/Linux等多种平台,这样方便目标系统的平台间传递;具有快速可靠的信息提取技术;能够存储大量的信息。

从可靠性、效率和易用性等各方面考虑,本文采用 XML文件进行静态信息的存储。存储方法是:为 OpenC++添加 XML解析器的操纵类 CXMLParser,通过操作 XML解析器将获取的静态信息进行组织并保存到 XML文件中。图 4为本逆向工程项目设计的静态信息文件的 XML Schema。

五、结束语

静态分析是获取目标系统的结构信息、调用流信息和数据流信息的主要手段,是逆向工程中静态模型生成的主要支持技术。静态分析可以通过编写词法分析和语法分析程序完成,也可利用开放编译器辅助完成。本文阐述了利用扩展后的OpenC++进行程序的静态分析,并将获取的静态信息存入静态信息 XML文件。这种处理方法不但提高了静态分析模块的开发速度,同时又方便了后续动态信息的收集。

[1]Rainer Koppler.A systematic approach to fuzzy parsing.Practice and Experience,Vol.27,No.6,pp.637-649,1997.

[2]Steven Klusener,Ralf Lammel.Deriving tolerant grammars from a base-line grammar.ICS M 2003:pp 179.

Studies of an Extended OpenC++Static Analysis Methods in Reverse Engineering

TANG Fa-jun
(Wuxi Institute of Commerce,Wuxi 214063,Jiangsu)

This paper presents an extended OpenC++static analysis methods in reverse engineering.Presents the extraction of static information OpenC++expansion strategy,in fault-tolerant parsing technology and nested definitions of classes,the structure of recognition and treatment and other aspects of the handling skills,describes the use of XML files for static information storage method.

reverse engineering;open compilers;static analysis

TB2

A

1671-5004(2010)06-0011-02

2010-12-11

汤发俊 (1977-),男,江苏建湖人,硕士,无锡商业职业技术学院讲师,主要研究方向:计算机应用、电子商务。

猜你喜欢

编译器逆向静态
逆向而行
静态随机存储器在轨自检算法
基于相异编译器的安全计算机平台交叉编译环境设计
逆向解答
机床静态及动态分析
具7μA静态电流的2A、70V SEPIC/升压型DC/DC转换器
通用NC代码编译器的设计与实现
逆向工程技术及应用
50t转炉静态控制模型开发及生产实践
编译器无关性编码在微控制器中的优势