C++ 简易挂钩程序

C++ 简易挂钩程序,c++,dll,hook,code-injection,C++,Dll,Hook,Code Injection,我正在尝试制作一个简单的globalhook,每当有人按下键盘上的键时,它就会将一些文本打印到一个.txt文件中。问题是,当我执行程序并按下某个程序中的某个键时,程序会卡住,不再响应。所以我认为问题在于hookprocedure在调用时不能正常工作/返回 这是my.exe文件中的代码: #include <Windows.h> #include <iostream> #include <fstream> #include <stdio.h> #in

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

这是my.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();
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
类型定义布尔(*安装)();
安装instal;
HINSTANCE hinst;
int main()
{
hinst=LoadLibrary(文本(“injectdll.dll”);
如果(!hinst)
{
printf(“找不到DLL。\n”);
}
instal=(安装)GetProcAddress(hinst,“安装”);
如果(!instal)
{
printf(“未找到函数。\n”);
}
如果(!instal())
{
printf(“无法执行func”);
}
printf(“程序已成功挂接。\n按enter键取消挂接函数并停止程序。\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;
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
#pragma数据段(“共享”)
HHOOK-hook=0;
#pragma data_seg()
#pragma注释(链接器,“/节:。共享,RWS”)
HINSTANCE hinst;
LRESULT回调meconnect(int代码、WPARAM WPARAM、LPARAM LPARAM)
{
如果(代码<0)
{
返回CallNextHookEx(hook、code、wParam、lParam);
}
文件*文件;
fopen_s(&file,“function.txt”,“a+”);
fprintf(文件,“函数键盘\u钩子被调用。\n”);
fclose(文件);
返回0;
}
外部“C”uu declspec(dllexport)bool install()
{ 
hook=SetWindowsHookEx(WH_键盘,(HOOKPROC)meconnect,hinst,0);
返回钩子!=NULL;
}
布尔WINAPI DllMain(HINSTANCE hDLL、DWORD REASURE、LPVOID保留){
切换(原因){
案例DLL\u进程\u附加:
hinst=hDLL;
打破
案例DLL\u进程\u分离:
打破
案例DLL\u线程\u连接:
打破
案例DLL\u线程\u分离:
打破
}
返回TRUE;
}
meconnect函数返回0,我不知道这是否正确,但我也尝试返回: 返回CallNextHookEx(hook、code、wParam、lParam); 和 返回CallNextHookEx(0,代码,wParam,lParam)


两者都没有改变结果中的任何内容。

安装
函数在主exe的上下文中运行。使其在成功时返回
HHOOK
句柄。当终止exe时,您需要该句柄来调用函数

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

无论如何,删除共享部分,它没有任何用途,只会带来问题

请注意,文件包含:

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

在钩子过程中始终返回
CallNextHookEx
的返回值

做:

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

最后,最重要的部分,如果调用
SetWindowsHookEx
的线程没有轮询消息队列,事情会变得很奇怪(正如您所注意到的)。做正确事情的简单方法就是调用MessageBox

将您的
getchar
调用替换为:

MessageBox(NULL, "Ok to leave", "Hooking Keyboard", MB_OK);
您的DLL将仅在具有相同位(32b或64b)的进程中加载。如果DLL为32位,则通过调用32位EXE上下文中的钩子过程来报告64位进程中的键盘活动。这就是您必须提供轮询消息队列的原因(它使回调调用成为可能)


编辑:WH_键盘允许全局和多比特挂钩。

非常感谢!它现在工作得很好,确实是getchar()导致了冻结。manuell,一般来说,迂回可以正常工作,但在某些程序上,我会收到一个标题为Werfault.exe的消息框,其标题为“Application error:“[hexadecimal]处的指令引用了[other hexadecimal]处的内存。内存无法读取”。你知道这个错误的根源是什么吗?我如何解决它;构建Dll的调试版本。在启动工具之前,连接到有故障的过程。打开你的工具。您可以看到调用堆栈以及崩溃的来源。
MessageBox(NULL, "Ok to leave", "Hooking Keyboard", MB_OK);