首页
论坛
课程
招聘
[原创]C++还原ring3 Inline Hook(附源码)
2012-1-26 15:31 7489

[原创]C++还原ring3 Inline Hook(附源码)

2012-1-26 15:31
7489
最近调试一网游,加了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定义全局变量。

[注意] 欢迎加入看雪团队!base上海,招聘安全工程师、逆向工程师多个坑位等你投递!

收藏
点赞0
打赏
分享
最新回复 (4)
雪    币: 381
活跃值: 活跃值 (19)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
笨奔 活跃值 1 2012-1-26 17:36
2
0
很不错,中规中局
雪    币: 90
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wangyuchen 活跃值 2012-1-26 22:04
3
0
谢谢了,很不错
雪    币: 578
活跃值: 活跃值 (25)
能力值: ( LV9,RANK:140 )
在线值:
发帖
回帖
粉丝
monsterok 活跃值 3 2012-1-27 00:58
4
0
常规方法。。
雪    币: 1644
活跃值: 活跃值 (51)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
yodamaster 活跃值 2012-2-8 10:14
5
0
感谢分享。。。
游客
登录 | 注册 方可回帖
返回