逆向 C++ 这些年来,逆向工程分析人员一直是凭借着汇编和 C 的知识对大多数软件进行逆向工程的,但是,现在随着越来越多的应用程序和恶意软件转而使用 C++语言进行开发,深入理解 C++ 面向对象方式开发的软件的反汇编技术就显得越发的必要。本文试图通过分析在反汇编时如何手工识别 C++对象,进而讨论如何自动完成这一分析过程最终介绍我们自己开发的自动化 工具,一步一步的帮助读者掌握逆向 C++程序的一些方法。 作者:Paul Vincent Sabanal
I.引言和必要性 1) 用 C++开发的恶意软件越来越多了 2.手工方法 A. 识别类及其构造函数 2)调用约定。这一点与 1)有关,类的成员函数在被调用时基本上是把函数的参数压入栈中,而使用 ECX 传递 this 指针。如下面这个例子,在为类新建了一个对象之后,new 返回的指针(该指针指向分配给对象的地址)EAX 的值马上被传给了 ECX,然后就调用了构造函数。 另外,我们有时还会遇到一些间接函数调用,这很可能是调用类的虚函数,当然,在静态分析的情况下(即不是在调试器中进行动态分析)如果不是事先明确的知道这个虚函数是哪个类的,要深入跟踪这个虚函数还是很困难的。我们考虑下面这个例子: 在这个例子里,我们首先要知道 ClassA 的虚函数表(virtual function table)在哪里,然后才能根据虚函数表来确定虚函数的代码所在的位置。 3)STL(标准模版库 Standard Template Library)中的代码和可执行文件导入的 DLL。另外,如果我们在检查二进制可执行文件时发现这个可执行文件使用了 STL 中的代码,这一点可以通过分析可执行文件要求导入的函数或者通过 IDA 的 FLIRT 之类的库签名识别方法来做到: 下面是调用 STL 中的代码的情况: 类的实例
那么怎么才能得到上面这张图呢? 我们可以使用-d1reportAllClassLayout 这个编译开关,它可以让 MSVC 编译器(译注:至少是 MSVC 6.0 以上的版本)生成一个.layout 文件,在该文件中包含有大量的极具价值的类的布局信息,包括基类在派生类中的位置,虚函数表,虚基类表(virtual base class table 我们下面会深入讨论),类的成员变量等信息(实际上我们这些图表都是从.layout文件中取出的)。 下面是这个类在内存中的存在形式: 注意指向虚函数表的指针(vfptr)是被添加在最前面的,而在虚函数表里面,各个虚函数是按照其声明的顺序排列的。类 Ex2 的虚函数表如下: 下面这个图是 PPT 里的更清楚一点: 当一个类是继承另一个类的话,情况又会怎么样呢? 下面讨论一个简单的单一继承关系
![]() ![]() 正如您所看到的,派生类只是简单的把基类嵌入到自己内部就完事了。但是万一要是有多重继承有会有什么情况发生呢?
![]() ![]() 内存中的情况会是这样:
![]() 看 PPT 上的图更清楚一点:
![]() ![]() 派生类将每个基类都嵌入了自身,而且每个基类还都保留有自己的虚函数
表。但是请注意,第一个基类的虚函数表是被派生类共享的,派生类的虚函数将 会被例在基类虚函数表的后面。另外要注意的是,因为 Ex5 中也有一个和 Ex4 的虚函数同名的 func1(),所以根据 C++的规则,Ex4 虚函数中的 func1()函数的 指针已经被 Ex5 的 func1()的函数指针给替换掉了。 Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1795732 |
|
来自: SpringEmpire > 《我的图书馆》