Some times,we need too hook some function to do something that's not so easy to do with normally add somecode.A solution is to hook focused functions and interface.Here is a template hook class maybe help your work easier,which complie with vs2005.It midify the jmp table to replace the function,maybe not?properly? for other compliers.
class HookPfn
{
?struct make_writeable
?{
??void* p;
??MEMORY_BASIC_INFORMATION mbi_thunk;
??make_writeable(void* _p):p(_p)
??{
???VirtualQuery(p, &mbi_thunk, sizeof(MEMORY_BASIC_INFORMATION));
???VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, PAGE_READWRITE, &mbi_thunk.Protect);
??
??}
??~make_writeable()
??{
???VirtualProtect(mbi_thunk.BaseAddress, mbi_thunk.RegionSize, mbi_thunk.Protect,&mbi_thunk.Protect);
??}
?};
public:
?template<class F>
?void restore(F pfn,unsigned long handle)
?{
??
??void* p;
??__asm mov eax,[pfn]
??__asm mov dword ptr[p],eax
??make_writeable write(p);
??__asm push ecx
??__asm mov eax,pfn
??__asm inc eax
??__asm mov ecx,handle
??__asm mov dword ptr[eax],ecx
??__asm pop ecx
?}
?template<class F1,class F2>
?unsigned long redirect(F1 pfn1,F2 pfn2)
?{
???//should use restrict object prevent?F1 and F2 's arguments and type not same
??void* p;
??__asm mov eax,[pfn1]
??__asm mov dword ptr[p],eax
??make_writeable write(p);
??unsigned long bas1,bas2,of1,of2,of;
??__asm push ecx
??__asm mov eax,pfn1
??__asm mov bas1,eax
??__asm inc eax
??__asm mov ecx,dword ptr[eax]
??__asm mov of1,ecx
??__asm mov eax,pfn2
??__asm mov bas2,eax
??__asm inc eax
??__asm mov ecx,dword ptr[eax]
??__asm mov of2,ecx
??of=(bas2-bas1+of2-of1)+of1;
??__asm mov eax,pfn1
??__asm inc eax
??__asm mov ecx,of
??__asm mov dword ptr[eax],ecx
??__asm pop ecx
??return of1;
?}
?
};
class mmt
{
public:
?void donothing()
{
}
?void donothing(int)
{
}
??void dosomething()
{
}
};
void fastcall(int a,int b)
{
}
void askcall(int,int)
{
}
It can be used as example:
int main()
{
?HookMemberFunction sh;
?unsigned long hd=sh.redirect(&fastcall,&askcall);//test api
?fastcall(0,0);//two?function
?askcall(0,0);
?sh.restore(&fastcall,hd);
?askcall(0,0);
?fastcall(0,0);
//test overlay functions(donothing)
?typedef void (mmt::*sp)(void);
?sp p1=&mmt::dosomething;
?sp p2=&mmt::donothing;
?hd=sh.redirect(p1,p2);
?mmt mt;//a class
?mt.donothing();
?mt.dosomething();
?sh.restore(p1,hd);
?mt.donothing();
?mt.dosomething();
}
Although it can be work right,addtionly we may be use it not properly.Youcan add some strict class to prevent bad use of it by check if the argument and return type is strictly same.,if you need it.