WH_JOURNALRECORD Hook Blocks Mouse Clicks + Keystrokes

Jason Bassos 1 Reputation point
2020-11-18T22:19:51.987+00:00

I am attempting to install a WH_JOURNALRECORD with SetWindowsHookEx:

#include <iostream>
#include <Windows.h>

LRESULT CALLBACK WndProc(int nCode, WPARAM wParam, LPARAM lParam)
{
 std::cout << "Hook called" << std::endl;
 return CallNextHookEx(NULL, nCode, wParam, lParam);
}

int main()
{
 HHOOK hook = SetWindowsHookEx(WH_JOURNALRECORD, WndProc, 0, 0);
 if (hook != NULL)
 {
 std::cout << "Hooked WH_JOURNALRECORD" << std::endl;
 }
 else
 {
 DWORD dw = GetLastError();
 std::cout << "Failed to install hook:" << "(Error: " << dw << ")" << std::endl;
 }

 MSG msg;
 while (GetMessage(&msg, NULL, 0, 0) > 0)
 {
 TranslateMessage(&msg);
 DispatchMessage(&msg);
 }
}

My application is signed with a certificate and ran under C:\Program Files as Administrator, as is required for JournalRecord hooks (/uiAccess=true). The application launches and the hook is installed successfully, however I never receive any output from my WndProc function. I can move my cursor, however I cannot click or type anything until I press ctrl+alt+del or another key combo that forces Windows to uninstall the JournalRecord hook.

According to the documentation, this type of hook is a global hook and can run within the same application context (ie, no DLL is required as is the case for other types of hooks). Despite being a console application, I have added a message loop so I don't believe that is the issue.

If anyone knows what I am doing wrong, or how I can solve this issue, any help is appreciated.

Windows API - Win32
Windows API - Win32
A core set of Windows application programming interfaces (APIs) for desktop and server applications. Previously known as Win32 API.
2,428 questions
C++
C++
A high-level, general-purpose programming language, created as an extension of the C programming language, that has object-oriented, generic, and functional features in addition to facilities for low-level memory manipulation.
3,542 questions
0 comments No comments
{count} votes

1 answer

Sort by: Most helpful
  1. Rita Han - MSFT 2,161 Reputation points
    2020-11-19T03:44:38.987+00:00

    Hello @Jason Bassos ,

    The application launches and the hook is installed successfully, however I never receive any output from my WndProc function. I can move my cursor, however I cannot click or type anything

    I can reproduce this issue using your code sample.

    SetWindowsHookEx can be used to inject a DLL into another process. A 32-bit DLL cannot be injected into a 64-bit process, and a 64-bit DLL cannot be injected into a 32-bit process. If an application requires the use of hooks in other processes, it is required that a 32-bit application call SetWindowsHookEx to inject a 32-bit DLL into 32-bit processes, and a 64-bit application call SetWindowsHookEx to inject a 64-bit DLL into 64-bit processes. The 32-bit and 64-bit DLLs must have different names.

    Refer to Remarks of SetWindowsHookEx for more information.

    So follow above instructions you will get it work. You can refer to my steps as below:

    1. Create a 32bit application and a 32bit DLL (window application in my test), and a 64bit application and a 64bit DLL.
    2. In DLL_PROCESS_ATTACH, you need to determine the current process is 32bit or 64bit. You can use IsWow64Process(). In 32bit DLL return FALSE to fail DLL load for 64bit applications. While, in 64bit DLL return FALSE to fail DLL load for 32bit applications.
    3. Configure the UI Access to true via Visual Studio like below, for both 32bit and 64bit applications. No need to set for DLLs.
    4. Put 32bit DLL at path: C:\Windows\SysWOW64, put others at C:\Windows\System32.
    5. Sign both 32bit and 64bit applications following this tutorial.
    6. Launch two applications and execute register hook. The 32bit application will hook all 32bit applications and the 64bit application will hook all 64bit applications.
    7. During hooking, logs will be written to two files journalX86.txt and journalX64.txt at D:.
    8. After finish hooking, make sure unregister the hook,

    41492-20201120-2.png

    Here take 32bit application and 32bit DLL as an example to show key code piece. Similar with 64bit.

    Application:

    			if (hooked)  
    			{  
    				HINSTANCE hinst = LoadLibrary(_T("hookX86Dll.dll"));  
    				typedef BOOL(*uninstall)();  
    				uninstall unInstall = (uninstall)GetProcAddress(hinst, "uninstall");  
    				unInstall();  
    				hooked = FALSE;  
    			}  
    			else  
    			{  
    
    				HINSTANCE hinst = LoadLibrary(_T("hookX86Dll.dll"));  
    				if (NULL == hinst)  
    				{  
    					DWORD dw = GetLastError();  
    					WCHAR info[200];  
    					RtlZeroMemory(info, sizeof(info));  
    					_snwprintf_s(info, sizeof(info), L"Failed to install hook: %d", dw);  
    					MessageBox(NULL, info, L"", MB_OK);  
    					break;  
    				}  
    
    				typedef DWORD(*Install)();  
    				Install install = (Install)GetProcAddress(hinst, "install");  
    				if (NULL == install)  
    				{  
    					DWORD dw = GetLastError();  
    					WCHAR info[200];  
    					RtlZeroMemory(info, sizeof(info));  
    					_snwprintf_s(info, sizeof(info), L"Failed to install hook: %d", dw);  
    					MessageBox(NULL, info, L"", MB_OK);  
    					break;  
    				}  
    
    				if (install())  
    					MessageBox(NULL, L"hook install fails", L"", MB_OK);  
    				else  
    					MessageBox(NULL, L"hook install successes", L"", MB_OK);  
    
    				hooked = TRUE;  
    			}  
    

    DLL:

    #include <windows.h>  
    #include <stdio.h>  
    #include <tchar.h>  
      
    HHOOK hhk;  
    static 	FILE* fileLog = NULL;  
      
    LRESULT CALLBACK journalRecordProc(int code, WPARAM wParam, LPARAM lParam) {  
      
    	fprintf(fileLog, "loggedJournal\n");  
    	//Beep(1000, 30);  
    	return CallNextHookEx(hhk, code, wParam, lParam);  
    	//return 0;  
    }  
      
    extern "C" __declspec(dllexport) DWORD install() {  
    	hhk = SetWindowsHookEx(WH_JOURNALRECORD, journalRecordProc, NULL, 0);  
    	if (hhk == NULL)  
    	{  
    		return GetLastError();  
    	}  
    	else  
    	{  
    		if (!fopen_s(&fileLog, "D:\\journalX86.txt", "a+"))  
    		{  
    			fprintf(fileLog, "registerred\n");  
    		}  
    		return 0;  
    	}  
    }  
    extern "C" __declspec(dllexport) void uninstall() {  
    	UnhookWindowsHookEx(hhk);  
    	fclose(fileLog);  
    }  
      
    BOOL APIENTRY DllMain( HMODULE hModule,  
                           DWORD  ul_reason_for_call,  
                           LPVOID lpReserved  
                         )  
    {  
    	BOOL is32Bit = FALSE;  
        switch (ul_reason_for_call)  
        {  
        case DLL_PROCESS_ATTACH:  
    		if (!IsWow64Process(GetCurrentProcess(), &is32Bit))  
    		{  
    			return FALSE;  
    		}  
    		if (is32Bit)  
    			return TRUE;  
    		else  
    			return FALSE;  
    		break;  
        case DLL_THREAD_ATTACH:  
        case DLL_THREAD_DETACH:  
        case DLL_PROCESS_DETACH:  
            break;  
        }  
        return TRUE;  
    }  
    

    Thank you!


    If the answer is helpful, please click "Accept Answer" and upvote it.

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.