hook com vtable entry

com interface 包括 d3d interface 都采用了 __stdcall 调用协议来声明成员函数,这样的声明使得编译出的汇编代码的传参中多出一个push,

所有参数push stack后,还会将对象对地址也push stack;

这样做的目的,使得可以用__stdcall 的 c函数来替换vtable中的函数,要求第一个参数是对象指针;其他参数和对应成员函数的参数相同;

因为com设计之初,就支持CINTERFACE.

 

#include "objbase.h"
__declspec(novtable) 
interface AA:public IUnknown
{
public:
    
virtual HRESULT STDMETHODCALLTYPE QueryInterface( 
            
/* [in] */ REFIID riid,
            
/* [iid_is][out] */ __RPC__deref_out void __RPC_FAR *__RPC_FAR *ppvObject) 
    {
        
return S_OK;
    }

    
virtual ULONG STDMETHODCALLTYPE AddRef( void)
    {
        
return 0;
    }

    
virtual ULONG STDMETHODCALLTYPE Release( void)
    {
        
return 0;
    }
   
//成员函数采用__stdcall 
    virtual void __stdcall v1(void* p)
    {
    }
    
virtual void __stdcall v2(void* p)
    {
    }
    
virtual void __stdcall v3(void* p)
    {
    }
};
//c函数声明比AA::v1要多出一个AA* pthis参数
void __stdcall fpv1( AA* pthis,void* p )
{
    pthis
->v2(p);
}

int _tmain(int argc, _TCHAR* argv[])
{
    AA aa1,aa2;

    unsigned 
int p1 = *(unsigned int*)&aa1;
    unsigned 
int p2 = *(unsigned int*)&aa2;
    unsigned 
int* v = (unsigned int*)p1;
    DWORD dwProtected 
= 0;

    VirtualProtect(v,
256,PAGE_EXECUTE_READWRITE,&dwProtected );//去掉可执行代码的写保护
    v[3= (unsigned int)&fpv1;//替换v1所在的vtable条目
    AA* pp1 = &aa1;
    pp1
->v1( NULL );//将会跳转到fpv1,查看汇编代码回看到push 0 之后还会有一个push pp1

    
return 0;
}


posted on 2011-05-21 09:49  cgwolver  阅读(678)  评论(0编辑  收藏  举报

导航