ManualMap 从 C++ 资源中注入一个 DLL

ManualMap inject a DLL from Resources in C++

我正在学习 C++,我需要帮助弄清楚如何使用 C++ 项目资源中的 ManualMap 注入来注入 DLL。

我在 C# 中有一个源代码,但我不确定如何转换它,我不想尝试转换大约 5000 行代码。

这是一个使用 ManualMapping 的未检测到的 DLL 注入,许多 GameGuard 未检测到它用于将 DLL 注入游戏。

#include <stdio.h>
#include <Windows.h>
#include <tlhelp32.h> /* PROCESSENTRY32 */
#include <conio.h> /* _getch() */
#include <shlwapi.h> /* StrStrI */

#pragma comment(lib, "shlwapi.lib") /* unresolved external symbol __imp__StrStrIW@8 */

typedef HMODULE (WINAPI *pLoadLibraryA)(LPCSTR);
typedef FARPROC (WINAPI *pGetProcAddress)(HMODULE,LPCSTR);

typedef BOOL (WINAPI *PDLL_MAIN)(HMODULE,DWORD,PVOID);

typedef struct _MANUAL_INJECT
{
    PVOID ImageBase;
    PIMAGE_NT_HEADERS NtHeaders;
    PIMAGE_BASE_RELOCATION BaseRelocation;
    PIMAGE_IMPORT_DESCRIPTOR ImportDirectory;
    pLoadLibraryA fnLoadLibraryA;
    pGetProcAddress fnGetProcAddress;
}MANUAL_INJECT,*PMANUAL_INJECT;

DWORD WINAPI LoadDll(PVOID p)
{
    PMANUAL_INJECT ManualInject;

    HMODULE hModule;
    DWORD i,Function,count,delta;

    PDWORD ptr;
    PWORD list;

    PIMAGE_BASE_RELOCATION pIBR;
    PIMAGE_IMPORT_DESCRIPTOR pIID;
    PIMAGE_IMPORT_BY_NAME pIBN;
    PIMAGE_THUNK_DATA FirstThunk,OrigFirstThunk;

    PDLL_MAIN EntryPoint;

    ManualInject=(PMANUAL_INJECT)p;

    pIBR=ManualInject->BaseRelocation;
    delta=(DWORD)((LPBYTE)ManualInject->ImageBase-ManualInject->NtHeaders->OptionalHeader.ImageBase); // Calculate the delta

    // Relocate the image

    while(pIBR->VirtualAddress)
    {
        if(pIBR->SizeOfBlock>=sizeof(IMAGE_BASE_RELOCATION))
        {
            count=(pIBR->SizeOfBlock-sizeof(IMAGE_BASE_RELOCATION))/sizeof(WORD);
            list=(PWORD)(pIBR+1);

            for(i=0;i<count;i++)
            {
                if(list[i])
                {
                    ptr=(PDWORD)((LPBYTE)ManualInject->ImageBase+(pIBR->VirtualAddress+(list[i] & 0xFFF)));
                    *ptr+=delta;
                }
            }
        }

        pIBR=(PIMAGE_BASE_RELOCATION)((LPBYTE)pIBR+pIBR->SizeOfBlock);
    }

    pIID=ManualInject->ImportDirectory;

    // Resolve DLL imports

    while(pIID->Characteristics)
    {
        OrigFirstThunk=(PIMAGE_THUNK_DATA)((LPBYTE)ManualInject->ImageBase+pIID->OriginalFirstThunk);
        FirstThunk=(PIMAGE_THUNK_DATA)((LPBYTE)ManualInject->ImageBase+pIID->FirstThunk);

        hModule=ManualInject->fnLoadLibraryA((LPCSTR)ManualInject->ImageBase+pIID->Name);

        if(!hModule)
        {
            return FALSE;
        }

        while(OrigFirstThunk->u1.AddressOfData)
        {
            if(OrigFirstThunk->u1.Ordinal & IMAGE_ORDINAL_FLAG)
            {
                // Import by ordinal

                Function=(DWORD)ManualInject->fnGetProcAddress(hModule,(LPCSTR)(OrigFirstThunk->u1.Ordinal & 0xFFFF));

                if(!Function)
                {
                    return FALSE;
                }

                FirstThunk->u1.Function=Function;
            }

            else
            {
                // Import by name

                pIBN=(PIMAGE_IMPORT_BY_NAME)((LPBYTE)ManualInject->ImageBase+OrigFirstThunk->u1.AddressOfData);
                Function=(DWORD)ManualInject->fnGetProcAddress(hModule,(LPCSTR)pIBN->Name);

                if(!Function)
                {
                    return FALSE;
                }

                FirstThunk->u1.Function=Function;
            }

            OrigFirstThunk++;
            FirstThunk++;
        }

        pIID++;
    }

    if(ManualInject->NtHeaders->OptionalHeader.AddressOfEntryPoint)
    {
        EntryPoint=(PDLL_MAIN)((LPBYTE)ManualInject->ImageBase+ManualInject->NtHeaders->OptionalHeader.AddressOfEntryPoint);
        return EntryPoint((HMODULE)ManualInject->ImageBase,DLL_PROCESS_ATTACH,NULL); // Call the entry point
    }

    return TRUE;
}

DWORD WINAPI LoadDllEnd()
{
    return 0;
}

DWORD GetTargetThreadIDFromProcName(const char * ProcName)
{
    PROCESSENTRY32 pe;
    HANDLE thSnapShot;
    BOOL retval, ProcFound = false;

    thSnapShot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
    if (thSnapShot == INVALID_HANDLE_VALUE)
    {
        //MessageBox(NULL, "Error: Unable to create toolhelp snapshot!", "2MLoader", MB_OK); 
        printf("Error: Unable to create toolhelp snapshot!");
        return false;
    }

    pe.dwSize = sizeof(PROCESSENTRY32);

    retval = Process32First(thSnapShot, &pe);
    while (retval)
    {
        if (StrStrI(pe.szExeFile, ProcName))
        {
            return pe.th32ProcessID;
        }
        retval = Process32Next(thSnapShot, &pe);
    }
    return 0;
}

void GetGamePath(char* buff) {
    HKEY hKey = 0;
    char path[255] = { 0 };
    char filename[255] = { 0 };
    DWORD dwType = 0;
    DWORD dwBufSize = 255;

    GetFullPathName("Game.exe", MAX_PATH, buff, NULL);

    //If file exists, then just exit.
    if (FILE *file = fopen(buff, "r")) {
        fclose(file);
        return;
    }

    if (RegOpenKeyEx(HKEY_CURRENT_USER, "Software\SomeGame\Game", 0, KEY_QUERY_VALUE | KEY_WOW64_64KEY, &hKey) == ERROR_SUCCESS)
    {
        bool failed = false;
        dwType = REG_SZ;
        if (RegQueryValueEx(hKey, "PATH", 0, &dwType, (BYTE*)&path, &dwBufSize) != ERROR_SUCCESS)
            failed = true;
        if (RegQueryValueEx(hKey, "FILENAME", 0, &dwType, (BYTE*)&filename, &dwBufSize) != ERROR_SUCCESS)
            failed = true;
        RegCloseKey(hKey);

        sprintf(buff, "%s%s", path, filename);

        if (failed) {
            GetFullPathName("Game.exe", MAX_PATH, buff, NULL);
        }
    }
}

int wmain(int argc,wchar_t* argv[])
{
    PIMAGE_DOS_HEADER pIDH;
    PIMAGE_NT_HEADERS pINH;
    PIMAGE_SECTION_HEADER pISH;

    HANDLE hProcess,hThread,hFile,hToken;
    PVOID /*buffer,*/image,mem;
    DWORD i,FileSize,ProcessId,ExitCode,read;

    TOKEN_PRIVILEGES tp;
    MANUAL_INJECT ManualInject;

    if(OpenProcessToken((HANDLE)-1,TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
    {
        tp.PrivilegeCount=1;
        tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;

        tp.Privileges[0].Luid.LowPart=20;
        tp.Privileges[0].Luid.HighPart=0;

        AdjustTokenPrivileges(hToken,FALSE,&tp,0,NULL,NULL);
        CloseHandle(hToken);
    }

    printf("\nOpening the DLL.\n");

    /*
    hFile=CreateFile("AO.dll",GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL); // Open the DLL

    if(hFile==INVALID_HANDLE_VALUE)
    {
        printf("\nError: Unable to open the DLL (%d)\n",GetLastError());
        return -1;
    }

    FileSize=GetFileSize(hFile,NULL);
    buffer=VirtualAlloc(NULL,FileSize,MEM_COMMIT|MEM_RESERVE,PAGE_READWRITE);

    if(!buffer)
    {
        printf("\nError: Unable to allocate memory for DLL data (%d)\n",GetLastError());

        CloseHandle(hFile);
        return -1;
    }

    // Read the DLL

    if(!ReadFile(hFile,buffer,FileSize,&read,NULL))
    {
        printf("\nError: Unable to read the DLL (%d)\n",GetLastError());

        VirtualFree(buffer,0,MEM_RELEASE);
        CloseHandle(hFile);

        return -1;
    }

    CloseHandle(hFile);
    */

    MODULE hModule = GetModuleHandle(NULL); // get the handle to the current module (the executable file)
    HRSRC hResource = FindResource(hModule, MAKEINTRESOURCE(RESOURCE_ID), RESOURCE_TYPE); // substitute RESOURCE_ID and RESOURCE_TYPE.
    HGLOBAL hMemory = LoadResource(hModule, hResource);
    DWORD dwSize = SizeofResource(hModule, hResource);
    LPVOID lpAddress = LockResource(hMemory);

    unsigned char *buffer = new char[dwSize];
    memcpy(buffer, lpAddress, dwSize);

    pIDH=(PIMAGE_DOS_HEADER)buffer;

    if(pIDH->e_magic!=IMAGE_DOS_SIGNATURE)
    {
        printf("\nError: Invalid executable image.\n");

        VirtualFree(buffer,0,MEM_RELEASE);
        return -1;
    }

    pINH=(PIMAGE_NT_HEADERS)((LPBYTE)buffer+pIDH->e_lfanew);

    if(pINH->Signature!=IMAGE_NT_SIGNATURE)
    {
        printf("\nError: Invalid PE header.\n");

        VirtualFree(buffer,0,MEM_RELEASE);
        return -1;
    }

    if(!(pINH->FileHeader.Characteristics & IMAGE_FILE_DLL))
    {
        printf("\nError: The image is not DLL.\n");

        VirtualFree(buffer,0,MEM_RELEASE);
        return -1;
    }

    // Retrieve process ID 
    ProcessId = 0;
    char buf[MAX_PATH] = { 0 };

    //Game.exe not started, attempt to start Game.exe (same path as this tool).
    if (ProcessId == 0) {
        // Gets the exe's full path name.
        GetGamePath(buf);
        printf("GamePath: ");
        printf(buf);
        printf("\n");
        LPCTSTR lpApplicationName = buf; /* The program to be executed */
        STARTUPINFO lpStartupInfo;
        PROCESS_INFORMATION lpProcessInfo;

        memset(&lpStartupInfo, 0, sizeof(lpStartupInfo));
        memset(&lpProcessInfo, 0, sizeof(lpProcessInfo));

        /* Create the process */
        if (!CreateProcess(lpApplicationName, NULL, NULL, NULL, FALSE, NULL, NULL, NULL, &lpStartupInfo, &lpProcessInfo)) {
            printf("Uh-Oh! CreateProcess() failed to start program %s\n", lpApplicationName);
            _getch();
            return 0;
        } else {
            WaitForSingleObject(lpProcessInfo.hProcess, 2000);
            CloseHandle(lpProcessInfo.hThread);
            CloseHandle(lpProcessInfo.hProcess);
            ProcessId = lpProcessInfo.dwProcessId; 
        }
    }
    printf("Game.exe ProcessId = %d\n", ProcessId);

    printf("\nOpening target process.\n");
    hProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE,ProcessId);

    if(!hProcess)
    {
        printf("\nError: Unable to open target process (%d)\n",GetLastError());

        VirtualFree(buffer,0,MEM_RELEASE);
        CloseHandle(hProcess);

        return -1;
    }

    printf("\nAllocating memory for the DLL.\n");
    image=VirtualAllocEx(hProcess,NULL,pINH->OptionalHeader.SizeOfImage,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); // Allocate memory for the DLL

    if(!image)
    {
        printf("\nError: Unable to allocate memory for the DLL (%d)\n",GetLastError());

        VirtualFree(buffer,0,MEM_RELEASE);
        CloseHandle(hProcess);

        return -1;
    }

    // Copy the header to target process

    printf("\nCopying headers into target process.\n");

    if(!WriteProcessMemory(hProcess,image,buffer,pINH->OptionalHeader.SizeOfHeaders,NULL))
    {
        printf("\nError: Unable to copy headers to target process (%d)\n",GetLastError());

        VirtualFreeEx(hProcess,image,0,MEM_RELEASE);
        CloseHandle(hProcess);

        VirtualFree(buffer,0,MEM_RELEASE);
        return -1;
    }

    pISH=(PIMAGE_SECTION_HEADER)(pINH+1);

    // Copy the DLL to target process

    printf("\nCopying sections to target process.\n");

    for(i=0;i<pINH->FileHeader.NumberOfSections;i++)
    {
        WriteProcessMemory(hProcess,(PVOID)((LPBYTE)image+pISH[i].VirtualAddress),(PVOID)((LPBYTE)buffer+pISH[i].PointerToRawData),pISH[i].SizeOfRawData,NULL);
    }

    printf("\nAllocating memory for the loader code.\n");
    mem=VirtualAllocEx(hProcess,NULL,4096,MEM_COMMIT|MEM_RESERVE,PAGE_EXECUTE_READWRITE); // Allocate memory for the loader code

    if(!mem)
    {
        printf("\nError: Unable to allocate memory for the loader code (%d)\n",GetLastError());

        VirtualFreeEx(hProcess,image,0,MEM_RELEASE);
        CloseHandle(hProcess);

        VirtualFree(buffer,0,MEM_RELEASE);
        return -1;
    }

    printf("\nLoader code allocated at %#x\n",mem);
    memset(&ManualInject,0,sizeof(MANUAL_INJECT));

    ManualInject.ImageBase=image;
    ManualInject.NtHeaders=(PIMAGE_NT_HEADERS)((LPBYTE)image+pIDH->e_lfanew);
    ManualInject.BaseRelocation=(PIMAGE_BASE_RELOCATION)((LPBYTE)image+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress);
    ManualInject.ImportDirectory=(PIMAGE_IMPORT_DESCRIPTOR)((LPBYTE)image+pINH->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
    ManualInject.fnLoadLibraryA=LoadLibraryA;
    ManualInject.fnGetProcAddress=GetProcAddress;

    printf("\nWriting loader code to target process.\n");

    WriteProcessMemory(hProcess,mem,&ManualInject,sizeof(MANUAL_INJECT),NULL); // Write the loader information to target process
    WriteProcessMemory(hProcess,(PVOID)((PMANUAL_INJECT)mem+1),LoadDll,(DWORD)LoadDllEnd-(DWORD)LoadDll,NULL); // Write the loader code to target process

    printf("\nExecuting loader code.\n");
    hThread=CreateRemoteThread(hProcess,NULL,0,(LPTHREAD_START_ROUTINE)((PMANUAL_INJECT)mem+1),mem,0,NULL); // Create a remote thread to execute the loader code

    if(!hThread)
    {
        printf("\nError: Unable to execute loader code (%d)\n",GetLastError());

        VirtualFreeEx(hProcess,mem,0,MEM_RELEASE);
        VirtualFreeEx(hProcess,image,0,MEM_RELEASE);

        CloseHandle(hProcess);

        VirtualFree(buffer,0,MEM_RELEASE);
        return -1;
    }

    WaitForSingleObject(hThread,INFINITE);
    GetExitCodeThread(hThread,&ExitCode);

    if(!ExitCode)
    {
        VirtualFreeEx(hProcess,mem,0,MEM_RELEASE);
        VirtualFreeEx(hProcess,image,0,MEM_RELEASE);

        CloseHandle(hThread);
        CloseHandle(hProcess);

        VirtualFree(buffer,0,MEM_RELEASE);
        return -1;
    }

    CloseHandle(hThread);
    VirtualFreeEx(hProcess,mem,0,MEM_RELEASE);

    CloseHandle(hProcess);

    printf("\nDLL injected at %#x\n",image);

    if(pINH->OptionalHeader.AddressOfEntryPoint)
    {
        printf("\nDLL entry point: %#x\n",(PVOID)((LPBYTE)image+pINH->OptionalHeader.AddressOfEntryPoint));
    }

    VirtualFree(buffer,0,MEM_RELEASE);
    return 0;
}