cwindowswinapidlldll-injection

DLL Injection not working, message box not popping up from explorer process


No errors are thrown, everything seems to execute properly, except the message box doesnt pop up on process attatch. Main function:

int main(int argc, wchar_t** argv){
    
    wchar_t bufdebug[MAX_PATH];

    HANDLE hTargetProcess = findProcess(L"explorer.exe", NULL);
    

    wchar_t dllfullpath[MAX_PATH];
    wchar_t* filepart = new wchar_t[MAX_PATH];
    wchar_t dllname[] = L"HelloWorldDLL.dll";

    GetFullPathName(dllname, MAX_PATH, dllfullpath, (LPWSTR*)&filepart);

    //MessageBox(NULL, dllfullpath, filepart, MB_OK);

    LPVOID lpBufTargetProc = VirtualAllocEx(hTargetProcess, NULL, wcslen(dllfullpath), MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if(lpBufTargetProc == nullptr) MessageBox(NULL, L"VEX Failed", NULL, MB_OK);

    size_t nbyteswritten = 0;

    int res = WriteProcessMemory(hTargetProcess, lpBufTargetProc, dllfullpath, wcslen(dllfullpath), &nbyteswritten);
    if(res == FALSE) MessageBox(NULL, L"WPM Failed", NULL, MB_OK);

    wsprintf(bufdebug, L"Bytes Written in target process: %d\n", nbyteswritten);

    //MessageBox(NULL, bufdebug, NULL, MB_OK);

    LPVOID pFuncLLW = (LPVOID)GetProcAddress(LoadLibrary(L"kernel32"), "LoadLibraryW");
    if (pFuncLLW == nullptr) MessageBox(NULL, L"GPA for LLW in kernel32 failed", L"Injection Failed", NULL);

    DWORD threadID = NULL;

    HANDLE hRemoteThread = CreateRemoteThread(hTargetProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)pFuncLLW, lpBufTargetProc, NULL, &threadID);
    if(hRemoteThread == nullptr) MessageBox(NULL, L"CRT Failed", L"Injection Failed", NULL);



    return 0;
}

findProcess function (tlhelp32 snapshot)

HANDLE findProcess(const wchar_t* processName, const DWORD pid)
{
    HANDLE hProcessSnap;
    HANDLE hProcess;
    PROCESSENTRY32 pe32;
    DWORD dwPriorityClass;

    // Take a snapshot of all processes in the system.
    hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (hProcessSnap == INVALID_HANDLE_VALUE) {
        return NULL;
    }

    pe32.dwSize = sizeof(PROCESSENTRY32);

    if (!Process32First(hProcessSnap, &pe32)) {
        CloseHandle(hProcessSnap);
        return FALSE;
    }

    if (processName == nullptr && pid != NULL) {
        do {

            if (pe32.th32ProcessID == pid) {

                hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
                if (hProcess != NULL) {
                    return hProcess;
                }
                else {
                    return NULL;
                }
            }

        } while (Process32Next(hProcessSnap, &pe32));
    }
    else if (processName != nullptr && pid == NULL) {
        do {

            if (!wcscmp(pe32.szExeFile, processName)) {

                hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID);
                if (hProcess != NULL) {
                    return hProcess;
                }
                else {
                    return NULL;
                }
            }

        } while (Process32Next(hProcessSnap, &pe32));
    }
    else return NULL;



    return NULL;
}

The DLL to inject HelloWorldDLL.dll source:


#define WIN32_LEAN_AND_MEAN
#include <windows.h>

DWORD WINAPI MessageBoxThread(LPVOID lpParam) {
    MessageBox(NULL, L"Hello world!", L"Hello World!", MB_OK);
    return 0;
}

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
    switch (ul_reason_for_call) {
    case DLL_PROCESS_ATTACH:
        CreateThread(NULL, NULL, MessageBoxThread, NULL, NULL, NULL);
        break;
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

Am I making some silly error? Ive compiled both in x64.

Ive outputted debug strings to output console of all the process handles, function pointers, memory buffers and they all seem to have some seemingly valid value, no idea whats going on. I tried turning windows defender antivirus completely off in case theres some hooking. No luck. Get full path name gets the dll path and everything fine.


Solution

  • When I tried your code I ran in to two problems. First one was of my own. I compiled the DLL as 32-bit instead of 64-bit. It is impossible to load a 32-bit DLL in a program that is 64-bit. So please make sure the DLL is 64-bit (and the EXE as well).

    The second problem was because of wcslen(). This function returns the amount of WCHAR's, not the amount of size it takes up in memory. Every WCHAR takes up two bytes in memory. That's fixed in the code below.

    I also added one extra character to include the zero-terminating character. In this case particularity it is not necessary, because VirtualAllocEx will always allocate more then 261 WCHAR's and initializes this as zero. But in other cases, if you need more then 261 WCHAR's, it's highly recommended you don't forget about the terminating zero.

    After this change, it should work.

    int main(int argc, wchar_t** argv){
        
        wchar_t bufdebug[MAX_PATH];
    
        HANDLE hTargetProcess = findProcess(L"explorer.exe", NULL);
        
    
        wchar_t dllfullpath[MAX_PATH];
        wchar_t* filepart = new wchar_t[MAX_PATH];
        wchar_t dllname[] = L"HelloWorldDLL.dll";
    
        GetFullPathName(dllname, MAX_PATH, dllfullpath, (LPWSTR*)&filepart);
    
        //MessageBox(NULL, dllfullpath, filepart, MB_OK);
    
        LPVOID lpBufTargetProc = VirtualAllocEx(hTargetProcess, NULL, (wcslen(dllfullpath)+1)*2, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
        if(lpBufTargetProc == nullptr) MessageBox(NULL, L"VEX Failed", NULL, MB_OK);
    
        size_t nbyteswritten = 0;
    
        int res = WriteProcessMemory(hTargetProcess, lpBufTargetProc, dllfullpath, (wcslen(dllfullpath)+1)*2, &nbyteswritten);
        if(res == FALSE) MessageBox(NULL, L"WPM Failed", NULL, MB_OK);
    
        wsprintf(bufdebug, L"Bytes Written in target process: %d\n", nbyteswritten);
    
        //MessageBox(NULL, bufdebug, NULL, MB_OK);
    
        LPVOID pFuncLLW = (LPVOID)GetProcAddress(LoadLibrary(L"kernel32"), "LoadLibraryW");
        if (pFuncLLW == nullptr) MessageBox(NULL, L"GPA for LLW in kernel32 failed", L"Injection Failed", NULL);
    
        DWORD threadID = NULL;
    
        HANDLE hRemoteThread = CreateRemoteThread(hTargetProcess, NULL, NULL, (LPTHREAD_START_ROUTINE)pFuncLLW, lpBufTargetProc, NULL, &threadID);
        if(hRemoteThread == nullptr) MessageBox(NULL, L"CRT Failed", L"Injection Failed", NULL);
    
    
    
        return 0;
    }