青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

S.l.e!ep.¢%

像打了激速一樣,以四倍的速度運轉(zhuǎn),開心的工作
簡單、開放、平等的公司文化;尊重個性、自由與個人價值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  C++博客 :: 首頁 :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理

用 Thunk 實現(xiàn) COM 的掛鉤

Posted on 2010-02-06 17:05 S.l.e!ep.¢% 閱讀(632) 評論(-1)  編輯 收藏 引用 所屬分類: COM

用 Thunk 實現(xiàn) COM 的掛鉤

您可以任意轉(zhuǎn)載這篇文章,但請在轉(zhuǎn)載時注明原始鏈接和作者,謝謝。

本文鏈接: http://blog.titilima.com/show-557-1.html
相關分享: 收藏到QQ書簽 ?添加到百度搜藏 ?新浪微博分享 ?提交天天網(wǎng)摘

COM 的掛鉤其實已經(jīng)是一個很古老的話題了,其核心技術就是替換 COM 對象虛表中相應位置的函數(shù)指針,從而達到掛鉤的效果。順便說一句,這個方法和內(nèi)核的 SSDT 掛鉤是十分類似的。其相應的實現(xiàn)代碼也十分簡單,如下所示:

C++代碼
  1. typedef ? struct ?_tagHookHelper?{ ??
  2. ???? PVOID *?vptr; ??
  3. }?HOOKHELPER,?*PHOOKHELPER; ??
  4. ??
  5. PVOID ?WINAPI?LSetComHook( ??
  6. ????IUnknown*?unk, ??
  7. ???? int ?index, ??
  8. ???? PVOID ?pfnHook) ??
  9. { ??
  10. ????PHOOKHELPER?p?=?(PHOOKHELPER)unk; ??
  11. ???? PVOID ?ret?=?p->vptr[index]; ??
  12. ??
  13. ???? DWORD ?dwOldProtect; ??
  14. ????VirtualProtect(&p->vptr[index],? sizeof ( PVOID ),?PAGE_READWRITE, ??
  15. ????????&dwOldProtect); ??
  16. ????p->vptr[index]?=?pfnHook; ??
  17. ????VirtualProtect(&p->vptr[index],? sizeof ( PVOID ),?dwOldProtect,?NULL); ??
  18. ???? return ?ret; ??
  19. }??

需要指出的是,這里要使用 VirtualProtect 改變虛表的頁面屬性,就像掛鉤 SSDT 時要改變 cr0 的保護屬性一樣。
整個的掛鉤過程及使用類似于這個樣子:

C++代碼
  1. typedef ? HRESULT ?(STDCALL?*?QIPtr)(IUnknown*?This,?REFIID?riid,? PVOID *?ppv); ??
  2. ??
  3. QIPtr?g_pfnQueryInterface?=?NULL; ??
  4. ??
  5. HREUSLT?STDCALL?HookQueryInterface(IUnknown*?This,?REFIID?riid,? PVOID *?ppv) ??
  6. { ??
  7. ???? HRESULT ?hr?=?g_pfnQueryInterface(This,?riid,?ppv); ??
  8. ????OutputDebugString(_T( "HookQueryInterface.\n" )); ??
  9. ???? return ?hr; ??
  10. } ??
  11. ??
  12. IUnknown*?punk?=?NULL; ??
  13. //?CoCreateInstance.... ??
  14. g_pfnQueryInterface?=?(QIPtr)LSetComHook(punk,?0,?HookQueryInterface); ??
  15. punk->QueryInterface(...);??

這種掛鉤的方式有一個局限性,就是掛鉤函數(shù) HookQueryInterface 不能作為一個非 static 的類成員函數(shù)來實現(xiàn)。與之類似,Win32 的 WNDPROC 也無法使用非 static 的類成員函數(shù)來封裝,實乃一大憾事。

當然,我們可以通過非常規(guī)的方法來解決這個問題,比如 thunk。
在開始實現(xiàn)我的 thunk 之前,先來看看一個 COM 方法調(diào)用的過程,考慮如下代碼:

C++代碼
  1. class ?A ??
  2. { ??
  3. public : ??
  4. ???? virtual ? void ?WINAPI?foo( int ?i); ??
  5. ???? int ?m_n; ??
  6. }; ??
  7. ??
  8. void ?WINAPI?A::foo( int ?i) ??
  9. { ??
  10. ????printf( "m_n?=?%d,?i?=?%d\n" ,?m_n,?i); ??
  11. } ??
  12. ??
  13. A?a; ??
  14. A*?pa?=?&a; ??
  15. pa->m_n?=?1; ??
  16. pa->foo(2);??

這個調(diào)用過程所對應的匯編代碼為:

反匯編代碼
  1. push????????2 ??
  2. mov?????????eax,dword?ptr?[pa] ??
  3. ;?vptr ??
  4. mov?????????ecx,dword?ptr?[eax] ??
  5. ;?this ??
  6. mov?????????edx,dword?ptr?[pa] ??
  7. push????????edx ??
  8. mov?????????eax,dword?ptr?[ecx] ??
  9. call????????eax??

也就是說,一個 COM 方法調(diào)用的壓棧順序為:

  1. 由右至左的各個參數(shù),也就是 STDCALL 調(diào)用約定的壓棧順序;
  2. this 指針;
  3. 當然,還有 call 的返回地址,這個壓棧是在 call 指令內(nèi)部完成的。

從上面可以看出來,為了把一個 COM 調(diào)用重定向到我們自己的類成員函數(shù)中,需要做以下工作:

  1. 保留原 COM 方法的各個參數(shù);
  2. 保留原 COM 對象的 this 指針;
  3. 加入我們自己類對象的 this 指針;
  4. 保留 call 原有的返回地址。

簡單說來,這個重定向的過程是將堆棧中插入另外一個 this 指針,僅此而已。
明確了這個操作的步驟,我們可以寫出如下的 thunk 代碼,這段代碼將被放到目標 COM 對象的虛表中。

匯編代碼
  1. ;?彈出?call?的返回地址 ??
  2. pop?eax ??
  3. ;?加入自己的?this?指針 ??
  4. push?this ??
  5. ;?重新壓入?call?的返回地址 ??
  6. push?eax ??
  7. ;?跳至掛鉤函數(shù)之中 ??
  8. jmp?addr??

相應地,我們?yōu)檫@個 thunk 定義一個結構:

C++代碼
  1. #pragma?pack(push,?1) ??
  2. typedef ? struct ?_tagHookThunk?{ ??
  3. ???? BYTE ?PopEax;?? //?0x58 ??
  4. ???? BYTE ?Push;???? //?0x68 ??
  5. ???? PVOID ?This; ??
  6. ???? BYTE ?PushEax;? //?0x50 ??
  7. ???? BYTE ?Jmp;????? //?0xe9 ??
  8. ???? PBYTE ?Addr; ??
  9. }?HOOKTHUNK,?*PHOOKTHUNK; ??
  10. #pragma?pack(pop) ??

以及一個用于保存掛鉤信息的結構:

C++代碼
  1. typedef ? struct ?_tagComHook?{ ??
  2. ????HOOKTHUNK?Thunk; ??
  3. ???? PVOID *?vptr; ??
  4. ???? int ?index; ??
  5. ???? PVOID ?pfnOriginal; ??
  6. }?COMHOOK;??

最后,就可以實現(xiàn)這個升級版的掛鉤函數(shù)了,如下:

C++代碼
  1. HCOMHOOK?WINAPI?LSetComHook( ??
  2. ????IUnknown*?unk, ??
  3. ???? int ?index, ??
  4. ???? PVOID ?This, ??
  5. ???? PVOID ?pfnHook, ??
  6. ???? PVOID *?pfnOriginal) ??
  7. { ??
  8. ????PHOOKHELPER?p?=?(PHOOKHELPER)unk; ??
  9. ??
  10. ????HCOMHOOK?h?=? new ?COMHOOK; ??
  11. ???? //?pop?eax ??
  12. ????h->Thunk.PopEax?=?0x58; ??
  13. ???? //?push?this ??
  14. ????h->Thunk.Push?=?0x68; ??
  15. ????h->Thunk.This?=?This; ??
  16. ???? //?push?eax ??
  17. ????h->Thunk.PushEax?=?0x50; ??
  18. ???? //?jmp?addr ??
  19. ????h->Thunk.Jmp?=?0xe9; ??
  20. ????h->Thunk.Addr?=?( PBYTE )(( int )pfnHook?-?( int )h?-? sizeof (HOOKTHUNK)); ??
  21. ????::FlushInstructionCache(::GetCurrentProcess(),?&h->Thunk, ??
  22. ???????? sizeof (HOOKTHUNK)); ??
  23. ??
  24. ????h->vptr?=?p->vptr; ??
  25. ????h->index?=?index; ??
  26. ????h->pfnOriginal?=?LSetComHook(unk,?index,?&h->Thunk); ??
  27. ??
  28. ????*pfnOriginal?=?h->pfnOriginal; ??
  29. ???? return ?h; ??
  30. }??

測試代碼如下,使用 B 類中的 hook_foo 掛鉤了上文中的 A::foo。

C++代碼
  1. typedef ? void ?(WINAPI?*?ptr)(A*?This,? int ?i); ??
  2. ??
  3. class ?B ??
  4. { ??
  5. public : ??
  6. ???? void ?WINAPI?hook_foo(A*?This,? int ?i); ??
  7. ????ptr?pfn; ??
  8. }; ??
  9. ??
  10. void ?WINAPI?B::hook_foo(A*?This,? int ?i) ??
  11. { ??
  12. ????puts( "hooked?by?B" ); ??
  13. ????pfn(This,?i); ??
  14. } ??
  15. ??
  16. B?b; ??
  17. HCOMHOOK?h?=?LSetComHook((IUnknown*)pa,?0,?&b, ??
  18. ????member_cast< PVOID >(&B::hook_foo),?( PVOID *)&b.pfn); ??
  19. pa->foo(2);??

其中 member_cast 用于非 static 成員的類型轉(zhuǎn)換,可以參考《獲取成員函數(shù)的指針》一文,再次感謝 likunkun 所提供的優(yōu)雅解決方案。
全部示例代碼見附件。

附件: comhook.zip (3.52 K, 下載次數(shù):210)

Tags: c/c++, win32, com

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            国产日韩欧美夫妻视频在线观看| 亚洲欧洲日韩综合二区| 欧美精品免费在线| 99国产精品久久久久久久成人热| 狂野欧美一区| 开心色5月久久精品| 欧美日韩一区二区高清| 国产精品99久久久久久久vr| 夜夜嗨av一区二区三区四季av| 国产精品久久久久久妇女6080 | 久久一区视频| 亚洲深夜激情| 国产精品久久一级| 最新中文字幕亚洲| 亚洲一区三区在线观看| 亚洲欧美日本另类| 久久久99久久精品女同性| 亚洲精品在线观看免费| 久久精品女人的天堂av| 亚洲国产精品一区二区第四页av | 激情久久久久久久| 在线亚洲电影| 在线亚洲精品福利网址导航| 免费亚洲视频| 免费在线观看一区二区| 久久久xxx| 99re66热这里只有精品4| 在线观看日韩一区| 久久精品视频网| 亚洲午夜免费视频| 亚洲欧美韩国| 日韩视频精品| 亚洲成人自拍视频| 女同一区二区| 久久精品一区二区三区不卡牛牛 | 久久久久久久欧美精品| 欧美一区二区精品| 国产精品videosex极品| 亚洲精品国久久99热| 亚洲精品国产精品国自产观看浪潮| 久久久国产精品一区二区中文| 亚洲毛片在线观看.| 亚洲欧美变态国产另类| 亚洲精品中文字幕有码专区| 亚洲电影免费观看高清| 亚洲成人在线免费| 亚洲精品1234| 欧美日韩岛国| 久久精品国产第一区二区三区最新章节| 日韩午夜激情电影| 亚洲免费激情| 亚洲在线一区| 欧美国内亚洲| 欧美在线精品一区| 日韩视频在线观看国产| 亚洲天堂av图片| 亚洲精品裸体| 午夜精品一区二区三区电影天堂 | 国产香蕉久久精品综合网| 国产综合色产在线精品| 欧美日韩免费观看一区三区| 欧美午夜一区二区| 亚洲国产精品国自产拍av秋霞| 国产区亚洲区欧美区| 欧美性猛交视频| 亚洲国产精品热久久| 午夜精品一区二区三区在线播放| 99国产精品99久久久久久| 久久gogo国模啪啪人体图| 香蕉亚洲视频| 久久久久久网站| 久久精品亚洲热| 久久免费黄色| 中文欧美在线视频| 欧美77777| 国产精品性做久久久久久| 久久精品久久综合| 亚洲黄网站在线观看| 亚洲国产成人精品久久久国产成人一区| 在线播放不卡| 欧美一区二区在线播放| 亚洲高清免费视频| 亚洲欧美综合网| 亚洲精品免费一区二区三区| 欧美亚洲免费在线| 一区二区欧美亚洲| 欧美福利视频网站| 狠狠网亚洲精品| 亚洲视频一二区| 欧美国产日韩视频| 18成人免费观看视频| 久久久水蜜桃| 亚洲欧美日韩第一区| 亚洲看片免费| 欧美精品www| 亚洲人成高清| 欧美激情精品久久久久久变态| 亚洲在线1234| 亚洲欧美激情四射在线日 | 国产精品视频一区二区高潮| 在线亚洲欧美视频| 亚洲视频999| 国产一区二区三区久久久久久久久 | 99国产精品久久久久久久久久| 久久久久se| 美女国产精品| 久久免费午夜影院| 亚洲免费成人av电影| 日韩视频在线你懂得| 国产美女一区二区| 女仆av观看一区| 欧美性大战久久久久久久蜜臀| 午夜精品免费视频| 久久人人超碰| 欧美激情精品久久久久久久变态 | 久久久亚洲精品一区二区三区| 国产欧美一级| 欧美激情va永久在线播放| 欧美日韩另类视频| 久久久视频精品| 欧美日韩综合不卡| 国产亚洲午夜高清国产拍精品| 噜噜噜噜噜久久久久久91| 久久久久久伊人| 欧美日韩免费看| 久久精品国产精品亚洲精品| 欧美岛国在线观看| 午夜在线观看欧美| 欧美紧缚bdsm在线视频| 亚洲国产高清aⅴ视频| 亚洲图片激情小说| 日韩网站在线观看| 久久人人九九| 久久久综合激的五月天| 国产精品久久99| 日韩亚洲欧美高清| 99在线|亚洲一区二区| 久久精品国产99国产精品| 午夜精品亚洲| 国产精品手机视频| 欧美波霸影院| 亚洲高清资源| 欧美成人精品不卡视频在线观看 | 午夜精品影院在线观看| 午夜国产精品视频| 国产亚洲视频在线| 久久天堂成人| 亚洲缚视频在线观看| 亚洲精品国产精品乱码不99按摩| 免费试看一区| 亚洲欧洲精品一区二区三区| 中文亚洲免费| 国产综合自拍| 嫩草伊人久久精品少妇av杨幂| 亚洲高清在线播放| 亚洲一区二区在| 国产原创一区二区| 欧美成年人网站| 亚洲一级二级| 欧美成人免费大片| 欧美激情成人在线视频| 在线亚洲精品福利网址导航| 久久福利视频导航| 91久久精品日日躁夜夜躁国产| 欧美激情在线| 欧美在线一二三| 日韩亚洲欧美成人| 久久久国产91| 午夜精品久久久久久| 免费黄网站欧美| 亚洲欧美成人在线| 亚洲精品五月天| 亚洲电影第三页| 国产一区在线看| 国产精品av一区二区| 欧美激情久久久久| 玖玖玖国产精品| 亚洲精品国产精品乱码不99按摩| 久久久久久电影| a91a精品视频在线观看| 激情久久婷婷| 狠狠爱www人成狠狠爱综合网| 欧美日韩一区二区三区四区五区| 免费成人黄色av| 久久综合中文色婷婷| 久久成人18免费观看| 午夜精品视频在线| 亚洲国产小视频在线观看| 欧美高清视频www夜色资源网| 亚洲性线免费观看视频成熟| 亚洲精品网站在线播放gif| 亚洲国产精品成人综合色在线婷婷| 国产一区二区精品久久| 精品999久久久| 亚洲人成啪啪网站| 这里只有精品视频| 亚洲欧美日韩成人高清在线一区| 中文在线一区| 欧美在线999| 久久久久网址|