目錄
1. 基本概念
2. 執行機制
2.1 鉤子鍊錶與鉤子子程
2.2 鉤子安裝與釋放
2.3 一些執行機制
2.4 系統鉤子與執行緒鉤子
2.5 鉤子的不足
2.6 幾點說明
鉤子(hook)是windows訊息處理機制的乙個平台,應用程式可以在上面設定子程式以監聽指定視窗的某種訊息,而且所監聽的視窗可以是由其他
他程序所建立的。當訊息到達後,在目標視窗處理函式之前處理它。鉤子機制允許應用程式截獲處理window訊息或特定事件。
鉤子實際上是乙個處理訊息的程式段,通過系統呼叫,把它掛入系統。每當特定的訊息發出,在沒有到達目的視窗前,
鉤子程式就先捕獲該訊息,亦即鉤子函式先得到控制權。這時鉤子函式即可以加工處理(改變)該訊息,也可以不作處理而繼續傳遞該訊息,還可以強制結束訊息的傳遞。
每個hook都有乙個與之相關的指標列表,稱之為鉤子鍊錶,它由系統來維護,這個鍊錶的指標指向由程式指定的**函式,當訊息來到時,就會呼叫這個**函式。
這些**函式被稱為鉤子的子程。
一些hook子程只監聽訊息,或者修改訊息,或者停止訊息前進,防止這些訊息傳遞到下乙個hook子程或者目標視窗。
最近安裝的鉤子安裝在鍊錶最前面,最早安裝的放在鍊錶的最後面,也就是說後加入鍊錶的鉤子會先獲得控制權。
windows並不要求解除安裝鉤子的順序與安裝的順序相反。第當乙個鉤子被解除安裝時,windows便釋放這個鉤子所佔的記憶體,並更新整個hook鍊錶。
如果安裝了鉤子,但在解除安裝它之前就結束了,那麼作業系統會自動將其所佔記憶體釋放。
使用api setwindowshookex將應用程式定義的鉤子安裝到鉤子鍊錶中。setwindowshookex總是在hook鍊錶開頭安裝hook子程。當指定的hook訊息發生時,
傳遞到下乙個子程,就要呼叫callnexthookex函式。
hhook setwindowshookex(
int idhook, // 鉤子的型別,即它處理的訊息型別
hookproc lpfn, // 鉤子子程的位址指標。如果dwthreadid引數為0
// 或是乙個由別的程序建立的執行緒的標識,
// lpfn必須指向dll中的鉤子子程。
// 除此以外,lpfn可以指向當前程序的一段鉤子子程**。
// 鉤子函式的入口位址,當鉤子鉤到任何訊息後便呼叫這個函式。
hinstance hmod, // 應用程式例項的控制代碼。標識包含lpfn所指的子程的dll。如果為null,則表明就鉤自己程序內的訊息。
// 如果dwthreadid 標識當前程序建立的乙個執行緒,
// 而且子程**位於當前程序,hmod必須為null。
// 可以很簡單的設定其為本應用程式的例項控制代碼。
dword dwthreadid // 與安裝的鉤子子程相關聯的執行緒的識別符號。
// 如果為0,鉤子子程與所有的執行緒關聯,即為全域性鉤子。
鉤子在使用完之後需要用unhookwindowshookex()解除安裝,否則會造成麻煩
在win16環境中,dll的全域性資料對每個載入它的程序來說都是相同的;而在win32環境中,情況卻發生了變化,
dll函式中的**所建立的任何物件(包括變數)都歸呼叫它的執行緒或程序所有。
當程序載入dll時,它會把這個dll的二進位制對映到自己的私有程序位址空間中,也就是程序的虛擬位址空間。而且複製該dll的全域性資料的乙份拷貝
因此,在win32環境下要想在多個程序中共享資料,就必須進行必要的設定。在訪問同乙個dll的各程序之間共享儲存器是通過儲存器對映檔案技術實現的。
也可以把這些需要共享的資料分離出來,放置在乙個獨立的資料段裡,並把該段的屬性設定為共享。
必須給這些變數賦初值,否則編譯器會把沒有賦初始值的變數放在乙個叫未被初始化的資料段中。
#pragma data_seg預處理指令用於設定共享資料段。例如:
#pragma data_seg("shareddataname")
hhook hhook=null;
#pragma data_seg()
在#pragma data_seg("shareddataname")和#pragma data_seg()之間的所有變數將被訪問該dll的所有程序看到和共享。再加上一條指令#pragma comment(linker,"/section:.shareddataname,rws"),
那麼這個資料節中的資料可以在所有dll的例項之間共享。
所有對這些資料的操作都針對同乙個例項的,而不是在每個程序的位址空間中都有乙份。
當程序隱式或顯式呼叫乙個動態庫里的函式時,系統都要把這個動態庫對映到這個程序的虛擬位址空間裡(以下簡稱"位址空間")。
這使得dll成為程序的一部分,以這個程序的身份執行,使用這個程序的堆疊。
setwindowshookex()函式的最後乙個引數決定了此鉤子是系統鉤子還是執行緒鉤子。
執行緒勾子用於監視指定執行緒的事件訊息。執行緒勾子一般在當前執行緒或者當前執行緒派生的執行緒內。
系統勾子監視系統中的所有執行緒的事件訊息。因為系統勾子會影響系統中所有的應用程式,所以勾子函式必須放在獨立的動態鏈結庫(dll) 中。
系統自動將包含"鉤子**函式"的dll對映到受鉤子函式影響的所有程序的位址空間中,即將這個dll注入了那些程序。
如果要實現系統鉤子(全域性鉤子),那麼就要把安裝鉤子,解除安裝鉤子,鉤子處理函式都要放到dll中,那麼就要保證這個dll盡可能的小,因為它會
對映到別的程序位址空間中去。
那麼如果才能通知到我們自己寫的應用程式呢?不要指望設定**函式了。就算你在鉤子dll中儲存乙個**函式位址,也是不行的,因為當這人dll
對映到別的程序位址空間中時,它的所有全域性變數都會被重新初始化,就算你用記憶體共享將這個變數共享了,那個**的位址很可能是被對映程序位址空間中的,也是不行的。
乙個很好的辦法是儲存乙個我們程式的執行緒id,把這個id共享了,當收到hook訊息時,呼叫postthreadmessage把這些訊息傳送到我們程式所在的執行緒。
這樣就能實現監聽訊息了。
1)由於全域性鉤子會把一段dll的二進位制**對映到別的exe中,這可能會很危險。
2)32位的dll不能對映到64位exe中,64位dll也不能對映到32位的exe中,所以就會導致會寫兩個版全的監聽程式32位和64位。32位dll與64位dll必須有不同的名字。
3)鉤子會消耗訊息處理時間,會導致效能差。
1)如果對於同一事件(如滑鼠訊息)既安裝了執行緒勾子又安裝了系統勾子,那麼系統會自動先呼叫執行緒勾子,然後呼叫系統勾子。
2)對同一事件訊息可安裝多個勾子處理過程,這些勾子處理過程形成了勾子鏈。當前勾子處理結束後應把勾子資訊傳遞給下乙個勾子函式。
3)勾子特別是系統勾子會消耗訊息處理時間,降低系統效能。只有在必要的時候才安裝勾子,在使用完畢後要及時解除安裝。
鉤子應用技術
鉤子 hook 技術,以其強大的功能,被廣泛的應用於系統監視,訊息管理。他可以在訊息到達目標視窗以前截獲訊息,並任意的處理系統訊息,達到一般應用程式無法達到的功能。本文主要從鉤子的種類,作用,應用入手,概要的介紹了鉤子技術的應用和作用。並附加乙個shell鉤子的例子和過程。讀者評分 3 評分次數 1...
鉤子及其應用(四)
三 簡單的訊息 spy的實現 凡寫過一些程式的人,大都用過vs的 spy 工具,非常好用。delphi 也有乙個類似的工具叫 winsignt32 說實話,比 spy 可是差遠了。這一篇將介紹如何實現乙個簡單的訊息 spy工具,其功能大概類似於 spy 的spy message 以此來學習全域性鉤子...
SSH原理與應用
ssh是每一台linux電腦的標準配置。隨著linux裝置從電腦逐漸擴充套件到手機 外設和家用電器,ssh的使用範圍也越來越廣。不僅程式設計師離不開它,很多普通使用者也每天使用。雖然本文內容只涉及初級應用,較為簡單,但是需要讀者具備最基本的 shell知識 和了解 公鑰加密 的概念。如果你對它們不熟...