前言
这是一个关于c++逆向的阅读材料,我大致做一些笔记,因为是全英文所以基本是翻译)
介绍
c++中主要是类,在我们理解c++时,对于c++目标的主要部分(类)以及这些部分如何联系在一起(类关系)有一个宏观的概念。
为了实现这种理解,我们必须能够:
(1)识别类
(2)识别类之间的关系
(3)识别类成员。
而人工分析检索c++类信息方法和自动化是这篇文章要讨论的内容。
手动分析c++二进制文件
本节介绍分析c++二进制文件的手动方法;它特别侧重于识别/提取c++类及其对应成员(变量、函数、构造函数/析构函数)和关系。请注意
首先,我们需要识别这是否是一个c++文件,或者运用了c++的类,下面几种可以判断:
1)大量使用ecx(这个ptr)。可能首先看到的事情之一是大量使用ecx(用作this指针)。可能看到的一个地方是,在函数即将被调用之前被赋值。另一种情况是,如果一个函数使用了ecx而没有首先初始化它,这意味着它可能是一个类成员函数。
.jpg) .jpg)2)调用约定。与(1)相关的是,类成员函数调用时使用堆栈中常用的函数参数,并指向类的对象(即thispointer.)。下面是一个类实例化的例子,在这个例子中,分配的类对象(eax)最终将被传递给ecx,然后调用构造函数
.jpg)此外,我们将注意到更可能是虚函数的间接函数调用;当然,如果不首先知道实际的类或在调试器下运行代码,就很难跟踪这些调用的去向。在这种情况下,我们必须首先知道ClassA的虚函数表(vftable)的位置,然后根据虚函数表中列出的函数列表确定函数的实际地址。
3)STL代码和导入的dll。判断一个样本是否为c++二进制文件的另一种方法是,目标是否使用STL代码,这可以通过导入函数或库签名识别(如IDA的FLIRT)来判断.
类布局
我们还应该熟悉类在内存中的布局方式。让我们从一个非常简单的类开始。
这个类的布局如图所示
为了保持4字节的边界上的对齐,填充被添加到最后一个成员变量。在Visual c++中,成员变量在内存中的位置与声明的顺序相同。
当类中包含虚函数:
内存布局将变成这样:
注意,在布局的开头添加了一个指向虚函数表的指针。该表按照虚函数声明的顺序包含虚函数的地址。类Ex2的虚函数表如下所示:
如果一个类继承另一个类呢?以下是一个类从单个类继承时的情况,即单个继承:
布局是这样的
派生类的布局被简单地附加到基类的布局中。在多重继承的情况下,会发生以下情况:
正如所看到的,每个基类的实例数据的副本将被嵌入到派生类的实例中,每个包含虚函数的基类将有自己的vftable。注意,第一个基类与当前对象共享一个vftable。当前对象的虚函数将被追加到第一个基类的虚函数列表的末尾。
Author: John Doe
Link: http://example.com/2022/02/09/C-Reserve/
Copyright: All articles in this blog are licensed under CC BY-NC-SA 3.0 unless stating additionally.