首页
社区
课程
招聘
[原创]C++类的内存分布与std::typeInfor分析
发表于: 2024-9-5 15:46 3967

[原创]C++类的内存分布与std::typeInfor分析

2024-9-5 15:46
3967

C++类的内存分布

1.非静态成员变量,虚函数,内存对齐会影响类内存大小.本文优先考虑64位程序

A 类结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
class A
 
{
 
​   virtual void Func(){};
 
​   int m_X;
 
​   short m_Y;
 
}
32位下 sizeof(A)==12字节节
64位下 sizeof(A)==16字节
实例化内存布局:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
32位下:
A:{
•   0-4 :虚函数表
•   4-8: m_X 成员变量
•   8-12: m_Y 成员变量 (内存对齐)
}
  
64位下:
A:{
•   0-8 :虚函数表
•   8-12: m_X 成员变量
•   12-16: m_Y 成员变量 (内存对齐)
}

1.如果类里面有虚函数,类前4个字节是个虚函数表的指针.(64位是前8字节)。

2.会和结构体一样,存在内存对齐行为(这里就不展开了)。

3.类的成员函数(非虚函数,虚函数会放在虚表里)不会占用类的内存。

2.当子类继承多个有虚函数的父类

说明:会有多个虚表,比声明成员类少一个。

1.例子中A和C中都有虚函数,B继承了A和C,B的内存中就有两个虚函数表;

2.内存布局和声明的顺序有对应关系,具体内存排列顺序请看 1的内容。

思考题:C类自己的虚表去了哪里?

公布答案:

1自己的虚表还是首地址的地方,它和第一个虚表融合到了一起。(请看下面图片讲解)

1:B类的原型

img

2:C类的原型

img

3:C类内存结构,红色是他继承的 B A D 类,绿色是自己成员x内存。

img

4:查看下第一个也就是 0x000000014001C9A8地址。

img

你会发现原本B类里面只有三个虚函数此时内存中有4个虚函数,讲解:红色方框内是被C类重写的函数,绿色方框是B类自己两个虚函数(因为不重名所以没被重写),而最后一个蓝色方框是C类自己的boo虚函数。

5:其余两个类 A和D的虚表中只有三个函数(A和D函数同名只是打印内容不同)没有蓝色方块的函数,这里就不贴图了,我相信你们能理解。

6:以上5条都是以继承的形式进行讨论的。别的形式就不准确了。

3.不以继承的形式使用其他类

说明:以成员变量的形式,会有多个虚表,比继承多一个。

C类:

1.第一个是自己,接下来依次声明排列。与继承内存布局不同。

4.std::type_infor逆向查找验证

在C++ 类中存在虚函数的情况下 : 类中虚表的地址减去一个指针的大小取值,然后值再加上12字节取出就是std::type_infor对象地址指针。

此图是32位C++类的结构:

不过在64位下放的就不是指针而是一个偏移

我目前测试环境是vs2022下,别的编译器就不清楚了.

image-20240830224350914

1.取出虚表地址 0x000000014001c9a8。

image-20240830225703992

2.虚表地址减去void*大小(64位下8字节)也就是箭头指向地址。

image-20240830225858973

3.取出箭头地址转到,再加上12字节也就是方框中的数据(0x0001f3c8)。

4.0x140000000(模块基址)+0x0001f3c8。

image-20240830230149916

5.红色方框就是std::type_infor里面的数据

1
2
3
0x000000014001d0c8=0x000000014001c9a8/*虚表首地址*/-sizeof(void*);
0x0001f3c8=*(DWORD)((QWORD)0x000000014001d0c8+12)
0x000000014001F3C8=0x140000000/*进程模块基址*/ +0x0001f3c8;

6.执行代码验证,学过汇编的同学都知道RAX一般情况下是用来存放函数返回值,本文中是(0x00000014001F3C8)。

image-20240830230728820

7.正向代码验证。

image-20240830230920681

C++ 类中无虚表(无虚函数)的情况下情况是不一样的如下.

image-20240830225355738

1.上图是有虚表的情况,调用了__RTtypeid函数其功能就是 本文中第四条所讲内容。

image-20240830225000821

2.没有虚表的情况,他将会直接std::type_infor对象地址指针赋值给目标。

5.std::type_infor 介绍

1.x64下std::type_infor大小固定为24字节。

2.+0 偏移:存放着 type_infor 的虚函数表,里面有一个虚函数 为type_info::`scalar deleting destructor'(unsigned int)。

3.+8 偏移:_UndecoratedName = 0x0000000000000000 <NULL>,如图:

image-20240831002232919

4.+0x10 偏移:是他的“类名”,这个“类名”是需要处理才是真正的类名,去掉开头6个字节和结尾3个字节。

5.至此type_infor 解析完毕。


[课程]Linux pwn 探索篇!

收藏
免费 0
支持
分享
最新回复 (2)
雪    币: 24377
活跃值: (4332)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
图片不显示
2024-9-5 19:00
0
雪    币: 200
活跃值: (40)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
huangyalei 图片不显示

图片是放在github上的 ,我这边几台电脑都是能正常显示的。

最后于 2024-9-5 21:22 被学海无涯~编辑 ,原因: 打错字
2024-9-5 21:21
0
游客
登录 | 注册 方可回帖
返回
//