一、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的过程中应该遵循安全建议,以防信息泄露造成不必要的损失。