- 作者: 雪山肥鱼
- 时间:20210903 21:10
- 目的: 虚函数地址的vcall 引入
研究代码如下
#include <iostream>
using namespace std;
class Myclass
{
public:
virtual void myvirfunc1()
{
cout << "I am myvirfun1()" << endl;
}
virtual void myvirfunc2()
{
cout << "I am myvirfun2()" << endl;
}
};
int main(int argc, char ** argv)
{
printf("myvirfunc1 的 地址 :%p\n", &Myclass::myvirfunc1);//0x00481474
printf("myvirfunc2 的 地址 :%p\n", &Myclass::myvirfunc2);//0x004812BC
Myclass * pMyObj = new Myclass();
//[0] = 0x00481037 {Project1.exe!Myclass::myvirfunc1(void)}
//[1] = 0x004813f2 {Project1.exe!Myclass::myvirfunc2(void)}
return 0;
}
只要不重新编译 虚函数表中存的虚函数地址就不会更改。

vcall 的引入
正常流程 应该如所示:

对于直接使用 类 去调用函数
&MyClass::myvirfunc1();//00481474
&MyClass::myvirfunc2();//004812BC

这两个地址不是虚函数的地址, 又是什么呢?
断点 打在 &MyClass::myvirfunc1:
offset MyCalss::`vcall{0} (00481474)
00481474 jmp Myclass::`vcall'{0}' (048254Dh)
0048254D mov eax,dword ptr [ecx] //this
//虚函数地址
00481037 jmp Myclass::myvirfunc1 (04827E0h)

最后一步的汇编不太懂。理解了再回来修改把。
所以这种调用方式是通过 vcall{n} 的方式兜了一圈,找到虚函数的。记住这个就行了。
网友评论