您的位置:

c#键盘钩子详解

一、hook的概念及c#中的实现

1、hook在操作系统中是一个用于拦截系统消息和通知的机制。使用c#实现hook的方式有多种,其中最为常用的就是使用Windows API中的SetWindowsHookEx函数。

//声明SetWindowsHookEx函数  
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]  

//设置钩子  
private static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);

//取消钩子  
private static extern bool UnhookWindowsHookEx(int idHook);  

//调用下一个钩子   
private static extern int CallNextHookEx(int idHook, int nCode, IntPtr wParam, IntPtr lParam);

//定义委托  
private delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);

//钩子指针  
private int hHook;

//钩子处理函数  
private int HookCallback(int nCode, IntPtr wParam, IntPtr lParam){  
   if (nCode >= 0){  
      Keys key = (Keys)wParam;  
      MessageBox.Show(key.ToString());  
   }  
   return CallNextHookEx(hHook, nCode, wParam, lParam);  
}

//启动钩子  
hHook = SetWindowsHookEx(WH_KEYBOARD_LL, new HookProc(HookCallback), Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);

2、上面代码中的WH_KEYBOARD_LL表示keyboard hook,而其中的GetHINSTANCE函数和GetExecutingAssembly函数获取程序集中第一个模块的HINSTANCE以及程序集信息的方法,则是用于在钩子被取消时卸载钩子。

二、hook的使用范例

1、Hook可以被用于很多地方,以下实例是在邮箱登录界面中使用hook拦截用户密码等敏感信息:

//邮箱登录窗口类  
public partial class LoginForm : Form{  
    private int hHook;//钩子句柄  
    private static HookProc HookCallback;//钩子处理函数  
    private const int WH_CALLWNDPROC = 4;//Hook类型  
    private const int WM_KEYDOWN = 0x100;  
    private const int WM_KEYUP = 0x101;  
    private const int WM_SYSKEYDOWN = 0x104;  
    private const int WM_SYSKEYUP = 0x105;  
    public LoginForm(){  
        InitializeComponent();  
    }  
    private void LoginForm_Load(object sender, EventArgs e){  
        //启动钩子  
        HookCallback = new HookProc(FormHookProc);  
        hHook = SetWindowsHookEx(WH_CALLWNDPROC, HookCallback, Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]), 0);  
    }  
    private void LoginForm_FormClosing(object sender, FormClosingEventArgs e){  
        //取消钩子  
        UnhookWindowsHookEx(hHook);  
    }  
    private int FormHookProc(int nCode, IntPtr wParam, IntPtr lParam){  
        if (nCode >= 0){  
            CallWndStruct cws = (CallWndStruct)Marshal.PtrToStructure(lParam, typeof(CallWndStruct));//获取消息结构体  
            Message? m = cws.message;//获取消息  
            if (m != null && (m.Value.Msg == WM_KEYDOWN || m.Value.Msg == WM_KEYUP || m.Value.Msg == WM_SYSKEYDOWN || m.Value.Msg == WM_SYSKEYUP)){  
                //获取按键值名称  
                string kstr = ((Keys)((int)m.Value.WParam)).ToString();  
                if ((kstr == "Enter" || kstr == "Return") && m.Value.Msg == WM_KEYDOWN){//如果是回车键,且是按下状态,则获取密码文本框中内容  
                    string pwd = this.password.Text.Trim();  
                    MessageBox.Show(pwd);//输出密码  
                }  
            }  
        }  
        return CallNextHookEx(hHook, nCode, wParam, lParam);  
    }  
}  

三、hook的危险性 & 安全建议

1、由于hook具有拦截系统消息和通知的机制,因此如果恶意程序使用hook,便可以窃取用户的输入信息,具有非常大的危险性。

2、使用hook需要谨慎,一般只用于开发调试、性能分析和系统管理等方面,而在用户场合则应禁止匿名用户使用hook,同时,不要随意安装任何第三方软件,以免被植入hook,造成个人信息泄露和安全问题。

四、小结

1、本文详细介绍了hook的概念和使用方式,以及hook的安全建议,通过对hook的了解和使用,可以更好地开发c#程序,同时了解如何防止hook被恶意程序利用。

2、在使用hook的过程中应该遵循安全建议,以防信息泄露造成不必要的损失。