-
-
[原创]C++还原ring3 Inline Hook(附源码)
-
发表于:
2012-1-26 15:31
9466
-
[原创]C++还原ring3 Inline Hook(附源码)
最近调试一网游,加了tmd壳,HOOK了三个API:DbgBreakPoint、DbgUiRemoteBreakin、DbgUserBreakPoint,平时调试前都用XT还原,突然想自己试试自己编码还原,于是简单写了个类,用于ring3 Inline Hook的还原。
先回顾一下ring3 Inline Hook的步骤:
1、获取被HOOK api的地址
2、用VirtualProtect为该地址添加写入权限
3、在该地址写入jmp指令,将代码跳转到自定义的函数。用VirtualProtect将权限改回去
4、将被修改的指令拷贝到自定义的函数执行,做堆栈平衡和自己的处理后,JMP回去
比较麻烦的是,被修改的指令的长度处理 和 它是否依赖于状态寄存器或堆栈。这里不考虑多线程情况下正好有一条线程跑到还未被完全修改的代码处,其实也不用考虑,大不了程序异常崩溃。
还原HOOK的方法很简单,获取被修改处原来的内容,用原来的内容写回去即可。有以下几种办法可以获取原来HOOK的内容:
1、从PE文件读取,需要算出API距离节头部的偏移,然后从PE文件直接读出来。
2、拷贝一份DLL后,再载入,然后获取内容再释放载入的DLL
3、在被HOOK前,先拷贝一份
我的程序已先于游戏模块初始化,因而我选择第三种方式。代码如下:
//lanbinfeng 2012-01-20
class HookFix
{
public:
HookFix(char* _dllName,char* _funcname,int _fixLenth)
{
m_fixLenth=0;
m_fixBuffer=NULL;
HMODULE hDll=::LoadLibrary(_dllName);
if(hDll==0)
return;
char* pFunction=(char*)::GetProcAddress(hDll,_funcname);
if(pFunction==NULL)
return;
m_fixBuffer =new char[_fixLenth];
m_fixLenth =_fixLenth;
m_dllName =_dllName;
m_funcname =_funcname;
memcpy(m_fixBuffer,pFunction,m_fixLenth);
}
BOOL fix()
{
if(m_fixBuffer==NULL)
return FALSE;
HMODULE hDll=::GetModuleHandle(m_dllName.c_str());
if(hDll==0)
return FALSE;
char* pFunction=(char*)::GetProcAddress(hDll,m_funcname.c_str());
if(pFunction==NULL)
return FALSE;
DWORD tmp;
::VirtualProtect(pFunction,m_fixLenth,PAGE_EXECUTE_READWRITE,&tmp);
memcpy(pFunction,m_fixBuffer,m_fixLenth);
::VirtualProtect(pFunction,m_fixLenth,tmp,&tmp);
delete[] m_fixBuffer;
m_fixBuffer=NULL;
return TRUE;
}
~HookFix()
{
if(m_fixBuffer!=NULL)
{
delete[] m_fixBuffer;
m_fixBuffer=NULL;
}
}
private:
std::string m_dllName;
std::string m_funcname;
int m_fixLenth;
char* m_fixBuffer;
};
///////////////////
使用时,直接定义全局变量。构造函数的三个参数分别是:dll名称或路径、api名称、还原长度
HookFix apifix[]={
HookFix("ntdll.dll","DbgBreakPoint",1),
HookFix("ntdll.dll","DbgUiRemoteBreakin",5),
HookFix("ntdll.dll","DbgUserBreakPoint",7)
};
在需要还原点的地方执行以下代码
for(int i=0;i<sizeof(apifix)/sizeof(HookFix);i++)
apifix[i].fix();
该类非常容易改为使用方式2获取原始数据,若使用方式2则不需要先于HOOK定义全局变量。
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)