通过虚函数指针绕过虚函数的保护机制

#include <iostream>
using namespace std;
class A
{
public:
        A()
        {
                a = 10;
        }
private:
        virtual void Func1()
        {
                cout << "class A Func1" << endl;
                cout << a << endl;
        }
        virtual void Func2()
        {
                cout << "class A Func2" << endl;
        }
private:
        int a;
};

int _tmain(int argc, _TCHAR* argv[])
{
        A a;
        //得到虚表的地址
        int* v_ptrAdrs = *((int**)&a);
        //得到虚表中的第一个值
        int* funcAddr = *((int**)v_ptrAdrs);

        typedef void (*gFUNC)();

        A* pp = &a;
        //如果你用的是vs,可以通过汇编压入this指针,目前只在vs2008下测试过
        __asm mov ecx, pp;
        //直接调用虚函数,此处绕过了private的保护
        (*(gFUNC)funcAddr)();
        return 0;
}


当然,这只能是在没有参数的情况下才能调用成功,如果存在参数,那么还是会失败,下面我们修改一下类A,为函数添加一个入参:

class A
{
public:
        A()
        {
                a = 10;
        }
public:
        virtual void Func1(int para)
        {
                cout << "class A Func1" << endl;
                cout << a*para << endl;
        }
        virtual void Func2()
        {
                cout << "class A Func2" << endl;
        }
private:
        int a;
};


 

我们通过汇编代码来查看为什么会失败,截取汇编代码如下:
(*(gFUNC)funcAddr)(10);
004144FD 8B F4            mov         esi,esp 
004144FF 6A 0A            push        0Ah                          --入栈,压参10
00414501 FF 55 DC         call        dword ptr [funcAddr]         --调用函数,跟入函数内部,我们会发现,函数的最后会进行出栈操作
00414504 83 C4 04         add         esp,4                        --出栈
00414507 3B F4            cmp         esi,esp 
00414509 E8 BE CC FF FF   call        @ILT+455(__RTC_CheckEsp) (4111CCh) 


通过上述汇编代码,就会发现,错误出在调用方式上,下面只要稍作改动就可以成功了。

int _tmain(int argc, _TCHAR* argv[])
{
        A a;
        //得到虚表的地址
        int* v_ptrAdrs = *((int**)&a);
        //得到虚表中的第一个值
        int* funcAddr = *((int**)v_ptrAdrs);

        typedef  void   (__stdcall *gFUNC)(int);

        A* pp = &a;
        //如果你用的是vs,可以通过汇编压入this指针,目前只在vs2008下测试过
        __asm mov ecx, pp;
        //直接调用虚函数,此处绕过了private的保护
        (*(gFUNC)funcAddr)(10);
        return 0;
}



 

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值