我是韩国学生。这是我报名后的第一个问题。
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 (“参数不正确”)。
所以我搜索了一下,但是我英语说得不好,而且我是个初学者,所以我不确定。
发布于 2020-10-23 03:45:31
dwThreadId 包含lpfn参数所指向的钩子过程的DLL句柄。如果hMod参数指定由当前进程创建的线程,并且钩子过程位于与当前进程关联的代码中,则必须将dwThreadId参数设置为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之间的区别:

编辑
根据文档
应用程序通过在调用WH_KEYBOARD函数中指定钩子类型和指向钩子过程的指针来安装钩子过程。这个钩子可以在安装它的线程的上下文中调用。调用是通过向安装钩子的线程发送消息进行的。因此,安装钩子的线程必须有一个消息循环。因此,如果您想要运行这个func,您需要添加一个消息循环。
您可以参考以下代码:
int main()
{
inject();
MSG msg;
while (GetMessageW(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}当您按下按钮时,消息框将弹出:

由于每次按下和释放键都有两条消息,所以每次按下按钮时,每个time.If都会触发两次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中每个值的消息。
https://stackoverflow.com/questions/64492788
复制相似问题