【发布时间】:2017-02-27 06:04:06
【问题描述】:
我编写了以下两个应用程序(dll、exe)来将 dll 挂接到 putty 以监听键盘事件。
一个应用程序是包含挂钩方法 (meconnect) 的 Dll 应用程序。
#include "stdafx.h"
#include <stdio.h>
#include <windows.h>
INT APIENTRY DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
/* open file */
FILE *file;
fopen_s(&file, "C:\\temp.txt", "a+");
switch (Reason) {
case DLL_PROCESS_ATTACH:
fprintf(file, "DLL attach function called.\n");
break;
case DLL_PROCESS_DETACH:
fprintf(file, "DLL detach function called.\n");
break;
case DLL_THREAD_ATTACH:
fprintf(file, "DLL thread attach function called.\n");
break;
case DLL_THREAD_DETACH:
fprintf(file, "DLL thread detach function called.\n");
break;
}
/* close file */
fclose(file);
return TRUE;
}
extern "C" __declspec(dllexport) LRESULT __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
//FILE *file;
//fopen_s(&file, "C:\\function.txt", "a+");
//fprintf(file, "Function keyboard_hook called.\n");
//fclose(file);
OutputDebugString(L"function keyboard hook called. \n");
//return 0;
return(CallNextHookEx(NULL, code, wParam, lParam));
}
这里的meconnect 方法将在 PuTTY 应用程序上触发键盘事件时调用。
下面给出的是将上面的 dll 注入 PuTTY 应用程序的代码。
// program.exe.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <Windows.h>
#include <string>
#include <io.h>
using namespace std;
void Usage()
{
printf("Usage: InjectDLL pid path-to-dll [-privilege]");
}
int _tmain(int argc, char* argv[])
{
/*
* Load library in which we'll be hooking our functions.
*/
HMODULE dll = LoadLibrary(L"C:\\drivers\\dllinject.dll");
//HMODULE dll = LoadLibrary((LPCTSTR)buf);
if (dll == NULL) {
printf("The DLL could not be found.\n");
getchar();
return -1;
}
/*
* Get the address of the function inside the DLL.
*/
HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, "_meconnect@12");
if (addr == NULL) {
printf("The function was not found.\n");
getchar();
return -1;
}
/*
* Hook the function.
*/
DWORD procID=0;
HWND targetWnd = FindWindowA("PuTTYConfigBox","PuTTY Configuration" );
//HWND windowHandle = FindWindowA(NULL, "Calculator.exe");
DWORD threadID = GetWindowThreadProcessId(targetWnd, &procID);
wchar_t msgBuf[1024] = L"";
wchar_t msgBuf2[1024] = L"";
wsprintf(msgBuf, L"the proc Id is %d", threadID);
OutputDebugString(msgBuf);
HHOOK handle = SetWindowsHookEx(WH_KEYBOARD, addr, dll, threadID);
DWORD x = GetLastError();
wsprintf(msgBuf2, L"the last error is %d", x);
OutputDebugString(msgBuf2);
if (handle == NULL) {
printf("The KEYBOARD could not be hooked.\n");
}
else{
printf("Program successfully hooked.\nPress enter to unhook the function and stop the program.\n");
}
/*
* Unhook the function.
*/
getchar();
UnhookWindowsHookEx(handle);
return 0;
}
当我运行上述代码时,setWindowsHookEx 总是返回 null,这意味着 SetWindowsHookEx 没有挂接到 PuTTY 应用程序。谁能帮我理解我在这里做错了什么。
【问题讨论】:
-
当
SetWindowsHookEx()失败时,GetLastError()返回什么? DLL 是为 32 位还是 64 位编译的? PuTTY 是 32 位还是 64 位?您不能将 32 位 DLL 注入 64 位进程,反之亦然。即使SetWindowsHookEx()成功,meconnect()也被宣布为错误。返回值必须是LRESULT而不是int,并且必须使用__stdcall调用约定。 -
改进你的错误处理,显示 GetLastError() 返回的值。您传递的
procID值不正确,它需要是线程ID,而不是进程ID。换句话说,您需要GetWindowThreadProcessId() 的返回值。顺便说一句,总是最好使用已知良好的代码,这并不容易做到。 -
@RemyLebeau,感谢 cmets。我已经根据给出的 cmets 修改了问题中的代码。在 meconnect 更改后,它会显示
The function was not found。我将meconnect修改为具有__stdcall调用约定并将返回类型更改为LRESULT。关于为什么找不到 meconnect 函数的任何想法 -
@HansPassant ,也感谢您的评论,我已将您的 cmets 合并到更新的代码中
-
您需要致电
GetProcAddress(dll, "_meconnect@12");获取x86和GetProcAddress(dll, "meconnect");获取 x64。如果您想要 x86 的未修饰名称形式 - 您需要通过 def 文件导出meconnect
标签: c++ winapi hook setwindowshookex