12.IDA-虚函数和虚表
来源:互联网 发布:owncloud支持windows 编辑:程序博客网 时间:2024/06/07 05:30
vtable
编译器会为每一个包含虚函数的类(或通过继承得到的子类)生成一个表,其中包含指向类中每一个虚函数的指针,这样的表就叫做虚表(vtable)
__vfptr
每个包含虚函数的类对象都获得__vfptr指针,并且是对象的第一个数据成员
编译器必须要保证虚函数表的指针存在于对象实例中最前面的位置
在计算对象的总大小时,也必须考虑到虚表指针。比如new,传递给new的大小值不仅包括类(以及任何超类)中的所有显式声明的字段占用的空间,而且包括虚表指针所需的任何空间
示例代码:
class Base{public: virtual void vf1() = 0; virtual void vf2(){ cout<<"Base::vf2"<<endl; } virtual void vf3(){ cout<<"Base::vf3"<<endl; } virtual void vf4(){ cout<<"Base::vf4"<<endl; }private: int x,y;};class Sub: public Base{public: virtual void vf1(){cout<<"Sub::vf1"<<endl; } virtual void vf3(){cout<<"Sub::vf3"<<endl; } virtual void vf5(){cout<<"Sub::vf5"<<endl; }private: int z;};void call_vf(Base* b){ b->vf3();}int _tmain(int argc, _TCHAR* argv[]){ Base *b = new Sub; call_vf(b);
IDA分析如下:
值得注意的是,虚表索引操作非常类似于结构体引用操作。实际上,它们之间并无区别
。因此,我们可以定义一个结构体来表示一个类的虚表的布局,然后利用这个已定义的结构体来提高反汇编代码清单的可读性
这个结构体允许将虚表引用操作重新格式化成以下形式:
注意:
C++虚函数绝不会被直接引用,也绝不应成为调用交叉引用的目标。所有C++虚函数应由至少一个虚表条目引用,并且始终是至少一个偏移量交叉引用的目标。
我们随便找到 vf1函数定义,然后点击它的交叉引用:
从而跳转到虚表,其显示如下:
.rdata:004031B8 const Base::`vftable' dd offset __purecall ; DATA XREF: Base::Base(void)+A↑o.rdata:004031BC dd offset Base::vf2(void).rdata:004031C0 dd offset Base::vf3(void).rdata:004031C4 dd offset Base::vf4(void).rdata:004031C8 dd offset const Sub::`RTTI Complete Object Locator'.rdata:004031CC const Sub::`vftable' dd offset Sub::vf1(void).rdata:004031CC ; DATA XREF: Sub::Sub(void)+12↑o.rdata:004031D0 dd offset Base::vf2(void).rdata:004031D4 dd offset Sub::vf3(void).rdata:004031D8 dd offset Base::vf4(void).rdata:004031DC dd offset Sub::vf5(void)
可以看到,类构造函数Sub:: Sub(void)使用了虚表的地址Sub::Sub(void)+12↑o, 那是因为new sub 调用了sub的隐式构造函数
windbg观察:
注意,Base的虚表第一个是002816e4 Test!purecall,这时因为在Base中,没有针对纯虚函数vf1的实现,所以在Base的虚表中并没有存储vf1的地址,这时,编译器会插入一个错误处理函数的地址,通常,该函数名为purecall,一旦它被调用,程序就会被终止
附
可以观察到:
1.new指针不为空,才会调用构造函数,这是由Visual C++的内部机制来保证的
2.函数的虚表位置一般都可以在构造函数中找到(很明显,this指针指向的地址就是虚表的位置)
- 12.IDA-虚函数和虚表
- 12.IDA-虚函数和虚表
- 12.IDA-虚函数和虚表
- 最深层了解虚表 ida
- OD和IDA快捷键
- A*和IDA*算法
- IDA 显示函数名称技巧
- ida idc函数列表全集
- IDA
- ida
- IDA*
- IDA*
- IDA*
- 第一步 认识IDA和UE
- A*算法 和 IDA*算法
- IDA插件-----获取指定函数参数个数
- IDA如何识别ARM的main函数
- 关于 [虚函数] 和 [虚函数表]
- 题目: 一个数如果恰好等于它的因子之和,这个数被成为”完数” 例如:6=1+2+3.请编程找出1000以内的完数
- 15.odoo入门——工作遇到的odoo的一些细节和javascript实现数据库操作后跳转页面
- MySQL百万级数据量查询优化
- 读写文本文件
- c#浅拷贝/深拷贝和内存分配
- 12.IDA-虚函数和虚表
- firefox 调试接口
- 数据结构——二叉树
- 文章标题
- Python 虚拟环境 windows平台 virtualenv
- Web报表系统葡萄城报表:多级报表
- 青蛙过河 HRBUST
- JVM调优:选择合适的GC collector (一)
- 事务丢失更新的解决方案