用 Thunk 實現 COM 的掛鉤
原文連結:http://www.titilima.cn/show-557-1.html
COM 的掛鉤其實已經是一個很古老的話題了,其核心技術就是替換 COM 物件虛表中相應位置的函式指標,從而達到掛鉤的效果。順便說一句,這個方法和核心的 SSDT 掛鉤是十分類似的。其相應的實現程式碼也十分簡單,如下所示:
需要指出的是,這裡要使用 VirtualProtect 改變虛表的頁面屬性,就像掛鉤 SSDT 時要改變 cr0 的保護屬性一樣。
整個的掛鉤過程及使用類似於這個樣子:
這種掛鉤的方式有一個侷限性,就是掛鉤函式 HookQueryInterface 不能作為一個非 static 的類成員函式來實現。與之類似,Win32 的 WNDPROC 也無法使用非 static 的類成員函式來封裝,實乃一大憾事。
當然,我們可以通過非常規的方法來解決這個問題,比如 thunk。
在開始實現我的 thunk 之前,先來看看一個 COM 方法呼叫的過程,考慮如下程式碼:
這個呼叫過程所對應的彙編程式碼為:
push 2
mov eax,dword ptr [pa]
; vptr
mov ecx,dword ptr [eax]
; this
mov edx,dword ptr [pa]
push edx
mov eax,dword ptr [ecx]
call eax
也就是說,一個 COM 方法呼叫的壓棧順序為:
- 由右至左的各個引數,也就是 STDCALL 呼叫約定的壓棧順序;
- this 指標;
- 當然,還有 call 的返回地址,這個壓棧是在 call 指令內部完成的。
從上面可以看出來,為了把一個 COM 呼叫重定向到我們自己的類成員函式中,需要做以下工作:
- 保留原 COM 方法的各個引數;
- 保留原 COM 物件的 this 指標;
- 加入我們自己類物件的 this 指標;
- 保留 call 原有的返回地址。
簡單說來,這個重定向的過程是將堆疊中插入另外一個 this 指標,僅此而已。
明確了這個操作的步驟,我們可以寫出如下的 thunk 程式碼,這段程式碼將被放到目標 COM 物件的虛表中。
; 彈出 call 的返回地址
pop eax
; 加入自己的 this 指標
push this
; 重新壓入 call 的返回地址
push eax
; 跳至掛鉤函式之中
jmp addr
相應地,我們為這個 thunk 定義一個結構:
以及一個用於儲存掛鉤資訊的結構:
最後,就可以實現這個升級版的掛鉤函式了,如下:
測試程式碼如下,使用 B 類中的 hook_foo 掛鉤了上文中的 A::foo。
其中 member_cast 用於非 static 成員的型別轉換,可以參考《獲取成員函式的指標》一文,再次感謝 likunkun 所提供的優雅解決方案。
點此下載全部示例程式碼
相關文章
- Thunk程式的實現原理以及在iOS中的應用iOS
- Thunk程式的實現原理以及在iOS中的應用(二)iOS
- 理解thunk函式的作用及co的實現函式
- 一種貨幣如果和美元直接掛鉤是怎樣實現的?
- 純C#鉤子實現及應用(轉)C#
- 使用VC++ ATL實現iStylePDF的COM外掛C++
- 用 Go 做了一個 Git WebHook 鉤子 實現自動部署GoGitWebHook
- WINDOWS鍵盤事件的掛鉤監控原理及其應用技術Windows事件
- 我對C++中THUNK一種實現技術的分析 (轉)C++
- Nuxt.js 應用中的 components:dirs 事件鉤子詳解UXJS事件
- Nuxt.js 應用中的 components:extend 事件鉤子詳解UXJS事件
- vue[原始碼]生命週期鉤子的實現Vue原始碼
- svn:鉤子post-commitMIT
- Nuxt.js 應用中的 kit:compatibility 事件鉤子詳解UXJS事件
- C#實現滑鼠、鍵盤鉤子C#
- 用CompletableFuture實現非同步任務非同步
- Thunk函式的使用函式
- Web Components 系列(十一)—— 實現 MyCard 的可複用Web
- 與遊戲頻繁掛鉤的SCP是什麼?遊戲
- Win32全域性鉤子實現 (轉)Win32
- 淺談內聯鉤取原理與實現
- 用slot和component實現表單共用
- DCOM實現分散式應用(二) (轉)分散式
- 這才是tapable裡面SyncLoopHook鉤子函式的實現OOPHook函式
- 外掛移植後,鉤子不起作用。
- 「Window平臺」異常掛鉤大法(1)
- Windows核心新手上路3——掛鉤KeUserModeCallBackWindows
- Windows核心新手上路1——掛鉤SSDTWindows
- 鉤子裡找不到新增外掛名稱的位置
- 用Python實現一個實時運動的大掛鐘效果Python
- 利用wps的com口用python實現excel轉pdfPythonExcel
- 如何在 Composer 專案中管理本地的 Git 鉤子?Git
- React實用外掛React
- Word2000/XP中內部COM外掛的程式設計實現 (轉)程式設計
- PostgreSQL 原始碼解讀(249)- 實現簡單的鉤子函式SQL原始碼函式
- PHP外掛系統的實現(七):外掛案例PHP
- 關於vim的實用外掛
- 實用!開發者的 Vim 外掛(一)