-
-
[原创]通过分析RTTI识别类及类之间的继承关系
-
发表于: 2013-2-21 14:23 6962
-
【文章标题】: 通过分析RTTI识别类及类之间的继承关系
【文章作者】: 绝对小白
【编写语言】: VC
【使用工具】:IDA6.1
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!
--------------------------------------------------------------------------------
背景交代
这篇文章是以前学习RTTI的时候写的,很多东西都是参考一此前辈的文章来的,望各位前辈多多包含,别拍砖啊。今天刚刚用到RTTI整理了一下,也不怕各位大牛笑话,因为最近看了厚黑心里学,所有就发上来了~!
【详细过程】
通过分析RTTI识别类及类之间的继承关系
一、什么是RTTI?
RTTI 是“Runtime Type Information”的缩写,意思是:运行时类型信息。RTTI(Run-Time Type Identification)运行时类型识别是由编译器生成的特殊信息,用于支持像dynamic_cast<>和typeid()这样的C++运算符,以及C++异常。
开启RTTI。
在默认情况下VC++6.0是把RTT关闭的。在VC++6.0菜单上的project-->setings-->C/C++进行设置,在Category:选择“C++ Language”,选中“Enable Run-Time Type Information(RTTI)复选框”如图:
三、预备知识补充。
为了实现 RTTI,MSVC编译器在编译完了的二进制可执行文件中加入一些结构体,这些结构体包含了代码中关于类(特别是多态类)的信息。这些结构体是:
1、RTTI Complete Object Locator结构体。
这个结构体在32位系统中占20个字节,其中包含了2个指针,一个指向当前类的信息,另一个指向类的继承关系信息。该结构体信息如下(来源于网上):
struct RTTICompleteObjectLocator
{
DWORD signature; //总是0 ?
DWORD offset; //这个vftable在整个类中的偏移
DWORD cdOffset; //构造函数位移的偏移
struct TypeDescriptor* pTypeDescriptor; //整个类的类型描述符
struct RTTIClassHierarchyDescriptor* pClassDescriptor; //描述继承关系(hierarchy)
};
2、其中TypeDescriptor结构信息如下,这个结构中定义当前类的类名,逆向的时候根据类名可以大概猜出这个类是做什么的。
struct TypeDescriptor{ VOID *pVFTable; //Always points to type_info’s vftable
DWORD spar3; //保留
char *name; //Class Name
}
ClassHierarchyDescriptor结构体。
该结构体记录了类的继承信息,包括基类的数量,以及一个RTTIBaseClassDescriptor结构数组。
struct ClassHierarchyDescriptor{DWORD signature; //总是 zero?DWORD attributes; //bit 0 set = multiple inheritance, bit 1 set = virtual inheritanceDWORD numBaseClasses; //number of classes in pBaseClassArraystruct RTTIBaseClassArray* pBaseClassArray;};
RTTIBaseClassDescriptor
这个结构体记录了关于基类的有关信息,它包括一个指向基类的TypeDescriptor 的指针和一个指向基类的RTTIClassHierarchyDescriptor 的指针另外它还包含有 一 个 PMD 结 构 体。这个结构体记录了这个类中各个基类的位置。
struct RTTIBaseClassDescriptor{struct TypeDescriptor* pTypeDescriptor; //type descriptor of the classDWORD numContainedBases; //number of nested classes following in the Base Class Arraystruct PMD where; //pointer-to-member displacement infoDWORD attributes; //flags, usually 0};
PMD结构体
PMD结构体描述一个基类是如何安置在一个完整的类里。如果是一个简单的继承,它被安置在从对象起始位置开始的一个固定的偏移,这个偏移就是_mdisp_字段。如果它是一个虚基类,那么需要从vbtable得到一个附加的偏移。
struct PMD
{
int mdisp; //成员偏移
int pdisp; //vbtable偏移
int vdisp; //vbtable内偏移
};
四、实战。
启用RTTI。
在开户RTTI后,MSVC编译器在vftable前(偏移-4)设置了一个指针,指向了“Complete Object Locator”(完整对象定位器)的结构。
把下面的代码编译为DEBUG版(什么DEBUG版的,为了更好的学校嘛):
#include <iostream>
class CFather
{
public:
virtual void SetTall(int a)
{
m_ntall=a;
}
virtual void ShowTall()
{
printf("m_ntall=%d\n",m_ntall);
}
public:
CFather(){}
virtual ~CFather(){}
private:
int m_ntall;
};
class CMother
{
public:
virtual void SetWeight(int a)
{
m_nWeight=a;
}
virtual void ShowWeight()
{
printf("m_Weight=%d\n",m_nWeight);
}
public:
CMother(){}
virtual ~CMother(){}
private:
int m_nWeight;
};
class CSon :public CFather,public CMother
{
public:
void SetAge(int a)
{
m_nAge=a;
}
void ShowAge()
{
printf("m_nAge=%d\n",m_nAge);
}
public:
CSon(){}
virtual ~CSon(){}
private:
int m_nAge;
};
int main(int argc, char* argv[])
{
CSon son;
son.SetAge(18);
son.ShowAge();
return 0;
}
IDA分析。
1、定位到虚表
首先来到找到构造函数,如图:
双击“j_??0CSon@@QAE@XZ”来到构造函数实的地方,如图:下面红色代码显示的地方可以看到两张虚表。关于继承的内存部局不了解的请自己查看相关资料。
上图显示的是son对象的内存部局
2、通过虚表,定位RTTICompleteObjectLocator结构,找到类名。
双击“_7CSon@@6BCFather@@@”这一全局变量,来到虚表的位置,如图:
上面已经说过了,RTTICompleteObjectLocator指针就在虚表前偏移-4的地方。也就是上面那个DWORD类型的“??_R4CSon@@6BCFather@@@”。如何确定是一个RTTICompleteObjectLocator结构指什,IDA后面已经给出注释,进一步确认,通过分析RTTICompleteObjectLocator->pTypeDescriptor是不是指向一个有效的TypeDescriptor;检查TypeDescriptor是否正确,可以看TypeDescriptor.name是不是以“.?AV(是VC编译的时候给类别加的的前缀)”开头的字串。
双击“ ??_R4CSon@@6BCFather@@@”,来到RTTICompleteObjectLocator的结构,如图:
通过TypeDescriptor.name检查是否有效,双击“??_R0?AVCSon@@@8”来到TypeDescriptor,如图:
整理后如下图:
找出类的继承信息、继承数量及基类信息。
来到RTTICompleteObjectLocator的结构,如图:
双击“ ??_R3CSon@@8”来到RTTIClassHierarchyDescriptor指针地址,如图:
转为ClassHierarchyDescriptor内存结构整理为,如图:
双击“??_R2CSon@@8”来到BaseClassArray内存地址,如图:
通过以上信息,一层层向上分析,直到找出类的类与类之间的关系。
教程结束。
图片太多,不能一一上传,发了个附件。
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课
赞赏
- [求助]未知编码 1375
- [原创]CTF2019 第一题:无限流[签到题] 1957
- [原创]CTF晋级赛Q2 第一题 2269
- [原创]通过分析RTTI识别类及类之间的继承关系 6963