C++ 在c++';s SetWindowsHookEx函数

C++ 在c++';s SetWindowsHookEx函数,c++,winapi,C++,Winapi,我是韩国学生。 这是我报名后的第一个问题 DWORD getProcessId() { PROCESSENTRY32 process_infor; process_infor.dwSize = sizeof(PROCESSENTRY32); HANDLE snap_handle = CreateToolhelp32Snapshot( TH32CS_SNAPALL, //스냅 단계 NULL //스냅할 pid ); if

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

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;
}
DWORD getProcessId(){
PROCESSENTRY32过程信息;
process_infor.dwSize=sizeof(PROCESSENTRY32);
HANDLE snap\u HANDLE=CreateToolhelp32Snapshot(
TH32CS_SNAPALL//스냅 단계
空的//스냅할 pid
);
if(捕捉句柄!=无效的句柄值){
Process32First(捕捉句柄和进程信息);
做{
wchar_t*temp=process_infor.szExeFile;
wstring-ws(温度);
字符串名称(ws.begin(),ws.end());
如果(名称==“notepad.exe”){
cout根据以下结果:

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;
}
int main()
{
    inject();
    MSG msg;
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }
}
if ((0x80000000 & lParam) == 0)//This means that when the key is pressed
{
    MessageBox(NULL, L"Success (dll injection)", L"Window", MB_OK);
}
按下按钮时,将弹出消息框:

因为每次按键和释放都有两条消息,func每次触发两次。如果您只想在每次按下按钮时触发,可以修改以下代码:

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;
}
int main()
{
    inject();
    MSG msg;
    while (GetMessageW(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessageW(&msg);
    }
}
if ((0x80000000 & lParam) == 0)//This means that when the key is pressed
{
    MessageBox(NULL, L"Success (dll injection)", L"Window", MB_OK);
}

您可以参考以查看LPRAM中每个值的消息。

欢迎使用堆栈溢出;我建议检查
GetProcAddress
的结果,以确保您确实找到了函数:如果它为NULL怎么办?此外,建议您在调用
SetWindowHookEx
后立即捕获最后一个错误号,因为t调用-可能执行I/O-可能会覆盖上一个错误并混淆报告。在设置窗口挂钩后立即执行
const DWORD err=GetLastError()
会捕获此错误。为
getProcessId
发布的代码没有进程名称(“notepad.exe”),但我认为这是粘贴示例时的一个输入错误。我建议您检查是否确实找到了一个有效的线程ID,并检查它:只有在得到非零响应时才调用
SetWindowsHookEx
。哦,我认为是“notepad.exe”是getProcessId中的一个输入错误。使用真实代码编写得很好。请编辑示例代码,使其能够编译;很明显,
getProcessId
希望获得字符串参数(
process\u name
)。然后我们可以更仔细地查看它。抱歉;;它已更改。GetProcAddress函数似乎工作正常。当我手动运行线程_func()时像这样的功能,消息框通常会出现在窗口中。嗯!非常感谢。这工作正常,现在我没有收到任何错误。但它运行正常,没有错误,但dll没有运行。为什么会这样?当使用名为Process Explorer的应用程序搜索时,dll不在记事本中。原因可能是Process Explorer无法运行检测链接的dll。您可以参考。如果此原始答案确实对您有帮助,请随时标记它以帮助有相同问题的人,并让我知道您是否有任何问题。谢谢。因此…Process Explore无法检测dll文件?没有其他问题,没有错误,并且似乎工作正常,但结果似乎无法运行.那么….在将dll插入记事本后,无法运行它?只要通过loadlibrary函数在main中加载dll,上述修改就会运行。非常感谢。感谢您,几乎所有操作都已成功^^^。但是,在上面的视频和我的代码中,我遇到了一个问题,即窗口出现两次,并且没有其他ac执行injectSuccess函数的输入或输出。我如何解决此问题?完成后,我接受您的帖子并结束此问题!