KItis KItis -4 years ago 207
C++ Question

SetWindowsHookEx returns null when hooking to specific thread

I have written following two applications (dll,exe) to hook a dll into putty in order to listen to keyboard events.

One application is Dll application which contains the hook method (

meconnect
).

#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));
}


here
meconnect
method will be called when the keyboard event is fired on PuTTY application.

Given below is the code that will inject above dll into PuTTY application.

// 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;
}


when I run the above code, setWindowsHookEx always return null, which means SetWindowsHookEx is not hooked into PuTTY application. Could anybody help me to understand what I am doing wrong here.

Answer Source

you need declare function in dll in next way:

extern "C" LRESULT  __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
//...
}

#ifdef _X86_
#define EXP_meconnect "_meconnect@12"
#elif defined(_AMD64_)
#define EXP_meconnect "meconnect"
#else
#error "unknown platform"
#endif

__pragma(comment(linker, "/export:meconnect=" EXP_meconnect))

for always export it by name "meconnect". another way - use def file


or if you declare it as

extern "C" __declspec(dllexport) LRESULT  __stdcall meconnect(int code, WPARAM wParam, LPARAM lParam) {
//...
}

in dll, you need in exe next code:

#ifdef _X86_
#define EXP_meconnect "_meconnect@12"
#elif defined(_AMD64_)
#define EXP_meconnect "meconnect"
#else
#error "unknown platform"
#endif

HOOKPROC addr = (HOOKPROC)GetProcAddress(dll, EXP_meconnect );
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download