首页
社区
课程
招聘
[原创]我们来聊聊C++多态吧,理解它,并找到它。
2019-10-14 19:54 3250

[原创]我们来聊聊C++多态吧,理解它,并找到它。

2019-10-14 19:54
3250

我们来聊聊C++多态吧,理解它,并找到它。

我们通过一段代码,先来了解多态的底层实现

class cVirtual {
public:
  virtual void func0() {};
  virtual void func1() {};
};

int main()
{
  cVirtual cv;
  cv.func0();
}

非常简单的类,如果这里没有多态函数的话这个类对象实际只占1个字节(占位字节),有了多态函数后类对象里会保存一张多态函数的地址表,那么这个对象就会占4个字节。

来看反汇编。

cVirtual cv;
005719B3  lea         ecx,[ebp-0Ch];分配对象占用内存
005719B6  call        005713C5;调用构造函数

CALL指令调用的就是编译器为这个类生成的构造函数,这么简单的类也要有构造函数??,猜的没错,就是用来初始化多态表的,走进去看。

......  
0057179F  pop         ecx  ;恢复this指针
005717A0  mov         dword ptr [ebp-8],ecx ;保存this指针
005717A3  mov         eax,dword ptr [ebp-8]  ;取出this指针
005717A6  mov         dword ptr [eax],577BF8h  ;多态表初始化
005717AC  mov         eax,dword ptr [ebp-8]  ;返回this指针
......

我把多余的代码删掉了,构造函数只做了这一件事情,就是把多态表的指针赋值到对象地址中,也就是文中的this指针。

由上面的代码可以看出,这个类的对象的内存应该如下图:


我们看下 0x577BF8 中保存的内容:

整理一下是这样的,0x005713C0,0x005713BB,0x0000000。

那么这两个有效地址就是我们代码中的两个多态函数,我们来验证下。

so,我们可以总结出,对象的虚表指针在以对象为基址的前4个字节中,虚表指针指向的是一个地址表,地址表中的每一个地址对应这个类中的每一个虚函数。

在上例中,析构函数中做了和构造函数一模一样的事情,因为在构造函数中已经对虚表赋值了,在析构函数中是不是有点多此一举?并不是,析构函数中重新赋值是防止读取的虚表不是自己的虚表,读者可以从继承的角度出发,来思考这个问题。

搞不懂去看我写的继承的文章吧,可能还没更。

重点来了:

虚表信息是在编译后会被链接到二进制文件中,so 虚表是一个固定地址。

虚表中的虚函数地址排序顺序依据虚函数在类中的声明顺序而定。

当虚函数被访问时,会根据对象的首地址,取出虚表地址,在取出虚表元素,需要多次寻址才能完成。

通过间接寻址访问虚表,只发生在使用对象的指针或者引用调用虚函数的时候才会发生,当使用对象调用虚函数,不需要查表访问。(调用自身的函数,未构成多态,查虚表只会降低效率)

------------------------------->找到它

在茫茫汇编代码中找到多态需要关注以下几点:

类中隐式定义了一个数据成员

该数据成员在首地址处,并占4个字节

构造函数会将此数据成员初始化为某个数组的首地址

这个地址属于数据区,是固定地址

在这个数组内,每个元素都是函数指针

这些函数它们被调用时,第一个参数一定是this指针,注意调用约定

在这些函数内部,很有可能会对this指针使用相对间接的访问方式

虚表初始化特征码(在构造或析构函数中出现):

;下面这段代码出现的函数,需要具有成员函数特征,传递对象首地址作为this指针

lea ecx,[ebp - 8];获取对象首地址
call xxxxxxxxh ;函数调用

mov reg,this ;某寄存器得到对象首地址

mov dword ptr[eax], xxxxxxxxh
; 向对象首地址写入4字节数据,查看并确认这4字节是否为函数地址表的首地址如果上述代码出现,应该高度怀疑此函数是一个构造或析构函数。

Good job.


晒下我家猫,虽然很影响我的工作效率,我还是选择原谅它,怎么样可爱吗。



[培训]二进制漏洞攻防(第3期);满10人开班;模糊测试与工具使用二次开发;网络协议漏洞挖掘;Linux内核漏洞挖掘与利用;AOSP漏洞挖掘与利用;代码审计。

最后于 2019-10-14 19:57 被Hasic编辑 ,原因: 代码格式化
收藏
点赞3
打赏
分享
最新回复 (5)
雪    币: 17810
活跃值: (59928)
能力值: (RANK:125 )
在线值:
发帖
回帖
粉丝
Editor 2019-10-14 20:49
2
0
感谢分享!
雪    币: 914
活跃值: (2188)
能力值: ( LV5,RANK:68 )
在线值:
发帖
回帖
粉丝
万剑归宗 1 2019-10-15 08:45
3
0
猫很可爱,你腿不错
雪    币: 83
活跃值: (1037)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
killpy 2 2019-10-15 14:44
4
0
写的很好 通俗易懂 
雪    币: 612
活跃值: (479)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Hasic 2019-10-15 21:49
5
0
killpy 写的很好 通俗易懂
谢谢 
雪    币: 612
活跃值: (479)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
Hasic 2019-10-15 21:49
6
0
万剑归宗 猫很可爱,你腿不错
哈哈哈哈哈哈  
游客
登录 | 注册 方可回帖
返回