系統鉤子

  • 2019 年 10 月 4 日
  • 筆記

# 系統鉤子

曾經有一段時間特別迷戀外掛程式,因此有所了解,但僅限於皮毛,由於缺乏的知識太多就放棄了,最近有個私活需要用到鉤子,所以重行來研究一番,其實也談不上研究,我是一個C#程式設計師,本來就沒有多少系統的知識(並不是每個C#程式設計師都是這樣),使用win32 api對我來說還是有些困難的,所以不能給出多麼高深的講解,這裡僅限於我是如何使用C#調用win32 api來實現系統鉤子的。

什麼是鉤子

我不覺得自己能說清楚什麼是鉤子,所以我推薦大家看一些 鉤子簡介

項目需求:

實現一個程式來禁用所有滑鼠按鍵,禁用任務管理器,禁用註冊表等。

涉及Win32 API

  1. SetWindowsHookEx (參考 )
  2. UnhookWindowsHookEx (參考 )

程式碼實現

  1. 要使用鉤子首先我們得有一個鉤子 我的鉤子程式碼 //定義個委託類型,因為設置鉤子的時候需要這種類型的委託實現 private delegate int HookProc(int nCode,IntPtr wparam,ref IntPtr lparam); //實現HookProc委託簽名的方法 private static int HookProcCallback(int nCode, IntPtr wparam, ref IntPtr lparam) { //這裡可以進行消息的過濾,返回0時所有的消息都不會進入下一個鉤子 return 0; }
  2. 設置鉤子到系統的鉤子鏈中 SetWindowsHookEx的定義的參數:
    1. 鉤子的類型,即它處理的消息類型(比如:鍵盤鉤子,滑鼠鉤子,Shell鉤子等)
    2. 鉤子回調函數,即接收的消息由誰處理
    3. 需要鉤子攔截的程式句柄,0/null為當前進程/模組,
    4. 是否為全局鉤子,如果為0則與所有執行緒關聯,即全局鉤子;否則,這個執行緒一定屬性上一個參數對應的進程/模組

    設置鉤子程式碼 //定義一個鉤子實例 var hookProc = new HookProc(HookProcCallback); //設置鉤子 hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, proc, null, 0); if(hkeyboardHook!=IntPtr.Zero){ //設置成功 }

# 完整程式碼

public class Hook  {      // 設置鉤子      [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]      public static extern IntPtr SetWindowsHookEx(int idHook, HookHandlerDelegate lpfn, IntPtr hmod, uint dwThreadID);        // 卸載鉤子      [DllImport("user32.dll")]      public static extern bool UnhookWindowsHookEx(IntPtr idHook);        // 獲取模組句柄      [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]      public static extern IntPtr GetModuleHandle(String modulename);      public const int WM_KEYDOWN = 0x0100;      public const int WH_KEYBOARD_LL = 13;      public const int WM_SYSKEYDOWN = 0x0104;      public struct KBDLLHOOKSTRUCT      {          public int vkCode;          public int scanCode;          public int flags;          public int time;          public int dwExtraInfo;      }      public delegate int HookHandlerDelegate(int nCode, IntPtr wparam, ref KBDLLHOOKSTRUCT lparam);      //鉤子回掉委託實例      private static HookHandlerDelegate proc;      //鉤子句柄      private static IntPtr hKeyboardHook;        private static int HookCallback(int nCode, IntPtr wparam, ref KBDLLHOOKSTRUCT lparam)      {          if (              nCode >= 0              &&              (wparam == (IntPtr)WM_KEYDOWN              ||              wparam == (IntPtr)WM_SYSKEYDOWN)              )          {              if (lparam.vkCode == 91 || lparam.vkCode == 164 || lparam.vkCode == 9 || lparam.vkCode == 115)              {                  return 1;              }              else              {                  return 0;              }          }          return 0;      }        public static void HookStart()      {          if (hKeyboardHook == IntPtr.Zero)          {              // 創建HookProc實例              proc = new HookHandlerDelegate(HookCallback);              using (Process curPro = Process.GetCurrentProcess())              using (ProcessModule curMod = curPro.MainModule)              {                  //定義全局鉤子                  hKeyboardHook = SetWindowsHookEx(WH_KEYBOARD_LL, proc,GetModuleHandle(curMod.FileName), 0);              }                if (hKeyboardHook == IntPtr.Zero)              {                  HookStop();                  throw new Exception("鉤子設置失敗");              }          }        }        public static void HookStop()      {          bool retKeyboard = true;          if (hKeyboardHook != IntPtr.Zero)          {              retKeyboard = UnhookWindowsHookEx(hKeyboardHook);              hKeyboardHook = IntPtr.Zero;          }          if (!(retKeyboard)) throw new Exception("卸載鉤子失敗");        }  }

Tags: