2

My problem is very simple and the title explains it all. Basically, when I compile my program with Visual Studio 2013, the dll injection works perfectly fine. When I compile the exact same program in Qt Creator, it doesn't.

I seem to have the same problem as this fellow: Why does Qt not work with dll injection?

Here is my code:

Injector.h

#ifndef INJECTOR_H_INCLUDED
#define INJECTOR_H_INCLUDED

#include <Windows.h>
#include <string>

class Injector
{
public:
    /**
    * Loads a DLL into the remote process
    * @Return true on sucess, false on failure
    */
    bool InjectDll(DWORD processId, std::string dllPath);
private:
};

#endif // INJECTOR_H_INCLUDED

Injector.cpp

#include "Injector.h"

bool Injector::InjectDll(DWORD processId, std::string dllPath)
{
    HANDLE hThread, hProcess;
    void*  pLibRemote = 0;  // the address (in the remote process) where szLibPath will be copied to;

    HMODULE hKernel32 = GetModuleHandleA("Kernel32");

    char DllFullPathName[_MAX_PATH];
    GetFullPathNameA(dllPath.c_str(), _MAX_PATH, DllFullPathName, NULL);
    printf("Loading dll: %s\n", DllFullPathName);

    // Get process handle
    hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);

    // copy file path in szLibPath
    char szLibPath[_MAX_PATH];
    strcpy_s(szLibPath, DllFullPathName);

    // 1. Allocate memory in the remote process for szLibPath
    pLibRemote = VirtualAllocEx(hProcess, NULL, sizeof(szLibPath), MEM_COMMIT, PAGE_READWRITE);

    if (pLibRemote == NULL)
    {
        printf("Couldn't allocate memory, please restart with administrator privileges\n");
        return false;
    }

    // 2. Write szLibPath to the allocated memory
    WriteProcessMemory(hProcess, pLibRemote, (void*)szLibPath, sizeof(szLibPath), NULL);

    // 3. Force remote process to load dll
    hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)GetProcAddress(hKernel32, "LoadLibraryA"), pLibRemote, 0, NULL);

    if (hThread == NULL)
    {
        printf("Couldn't load DLL");
        return false;
    }

    printf("Dll successfully loaded\n");

    return true;
}

main.cpp

#include "injector.h"
int main(int argc, char *argv[])
{
    Injector inject;
    DWORD processId = 6224;
    inject.InjectDll(processId, "MyDLL.dll");
    system("pause");
}

And this is the DLL (I use the same DLL in both scenario, I don't recompile it):

#include <Windows.h>
#include <stdio.h>

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        AllocConsole();
        freopen("CONOUT$", "w", stdout);

        printf("base address: %X\n", (DWORD)GetModuleHandle(NULL));

        break;
    case DLL_PROCESS_DETACH:
        FreeConsole();
    }

    return TRUE;
}

The program compiled in VS2013 correctly injects the dll, while the program compiled in Qt Creator says the dll injection was successful, yet the dll is never injected.

NOTE: The program I'm trying to inject is the same in both scenario and was NOT made with Qt.

Here are the compilers output:

Visual Studio:

cl /c /Zi /W3 /WX- /sdl /O2 /Oi /Oy- /GL /D _CRT_SECURE_NO_WARNINGS /D _MBCS /Gm- /EHsc /MD /GS /Gy /fp:precise /Zc:wchar_t /Zc:forScope /Fo"Release\" /Fd"Release\vc120.pdb" /Gd /TP /analyze- /errorReport:prompt Injector.cpp main.cpp

Qt:

C:\Qt\Qt5.4.0\Tools\QtCreator\bin\jom.exe -f Makefile.Release cl -c -nologo -Zm200 -Zc:wchar_t -FS -O2 -MD -Zc:strictStrings -GR -W3 -w34100 -w34189 -EHsc -DUNICODE -DWIN32 -DWIN64 -DQT_NO_DEBUG -DQT_CORE_LIB -DNDEBUG -I"C:\Qt\Qt5.4.0\5.4\msvc2013_64_opengl\include" -I"C:\Qt\Qt5.4.0\5.4\msvc2013_64_opengl\include\QtCore" -I"release" -I"." -I"C:\Qt\Qt5.4.0\5.4\msvc2013_64_opengl\mkspecs\win32-msvc2013" -Forelease\ @C:\Users\JFG\AppData\Local\Temp\injector.obj.7040.0.jom injector.cpp link /NOLOGO /DYNAMICBASE /NXCOMPAT /INCREMENTAL:NO /SUBSYSTEM:CONSOLE "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='' processorArchitecture=''" /MANIFEST:embed /OUT:release\test_dll_inection_qt.exe @C:\Users\JFG\AppData\Local\Temp\test_dll_inection_qt.exe.7040.469.jom

Any help would be appreciated, thank you.

Community
  • 1
  • 1
MyUsername112358
  • 1,320
  • 14
  • 39
  • What compiler flags are set for VS and Qt? – txtechhelp Jan 20 '15 at 21:30
  • I'm not exactly sure how to see which flags are set on Qt, but I didn't add any by myself in either VS or Qt – MyUsername112358 Jan 20 '15 at 21:33
  • VS has some default compiler options set if do nothing (i.e. blank project and start compiling), with both VS and Qt you can see what the compiler is being fed (the options being used) in the 'compiler output' window (might take switching some settings in the IDE) – txtechhelp Jan 20 '15 at 21:42
  • That's an awfully large code dump for this kind of question. Exactly where is it failing? – MrEricSir Jan 20 '15 at 21:56
  • I added the compilers output to the original post. I'm not sure if all any of these indicate a problem to you? I'm gonna look into it... – MyUsername112358 Jan 20 '15 at 21:56
  • @MrEricSir - I said exactly where it was failing... Not sure what more you want? In Qt, the program prints that the injection was successful, yet the dll is never injected. – MyUsername112358 Jan 20 '15 at 21:57
  • But which line *specifically* is the problem? – MrEricSir Jan 20 '15 at 22:01
  • If I knew what line was the problem, the problem would be easy to solve... Plus, the programs works in VS, so how could the problem comes from a line in my program? It seems to have something to do with how Qt compiles it, but I'm not knowledgeable about Qt enough to know what the problem is. – MyUsername112358 Jan 20 '15 at 22:02
  • 1
    The problem is that you're checking for the handle of the created thread, which is not the same as checking for whether or not your DLL was loaded. You'll need to figure out how to remotely retrieve the result of `LoadLibraryA`. Edit: you might try calling `GetExitCodeThread` which would return the result returned by your `ThreadProc` you had provided (that is, the result of `LoadLibraryA`). Make sure to handle the case where the target thread is *still running*. – inetknght Jan 20 '15 at 22:10
  • So there is something wierd happening... GetExitCodeThread returns 0 in Qt, indicating an error, but GetLastError also returns 0, indicating ERROR_SUCCESS... any idea what is happening?? – MyUsername112358 Jan 20 '15 at 22:27

1 Answers1

2

The problem was that Qt compiled my program in 64bit while visual studio compiled it in 32bit.

I'm still not sure why injecting a 32bit dll in a 32bit target fails because of a 64bit injector, but for now I solved my problem...

MyUsername112358
  • 1,320
  • 14
  • 39