Results 1 to 2 of 2
  1. #1
    Grooguz
    Grooguz is offline
    BanHammer Holder
    Grooguz's Avatar
    Join Date
    2010 May
    Posts
    678
    Thanks Thanks Given 
    152
    Thanks Thanks Received 
    537
    Thanked in
    167 Posts
    Rep Power
    14

    Dll Injection with CreateRemoteThread

    CompleteInject.cpp
    #include <windows.h>
    #include <stdio.h>

    /************************************************** *************************************************/
    // Function:
    // Inject
    //
    // Parameters:
    // HANDLE hProcess - The handle to the process to inject the DLL into.
    //
    // const char* dllname - The name of the DLL to inject into the process.
    //
    // const char* funcname - The name of the function to call once the DLL has been injected.
    //
    // Description:
    // This function will inject a DLL into a process and execute an exported function
    // from the DLL to "initialize" it. The function should be in the format shown below,
    // not parameters and no return type. Do not forget to prefix extern "C" if you are in C++
    //
    // __declspec(dllexport) void FunctionName(void)
    //
    // The function that is called in the injected DLL
    // -MUST- return, the loader waits for the thread to terminate before removing the
    // allocated space and returning control to the Loader. This method of DLL injection
    // also adds error handling, so the end user knows if something went wrong.
    /************************************************** *************************************************/

    void Inject(HANDLE hProcess, const char* dllname, const char* funcname)
    {
    //------------------------------------------//
    // Function variables. //
    //------------------------------------------//

    // Main DLL we will need to load
    HMODULE kernel32 = NULL;

    // Main functions we will need to import
    FARPROC loadlibrary = NULL;
    FARPROC getprocaddress = NULL;
    FARPROC exitprocess = NULL;
    FARPROC exitthread = NULL;
    FARPROC freelibraryandexitthread = NULL;

    // The workspace we will build the codecave on locally
    LPBYTE workspace = NULL;
    DWORD workspaceIndex = 0;

    // The memory in the process we write to
    LPVOID codecaveAddress = NULL;
    DWORD dwCodecaveAddress = 0;

    // Strings we have to write into the process
    char injectDllName[MAX_PATH + 1] = {0};
    char injectFuncName[MAX_PATH + 1] = {0};
    char injectError0[MAX_PATH + 1] = {0};
    char injectError1[MAX_PATH + 1] = {0};
    char injectError2[MAX_PATH + 1] = {0};
    char user32Name[MAX_PATH + 1] = {0};
    char msgboxName[MAX_PATH + 1] = {0};

    // Placeholder addresses to use the strings
    DWORD user32NameAddr = 0;
    DWORD user32Addr = 0;
    DWORD msgboxNameAddr = 0;
    DWORD msgboxAddr = 0;
    DWORD dllAddr = 0;
    DWORD dllNameAddr = 0;
    DWORD funcNameAddr = 0;
    DWORD error0Addr = 0;
    DWORD error1Addr = 0;
    DWORD error2Addr = 0;

    // Where the codecave execution should begin at
    DWORD codecaveExecAddr = 0;

    // Handle to the thread we create in the process
    HANDLE hThread = NULL;

    // Temp variables
    DWORD dwTmpSize = 0;

    // Old protection on page we are writing to in the process and the bytes written
    DWORD oldProtect = 0;
    DWORD bytesRet = 0;

    //------------------------------------------//
    // Variable initialization. //
    //------------------------------------------//

    // Get the address of the main DLL
    kernel32 = LoadLibrary("kernel32.dll");

    // Get our functions
    loadlibrary = GetProcAddress(kernel32, "LoadLibraryA");
    getprocaddress = GetProcAddress(kernel32, "GetProcAddress");
    exitprocess = GetProcAddress(kernel32, "ExitProcess");
    exitthread = GetProcAddress(kernel32, "ExitThread");
    freelibraryandexitthread = GetProcAddress(kernel32, "FreeLibraryAndExitThread");

    // This section will cause compiler warnings on VS8,
    // you can upgrade the functions or ignore them

    // Build names
    _snprintf(injectDllName, MAX_PATH, "%s", dllname);
    _snprintf(injectFuncName, MAX_PATH, "%s", funcname);
    _snprintf(user32Name, MAX_PATH, "user32.dll");
    _snprintf(msgboxName, MAX_PATH, "MessageBoxA");

    // Build error messages
    _snprintf(injectError0, MAX_PATH, "Error");
    _snprintf(injectError1, MAX_PATH, "Could not load the dll: %s", injectDllName);
    _snprintf(injectError2, MAX_PATH, "Could not load the function: %s", injectFuncName);

    // Create the workspace
    workspace = (LPBYTE)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, 1024);

    // Allocate space for the codecave in the process
    codecaveAddress = VirtualAllocEx(hProcess, 0, 1024, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    dwCodecaveAddress = PtrToUlong(codecaveAddress);

    // Note there is no error checking done above for any functions that return a pointer/handle.
    // I could have added them, but it'd just add more messiness to the code and not provide any real
    // benefit. It's up to you though in your final code if you want it there or not.

    //------------------------------------------//
    // Data and string writing. //
    //------------------------------------------//

    // Write out the address for the user32 dll address
    user32Addr = workspaceIndex + dwCodecaveAddress;
    dwTmpSize = 0;
    memcpy(workspace + workspaceIndex, &dwTmpSize, 4);
    workspaceIndex += 4;

    // Write out the address for the MessageBoxA address
    msgboxAddr = workspaceIndex + dwCodecaveAddress;
    dwTmpSize = 0;
    memcpy(workspace + workspaceIndex, &dwTmpSize, 4);
    workspaceIndex += 4;

    // Write out the address for the injected DLL's module
    dllAddr = workspaceIndex + dwCodecaveAddress;
    dwTmpSize = 0;
    memcpy(workspace + workspaceIndex, &dwTmpSize, 4);
    workspaceIndex += 4;

    // User32 Dll Name
    user32NameAddr = workspaceIndex + dwCodecaveAddress;
    dwTmpSize = (DWORD)strlen(user32Name) + 1;
    memcpy(workspace + workspaceIndex, user32Name, dwTmpSize);
    workspaceIndex += dwTmpSize;

    // MessageBoxA name
    msgboxNameAddr = workspaceIndex + dwCodecaveAddress;
    dwTmpSize = (DWORD)strlen(msgboxName) + 1;
    memcpy(workspace + workspaceIndex, msgboxName, dwTmpSize);
    workspaceIndex += dwTmpSize;

    // Dll Name
    dllNameAddr = workspaceIndex + dwCodecaveAddress;
    dwTmpSize = (DWORD)strlen(injectDllName) + 1;
    memcpy(workspace + workspaceIndex, injectDllName, dwTmpSize);
    workspaceIndex += dwTmpSize;

    // Function Name
    funcNameAddr = workspaceIndex + dwCodecaveAddress;
    dwTmpSize = (DWORD)strlen(injectFuncName) + 1;
    memcpy(workspace + workspaceIndex, injectFuncName, dwTmpSize);
    workspaceIndex += dwTmpSize;

    // Error Message 1
    error0Addr = workspaceIndex + dwCodecaveAddress;
    dwTmpSize = (DWORD)strlen(injectError0) + 1;
    memcpy(workspace + workspaceIndex, injectError0, dwTmpSize);
    workspaceIndex += dwTmpSize;

    // Error Message 2
    error1Addr = workspaceIndex + dwCodecaveAddress;
    dwTmpSize = (DWORD)strlen(injectError1) + 1;
    memcpy(workspace + workspaceIndex, injectError1, dwTmpSize);
    workspaceIndex += dwTmpSize;

    // Error Message 3
    error2Addr = workspaceIndex + dwCodecaveAddress;
    dwTmpSize = (DWORD)strlen(injectError2) + 1;
    memcpy(workspace + workspaceIndex, injectError2, dwTmpSize);
    workspaceIndex += dwTmpSize;

    // Pad a few INT3s after string data is written for seperation
    workspace[workspaceIndex++] = 0xCC;
    workspace[workspaceIndex++] = 0xCC;
    workspace[workspaceIndex++] = 0xCC;

    // Store where the codecave execution should begin
    codecaveExecAddr = workspaceIndex + dwCodecaveAddress;

    // For debugging - infinite loop, attach onto process and step over
    //workspace[workspaceIndex++] = 0xEB;
    //workspace[workspaceIndex++] = 0xFE;

    //------------------------------------------//
    // User32.dll loading. //
    //------------------------------------------//

    // User32 DLL Loading
    // PUSH 0x00000000 - Push the address of the DLL name to use in LoadLibraryA
    workspace[workspaceIndex++] = 0x68;
    memcpy(workspace + workspaceIndex, &user32NameAddr, 4);
    workspaceIndex += 4;

    // MOV EAX, ADDRESS - Move the address of LoadLibraryA into EAX
    workspace[workspaceIndex++] = 0xB8;
    memcpy(workspace + workspaceIndex, &loadlibrary, 4);
    workspaceIndex += 4;

    // CALL EAX - Call LoadLibraryA
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0xD0;

    // MessageBoxA Loading
    // PUSH 0x000000 - Push the address of the function name to load
    workspace[workspaceIndex++] = 0x68;
    memcpy(workspace + workspaceIndex, &msgboxNameAddr, 4);
    workspaceIndex += 4;

    // Push EAX, module to use in GetProcAddress
    workspace[workspaceIndex++] = 0x50;

    // MOV EAX, ADDRESS - Move the address of GetProcAddress into EAX
    workspace[workspaceIndex++] = 0xB8;
    memcpy(workspace + workspaceIndex, &getprocaddress, 4);
    workspaceIndex += 4;

    // CALL EAX - Call GetProcAddress
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0xD0;

    // MOV [ADDRESS], EAX - Save the address to our variable
    workspace[workspaceIndex++] = 0xA3;
    memcpy(workspace + workspaceIndex, &msgboxAddr, 4);
    workspaceIndex += 4;

    //------------------------------------------//
    // Injected dll loading. //
    //------------------------------------------//

    /*
    // This is the way the following assembly code would look like in C/C++

    // Load the injected DLL into this process
    HMODULE h = LoadLibrary("mydll.dll");
    if(!h)
    {
    MessageBox(0, "Could not load the dll: mydll.dll", "Error", MB_ICONERROR);
    ExitProcess(0);
    }

    // Get the address of the export function
    FARPROC p = GetProcAddress(h, "Initialize");
    if(!p)
    {
    MessageBox(0, "Could not load the function: Initialize", "Error", MB_ICONERROR);
    ExitProcess(0);
    }

    // So we do not need a function pointer interface
    __asm call p

    // Exit the thread so the loader continues
    ExitThread(0);
    */

    // DLL Loading
    // PUSH 0x00000000 - Push the address of the DLL name to use in LoadLibraryA
    workspace[workspaceIndex++] = 0x68;
    memcpy(workspace + workspaceIndex, &dllNameAddr, 4);
    workspaceIndex += 4;

    // MOV EAX, ADDRESS - Move the address of LoadLibraryA into EAX
    workspace[workspaceIndex++] = 0xB8;
    memcpy(workspace + workspaceIndex, &loadlibrary, 4);
    workspaceIndex += 4;

    // CALL EAX - Call LoadLibraryA
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0xD0;

    // Error Checking
    // CMP EAX, 0
    workspace[workspaceIndex++] = 0x83;
    workspace[workspaceIndex++] = 0xF8;
    workspace[workspaceIndex++] = 0x00;

    // JNZ EIP + 0x1E to skip over eror code
    workspace[workspaceIndex++] = 0x75;
    workspace[workspaceIndex++] = 0x1E;

    // Error Code 1
    // MessageBox
    // PUSH 0x10 (MB_ICONHAND)
    workspace[workspaceIndex++] = 0x6A;
    workspace[workspaceIndex++] = 0x10;

    // PUSH 0x000000 - Push the address of the MessageBox title
    workspace[workspaceIndex++] = 0x68;
    memcpy(workspace + workspaceIndex, &error0Addr, 4);
    workspaceIndex += 4;

    // PUSH 0x000000 - Push the address of the MessageBox message
    workspace[workspaceIndex++] = 0x68;
    memcpy(workspace + workspaceIndex, &error1Addr, 4);
    workspaceIndex += 4;

    // Push 0
    workspace[workspaceIndex++] = 0x6A;
    workspace[workspaceIndex++] = 0x00;

    // MOV EAX, [ADDRESS] - Move the address of MessageBoxA into EAX
    workspace[workspaceIndex++] = 0xA1;
    memcpy(workspace + workspaceIndex, &msgboxAddr, 4);
    workspaceIndex += 4;

    // CALL EAX - Call MessageBoxA
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0xD0;

    // ExitProcess
    // Push 0
    workspace[workspaceIndex++] = 0x6A;
    workspace[workspaceIndex++] = 0x00;

    // MOV EAX, ADDRESS - Move the address of ExitProcess into EAX
    workspace[workspaceIndex++] = 0xB8;
    memcpy(workspace + workspaceIndex, &exitprocess, 4);
    workspaceIndex += 4;

    // CALL EAX - Call MessageBoxA
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0xD0;

    // Now we have the address of the injected DLL, so save the handle

    // MOV [ADDRESS], EAX - Save the address to our variable
    workspace[workspaceIndex++] = 0xA3;
    memcpy(workspace + workspaceIndex, &dllAddr, 4);
    workspaceIndex += 4;

    // Load the initilize function from it

    // PUSH 0x000000 - Push the address of the function name to load
    workspace[workspaceIndex++] = 0x68;
    memcpy(workspace + workspaceIndex, &funcNameAddr, 4);
    workspaceIndex += 4;

    // Push EAX, module to use in GetProcAddress
    workspace[workspaceIndex++] = 0x50;

    // MOV EAX, ADDRESS - Move the address of GetProcAddress into EAX
    workspace[workspaceIndex++] = 0xB8;
    memcpy(workspace + workspaceIndex, &getprocaddress, 4);
    workspaceIndex += 4;

    // CALL EAX - Call GetProcAddress
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0xD0;

    // Error Checking
    // CMP EAX, 0
    workspace[workspaceIndex++] = 0x83;
    workspace[workspaceIndex++] = 0xF8;
    workspace[workspaceIndex++] = 0x00;

    // JNZ EIP + 0x1C to skip eror code
    workspace[workspaceIndex++] = 0x75;
    workspace[workspaceIndex++] = 0x1C;

    // Error Code 2
    // MessageBox
    // PUSH 0x10 (MB_ICONHAND)
    workspace[workspaceIndex++] = 0x6A;
    workspace[workspaceIndex++] = 0x10;

    // PUSH 0x000000 - Push the address of the MessageBox title
    workspace[workspaceIndex++] = 0x68;
    memcpy(workspace + workspaceIndex, &error0Addr, 4);
    workspaceIndex += 4;

    // PUSH 0x000000 - Push the address of the MessageBox message
    workspace[workspaceIndex++] = 0x68;
    memcpy(workspace + workspaceIndex, &error2Addr, 4);
    workspaceIndex += 4;

    // Push 0
    workspace[workspaceIndex++] = 0x6A;
    workspace[workspaceIndex++] = 0x00;

    // MOV EAX, ADDRESS - Move the address of MessageBoxA into EAX
    workspace[workspaceIndex++] = 0xA1;
    memcpy(workspace + workspaceIndex, &msgboxAddr, 4);
    workspaceIndex += 4;

    // CALL EAX - Call MessageBoxA
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0xD0;

    // ExitProcess
    // Push 0
    workspace[workspaceIndex++] = 0x6A;
    workspace[workspaceIndex++] = 0x00;

    // MOV EAX, ADDRESS - Move the address of ExitProcess into EAX
    workspace[workspaceIndex++] = 0xB8;
    memcpy(workspace + workspaceIndex, &exitprocess, 4);
    workspaceIndex += 4;

    // Now that we have the address of the function, we cam call it,
    // if there was an error, the messagebox would be called as well.

    // CALL EAX - Call ExitProcess -or- the Initialize function
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0xD0;

    // If we get here, the Initialize function has been called,
    // so it's time to close this thread and optionally unload the DLL.

    //------------------------------------------//
    // Exiting from the injected dll. //
    //------------------------------------------//

    // Call ExitThread to leave the DLL loaded
    #if 1
    // Push 0 (exit code)
    workspace[workspaceIndex++] = 0x6A;
    workspace[workspaceIndex++] = 0x00;

    // MOV EAX, ADDRESS - Move the address of ExitThread into EAX
    workspace[workspaceIndex++] = 0xB8;
    memcpy(workspace + workspaceIndex, &exitthread, 4);
    workspaceIndex += 4;

    // CALL EAX - Call ExitThread
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0xD0;
    #endif

    // Call FreeLibraryAndExitThread to unload DLL
    #if 0
    // Push 0 (exit code)
    workspace[workspaceIndex++] = 0x6A;
    workspace[workspaceIndex++] = 0x00;

    // PUSH [0x000000] - Push the address of the DLL module to unload
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0x35;
    memcpy(workspace + workspaceIndex, &dllAddr, 4);
    workspaceIndex += 4;

    // MOV EAX, ADDRESS - Move the address of FreeLibraryAndExitThread into EAX
    workspace[workspaceIndex++] = 0xB8;
    memcpy(workspace + workspaceIndex, &freelibraryandexitthread, 4);
    workspaceIndex += 4;

    // CALL EAX - Call FreeLibraryAndExitThread
    workspace[workspaceIndex++] = 0xFF;
    workspace[workspaceIndex++] = 0xD0;
    #endif

    //------------------------------------------//
    // Code injection and cleanup. //
    //------------------------------------------//

    // Change page protection so we can write executable code
    VirtualProtectEx(hProcess, codecaveAddress, workspaceIndex, PAGE_EXECUTE_READWRITE, &oldProtect);

    // Write out the patch
    WriteProcessMemory(hProcess, codecaveAddress, workspace, workspaceIndex, &bytesRet);

    // Restore page protection
    VirtualProtectEx(hProcess, codecaveAddress, workspaceIndex, oldProtect, &oldProtect);

    // Make sure our changes are written right away
    FlushInstructionCache(hProcess, codecaveAddress, workspaceIndex);

    // Free the workspace memory
    HeapFree(GetProcessHeap(), 0, workspace);

    // Execute the thread now and wait for it to exit, note we execute where the code starts, and not the codecave start
    // (since we wrote strings at the start of the codecave) -- NOTE: void* used for VC6 compatibility instead of UlongToPtr
    hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)((void*)codecaveExecAddr), 0, 0, NULL);
    WaitForSingleObject(hThread, INFINITE);

    // Free the memory in the process that we allocated
    VirtualFreeEx(hProcess, codecaveAddress, 0, MEM_RELEASE);
    }

  2. The Following User Says Thank You to Grooguz For This Useful Post:


  3. #2
    annnnndre
    annnnndre is offline
    Senior Member annnnndre's Avatar
    Join Date
    2011 Jul
    Location
    By your side, let's the game begin'
    Posts
    336
    Thanks Thanks Given 
    118
    Thanks Thanks Received 
    177
    Thanked in
    87 Posts
    Rep Power
    0
    Cool, I'll try to do my own to use on GunZ;

Similar Threads

  1. [C++] Process Injection
    By Dwar in forum C/C++
    Replies: 2
    Last Post: 2014-06-29, 08:00 PM
  2. [Dev] DLL Injection Possible
    By Abstract in forum Forsaken World Bots, Hacks, Cheats
    Replies: 0
    Last Post: 2011-05-08, 12:16 AM
  3. [C++] DLL Injection Class
    By Dwar in forum C/C++
    Replies: 1
    Last Post: 2010-11-29, 04:08 PM
  4. Analyzing DLL Injection
    By Dwar in forum Programming Tutorials
    Replies: 2
    Last Post: 2010-11-29, 04:02 PM
  5. [help] making dll injection
    By gosicks in forum C/C++
    Replies: 5
    Last Post: 2010-10-30, 09:10 AM

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •