作为初学者课程,我想将此教程http://null-byte.wonderhowto.com/how-to/create-simple-hidden-console-keylogger-c-sharp-0132757/移植到Windows窗体应用程序。 这应该向用户显示在名为'lblMessage'的标签内按下了什么键。
我现在将代码分成两部分。
Form1.cs的
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.IO;
namespace WindowsFormsApplication3
{
public partial class Form1 : Form
{
public GlobalKeyHook hook = new GlobalKeyHook();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Origin
// _hookID = SetHook(_proc);
hook._hookID = hook.SetHook(_proc);
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
// Origin
// UnhookWindowsHookEx(_hookID);
hook.UnhookWindowsEx(_hookID);
}
}
}
GlobalKeyHook.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
namespace WindowsFormsApplication3
{
class GlobalKeyHook : Form
{
#region DLLs
[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private 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)]
private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode,
IntPtr wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr GetModuleHandle(string lpModuleName);
#endregion
#region Fields and delegation
private const int WH_KEYBOARD_LL = 13;
private const int WM_KEYDOWN = 0x0100;
private static LowLevelKeyboardProc _proc = HookCallback;
public static IntPtr _hookID = IntPtr.Zero;
public delegate IntPtr LowLevelKeyboardProc(
int nCode, IntPtr wParam, IntPtr lParam);
#endregion
public GlobalKeyHook()
{
IntPtr hookID = _hookID;
LowLevelKeyboardProc proc = _proc;
}
static Form form = new Form();
#region Methods
private static IntPtr HookCallback(
int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
Console.WriteLine((Keys)vkCode);
form.Text = vkCode.ToString();
}
return CallNextHookEx(_hookID, nCode, wParam, lParam);
}
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);
}
}
#endregion
}
}
但我无法在Form1类中使用public static IntPtr _hookID
,方法SetHook()
或DLL UnhookWindowsHookEx
。是不是可以从另一个类使用这个“类型”?
答案 0 :(得分:2)
您需要将GlobalKeyHook类设置为public class GlobalKeyHook
。
答案 1 :(得分:2)
不确定这会解决您的所有问题,但可以帮助您避免其中一些问题。
如果这是.net 4.0或更高版本,则SetWindowsHookEX()
调用可能会返回0(失败),因为.net不再模拟托管dll的本机模块。要解决此问题,您可以为LoadLibrary()
添加DllImport,如下所示:
[DllImport("kernel32", SetLastError = true, CharSet = CharSet.Ansi)]
public static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)]string lpFileName);
然后在致电SetWindowsHookEX()
之前的某个地方执行此操作:
IntPtr hinstDLL = UnsafeMethods.LoadLibrary("user32.dll");
并按照以下方式致电SetWindowsHookEX()
:
SetWindowsHookEx(WH_KEYBOARD_LL, proc,
hinstDLL, 0);
基本上SetWindowsHookEX()
需要一个有效的模块句柄,它会验证但从不实际使用它。加载user32
的原因是,因为你正在从中调用函数,所以你可以使用它。
此外,在您的构造函数中,只需将其设置为IntPtr.Zero。如果您始终将其设置为IntPtr.Zero,则无需进行_hookID
。同样值得注意的是,如果运行此计算机的计算机使用IntPtr,则不到win7sp1.Zero将无效(至少99%肯定。)
我强烈建议你查看This set of hooks他们有一个很好的钩子库实现,你可以随意扩展它。