成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

網絡安全編程:Windows鉤子函數

安全
Windows下的窗口應用程序是基于消息驅動的,但是在某些情況下需要捕獲或者修改消息,從而完成一些特殊的功能。

[[401215]]

 Windows下的窗口應用程序是基于消息驅動的,但是在某些情況下需要捕獲或者修改消息,從而完成一些特殊的功能。對于捕獲消息而言,無法使用IAT或Inline Hook之類的方式去進行捕獲,不過Windows提供了專門用于處理消息的鉤子函數。

01 鉤子原理

Windows下的應用程序大部分是基于消息模式機制的,一些CUI的程序不是基于消息的。Windows下的應用程序都有一個消息過程函數,根據不同的消息來完成不同的功能。Windows操作系統提供的鉤子機制的作用是用來截獲、監視系統中的消息。Windows操作系統提供了很多不同種類的鉤子,可以處理不同的消息。

Windows系統提供的鉤子按照掛鉤范圍分為局部鉤子和全局鉤子。局部鉤子是針對一個線程的,而全局鉤子則是針對整個操作系統內基于消息機制的應用程序的。全局鉤子需要使用DLL文件,DLL文件里存放了鉤子函數的代碼。

在操作系統中安裝全局鉤子以后,只要進程接收到可以發出鉤子的消息后,全局鉤子的DLL文件會被操作系統自動或強行地加載到該進程中。由此可見,設置消息鉤子也是一種可以進行DLL注入的方法。

02 鉤子函數

鉤子函數主要有3個,分別是SetWindowsHookEx()、CallNextHookEx()和UnhookWindowsHookEx()。下面介紹這些函數的使用方法。

SetWindowsHookEx()函數的定義如下: 

  1. HHOOK SetWindowsHookEx(  
  2.  int idHook,  
  3.  HOOKPROC lpfn,  
  4.  HINSTANCE hMod,  
  5.  DWORD dwThreadId  
  6. ); 

該函數的返回值為一個鉤子句柄。這個函數有4個參數,下面分別進行介紹。

lpfn:該參數指定為 Hook 函數的地址。如果 dwThreadId 參數被賦值為 0,或者被設置為一個其他進程中的線程 ID,那么 lpfn 則屬于 DLL 中的函數過程。如果 dwThreadId 為當前進程中的線程 ID,那么 lpfn 可以是指向當前進程中的函數過程,也可以是屬于 DLL 中的函數過程。

hMod:該參數指定鉤子函數所在模塊的模塊句柄。該模塊句柄就是 lpfn 所在的模塊的句柄。如果 dwThreadId 為當前進程中的線程 ID,而且 lpfn 所指向的函數在當前進程中,那么 hMod 將被設置為 NULL。

dwThreadId:該參數設置為需要被掛鉤的線程的 ID 號。如果設置為 0,表示在所有的線程中掛鉤(這里的“所有的線程”表示基于消息機制的所有的線程)。如果指定為具體的線程的 ID 號,表示要在指定的線程中進行掛鉤。該參數影響上面兩個參數的取值。該參數的取值決定了該鉤子屬于全局鉤子,還是局部鉤子。

idHook:該參數表示鉤子的類型。由于鉤子的類型非常多,因此放在所有的參數后面進行介紹。下面介紹幾個常用到的鉤子,也可能是大家比較關心的幾個類型。

1. WH_GETMESSAGE

安裝該鉤子的作用是監視被投遞到消息隊列中的消息。也就是當調用GetMessage()或PeekMessage()函數時,函數從程序的消息隊列中獲取一個消息后調用該鉤子。

WH_GETMESSAGE鉤子函數的定義如下: 

  1. LRESULT CALLBACK GetMsgProc(  
  2.  int code, // 鉤子編碼  
  3.  WPARAM wParam, // 移除選項  
  4.  LPARAM lParam // 消息  
  5. ); 

2. WH_MOUSE

安裝該鉤子的作用是監視鼠標消息。該鉤子函數的定義如下: 

  1. LRESULT CALLBACK MouseProc(  
  2.  int nCode, // 鉤子編碼  
  3.  WPARAM wParam, // 消息標識符  
  4.  LPARAM lParam // 鼠標的坐標  
  5. ); 

3. WH_KEYBOARD

安裝該鉤子的作用是監視鍵盤消息。該鉤子函數的定義如下: 

  1. LRESULT CALLBACK KeyboardProc(  
  2.  int code, // 鉤子編碼  
  3.  WPARAM wParam, // 虛擬鍵編碼  
  4.  LPARAM lParam // 按鍵信息  
  5. ); 

4. WH_DEBUG

安裝該鉤子的作用是調試其他鉤子的鉤子函數。該鉤子函數的定義如下: 

  1. LRESULT CALLBACK DebugProc(  
  2.  int nCode, // 鉤子編碼  
  3.  WPARAM wParam, // 鉤子類型  
  4.  LPARAM lParam // 調試信息  
  5. ); 

從上面的這些鉤子函數定義可以看出,每個鉤子函數的定義都是一樣的。每種類型的鉤子監視、截獲的消息不同。雖然它們的定義都是相同的,但是函數參數的意義是不同的。

接著介紹跟鉤子有關的另外一個函數:UnhookWindowsHookEx(),其定義如下: 

  1. BOOL UnhookWindowsHookEx(  
  2.  HHOOK hhk // 鉤子函數的句柄  
  3. ); 

這個函數是用來移除先前用SetWindowsHookEx()安裝的鉤子。該函數只有一個參數,是鉤子句柄,也就是調用該函數通過指定的鉤子句柄來移除與其相應的鉤子。

在操作系統中,可以多次反復地使用SetWindowsHookEx()函數來安裝鉤子,而且可以安裝多個同樣類型的鉤子。這樣,鉤子就會形成一條鉤子鏈,最后安裝的鉤子會首先截獲到消息。當該鉤子對消息處理完畢以后,會選擇返回,或者選擇把消息繼續傳遞下去。在通常情況下,如果為了屏蔽消息,則直接在鉤子函數中返回一個非零值。比如要在自己程序中屏蔽鼠標消息,則在安裝的鼠標鉤子函數中直接返回非零值即可。如果為了消息在經過鉤子函數后可以繼續傳達到目標窗口,必須選擇將消息繼續傳遞。使消息能繼續傳遞的函數的定義如下: 

  1. LRESULT CallNextHookEx(  
  2.  HHOOK hhk, // 當前鉤子的句柄  
  3.  int nCode, // 傳遞給釣子函數的釣子編碼  
  4.  WPARAM wParam, // 傳遞給釣子函數的值  
  5.  LPARAM lParam // 傳遞給釣子函數的值  
  6. ); 

該函數有4個參數。第一個參數是鉤子句柄,就是調用SetWindowsHookEx()函數的返回值;后面3個參數是鉤子函數的參數,直接依次抄過來即可。例如: 

  1. HHOOK g_Hook = SetWindowsHook(……);  
  2. LRESULT CALLBACK GetMsgProc(  
  3.  int code, // 鉤子編碼  
  4.  WPARAM wParam, // 移除選項  
  5.  LPARAM lParam // 消息  
  6.  
  7.  
  8.  return CallNextHookEx(g_Hook, code, wParam, lParam); 

03 鉤子實例

Windows鉤子的應用比較廣。無論是安全產品還是惡意軟件,甚至是常規軟件,都會用到Windows提供的鉤子功能。

1. 全局鍵盤鉤子

下面來寫一個可以截獲鍵盤消息的鉤子程序,其功能非常簡單,就是把按下的鍵對應的字符顯示出來。既然要截獲鍵盤消息,那么肯定是截獲系統范圍內的鍵盤消息,因此需要安裝全局鉤子,這樣就需要DLL文件的支持。先來新建一個DLL文件,在該DLL文件中需要定義兩個導出函數和兩個全局變量,定義如下: 

  1. extern "C" __declspec(dllexport) VOID SetHookOn();  
  2. extern "C" __declspec(dllexport) VOID SetHookOff();  
  3. // 鉤子句柄  
  4. HHOOK g_Hook = NULL 
  5. // DLL 模塊句柄  
  6. HINSTANCE g_Inst = NULL

在DllMain()函數中,需要保存該DLL模塊的句柄,以方便安裝全局鉤子。代碼如下: 

  1. BOOL APIENTRY DllMain( HANDLE hModule,  
  2.  DWORD ul_reason_for_call, 
  3.  LPVOID lpReserved  
  4.  )  
  5.  
  6.  // 保存 DLL 的模塊句柄  
  7.  g_Inst = (HINSTANCE)hModule;  
  8.  return TRUE;  

安裝與卸載鉤子的函數如下: 

  1. VOID SetHookOn()  
  2.  
  3.  // 安裝鉤子  
  4.  g_Hook = SetWindowsHookEx(WH_KEYBOARD, KeyboardProc, g_Inst, 0);  
  5. VOID SetHookOff()  
  6.  
  7.  // 卸載鉤子  
  8.  UnhookWindowsHookEx(g_Hook);  

對于Windows鉤子來說,上面的這些步驟基本上都是必需的,或者是差別不大,關鍵在于鉤子函數的實現。這里是為了獲取鍵盤按下的鍵,鉤子函數如下: 

  1. // 鉤子函數  
  2. LRESULT CALLBACK KeyboardProc(  
  3.   int code, // 鉤子編碼  
  4.   WPARAM wParam, // 虛擬鍵編碼  
  5.   LPARAM lParam // 按建信息  
  6.  
  7.  
  8.   if ( code < 0 )  
  9.   {  
  10.     return CallNextHookEx(g_Hook, code, wParam, lParam);  
  11.   }  
  12.   if ( code == HC_ACTION && lParam > 0 )  
  13.   {  
  14.     char szBuf[MAXBYTE] = { 0 };  
  15.     GetKeyNameText(lParam, szBuf, MAXBYTE);  
  16.     MessageBox(NULL, szBuf, NULL, MB_OK);  
  17.   } 
  18.   return CallNextHookEx(g_Hook, code, wParam, lParam);  

關于鉤子函數,這里簡單地解釋一下,首先是進入鉤子函數的第一個判斷。 

  1. if ( code < 0 )  
  2.  
  3.  return CallNextHookEx(g_Hook, code, wParam, lParam);  

如果code的值小于0,則必須調用CallNextHookEx(),將消息繼續傳遞下去,不對該消息進行處理,并返回CallNextHookEx()函數的返回值。這一點是MSDN上要求這么做的。 

  1. if ( code == HC_ACTION && lParam > 0 )  
  2.  
  3.  char szBuf[MAXBYTE] = { 0 };  
  4.  GetKeyNameText(lParam, szBuf, MAXBYTE); 
  5.   MessageBox(NULL, szBuf, NULL, MB_OK); 

如果code等于HC_ACTION,表示消息中包含按鍵消息;如果為WM_KEYDOWN,則顯示按鍵對應的文本。

將該DLL文件編譯連接。為了測試該DLL文件,新建一個MFC的Dialog工程,添加兩個按鈕,如圖1所示。

圖1  鍵盤鉤子的測試程序

分別對這兩個按鈕添加代碼,具體如下: 

  1. void CHookTestDlg::OnButton1()  
  2.  
  3.  // 在這里添加控制通知的處理程序  
  4.  SetHookOn();  
  5.  
  6. void CHookTestDlg::OnButton2()  
  7.  
  8.  // 在這里添加控制通知的處理程序  
  9.  SetHookOff();  

直接調用DLL文件導出這兩個函數,不過在使用之前要先對這兩個函數進行聲明,否則編譯器因無法找到這兩個函數的原型而導致連接失敗。定義如下: 

  1. extern "C" VOID SetHookOn();  
  2. extern "C" VOID SetHookOff(); 

進行編譯連接,提示出錯,內容如下: 

  1. Linking...  
  2. HookTestDlg.obj : error LNK2001: unresolved external symbol _SetHookOn  
  3. HookTestDlg.obj : error LNK2001: unresolved external symbol _SetHookOff  
  4. Debug/HookTest.exe : fatal error LNK1120: 2 unresolved externals  
  5. Error executing link.exe.  
  6. HookTest.exe - 3 error(s), 0 warning(s) 

從給出的提示可以看出是連接錯誤,找不到外部的符號。將DLL編譯連接后生成的DLL文件和LIB文件都復制到測試工程的目錄下,并將LIB文件添加到工程中。在代碼中添加如下語句: 

  1. #pragma comment (lib, KeyBoradHookTest) 

再次連接,成功!

運行測試程序,并單擊“HookOn”按鈕,隨便按下鍵盤上的任意一個鍵,會出現提示對話框,如圖2所示。

圖2  截獲到的鍵盤輸入

從圖2中可以看出,當按下鍵盤上的按鍵時,程序將捕獲到按鍵。到此,鍵盤鉤子的例子程序就完成了。

2. 低級鍵盤鉤子

數據防泄露軟件通常會禁止PrintScreen鍵,防止通過截屏將數據保存為圖片而導致泄密。這類軟件想要實現是比較簡單的,但是想要將功能做得強大些,還是需要下功夫的。數據防泄露的軟件除了要有兼容性好的底層驅動的設計,還要有完善的規則設置。此外就是需要軟件安全人員對其進行各種各樣的攻擊,避免數據防泄露軟件因為各種各樣的原因而被心懷惡意者突破。

這里介紹如何禁止PrintScreen鍵。其實很簡單,只要安裝低級鍵盤鉤子(WH_KEYBO ARD_LL)就可以搞定。普通的鍵盤鉤子(WH_KEYBOARD)是無法過濾一些系統按鍵的。在低級鍵盤鉤子的回調函數中,判斷是否為PrintScreen鍵,如果是,則直接返回TRUE(前面提到,如果想屏蔽某個消息的話,那么在鉤子函數中對該消息進行處理后,直接返回一個非零值),如果不是,則傳遞給鉤子鏈的下一處。

代碼如下: 

  1. extern "C" __declspec(dllexport) BOOL SetHookOn()  
  2.  
  3.   if ( g_hHook != NULL ) 
  4.   {  
  5.     return FALSE;  
  6.   }  
  7.   g_hHook = SetWindowsHookEx(WH_KEYBOARD_LL, LowLevelKeyboardProc, g_hIns, NULL);  
  8.   if ( NULL == g_hHook )  
  9.   {  
  10.     MessageBox(NULL, "安裝鉤子出錯 !", "error", MB_ICONSTOP);  
  11.     return FALSE; 
  12.   }  
  13.   return TRUE;  
  14.  
  15. extern "C" __declspec(dllexport) BOOL SetHookOff()  
  16.  
  17.   if ( g_hHook == NULL )  
  18.   {  
  19.     return FALSE;  
  20.   }  
  21.   UnhookWindowsHookEx(g_hHook);  
  22.   g_hHook = NULL 
  23.   return TRUE;  
  24.  
  25. LRESULT CALLBACK LowLevelKeyboardProc(  
  26.   int nCode, WPARAM wParam, LPARAM lParam)  
  27.  
  28.   KBDLLHOOKSTRUCT *Key_Info = (KBDLLHOOKSTRUCT*)lParam; 
  29.   if ( HC_ACTION == nCode )  
  30.   {  
  31.     if ( WM_KEYDOWN == wParam || WM_SYSKEYDOWN == wParam )  
  32.     {  
  33.       if ( Key_Info->vkCode == VK_SNAPSHOT )  
  34.       {  
  35.         return TRUE;  
  36.       }  
  37.     }  
  38.   }  
  39.   return CallNextHookEx(g_hHook, nCode, wParam, lParam);  

代碼量非常短,然而,就是這短短的代碼阻止了數據的泄露。當然,對于一個攻擊者來說,這個代碼無法保護數據,這種保護也就很脆弱了。任何的保護都有突破的辦法,攻擊無處不在,攻擊者會嘗試任何手段突破所有的保護。

3. 使用鉤子進行DLL注入

Windows提供的鉤子類型非常多,其中一種類型的鉤子非常實用,那就是WH_GETME SSAGE鉤子。它可以很方便地將DLL文件注入到所有的基于消息機制的程序中。

在有些情況下,需要DLL文件完成一些功能,但是完成功能時需要DLL在目標進程的空間中。這時,就需要使用WH_GETMESSAGE消息把DLL注入到目標的進程中。代碼非常簡單,這里直接給出DLL文件的代碼,具體如下: 

  1. #include <windows.h>  
  2. extern "C" __declspec(dllexport) VOID SetHookOn();  
  3. extern "C" __declspec(dllexport) VOID SetHookOff();  
  4. HHOOK g_HHook = NULL 
  5. HINSTANCE g_hInst = NULL 
  6. VOID DoSomeThing()  
  7.  
  8.   /*  
  9.   ……  
  10.   自己要實現功能的代碼  
  11.   ……  
  12.   */  
  13.  
  14. BOOL WINAPI DllMain(  
  15.   HINSTANCE hinstDLL, // DLL 模塊的句柄  
  16.   DWORD fdwReason, // 調用函數的原因  
  17.   LPVOID lpvReserved // 保留的  
  18.  
  19.  
  20.   switch ( fdwReason )  
  21.   {  
  22.   case DLL_PROCESS_ATTACH:  
  23.     {  
  24.       g_hInst = hinstDLL 
  25.       DoSomeThing();  
  26.       break;  
  27.     }  
  28.   }  
  29.   return TRUE;  
  30.  
  31. LRESULT CALLBACK GetMsgProc(  
  32.   int code, // 鉤子編碼  
  33.   WPARAM wParam, // 移除選項  
  34.   LPARAM lParam // 消息  
  35.  
  36.  
  37.   return CallNextHookEx(g_HHook, code, wParam, lParam);  
  38.  
  39. VOID SetHookOn()  
  40.  
  41.   g_HHook = SetWindowsHookEx(WH_GETMESSAGE, GetMsgProc, g_hInst, 0); 
  42.  
  43. VOID SetHookOff()  
  44.  
  45.   UnhookWindowsHookEx(g_HHook);  

整個代碼就是這樣。只要知道,在需要DLL大范圍地注入到基于消息的進程中時,可以使用這種方法。 

 

責任編輯:龐桂玉 來源: 計算機與網絡安全
相關推薦

2021-01-18 10:35:18

網絡安全Windows代碼

2021-03-03 12:20:42

網絡安全DLL編程

2023-06-19 08:23:28

kubernetes容器

2021-02-07 10:55:01

網絡安全文件API

2021-01-26 13:45:03

網絡安全Winsock編程

2021-03-05 13:46:56

網絡安全遠程線程

2021-05-08 11:50:59

網絡安全API函數代碼

2021-03-19 10:23:45

網絡安全內核文件

2021-04-14 15:53:58

網絡安全C語言wcslen

2021-02-21 18:19:43

網絡安全網絡安全編程創建進程

2021-02-23 10:20:07

網絡安全進程代碼

2011-05-20 17:59:06

回調函數

2016-10-10 00:18:27

2021-04-06 11:04:54

網絡安全C語言代碼

2021-02-15 15:23:03

網絡安全注冊表API

2021-06-18 09:55:09

網絡安全目錄監控

2011-03-17 13:32:45

2021-03-01 11:20:13

網絡安全多線程代碼

2021-05-12 14:57:13

網絡安全密碼代碼

2021-06-15 11:16:24

網絡安全U盤軟件
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品一级| 丁香五月缴情综合网 | 国产视频二区 | 国产精品一区二区精品 | 国产一二三视频在线观看 | 国产电影一区二区在线观看 | 欧美激情一区二区三区 | 新疆少妇videos高潮 | 国产一二区在线 | 亚洲一区二区在线 | 国产精品久久久久久 | 一区二区三区在线播放 | 亚洲综合色站 | 欧美久久天堂 | 91色综合 | 久久久久成人精品免费播放动漫 | 亚洲国产成人在线 | 日韩欧美网 | 91视频免费黄 | 日本精品一区二区三区视频 | 九九久久这里只有精品 | 午夜影院 | 一区二区三区四区视频 | 日韩欧美精品在线 | www.亚洲一区 | 91免费看片 | 极品的亚洲 | 日本中文字幕日韩精品免费 | 91精品国产91久久久久久 | 精品一二三 | 午夜影晥 | 久久久噜噜噜久久中文字幕色伊伊 | 成人av网站在线观看 | 久久一二三区 | 欧美激情 一区 | 国产一区二区在线播放 | 久久久久久国产精品免费免费 | 免费观看一级视频 | 亚洲精品日韩在线 | 国产清纯白嫩初高生视频在线观看 | 蜜桃免费一区二区三区 |