vs2019 查看类的虚函数_VS命令行下查看虚函数表和类内存布局,以及实例验证

方法其实很简单。

1.打开VS自带的命令行工具。当然,你把cl.exe的目录写到环境变量中,直接在cmd中也能用。

这是VS2012的。

下面这个是VS2013的。都一样。

2.使用cl命令的/d1 reportAllClassLayout或reportSingleClassLayoutXXX选项。这里的reportAllClassLayout选项会打印大量相关类的信息,一般用处不大。而reportSingleClassLayoutXXX选项的XXX代表要编译的代码中类的名字(这里XXX类),打印XXX类的内存布局和虚函数表(如果代码中没有对应的类,则选项无效)。

其中,/d1reportSingleClassLayoutXXX  显示指定XXX类的内存布局

/d1reportAllClassLayou          显示所有类的内存布局

举个例子。

下述两个类存储在test.cpp文件中。

class A{

public:

void doX(){

std::cout << "A function of X";

}

private:

int a;

};

class B: public A{

public:

virtual void doX(){

std::cout << "B function of X";

}

};

在命令行中输入 cl /d1reportSingleClassLayoutB test.cpp

结果如下所示:

class B size(8):

+---

0 | {vfptr}

| +--- (base class A)

4 | | a

| +---

+---

B::$vftable@:

| &B_meta

| 0

0 | &B::doX

B::doX this adjustor: 0

在命令行中输入 cl /d1reportSingleClassLayoutA test.cpp

结果如下所示:

class A size(4):

+---

0 | a

+---

3.实际操作来验证

根据上面得到的虚函数表所在的位置,我们来进行一下hack行为。

#include

class A{

public:

void showMe(){

std::cout << "A function of X" << std::endl;

}

private:

int a;

};

class B : public A{

public:

virtual void showMe(){

std::cout << "B function of X" << std::endl;

}

};

int main(){

//获取基类成员函数所在的内存调用地址

typedef void (A::* Aptr)();

Aptr classPtr = &A::showMe;

void* iPtr = &classPtr;

//获取派生类对象中虚函数表的起始地址

B* bPtr = new B();

void* bAddr = bPtr;

int* BVTaddr = (int*)(bAddr); // + 1;

//因为只有一个虚函数,所以

//该虚函数的调用地址就直接存在了虚表地址上

//用基类A中的实函数地址来覆盖虚函数的地址

//这样调用时,就成了动态调用实函数了

*BVTaddr = (int)iPtr;

//通过指针调用虚函数,hack成功

//注意,只有通过指针或者引用,才能实现多态调用

bPtr->showMe();

//释放内存,避免泄漏

delete bPtr;

//system("pause");

}

使用Microsoft (R) C/C++ Optimizing Compiler Version 18.00.31101 for x86编译器和gcc version 4.7.1编译器,两个编译器输出结果相同,

结果均输出为  A function of X

表明这两个编译器,都是将虚表的起始地址,放在了对象的头部。如下所示:

class B size(8):

+---

0 | {vfptr}

| +--- (base class A)

4 | | a

| +---

+---

B::$vftable@:

| &B_meta

| 0

0 | &B::showMe

B::showMe this adjustor: 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值