远程线程钩子要放在一个DLL里,DLL里的结构一般就是 安装钩子函数,卸载钩子函数,和回调函数
下面是DLL文件的代码,就正常创建类库就行了
就这种,别选 什么标准库,.net core之类的类库,创建类库的时候可以添加一个WinForm窗体程序,按下某键的时候呼出
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace DLL
{
public class Class1
{
#region 常数和结构
public const int WH_KEYBOARD = 2;
public const int VK_F8 = 119;
#endregion
#region Api
//安装钩子的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int SetWindowsHookEx(int idHook, HookProc lpfn, IntPtr hInstance, int threadId);
//卸下钩子的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern bool UnhookWindowsHookEx(int idHook);
//下一个钩挂的函数
[DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern int CallNextHookEx(int idHook, int nCode, Int32 wParam, IntPtr lParam);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr GetModuleHandle(string lpModuleName);
//查找窗口句柄
[DllImport("User32.dll", EntryPoint = "FindWindow")]
private static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
//根据窗口句柄获取到进程和线程的ID
[System.Runtime.InteropServices.DllImportAttribute("user32.dll", EntryPoint = "GetWindowThreadProcessId")]
public static extern int GetWindowThreadProcessId(IntPtr hWnd, ref int lpdwProcessId);
[System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = "GetLastError")]
public static extern uint GetLastError();
[System.Runtime.InteropServices.DllImportAttribute("kernel32.dll", EntryPoint = "LoadLibraryA")]
public static extern System.IntPtr LoadLibraryA( string lpLibFileName);
#endregion
//回调函数委托
public delegate int HookProc(int nCode, Int32 wParam, IntPtr lParam);
int hHook;
public bool InstallHook()
{
IntPtr hwnd = FindWindow(null, "代码注入器");
int pid = 0;
if ((int)hwnd == 0)
{
MessageBox.Show("未打开游戏");
return false;
}
int tid = GetWindowThreadProcessId(hwnd, ref pid);
HookProc proc = HookCallProc;
//屏蔽这几种方法获取到的hInstance都是假的
//IntPtr hMoudle = GetModuleHandle(null);
//Module module = Assembly.GetExecutingAssembly().GetModule("Dll.dll");
//IntPtr hinstance = Marshal.GetHINSTANCE(module);
IntPtr hInstance = LoadLibraryA("DLL.dll");
hHook = SetWindowsHookEx(WH_KEYBOARD, proc, hInstance, tid);
if (hHook == 0)
{
MessageBox.Show("钩子安装失败!!!");
return false;
}
return true;
}
public bool UnInstallHook()
{
return UnhookWindowsHookEx(hHook);
}
//dll必须生成Release版 Debug版调用回调函数会导致目标崩溃
Form1 form1;
public int HookCallProc(int nCode, Int32 wParam, IntPtr lParam)
{
Console.WriteLine(lParam.ToString("x"));
//IntPtr 根据平台 动态生成是64位还是32位的,因为这是64位系统,如果强转成int会报一个溢出异常
Console.WriteLine((Int64)lParam >> 31);
//wParam是虚拟键码 ,lParam的第32位是表示按键是按下或者弹开,0表示按下
if (wParam == VK_F8 && ((Int64)lParam >> 31) == 0)
{
if (form1 == null)
{
form1 = new Form1();
form1.Show();
}
}
return CallNextHookEx(hHook,nCode,wParam,lParam);
}
}
}
下面 在创建一个WinForm程安装钩子,这个程序 要引用上面这个DLL,并且把dll文件放在程序目录下,如果在一个解决方案里,引用了dll,他会自动复制过去。下面是代码
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
namespace KeyboardHook
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
DLL.Class1 c = new DLL.Class1();
private void button1_Click(object sender, EventArgs e)
{
if (c.InstallHook())
{
MessageBox.Show("钩子安装成功");
}
}
private void button2_Click(object sender, EventArgs e)
{
if (c.UnInstallHook())
{
MessageBox.Show("钩子卸载成功");
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
c.UnInstallHook();
}
}
}