关于C# 创建远程线程钩子,实现在目标程序按某键,创建出一个窗口

本文介绍了如何使用C#创建一个远程线程钩子,该钩子驻留在DLL中,包含安装、卸载钩子和回调函数。当目标程序触发特定按键时,DLL会触发一个WinForm窗口的显示。创建DLL时应避免选择.NET Core等标准库,而是在WinForm应用程序中安装钩子,确保DLL与程序在同一目录下。
摘要由CSDN通过智能技术生成

远程线程钩子要放在一个DLL里,DLL里的结构一般就是 安装钩子函数,卸载钩子函数,和回调函数

下面是DLL文件的代码,就正常创建类库就行了b50fbfc8a311344a6446f2181bc036c7.png

 就这种,别选 什么标准库,.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();
        }
    }
}

 

 

 

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值