-
-
[原创]从反汇编的角度学C/C++之多重继承与多继承
-
发表于: 2021-10-3 17:15 6351
-
在类的继承关系中,我们可以进行多重继承,那么它和单继承相比数据排布等等有什么不同,通过如下定义的代码来观察多重继承的特点。
首先我们看看构造函数的反汇编结果
可以看到,在虚函数中,首先调用父类Base2的构造函数,随后初始化虚表指针然后在进行类变量赋值,接着看下父类构造函数
接着继续看祖父类Base1的构造函数
由上可以得出
多重继承的构造函数执行流程是:祖父类构造函数(Base1)->父类构造函数(Base2)->子类构造函数(Sub)。在每个构造函数开始之前都会把自己的虚函数表赋值给虚表指针。
类变量地址中的数据是按照:虚表指针->按照祖父类(Base1)的类变量->父类类变量(Base2)->子类类变量(Sub)依次排布
此时查看类地址在内存中存储的数据可以看到如下的内容
接着我们看一下虚函数表在多重继承中有什么特点,IDA查看结果如下
为了方便展示,同样根据函数后重命名,结果如下
可以看到,在多重继承中,子类中的虚函数表最终存储的虚函数地址是低一层子类重载的地址。比如fun1被Sub重载了,那么它就会报错Sub_fun1,而fun2没被Sub重载,但是被Base2重载,所以它不是保存Base1_fun2而是Base2_fun2,而fun3没被Base2和Sub1重载,那么保存的就是Base1_fun3。
C++和其他面向对象不同的一大特点就是可以多继承,修改定义如下
接着查看子类构造函数
可以看到和多重继承相比,在多继承中,子类构造函数会依照继承顺序从左到右调用父类构造函数。而且调用父类构造函数的时候,传的地址是经过计算的,在调用Base2的构造函数的时候,这里ecx之所以加8是因为虚表指针占4个字节,Base1类中的x占4个字节。其次就是会赋值两个虚表地址,而被赋值的位置也是经过计算的,第二个虚表指针赋值的时候eax+8,这个8和意思和add ecx, 8一样。
在依次查看Base1和Base2的构造函数
可以看到Base1和Base2由于没用父类,所以他们的构造函数就是首先赋值虚表指针,然后赋值类成员变量。所以数据的排布以及在内存中的情况会如下图所示
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)
赞赏
- [原创]CVE-2022-21882提权漏洞学习笔记 16383
- [原创]CVE-2021-1732提权漏洞学习笔记 19489
- [原创]CVE-2014-1767提权漏洞学习笔记 15192
- [原创]CVE-2018-8453提权漏洞学习笔记 18526
- [原创]CVE-2020-1054提权漏洞学习笔记 13542