首页 文章

简单的挂钩程序

提问于
浏览
2

我正在尝试创建一个简单的globalhook,只要有人按下键盘上的某个键,就会将一些文本打印到.txt文件中 . 问题是当我执行我的程序并按某个程序中的某个键时,程序会卡住并且不再响应 . 所以我认为问题是hookprocedure在调用时不能正常工作/返回 .

这是我的.exe文件中的代码:

#include <Windows.h>
#include <iostream>
#include <fstream>
#include <stdio.h>
#include <stdlib.h>
#include <wingdi.h>
#include <string>

using namespace std;

typedef bool (*install)();
install instal;
HINSTANCE hinst;

int main()
{
hinst = LoadLibrary(TEXT("injectdll.dll"));
if(!hinst)
{
printf("The DLL could not be found.\n");
}

instal = (install) GetProcAddress(hinst, "install");
if(!instal) 
{
    printf("The function was not found.\n");
}

if(!instal())
{
    printf("func couldn't be executed");
}

printf("Program successfully hooked.\nPress enter to unhook the function and stop the program.\n");
getchar();
}

这是我的DLL中的代码:

#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <Strsafe.h>

using namespace std;

#pragma data_seg(".shared")
HHOOK hook = 0;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")

HINSTANCE hinst;

LRESULT CALLBACK meconnect(int code, WPARAM wParam, LPARAM lParam) 
{
if (code < 0) 
{
    return CallNextHookEx(hook, code, wParam, lParam);
}
FILE *file;
fopen_s(&file, "function.txt", "a+");
fprintf(file, "Function keyboard_hook called.\n");
fclose(file);

return 0;
}

extern "C" __declspec(dllexport) bool install() 
{ 
hook = SetWindowsHookEx(WH_KEYBOARD, (HOOKPROC) meconnect, hinst, 0);
return hook != NULL;
}

BOOL WINAPI DllMain(HINSTANCE hDLL, DWORD Reason, LPVOID Reserved) {

switch(Reason) {
case DLL_PROCESS_ATTACH:
            hinst = hDLL;
    break;
case DLL_PROCESS_DETACH:
    break;
case DLL_THREAD_ATTACH:
    break;
case DLL_THREAD_DETACH:
    break;
}

return TRUE;
}

meconnect函数返回0,我不知道这是否正确,但我也试过返回:return CallNextHookEx(hook,code,wParam,lParam);并返回CallNextHookEx(0,代码,wParam,lParam);

两者都没有改变结果 .

1 回答

  • 0

    install 函数在主exe的上下文中运行 . 让它在成功时返回 HHOOK 句柄 . 终止exe时,需要该句柄来调用UnhookWindowsHookEx函数 .

    或者,您可以将 HHOOK 存储在DLL中的常规全局变量中,并实现导出的 uninstall 函数,该函数将调用 UnhookWindowsHookEx .

    无论如何,删除共享部分,这没有任何意义,只能带来问题 .

    请注意CallNextHookEx documentation包含:

    Parameters
       hhk [in, optional]
          Type: HHOOK
          This parameter is ignored.
    

    调用 CallNextHookEx 时将NULL作为参数1传递

    始终在Hook过程中返回 CallNextHookEx 的返回值 .

    做:

    LRESULT CALLBACK meconnect(int code, WPARAM wParam, LPARAM lParam) {
        if (code >= 0) {
            FILE *file = 0;
            fopen_s(&file, "function.txt", "a+");
            if ( file ) {
                fprintf(file, "Function keyboard_hook called.\n");
                fclose(file);
            }
        }
        return CallNextHookEx( NULL, code, wParam, lParam);
    }
    

    DLL在具有键盘活动的进程中加载 . 然后在“当前目录”中打开文本文件 . 由于访问权限原因,它可能会失败,并且您不希望文本文件在任何地方喷出:使用文本文件的有效完整路径 .

    最后, most important part ,如果调用 SetWindowsHookEx 的线程没有轮询消息队列,事情会变得怪异(如你所注意到的) . 做正确事情的简单方法就是调用MessageBox .

    getchar 呼叫替换为:

    MessageBox(NULL, "Ok to leave", "Hooking Keyboard", MB_OK);
    

    您的DLL将仅在具有相同位数(32b或64b)的进程中加载 . 如果您的DLL是32位,则通过调用Hook过程报告64位的键盘活动,即32位EXE的 in the context . 这就是您必须提供轮询消息队列的原因(它使回调调用成为可能) .

    编辑:WH_KEYBOARD允许全局和多位数挂钩 .

相关问题