I have a qt gui build as a DLL when compiled as x64 it works correctly, however, when I compile it as x86 and inject it into a 32bits process, its DllMain entry never gets called.
After a lot of time searching and recompiling the qt source I figured out it maybe is not a problem with qt because I have been able to reproduce the issue with a "clean" "non-qt" dll project:
source
#include <Windows.h>
BOOL APIENTRY DllMain( HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
break;
}
OutputDebugString(L"DllMain");
return TRUE;
}
And this is how I'm injecting the dll:
void injectDLL(DWORD processID, const QString& dllPath)
{
// Open the target process.
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processID);
if (!processHandle)
{
qDebug() << "Failed to open process";
return;
}
// Allocate memory in the target process.
LPVOID remoteMemory = VirtualAllocEx(processHandle, NULL, dllPath.length(), MEM_COMMIT, PAGE_READWRITE);
if (!remoteMemory)
{
qDebug() << "Failed to allocate memory in the remote process";
CloseHandle(processHandle);
return;
}
// Write the path of the DLL to be injected into the allocated memory in the target process.
if (!WriteProcessMemory(processHandle, remoteMemory, dllPath.toStdWString().c_str(), dllPath.length() * sizeof(wchar_t), NULL))
{
qDebug() << "Failed to write path to the remote process memory";
VirtualFreeEx(processHandle, remoteMemory, 0, MEM_RELEASE);
CloseHandle(processHandle);
return;
}
// Get the address of the LoadLibraryW function.
LPVOID loadLibraryAddress = GetProcAddress(GetModuleHandle(L"kernel32.dll"), "LoadLibraryW");
if (!loadLibraryAddress)
{
qDebug() << "Failed to get the address of LoadLibraryW";
VirtualFreeEx(processHandle, remoteMemory, 0, MEM_RELEASE);
CloseHandle(processHandle);
return;
}
// Create a remote thread in the target process and pass the address of LoadLibraryW and the address of the allocated memory as arguments.
HANDLE remoteThread = CreateRemoteThread(processHandle, NULL, 0, (LPTHREAD_START_ROUTINE)loadLibraryAddress, remoteMemory, 0, NULL);
if (!remoteThread)
{
qDebug() << "Failed to create a remote thread in the target process";
VirtualFreeEx(processHandle, remoteMemory, 0, MEM_RELEASE);
CloseHandle(processHandle);
return;
}
// Wait for the remote thread to finish.
WaitForSingleObject(remoteThread, INFINITE);
// Cleanup.
CloseHandle(remoteThread);
VirtualFreeEx(processHandle, remoteMemory, 0, MEM_RELEASE);
CloseHandle(processHandle);
}
int main()
{
// wmplayer.exe pid
injectDLL(51836, "D:/repos/Dll/Debug/Dll.dll");
return 0;
}
I'm testing injecting the dll into C:\Program Files (x86)\Windows Media Player\wmplayer.exe which is an x32 exe.
I'm debugging the dll on vs22 but after injected it never gets called, and neither the OutputDebugString(L"DllMain"); is printed.
I'm trying to fix the problem on my qt dll, which probably is the same as the sample I provided above.
What I'm missing or doing wrong?
Are you sure the process id that is passed into the
injectDll()method is correct? I suggest implementing the following method and declaring it like this.