滑鼠鉤子、鍵盤鉤子等大家一定是耳熟能詳,在 windows 環境下程式設計的朋友們肯定都和他們打過交道,比如說截獲密碼什麼的都可以用到他們。本文將介紹一種辦法可以列舉所有的全域性鉤子,找到到底是什麼動態庫建立了鉤子(大部分全域性鉤子都需要通過動態庫來實現)。
下圖是程式執行後顯示的所有的全域性鉤子,包括鉤子函式在那個動態庫中,也就是建立鉤子的動態庫。圖中顯示的鉤子控制代碼是指得在當前程序中的控制代碼,不是系統範圍的。比如說 mousehook 新增了乙個全域性的滑鼠鉤子,那麼在 explorer 中這個鉤子的控制代碼和在 word 中的控制代碼是不同的(這一點我是通過 icesword 觀察到的),但都是 mousehook 新增的鉤子都在 mousehook.dll 動態庫中。如果想獲得 icesword 一樣的結果可以針對每乙個程序列舉全域性鉤子(沒試過)。l另外,如果滑鼠鉤子和鍵盤鉤子不能夠顯示動態庫,可以先動一動滑鼠,摁幾下鍵盤再重新整理應該就可以顯示。
之所以會寫這篇文章是因為在程式設計板塊中有乙個主題說判斷全域性鉤子的呼叫者,所以才想著能不能列舉出所有的全域性鉤子。但那個主題好像說的是鉤子的呼叫者,又好像全域性鉤子指得是 hook api 型別的鉤子,沒搞懂。在那個主題下 zmworm 大俠好像說可以通過乙個鉤子鏈的東東來列舉鉤子,不過大俠沒有細說,我自己也沒有在符號檔案中找到有關鉤子鏈的符號(我只會這一種辦法找系統內部變數,比如活動程序鏈就可以通過這種辦法找到位置),所以準備從 callnexthookex 函式慢慢往下追希望能夠找到系統是怎麼找到下乙個鉤子函式的。本文介紹的方法就是這樣來的(另外有乙個很重要的一點會在文章的最後提到)。
invoke psgetcurrentthread
mov ebx, [eax+130h]
mov _gpticurrent, ebx
invoke dbgprint, $cta0("ethread:%08x, win32thread:%08x/n"), eax, _gpticurrent
assume esi : nothing
mov ebx, -1
.while ebx!=12
invoke _phkfirstvalid, _gpticurrent, ebx
assume eax : ptr hook
.while eax
push eax ;_phknextvalid 的引數
;根據 win32k.sys 中的 _***hkcallhook 得到下面的**
mov edx, [eax].ihmod
cmp edx, -1
jz @f
mov esi, _gpticurrent ;esi -> threadinfo
mov esi, [esi+2ch] ;esi -> processinfo
mov edx, [esi+edx*4+0a8h] ;edx = [esi].ahmodlibloaded[ihmod]
@@:;-------------------------------------
m2m [edi].handle, [eax].hmodule
m2m [edi].funcoffset, [eax].offpfn
mov [edi].funcbaseaddr, edx
m2m [edi].ihook, [eax].ihook
;-------------------------------------
invoke dbgprint, $cta0("handle:%08x funcoffset:%08x funcbaseaddr:%08x ihook:%d ihmod:%d/n"), /
[eax].hmodule, [eax].offpfn, edx, [eax].ihook, [eax].ihmod
call _phknextvalid
add dwbytesreturned, sizeof hook_info
add edi, sizeof hook_info
.endw
inc ebx
.endw
上面給出的就是核心**,先找到執行緒的 win32thread 結構,通過這個結構就可以呼叫 win32k.sys 的內部函式 _phkfirstvalid 找到第乙個鉤子函式。然後再通過 _phknextvalid 函式列舉所有的鉤子函式。因為每個系統中這兩個函式的位址不同,所以我把反彙編後的**直接提取出來使用。這樣可以避免因為系統不同的原因而出錯。不過我只在 winxp+sp2 下執行過,沒有在其他的系統下測試,如果大家不能正確執行只好自己修改源**啦。
_phkfirstvalid 函式接收兩個引數,第乙個是 win32thread 結構的位址,第二個是要列舉的鉤子的型別,比如滑鼠鉤子。函式返回 hook 結構的位址。
hook struct
hmodule dd ?
_z_ dd 4 dup (?)
phknext dd ? ;14h
ihook dd ? ;18h
offpfn dd ? ;1ch
flags dd ? ;20h
ihmod dd ? ;24h
ptihooked dd ?
rpdesk dd ?
hook ends
hmodule 是鉤子的控制代碼,
_z_ 這幾個不知道是幹什麼的,
phknext 指向下乙個 hook 結構,
ihook 鉤子型別,
offpfn 鉤子函式的位址,一般都是相對鉤子模組的基位址的偏移值,
flags 一些鉤子的屬性,比如說鉤子是不是已經被銷毀,
ihmod 不太清楚,好像是模組索引。
_phknextvalid 函式通過當前鉤子函式的 hook 結構找到下乙個鉤子函式的 hook 結構。
找到了鉤子函式的 hook 結構後,再通過 ihmod 成員找到鉤子模組的基位址。這一部分可以參考 _***hkcallhook 函式的**。然後把這些資訊返回給 ring3 下的程式顯示出來。
本文給出的**和結構很大一部分來之於大家手上都有的「那份」**。:)
全域性鉤子和區域性鉤子
蒐集了許多的資料,也做了各種嘗試,但是還不是很明白具體的分類.根據目前所掌握的總結一下 區域性鉤子 注意事項 第乙個引數是wh keyboard類似的區域性鉤子引數,第二個是 函式,可以再當前dll exe 中也可以在其他的dll中 第三個引數可設為0就可以,可能是忽略這個引數了吧.第四個引數是當前...
區域性鉤子和和全域性鉤子
區域性鉤子的使用 1在自定義的form類中寫 clean 欄位名 2 取出欄位的真正值,name self.cleaned data.get name 3判斷自己的規則,如果判斷失敗,丟擲validationerror 4 如果通過,return name 區域性鉤子 def clean name ...
C 全域性鉤子和區域性鉤子記錄
源自 最近碰巧要使用鍵盤鉤子,於是在網上搜尋了一番,發現大多數部落格的文章都是雷同的,根本就沒有講清楚全域性鉤子和區域性鉤子的區別,於是特開一貼,講全域性鉤子和區域性鉤子捋一捋。也供後面的人學習。因為大部分應用都應該採用區域性鉤子,所以我這兒使用的是區域性鉤子,而全域性鉤子的例子網上到處都是。大部分...