SetWindowsHookEx injection

Hello fellow skids. This will be a post regarding available injection method which Roblox was supposed to patch, but unfortunately its still in work since then and now. The method called “SetWindowsHookEx” which most of you may noticed already who had tried to figure out how it works using opensource injectors supporting this kind of injection.
I will be giving you an example of it with code below.

(Another note, that it may inject itself into injector process to create hook with RobloxPlayerBeta.exe after).

bool SetWindowsHookEx(DWORD processId, LPCSTR dllPath) {
	HMODULE hModDll = LoadLibrary(dllPath);
	HOOKPROC procAddress = (HOOKPROC)GetProcAddress(hModDll, "HookProcedure");
	HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
	THREADENTRY32 te32;
	// Take snaphsot of all running threads
	hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
	// Set structure size
	te32.dwSize = sizeof(THREADENTRY32);
	DWORD threadId = 0
	do {
		if (te32.th32OwnerProcessID == processId) {
			threadId = te32.th32ThreadID;
			HANDLE hThread = OpenThread(READ_CONTROL, FALSE, te32.th32ThreadID);
			if (hThread) {
				HHOOK hookHandle = SetWindowsHookExA(WH_KEYBOARD, procAddress, hModDll, (DWORD)threadId);
			}			
		}
	} while (Thread32Next(hThreadSnap, &te32));
}

As you can see, we use WH_KEYBOARD method at this point which works like calling function whenever you press or interact with dll window you hooked with your process.
You can modify code that i’ve given to whatever you want and try out, but be sure that the dll you will inject into RobloxPlayerBeta.exe will be x64 and will have window creation upon injecting (i recommend using CMake to create a form).

You can take a look at the POC (Proof Of working Concept) below.

3 Likes

If you have anything else to add or tell about it, please type below incase.

1 Like

It seems like you are trying to set a global keyboard hook for a specific process using the Windows API. However, there are a few issues in your code:

  1. Missing Loop Termination Condition: The do-while loop is missing a semicolon at the end of the while line.

cCopy code

do {
    // ...
} while (Thread32Next(hThreadSnap, &te32));
  1. Thread ID Type Mismatch: The SetWindowsHookExA function expects the thread ID as a DWORD parameter, but you are passing it as a HANDLE.Change:

cCopy code

HHOOK hookHandle = SetWindowsHookExA(WH_KEYBOARD, procAddress, hModDll, (DWORD)threadId);

to:

cCopy code

HHOOK hookHandle = SetWindowsHookExA(WH_KEYBOARD, procAddress, hModDll, threadId);
  1. Resource Leak: The code loads the DLL with LoadLibrary but does not free it with FreeLibrary after setting the hook.After setting the hook, you should free the library using FreeLibrary:

cCopy code

FreeLibrary(hModDll);
  1. Error Handling: It’s a good practice to check for errors and handle them appropriately. For example, you should check if LoadLibrary and GetProcAddress return NULL, and if CreateToolhelp32Snapshot and OpenThread return INVALID_HANDLE_VALUE.

Here’s an updated version of your code with these changes:

cCopy code

bool SetWindowsHookEx(DWORD processId, LPCSTR dllPath) {
    HMODULE hModDll = LoadLibrary(dllPath);
    if (hModDll == NULL) {
        // Handle error
        return false;
    }

    HOOKPROC procAddress = (HOOKPROC)GetProcAddress(hModDll, "HookProcedure");
    if (procAddress == NULL) {
        // Handle error
        FreeLibrary(hModDll);
        return false;
    }

    HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
    if (hThreadSnap == INVALID_HANDLE_VALUE) {
        // Handle error
        FreeLibrary(hModDll);
        return false;
    }

    THREADENTRY32 te32;
    te32.dwSize = sizeof(THREADENTRY32);
    DWORD threadId = 0;

    do {
        if (te32.th32OwnerProcessID == processId) {
            threadId = te32.th32ThreadID;
            HANDLE hThread = OpenThread(READ_CONTROL, FALSE, te32.th32ThreadID);
            if (hThread != NULL) {
                HHOOK hookHandle = SetWindowsHookExA(WH_KEYBOARD, procAddress, hModDll, threadId);
                // Check for SetWindowsHookExA failure if needed

                CloseHandle(hThread);
            }
        }
    } while (Thread32Next(hThreadSnap, &te32));

    CloseHandle(hThreadSnap);
    FreeLibrary(hModDll);

    return true;
}

Remember to add appropriate error handling based on your specific requirements. Also, note that setting a global hook might have security implications, so use it responsibly and be aware of the potential impact on system performance and behavior.

1 Like

chatgpt yap

1 Like

I haven’t looked to much into it but rune CE ( rune cheat engine ) possibly could’ve used this method and as a tiny part of the community knows. it is definitely something exploitable but I also do believe this is detected after some time.

Also anything I’m saying could be incorrect I have a very small amount of knowledge about rune’s injection method so don’t quote me!

havent touched this stuff in years but looks legit

this doesnt work LOL