首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++的SetWindowsHookEx函数

C++的SetWindowsHookEx函数
EN

Stack Overflow用户
提问于 2020-10-23 01:49:39
回答 1查看 330关注 0票数 3

我是韩国学生。这是我报名后的第一个问题。

代码语言:javascript
复制
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 (“参数不正确”)。

所以我搜索了一下,但是我英语说得不好,而且我是个初学者,所以我不确定。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-10-23 03:45:31

根据SetWindowsHookExW

dwThreadId 包含lpfn参数所指向的钩子过程的DLL句柄。如果hMod参数指定由当前进程创建的线程,并且钩子过程位于与当前进程关联的代码中,则必须将dwThreadId参数设置为NULL。

所以SetWindowsHookExW需要的是线程ID,传入notepad.exe的进程ID,所以参数是错误的。

我创建了一个示例并测试了以下代码:

代码语言:javascript
复制
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,您需要添加一个消息循环。

您可以参考以下代码:

代码语言:javascript
复制
int main()
{
    inject();
    MSG msg;
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }
}

当您按下按钮时,消息框将弹出:

由于每次按下和释放键都有两条消息,所以每次按下按钮时,每个time.If都会触发两次func,您可以修改以下代码:

代码语言:javascript
复制
if ((0x80000000 & lParam) == 0)//This means that when the key is pressed
{
    MessageBox(NULL, L"Success (dll injection)", L"Window", MB_OK);
}

您可以参考KeyboardProc来查看lParam中每个值的消息。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64492788

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档