亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > C++ > 正文

淺談c++ hook 鉤子的使用介紹

2020-05-23 13:36:28
字體:
來源:轉載
供稿:網友

一、基本概念:

鉤子(Hook),是Windows消息處理機制的一個平臺,應用程序可以在上面設置子程以監視指定窗口的某種消息,而且所監視的窗口可以是其他進程所創建的。當消息到達后,在目標窗口處理函數之前處理它。鉤子機制允許應用程序截獲處理window消息或特定事件。

鉤子實際上是一個處理消息的程序段,通過系統調用,把它掛入系統。每當特定的消息發出,在沒有到達目的窗口前,鉤子程序就先捕獲該消息,亦即鉤子函數先得到控制權。這時鉤子函數即可以加工處理(改變)該消息,也可以不作處理而繼續傳遞該消息,還可以強制結束消息的傳遞。

二、運行機制:

1、鉤子鏈表和鉤子子程:

每一個Hook都有一個與之相關聯的指針列表,稱之為鉤子鏈表,由系統來維護。這個列表的指針指向指定的,應用程序定義的,被Hook子程調用的回調函數,也就是該鉤子的各個處理子程。當與指定的Hook類型關聯的消息發生時,系統就把這個消息傳遞到Hook子程。一些Hook子程可以只監視消息,或者修改消息,或者停止消息的前進,避免這些消息傳遞到下一個Hook子程或者目的窗口。最近安裝的鉤子放在鏈的開始,而最早安裝的鉤子放在最后,也就是后加入的先獲得控制權。

Windows 并不要求鉤子子程的卸載順序一定得和安裝順序相反。每當有一個鉤子被卸載,Windows 便釋放其占用的內存,并更新整個Hook鏈表。如果程序安裝了鉤子,但是在尚未卸載鉤子之前就結束了,那么系統會自動為它做卸載鉤子的操作。

鉤子子程是一個應用程序定義的回調函數(CALLBACK Function),不能定義成某個類的成員函數,只能定義為普通的C函數。用以監視系統或某一特定類型的事件,這些事件可以是與某一特定線程關聯的,也可以是系統中所有線程的事件。

鉤子子程必須按照以下的語法:

 LRESULT CALLBACK HookProc  int nCode,    WPARAM wParam,    LPARAM lParam  ); 

HookProc是應用程序定義的名字。

nCode參數是Hook代碼,Hook子程使用這個參數來確定任務。這個參數的值依賴于Hook類型,每一種Hook都有自己的Hook代碼特征字符集。

wParam和lParam參數的值依賴于Hook代碼,但是它們的典型值是包含了關于發送或者接收消息的信息。

2、鉤子的安裝與釋放:

使用API函數SetWindowsHookEx()把一個應用程序定義的鉤子子程安裝到鉤子鏈表中。SetWindowsHookEx函數總是在Hook鏈的開頭安裝Hook子程。當指定類型的Hook監視的事件發生時,系統就調用與這個Hook關聯的Hook鏈的開頭的Hook子程。每一個Hook鏈中的Hook子程都決定是否把這個事件傳遞到下一個Hook子程。Hook子程傳遞事件到下一個Hook子程需要調用CallNextHookEx函數。

HHOOK SetWindowsHookEx(       int idHook,   // 鉤子的類型,即它處理的消息類型       HOOKPROC lpfn,  // 鉤子子程的地址指針。如果dwThreadId參數為0     // 或是一個由別的進程創建的線程的標識,     // lpfn必須指向DLL中的鉤子子程。     // 除此以外,lpfn可以指向當前進程的一段鉤子子程代碼。     // 鉤子函數的入口地址,當鉤子鉤到任何消息后便調用這個函數。       HINSTANCE hMod, // 應用程序實例的句柄。標識包含lpfn所指的子程的DLL。     // 如果dwThreadId 標識當前進程創建的一個線程,     // 而且子程代碼位于當前進程,hMod必須為NULL。     // 可以很簡單的設定其為本應用程序的實例句柄。       DWORD dwThreadId // 與安裝的鉤子子程相關聯的線程的標識符。     // 如果為0,鉤子子程與所有的線程關聯,即為全局鉤子。             );  

函數成功則返回鉤子子程的句柄,失敗返回NULL。 

以上所說的鉤子子程與線程相關聯是指在一鉤子鏈表中發給該線程的消息同時發送給鉤子子程,且被鉤子子程先處理。

在鉤子子程中調用得到控制權的鉤子函數在完成對消息的處理后,如果想要該消息繼續傳遞,那么它必須調用另外一個SDK中的API函數CallNextHookEx來傳遞它,以執行鉤子鏈表所指的下一個鉤子子程。這個函數成功時返回鉤子鏈中下一個鉤子過程的返回值,返回值的類型依賴于鉤子的類型。這個函數的原型如下:

LRESULT CallNextHookEx   (   HHOOK hhk;   int nCode;   WPARAM wParam;   LPARAM lParam;   ); 

hhk為當前鉤子的句柄,由SetWindowsHookEx()函數返回。

NCode為傳給鉤子過程的事件代碼。

wParam和lParam 分別是傳給鉤子子程的wParam值,其具體含義與鉤子類型有關。

鉤子函數也可以通過直接返回TRUE來丟棄該消息,并阻止該消息的傳遞。否則的話,其他安裝了鉤子的應用程序將不會接收到鉤子的通知而且還有可能產生不正確的結果。

鉤子在使用完之后需要用UnHookWindowsHookEx()卸載,否則會造成麻煩。釋放鉤子比較簡單,UnHookWindowsHookEx()只有一個參數。函數原型如下:

UnHookWindowsHookEx ( HHOOK hhk; );

函數成功返回TRUE,否則返回FALSE。

3、一些運行機制:

在Win16環境中,DLL的全局數據對每個載入它的進程來說都是相同的;而在Win32環境中,情況卻發生了變化,DLL函數中的代碼所創建的任何對象(包括變量)都歸調用它的線程或進程所有。當進程在載入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的所有進程看到和共享。

當進程隱式或顯式調用一個動態庫里的函數時,系統都要把這個動態庫映射到這個進程的虛擬地址空間里(以下簡稱"地址空間")。這使得DLL成為進程的一部分,以這個進程的身份執行,使用這個進程的堆棧。

對于創建全局鉤子,我們需要采用DLL注入的方式,Hook的DLL工程主代碼如下:

#include <Windows.h>  #pragma data_seg("HookWnd") HHOOK   g_HookWnd   = NULL;  //鉤子句柄 HWND   g_DestWnd   = NULL;  //目的窗口句柄,就是截獲的消息要發往什么窗口 HINSTANCE g_hInst    = NULL; #pragma data_seg()  #pragma comment( linker, "/section:HookWnd,RWS" )  __declspec(dllexport) BOOL SetHook(HWND hWnd); __declspec(dllexport) void DestroyHook();  #define WM_MYMESSAGE (WM_USER + 1)  BOOL WINAPI DllMain(HINSTANCE hinstDll, DWORD fdwReason, LPVOID lpvReserved) {   g_hInst = hinstDll;//保存應用程序實例   return TRUE; }   LRESULT CALLBACK MyWndProc(int nCode, WPARAM wParam, LPARAM lParam) {   CWPSTRUCT *pCwp = reinterpret_cast<CWPSTRUCT*>(lParam);   if (pCwp->message == WM_SHOWWINDOW)   {     ::SendMessage(g_DestWnd, WM_MYMESSAGE, wParam, reinterpret_cast<LPARAM>(pCwp->hwnd));     return 0;   }   else     return CallNextHookEx(g_HookWnd, nCode, wParam, lParam); }  BOOL SetHook(HWND hWnd) {   if (NULL == hWnd)     return FALSE;      g_DestWnd = hWnd;    //第三個參數還可通過些方法獲得:GetModuleHandle("HookTest.dll")   return (NULL != (g_HookWnd = ::SetWindowsHookEx(WH_CALLWNDPROC, MyWndProc, g_hInst, 0))); }  void DestroyHook() {   if (NULL != g_HookWnd)    {     UnhookWindowsHookEx(g_HookWnd);     g_DestWnd = NULL;   } }

4、系統鉤子與線程鉤子:

SetWindowsHookEx()函數的最后一個參數決定了此鉤子是系統鉤子還是線程鉤子。

線程勾子用于監視指定線程的事件消息。線程勾子一般在當前線程或者當前線程派生的線程內。

系統勾子監視系統中的所有線程的事件消息。因為系統勾子會影響系統中所有的應用程序,所以勾子函數必須放在獨立的動態鏈接庫(DLL) 中。系統自動將包含"鉤子回調函數"的DLL映射到受鉤子函數影響的所有進程的地址空間中,即將這個DLL注入了那些進程。

幾點說明:

(1)如果對于同一事件(如鼠標消息)既安裝了線程勾子又安裝了系統勾子,那么系統會自動先調用線程勾子,然后調用系統勾子。

(2)對同一事件消息可安裝多個勾子處理過程,這些勾子處理過程形成了勾子鏈。當前勾子處理結束后應把勾子信息傳遞給下一個勾子函數。

(3)勾子特別是系統勾子會消耗消息處理時間,降低系統性能。只有在必要的時候才安裝勾子,在使用完畢后要及時卸載。

三、鉤子類型

 每一種類型的Hook可以使應用程序能夠監視不同類型的系統消息處理機制。下面描述所有可以利用的Hook類型。

1、WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks

WH_CALLWNDPROC和WH_CALLWNDPROCRET Hooks使你可以監視發送到窗口過程的消息。系統在消息發送到接收窗口過程之前調用WH_CALLWNDPROC Hook子程,并且在窗口過程處理完消息之后調用WH_CALLWNDPROCRET Hook子程。

WH_CALLWNDPROCRET Hook傳遞指針到CWPRETSTRUCT結構,再傳遞到Hook子程。CWPRETSTRUCT結構包含了來自處理消息的窗口過程的返回值,同樣也包括了與這個消息關聯的消息參數。

2、WH_CBT Hook

在以下事件之前,系統都會調用WH_CBT Hook子程,這些事件包括:

    1. 激活,建立,銷毀,最小化,最大化,移動,改變尺寸等窗口事件;
    2. 完成系統指令;
    3. 來自系統消息隊列中的移動鼠標,鍵盤事件;
    4. 設置輸入焦點事件;
    5. 同步系統消息隊列事件。

Hook子程的返回值確定系統是否允許或者防止這些操作中的一個。

3、WH_DEBUG Hook

在系統調用系統中與其他Hook關聯的Hook子程之前,系統會調用WH_DEBUG Hook子程。你可以使用這個Hook來決定是否允許系統調用與其他Hook關聯的Hook子程。

4、WH_FOREGROUNDIDLE Hook

當應用程序的前臺線程處于空閑狀態時,可以使用WH_FOREGROUNDIDLE Hook執行低優先級的任務。當應用程序的前臺線程大概要變成空閑狀態時,系統就會調用WH_FOREGROUNDIDLE Hook子程。

5、WH_GETMESSAGE Hook

應用程序使用WH_GETMESSAGE Hook來監視從GetMessage or PeekMessage函數返回的消息。你可以使用WH_GETMESSAGE Hook去監視鼠標和鍵盤輸入,以及其他發送到消息隊列中的消息。

6、WH_JOURNALPLAYBACK Hook

WH_JOURNALPLAYBACK Hook使應用程序可以插入消息到系統消息隊列??梢允褂眠@個Hook回放通過使用WH_JOURNALRECORD Hook記錄下來的連續的鼠標和鍵盤事件。只要WH_JOURNALPLAYBACK Hook已經安裝,正常的鼠標和鍵盤事件就是無效的。WH_JOURNALPLAYBACK Hook是全局Hook,它不能象線程特定Hook一樣使用。WH_JOURNALPLAYBACK Hook返回超時值,這個值告訴系統在處理來自回放Hook當前消息之前需要等待多長時間(毫秒)。這就使Hook可以控制實時事件的回放。WH_JOURNALPLAYBACK是system-wide local hooks,它們不會被注射到任何行程位址空間。

7、WH_JOURNALRECORD Hook

WH_JOURNALRECORD Hook用來監視和記錄輸入事件。典型的,可以使用這個Hook記錄連續的鼠標和鍵盤事件,然后通過使用WH_JOURNALPLAYBACK Hook來回放。WH_JOURNALRECORD Hook是全局Hook,它不能象線程特定Hook一樣使用。WH_JOURNALRECORD是system-wide local hooks,它們不會被注射到任何行程位址空間。

8、WH_KEYBOARD Hook

在應用程序中,WH_KEYBOARD Hook用來監視WM_KEYDOWN and WM_KEYUP消息,這些消息通過GetMessage or PeekMessage function返回??梢允褂眠@個Hook來監視輸入到消息隊列中的鍵盤消息。

9、WH_KEYBOARD_LL Hook

WH_KEYBOARD_LL Hook監視輸入到線程消息隊列中的鍵盤消息。

10、WH_MOUSE Hook

WH_MOUSE Hook監視從GetMessage 或者 PeekMessage 函數返回的鼠標消息。使用這個Hook監視輸入到消息隊列中的鼠標消息。

11、WH_MOUSE_LL Hook

WH_MOUSE_LL Hook監視輸入到線程消息隊列中的鼠標消息。

12、WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks

WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我們可以監視菜單,滾動條,消息框,對話框消息并且發現用戶使用ALT+TAB or ALT+ESC 組合鍵切換窗口。WH_MSGFILTER Hook只能監視傳遞到菜單,滾動條,消息框的消息,以及傳遞到通過安裝了Hook子程的應用程序建立的對話框的消息。WH_SYSMSGFILTER Hook監視所有應用程序消息。

WH_MSGFILTER 和 WH_SYSMSGFILTER Hooks使我們可以在模式循環期間過濾消息,這等價于在主消息循環中過濾消息。

通過調用CallMsgFilter function可以直接的調用WH_MSGFILTER Hook。通過使用這個函數,應用程序能夠在模式循環期間使用相同的代碼去過濾消息,如同在主消息循環里一樣。

13、WH_SHELL Hook

外殼應用程序可以使用WH_SHELL Hook去接收重要的通知。當外殼應用程序是激活的并且當頂層窗口建立或者銷毀時,系統調用WH_SHELL Hook子程。

WH_SHELL 共有5鐘情況:
1. 只要有個top-level、unowned 窗口被產生、起作用、或是被摧毀;
2. 當Taskbar需要重畫某個按鈕;
3. 當系統需要顯示關于Taskbar的一個程序的最小化形式;
4. 當目前的鍵盤布局狀態改變;
5. 當使用者按Ctrl+Esc去執行Task Manager(或相同級別的程序)。

按照慣例,外殼應用程序都不接收WH_SHELL消息。所以,在應用程序能夠接收WH_SHELL消息之前,應用程序必須調用SystemParametersInfo function注冊它自己。

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持VEVB武林網。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
狠狠色狠狠色综合日日小说| 高清亚洲成在人网站天堂| 国产精品国内视频| 久久久久久久久电影| 91丨九色丨国产在线| 在线成人激情黄色| 国产精品国产三级国产aⅴ浪潮| 亚洲区免费影片| 91精品综合久久久久久五月天| 亚洲性夜色噜噜噜7777| 亚洲欧美国产制服动漫| 亚洲色在线视频| 亚洲一区二区久久久久久| 成人网页在线免费观看| 精品毛片三在线观看| 日韩精品在线看| 麻豆国产va免费精品高清在线| 国产精品一区二区三| 一本色道久久88亚洲综合88| 国产精品久久久久久久午夜| 日本久久久久久久久| 亚洲国产精品成人av| 少妇精69xxtheporn| 久久青草精品视频免费观看| 九九热精品视频国产| 国产噜噜噜噜噜久久久久久久久| 日韩中文字幕精品视频| 亚洲自拍小视频免费观看| 欧美电影免费在线观看| 亚洲丁香久久久| 国产一区二区黄| 精品视频中文字幕| 亚洲欧美国产制服动漫| 中文字幕日韩精品在线| 欧美激情视频在线观看| 国产精品免费久久久久久| 国内精品视频在线| 韩日欧美一区二区| 欧美成人免费va影院高清| 日韩电影在线观看永久视频免费网站| 日韩精品视频在线免费观看| 欧美在线欧美在线| 日韩一区二区欧美| 久热爱精品视频线路一| 亚洲精品女av网站| 不卡中文字幕av| 91精品久久久久久久久久| 91精品国产网站| 麻豆乱码国产一区二区三区| 欧美福利在线观看| 97超视频免费观看| 国产精品欧美一区二区三区奶水| 亚洲色图校园春色| 亚洲福利视频网站| 国产亚洲精品高潮| 日韩视频―中文字幕| 国产a∨精品一区二区三区不卡| 日韩精品在线免费播放| 国产日产欧美a一级在线| 色偷偷噜噜噜亚洲男人| 欧美精品做受xxx性少妇| 亚洲自拍偷拍网址| 国产精品久久久久久久久久ktv| 57pao国产成人免费| 51精品在线观看| 亚洲性猛交xxxxwww| 亚洲成avwww人| 欧美激情第一页xxx| 亚洲资源在线看| 国产精品爽黄69天堂a| 国产成人免费91av在线| 国产精品久久久久久久久久久久久| 亚洲精品日韩激情在线电影| 久久久久久久网站| 中文字幕日韩精品在线观看| 高清欧美电影在线| 国产精品久久久久久网站| 国产日韩欧美夫妻视频在线观看| 国产精品成人一区二区三区吃奶| 欧美视频在线观看免费网址| 在线精品国产欧美| 亚洲人午夜精品| 国产精品日韩在线播放| 亚洲第一精品夜夜躁人人爽| 尤物99国产成人精品视频| 韩国精品美女www爽爽爽视频| 国产成人a亚洲精品| 伊人久久五月天| 68精品久久久久久欧美| 欧美成人精品h版在线观看| 欧美高清视频免费观看| 日韩精品在线观看网站| 国产精品1234| 亚洲欧美中文日韩v在线观看| 国产精品18久久久久久麻辣| 国产成人精品视频在线| 在线观看日韩视频| 国内精品久久久久影院优| 国内精品视频在线| 668精品在线视频| 91高潮在线观看| 欧美性猛交xxxx乱大交| 在线国产精品播放| 国产精品一区二区三区成人| 日韩av黄色在线观看| 日韩av免费在线| 日韩精品极品视频免费观看| 国产欧美在线视频| 欧美激情欧美激情| 精品成人久久av| 成人在线观看视频网站| 性色av一区二区咪爱| 亚洲mm色国产网站| 亚洲一区av在线播放| 欧美国产日韩一区二区三区| 国产欧美日韩免费看aⅴ视频| 欧美超级乱淫片喷水| 久久国产精品免费视频| 欧美中文在线字幕| www.99久久热国产日韩欧美.com| 亚洲丝袜在线视频| 成人黄色生活片| 欧美日韩裸体免费视频| 欧美一级淫片丝袜脚交| 91精品国产91久久久久久不卡| 狠狠色狠狠色综合日日五| 亚洲无亚洲人成网站77777| 美女视频黄免费的亚洲男人天堂| 欧美午夜精品久久久久久人妖| 欧美成人午夜剧场免费观看| 欧美一级片免费在线| 一区二区亚洲欧洲国产日韩| 影音先锋欧美在线资源| 精品无人区乱码1区2区3区在线| 精品一区二区电影| 久久久久久国产精品久久| 中文字幕欧美国内| 成人疯狂猛交xxx| 国产精品自拍网| 亚洲视频在线观看免费| 久久九九免费视频| 精品香蕉在线观看视频一| 亚洲国产中文字幕久久网| 中文字幕欧美国内| 欧美精品制服第一页| 美女性感视频久久久| 亚洲免费小视频| 亚洲日本中文字幕免费在线不卡| 国产精品入口免费视频一| 日韩av免费在线| 精品久久久久久久久国产字幕| 欧美性xxxx在线播放| 国产一区二区av| 欧美激情区在线播放| 亚洲国产精品资源| 亚洲欧洲一区二区三区久久| 九九久久久久99精品| 国产精品久久久久久久久免费看| 最新69国产成人精品视频免费| 久久久久久久久久久网站| 精品偷拍各种wc美女嘘嘘| 2019日本中文字幕| 最近免费中文字幕视频2019| 日韩免费观看视频|