刺激战场
六合彩
贵宾厅
  • 1339阅读
  • 2回复

Detour Hook COM成员函数present和Hook 类成员函数 [复制链接]

上一主题 下一主题
离线啊冲
 

只看楼主 倒序阅读 使用道具 楼主  发表于: 2016-02-15




[cpp] view plain copy
  1. void * pPresent=NULL;//IDirect3DDevice9::Present函数地址指针   


[cpp] view plain copy
  1. pPresent=(void*)*(DWORD*)(*(DWORD*)Device+0x44);//IDirect3DDevice9* Device  
  2.   
  3.     DetourTransactionBegin();  
  4.     DetourUpdateThread(GetCurrentThread());  
  5.     DetourAttach((PVOID *)&pPresent, New_Present);  
  6.     DWORD nErr = DetourTransactionCommit();  


[cpp] view plain copy
  1. HRESULT __stdcall New_Present(  
  2.                              LPDIRECT3DDEVICE9 pDxdevice,   //类的this指针   
  3.                              CONST RECT * pSourceRect,      //此参数请参考dx sdk   
  4.                              CONST RECT * pDestRect,        //同上   
  5.                              HWND hDestWindowOverride,      //同上   
  6.                              CONST RGNDATA * pDirtyRegion   //同上   
  7.   
  8.                              )  
  9. {  
  10.     __asm pushad  
  11.     static float lastTime = (float)timeGetTime();  
  12.     float currTime  = (float)timeGetTime();  
  13.     float timeDelta = (currTime - lastTime)*0.001f;  
  14.     Device->BeginScene();  
  15.     Device->Clear(0, NULL, D3DCLEAR_TARGET,D3DCOLOR_XRGB(0,0,0), 1.0f, 0);  
  16.     fps.CalcFPS(timeDelta);  
  17.     fps.Show();  
  18.     Device->EndScene();  
  19.     __asm popad  
  20.     __asm  
  21.     {    
  22.         push pDirtyRegion  
  23.         push hDestWindowOverride  
  24.         push pDestRect  
  25.         push pSourceRect  
  26.         push pDxdevice  
  27.         call pPresent  
  28.     }  
  29.   
  30.     lastTime = currTime;  
  31. }  

另一种方式,采用__declspec(naked)方式,注意的是这种方式不需要编译器添加任何汇编代码,在标明naked的函数中是不可以使用任何赋值,所以把它单独提出来:还要注意子函数New_Present_Sub最好用__stdcall,这样不用考虑堆栈平衡
[cpp] view plain copy
  1. void __stdcall New_Present_Sub( LPDIRECT3DDEVICE9 pDxdevice)  
  2. {  
  3.     if (pDxdevice)  
  4.     {  
  5.         static BOOL bInitFps = FALSE;  
  6.         if (!bInitFps)  
  7.         {  
  8.             bInitFps = g_fps.Create(pDxdevice);  
  9.             MyOutputDebugString("tpfps-[New_Present] g_fps.Create");  
  10.         }  
  11.   
  12.         if (bInitFps)  
  13.         {  
  14.             static DWORD lastTime = timeGetTime();  
  15.             DWORD currTime  = timeGetTime();  
  16.             DWORD timeDelta = (currTime - lastTime);  
  17.             pDxdevice->BeginScene();  
  18.             g_fps.CalcFPS(timeDelta);//传入的是毫秒  
  19.             switch (g_nOpe)  
  20.             {  
  21.             case SHOW_FPS:  
  22.                 {  
  23.                     g_fps.Show();  
  24.                 }  
  25.                 break;  
  26.   
  27.             case RECODE_FPS:  
  28.                 {    
  29.                     g_fps.RecordShow(pDxdevice, g_bAutoRecord, g_nAutoRecordTime);  
  30.                     if (g_fps.bAutoRecordExit())  
  31.                     {  
  32.                         MyOutputDebugString("[New_Present]bAutoRecordExit");  
  33.                         g_nOpe = UNRECODE_FPS;  
  34.                     }  
  35.                 }  
  36.                 break;  
  37.   
  38.             case UNRECODE_FPS:  
  39.                 {  
  40.                     g_fps.EndRecord(pDxdevice);  
  41.                     g_nOpe = SHOW_FPS;  
  42.                 }  
  43.                 break;  
  44.   
  45.             default:  
  46.                 break;  
  47.             }  
  48.   
  49.             pDxdevice->EndScene();  
  50.             lastTime = currTime;  
  51.   
  52.         }  
  53.     }  
  54. }  
  55. __declspec(naked) HRESULT __stdcall New_Present(  
  56.                               LPDIRECT3DDEVICE9 pDxdevice,  //类的this指针   
  57.                               CONST RECT * pSourceRect,     //此参数请参考dx sdk   
  58.                               CONST RECT * pDestRect,       //同上   
  59.                               HWND hDestWindowOverride,     //同上   
  60.                               CONST RGNDATA * pDirtyRegion  //同上   
  61.                               )  
  62. {  
  63.     __asm// 必不可少的,把ebp代码去掉或pushad去掉,都会程序OVER  
  64.     {  
  65.         push ebp  
  66.         mov ebp, esp  
  67.         pushad  
  68.         pushfd  
  69.     }  
  70.   
  71.     __asm  
  72.     {    
  73.         mov esi, pDxdevice  
  74.         push esi  
  75.         mov eax, New_Present_Sub  
  76.         call eax  
  77.     }  
  78.     __asm  
  79.     {  
  80.         popfd  
  81.         popad  
  82.         mov esp, ebp  
  83.         pop ebp  
  84.         jmp g_pPresent  
  85.     }  
  86. }  


  
Hook类成员函数:术语说明:
原函数:被hook的target
hook函数:指自己写的函数,也即让原函数jmp到该函数
原因分析:
用detours hook类成员函数,因为成员函数会有一个this指针,如果在hook函数中调用原函数,没有传入this指针,那么原函数的调用将会出错。
解决方法是:
1. 首先在ollydbg中找到这个this指针。其实也就是那个类的对象地址,一般来说,在ollydbg中调用原函数时,也即在call原函数之前,总会有一条指令mov ecx,xxx或者lea ecx,xxx,那个ecx就是我们要找的this指针!
2. 在hook函数调用原函数时使用内联汇编代码调用,push所有的参数之后,然后初始化ecx为this指针的值!然后在call原函数,这样call原函数就不会出现崩溃。

需要注意的地方:
1. 注意原函数是否能自动平衡堆栈,如不行,则需要在hook函数中自己手动平衡堆栈
2. hook函数返回时,必须是手动编写汇编返回(ret),不要让系统帮忙返回!在带有参数的hook例子中,系统帮忙放回必定出错!
3. ret后面的值与传入hook函数的参数有关,一般来说,该值=4*参数个数

或者如上面:代替的函数原型第一个参数加this即可。

顶0踩
善者 慈悲心常在 无怨无恨 以苦为乐
默认压缩密码www.hifyl.com
文件分享密码问题:http://www.hifyl.com/read-htm-tid-4444.html
离线im86165507

只看该作者 沙发  发表于: 2016-02-15
离线v2680267313

只看该作者 板凳  发表于: 2016-04-30
用户被禁言,该主题自动屏蔽!
快速回复
限100 字节
批量上传需要先选择文件,再选择上传
 
上一个 下一个