c++ - 在 c++ 的 SetWindowsHookEx 函数中
问题描述
我是韩国学生。现在这是我注册后的第一个问题。
DWORD getProcessId() {
PROCESSENTRY32 process_infor;
process_infor.dwSize = sizeof(PROCESSENTRY32);
HANDLE snap_handle = CreateToolhelp32Snapshot(
TH32CS_SNAPALL, //스냅 단계
NULL //스냅할 pid
);
if (snap_handle != INVALID_HANDLE_VALUE) {
Process32First(snap_handle, &process_infor);
do {
wchar_t* temp = process_infor.szExeFile;
wstring ws(temp);
string name(ws.begin(), ws.end());
if (name == "notepad.exe") {
cout << name << " : " << process_infor.th32ProcessID << endl;
return process_infor.th32ProcessID;
}
} while (Process32Next(snap_handle, &process_infor));
}
CloseHandle(snap_handle);
return FALSE;
}
BOOL inject() {
HMODULE dll_handle;
HOOKPROC func;
HHOOK process_hook;
dll_handle = LoadLibrary(L"hello.dll");
func = (HOOKPROC) GetProcAddress(dll_handle, "injectSuccess");
cout << "handle : " << dll_handle << endl;
cout << "pid : " << getProcessId() << endl;
process_hook = SetWindowsHookEx(
WH_KEYBOARD,
func,
dll_handle,
getProcessId()
);
cout << "pook : " << process_hook << endl;
cout << "err : " << GetLastError() << endl;
FreeLibrary(dll_handle);
return FALSE;
}
SetWindowsHookEx
在这种情况下,注入功能似乎存在问题。dll文件加载好,injectSuccess
里面的函数也好抓取。(我试过运行它,但它起作用了)而且我想知道是否输入了错误的参数值SetWindowsHookEx
,所以我比较并不断检查它们,但我没有发现任何差异。所以,我尝试GetLastError()
了SetWindowsHookEx
下面的返回值,但返回值为0,错误代码为87(“参数不正确”)。
所以我搜索了,但我英语说得不好,而且我是初学者,所以我不确定。
解决方案
dwThreadId
包含 lpfn 参数指向的钩子过程的 DLL 句柄。如果 dwThreadId 参数指定由当前进程创建的线程并且挂钩过程在与当前进程关联的代码内,则 hMod 参数必须设置为 NULL。
所以SetWindowsHookExW
需要的是线程ID,而你传入notepad.exe的进程ID,所以参数错误。
我创建一个示例并测试以下代码:
BOOL inject() {
HMODULE dll_handle;
HOOKPROC func;
HHOOK process_hook;
dll_handle = LoadLibrary(L"hello.dll");
if (dll_handle) func = (HOOKPROC)GetProcAddress(dll_handle, "injectSuccess");
else return FALSE;
cout << "handle : " << dll_handle << endl;
cout << "pid : " << getProcessId() << endl;
HWND h = FindWindow(L"notepad", NULL);
DWORD pid;
threadID = GetWindowThreadProcessId(h, NULL);
cout << "threadID = " << threadID << endl;
process_hook = SetWindowsHookEx(
WH_KEYBOARD,
func,
dll_handle,
threadID
);
cout << "pook : " << process_hook << endl;
cout << "err : " << GetLastError() << endl;
if(dll_handle) FreeLibrary(dll_handle);
return FALSE;
}
这个例子对我有用,你可以看到 pid 和 threadID 之间的区别:
编辑
根据文件:
应用程序通过在调用 SetWindowsHookEx 函数时指定 WH_KEYBOARD 挂钩类型和指向挂钩过程的指针来安装挂钩过程。这个钩子可以在安装它的线程的上下文中被调用。通过向安装钩子的线程发送消息来进行调用。因此,安装钩子的线程必须有一个消息循环。所以如果你想运行这个函数,你需要添加一个消息循环。
您可以参考以下代码:
int main()
{
inject();
MSG msg;
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
当您按下按钮时,将弹出消息框:
因为每次按键按下和释放都有两条消息,所以func每次触发两次。如果只想在每次按下按钮时触发,可以修改如下代码:
if ((0x80000000 & lParam) == 0)//This means that when the key is pressed
{
MessageBox(NULL, L"Success (dll injection)", L"Window", MB_OK);
}
您可以参考KeyboardProc来查看 lParam 中每个值的消息。
推荐阅读
- excel - excel vba检查范围内的任何单元格是否为空
- python - 按年份分组并将函数应用于另一列 - Python,Pandas
- stm32 - STM32L0xx:获取时钟速度
- c - Why console cannot catch mouse event after using function system()?
- node.js - 如何让聊天机器人(机器人框架)将附件从任何文件夹发送给用户(NodeJS)?
- android - AOSP WifiSettings 接入点列表未更新
- python - 使用 numpy 创建具有嵌套循环的多个矩阵
- javascript - 角度将数据传递给子组件
- java - 如何从意图菜单创建实例方法而不是静态方法
- javascript - Google Maps API - 如何使标记和地图居中