首页
社区
课程
招聘
[原创]虚函数表地址究竟放了啥!!!
发表于: 2011-3-31 13:01 5453

[原创]虚函数表地址究竟放了啥!!!

2011-3-31 13:01
5453

作者:yulongying
链接:http://bbs.pediy.com/showthread.php?p=942469

很久都没有用c++了 一直都是用c, 发现很多忽然生疏了不少,今天闲来无聊用OD跟踪c++类的函数表 很多人应该都知道了,所以再次声明 此文章是献给新手的,高手莫笑!
跟踪过程已经不是什么新鲜事了,这个网站就有介绍
http://blog.sina.com.cn/s/blog_511703010100m5rh.html

我的源码如下:
class CBase
{
public:
        int m_test1;
        int m_test2;
        CBase(void);
        virtual int add(int a, int b){return a+b;}
        virtual int sub(int a, int b){return a-b;}
public:
        ~CBase(void);
};
CBase::CBase(void)
{
        m_test1 = 1;
        m_test2 = 2;
}

CBase::~CBase(void)
{
}

class CFromBase :
        public CBase
{
public:
        int b;
        CFromBase(void);
        virtual int add(int a, int b){return a+b+1;}
        virtual int sub(int a, int b){return a-b-1;}
public:
        ~CFromBase(void);
};

CFromBase::CFromBase(void)
{
}

CFromBase::~CFromBase(void)
{
}
int main()
{
        CBase *base = new CFromBase();
        int a = sizeof(CBase);
        int c = sizeof(CFromBase);
        int b = base->add(1, 2);
        printf("%d hello world!, 0x%X, %d, %d", b, *(int *)base, ((int *)base)[1],((int *)base)[2]   );

        system("pause");
}

0041171D    6A 10           push    10
0041171F    E8 99FAFFFF     call    ClassAsm.004111BD                          ; 申请sizeof(virtual table)+sizeof(m_test1)+sizeof(m_test2)大小的内存
00411724    83C4 04         add     esp, 4
00411727    8985 FCFEFFFF   mov     dword ptr ss:[ebp-104], eax
0041172D    C745 FC 0000000>mov     dword ptr ss:[ebp-4], 0
00411734    83BD FCFEFFFF 0>cmp     dword ptr ss:[ebp-104], 0
0041173B    74 13           je      short ClassAsm.00411750
0041173D    8B8D FCFEFFFF   mov     ecx, dword ptr ss:[ebp-104]
00411743    E8 D0F9FFFF     call    ClassAsm.00411118                          ; 子类CFromBase构造 跟进去

关键代码
00411598    B8 CCCCCCCC     mov     eax, CCCCCCCC
0041159D    F3:AB           rep     stos dword ptr es:[edi]
0041159F    59              pop     ecx
004115A0    894D F8         mov     dword ptr ss:[ebp-8], ecx
004115A3    8B4D F8         mov     ecx, dword ptr ss:[ebp-8]
004115A6    E8 DBFBFFFF     call    ClassAsm.00411186                          ; 基CBase类构造
004115AB    8B45 F8         mov     eax, dword ptr ss:[ebp-8]
004115AE    C700 50664100   mov     dword ptr ds:[eax], ClassAsm.00416650      ; 虚函数表地址00416650
在数据窗口查看下这个地址 在命令行窗口dd 0041665
00416650  0041122B  ClassAsm.0041122B
00416654  00411230  ClassAsm.00411230
有两个地址0041122B  00411230
再分别查看下两个地址放的什么 代码 在命令行窗口输入 da 0041122B
0041122B   /E9 B0030000     jmp     ClassAsm.004115E0
00411230   |E9 EB030000     jmp     ClassAsm.00411620
说明virtual table里面放的是一些jmp 代码 跟踪不难发现004115E0  00411620这个两个地址就是CFromBase的两个虚函数add sub的地址

如果在这里跟进去的时候
004115A6    E8 DBFBFFFF     call    ClassAsm.00411186                          ; 基CBase类构造

也会类似一句
00411486    C700 40664100   mov     dword ptr ds:[eax], ClassAsm.00416640

输入dd 00416640发现也放两个地址
00416640  004111E0  ClassAsm.004111E0
00416644  0041114A  ClassAsm.0041114A
其实这连个地址也是两个jmp代码, jmp到CBase的两个虚函数add sub的地址。

调用int b = base->add(1, 2);的时候

0041178A    8B45 EC         mov     eax, dword ptr ss:[ebp-14]
0041178D    8B10            mov     edx, dword ptr ds:[eax]                    ; 取出虚函数表的地址
0041178F    8B4D EC         mov     ecx, dword ptr ss:[ebp-14]                 ; ecx 都知道了 放this指针的
00411792    8B02            mov     eax, dword ptr ds:[edx]                    ; eax 放的是0041122b 也就是jmp CFromBase::add代码
00411794    FFD0            call    near eax                                   ; 跳转到执行jmp CFromBase::add代码   可以跟进去跟进去验证下 呵呵。

希望跟我一样的新手们看了有点收获。 呵呵!!!为了方便 c++代码还是放附件里面

补充:刚刚做了这样一个有趣的实验 代码如下:
CBase *base = new CFromBase();
        int a = sizeof(CBase);
        int c = sizeof(CFromBase);
        int b = base->add(1, 2);

        typedef int (__stdcall *FUN)(int , int);

        FUN fun_add = (FUN)(*(int**) base)[0];
        FUN fun_sub = (FUN)(*(int**) base)[1];
       

        int d = fun_add(2,5);//==base->add(2, 5);
        int e = fun_sub(4,6);//==base->sub(4, 6);

        printf("0x%d hello world!, %d, %d, %d, %d", *(int *)base, ((int *)base)[1],((int *)base)[2], d, e);


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (0)
游客
登录 | 注册 方可回帖
返回
//