Monday, August 15, 2011

Hook Specials 8: Realize ring3 hook

Author:bzhkl
That is original realized on code of russia ,The advantage of code is:
1. Don't first use hook on agency's function,be Called again ,Later hook again,Otherwise multithreading go wrong.
2. Non hard code ,The structure is better.

bool AfxHookCode(void* TargetProc, void* NewProc,void ** l_OldProc, int bytescopy = 5)
{

  DWORD dwOldProtect;

  ::VirtualProtect((LPVOID)TargetProc, bytescopy, PAGE_EXECUTE_READWRITE, &dwOldProtect);

  *l_OldProc = new unsigned char[bytescopy+5];          //Apple for Space for instruction of be covered to copyed.


  memcpy(*l_OldProc, TargetProc, bytescopy);           // Decided beforehandl to save code of be broken
  *((unsigned char*)(*l_OldProc) + bytescopy) = 0xe9;    // 我的内存的代码执行完 跳到原来的 代码 + 破坏的代码的长度 上去

                            //被破坏指令的长度     //E9 opcode长度          //算出偏移的OPCODE    = 被HOOK函数地址的地址 + 破坏指令的长度 - 我分配内存的结束地址                           
    *(unsigned int *)((unsigned char*)(*l_OldProc) +bytescopy          +     1)          =   (unsigned int)(TargetProc) + bytescopy - ( (unsigned int)((*l_OldProc)) + 5 + bytescopy ) ;  // 我内存代码跳到原来代码上的偏移


  *(unsigned char*)TargetProc =(unsigned char)0xe9;             //被HOOK的函数头改为jmp


                                  //算出偏移的OPCODE  = 代理函数地址 - 被HOOK函数地址
  *(unsigned int*)((unsigned int)TargetProc +1) = (unsigned int)NewProc - ( (unsigned int)TargetProc + 5) ; //被HOOK的地方跳到我的新过程 接受过滤


  ::VirtualProtect((LPVOID)TargetProc, bytescopy, dwOldProtect, 0);
  return true;
}


bool AfxUnHookCode(void* TargetAddress, void * l_SavedCode, unsigned int len)
{
    DWORD dwOldProtect;

    ::VirtualProtect((LPVOID)TargetAddress, len, PAGE_EXECUTE_READWRITE, &dwOldProtect);  

    // Recover code of be broken
    memcpy(TargetAddress, l_SavedCode, len);

    ::VirtualProtect((LPVOID)TargetAddress, len, dwOldProtect, 0);

    return true;
}



unsigned int *  OldProc;
typedef
int
(__stdcall * MYMESSAGEBOX)     //用于调用自己分配内存处的代码强制转换
   (
    IN HWND hWnd,
    IN LPCSTR lpText,
    IN LPCSTR lpCaption,
    IN UINT uType);


int
__stdcall       // 这里不声明成stdcall的话 编译器认为是C声明方式 要自己平衡堆栈 
MyMessageBox(
    IN HWND hWnd,
    IN LPCSTR lpText,
    IN LPCSTR lpCaption,
    IN UINT uType)
{

  // 这里可以执行一些过滤行为 比如改变参数 或者 直接模拟返回正确的结果
  if ( strcmp(lpText, "sample") == 0)
  {
    printf("filter");
    return 1;
  }


      //强制转换成API函数类型 调用原来的函数
   return ( (MYMESSAGEBOX) OldProc)(hWnd, lpText, lpCaption, uType);

}




int main()
{
  MessageBox(0, "sample", "caption", MB_OK);   //正常调用MSG

                                                                // 这里一定要传地址变量的地址  直接传地址的话 地址变量是一份拷贝 根本不能保存分配的内存的地址(在我看来 指针就是地址变量)
                                  //当初写的时候调了3遍才知道这个原因- -
  AfxHookCode((void*)MessageBox, (void*)MyMessageBox, (void**)&OldProc, 5);


  MessageBox(0, "sample", "caption", MB_OK);  //Be filtered
  AfxUnHookCode((void*)MessageBox, OldProc, 5); // Recover code of be hook

  getchar();

  return 0;
}

No comments:

Post a Comment