1

我正在尝试将我的 DLL 注入到我刚刚创建的 64 位进程中。我最初创建它暂停,以便我可以在该进程中应用 WinAPI 补丁蹦床(从我注入的 DLL。)但如果我理解正确,我不能将我的 DLL 注入到暂停的进程中。

所以我想出了下面的代码,按照这个家伙的建议,但它并没有走远。失败,VirtualProtectEx我得到一个错误代码ERROR_INVALID_ADDRESS。我在下面的来源中标记了它。

知道我在哪里搞砸了吗?

PROCESS_INFORMATION pi = {0};
STARTUPINFO si = {0};
si.cb = sizeof(si);

WCHAR buffer[MAX_PATH];
::StringCchCopy(buffer, _countof(buffer), L"injected-process.exe");

if(CreateProcessW(0, buffer, 0, 0, 0, CREATE_SUSPENDED, 0, 0, &si, &pi))
{
    inject_dll_into_suspended_x64_proc(pi.hProcess, pi.hThread, "injected-process.exe");

    //... continue on
}

然后是准备注入过程的代码:

bool inject_dll_into_suspended_x64_proc(HANDLE hProc, HANDLE hMainThread, const char* pstrProcFileName)
{
    bool bRes = false;
    int nOSError = NO_ERROR;

    DWORD dwEntryOffset = 0;
    LOADED_IMAGE li = { 0 };
    if (::MapAndLoad(pstrProcFileName, NULL, &li, FALSE, TRUE))
    {
        dwEntryOffset = li.FileHeader->OptionalHeader.AddressOfEntryPoint;
        ::UnMapAndLoad(&li);
    }

    if(dwEntryOffset)
    {
        //  90               nop              
        //  EB FE            jmp         self
        static BYTE inject_asm_x64[] = {
            0x90,
            0xEB, 0xFE,
        };
        BYTE buffBackup[sizeof(inject_asm_x64)] = { 0 };

        //Get process base addr
        BYTE* pBaseAddr = (BYTE*)::VirtualAllocEx(hProc, NULL, sizeof(buffBackup), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
        if (pBaseAddr)
        {
            BYTE* pAddr = pBaseAddr + dwEntryOffset;

            DWORD dwOldProtect = 0;
            if (::VirtualProtectEx(hProc, pAddr, sizeof(buffBackup), PAGE_EXECUTE_READWRITE, &dwOldProtect))    //** FAILS: With error code: 487, or ERROR_INVALID_ADDRESS
            {
                __try
                {
                    //Backup what we have there now
                    size_t szcbRead = 0;
                    if (::ReadProcessMemory(hProc, pAddr, buffBackup, sizeof(buffBackup), &szcbRead) &&
                        szcbRead == sizeof(buffBackup))
                    {
                        //Now write our code into entry point
                        size_t dwcbSzWrtn = 0;
                        if (WriteProcessMemory(hProc, pAddr, inject_asm_x64, sizeof(inject_asm_x64), &dwcbSzWrtn) &&
                            dwcbSzWrtn == sizeof(inject_asm_x64))
                        {
                            bool bIntermediateSuccess = false;
                            bool bThreadIsSuspended = true;

                            //Resume thread
                            if (ResumeThread(hMainThread) == 1)
                            {
                                bThreadIsSuspended = false;

                                CONTEXT context;
                                bool bReached = false;

                                //Wait for it to reach our JMP self opcode
                                for(;; ::Sleep(1))
                                {
                                    if(!::GetThreadContext(hMainThread, &context))
                                    {
                                        //Failed
                                        nOSError = ::GetLastError();
                                        break;
                                    }

                                    if(context.Rip == (DWORD64)(pAddr + 1))     //First is nop, so skip it
                                    {
                                        //Got it
                                        bReached = true;
                                        break;
                                    }
                                }

                                if(bReached)
                                {
                                    //Do our DLL injection now
                                    if(inject_dll_here(hProc))
                                    {
                                        //Injected OK
                                        bIntermediateSuccess = true;
                                    }
                                    else
                                        nOSError = ::GetLastError();

                                    //Suspend main thread
                                    if(::SuspendThread(hMainThread) == 0)
                                    {
                                        //Thread is again suspended
                                        bThreadIsSuspended = true;
                                    }
                                    else
                                    {
                                        //Failed
                                        nOSError = ::GetLastError();
                                        bIntermediateSuccess = false;
                                    }
                                }
                            }
                            else
                                nOSError = ::GetLastError();

                            if(bThreadIsSuspended)
                            {
                                //Revert process memory back
                                if (WriteProcessMemory(hProc, pAddr, buffBackup, sizeof(buffBackup), &dwcbSzWrtn) &&
                                    dwcbSzWrtn == sizeof(buffBackup))
                                {
                                    //Now restore the main thread
                                    if (ResumeThread(hMainThread) == 1)
                                    {
                                        //Done
                                        bRes = bIntermediateSuccess;
                                    }
                                    else
                                        nOSError = ::GetLastError();
                                }
                                else
                                    nOSError = ::GetLastError();
                            }
                        }
                        else
                            nOSError = ::GetLastError();
                    }
                    else
                        nOSError = ::GetLastError();
                }
                __finally
                {
                    //Reset protection flags
                    ::VirtualProtectEx(hProc, pAddr, sizeof(buffBackup), dwOldProtect, NULL);
                }
            }
            else
                nOSError = ::GetLastError();

            //Free mem
            ::VirtualFreeEx(hProc, pBaseAddr, 0, MEM_RELEASE);
        }
        else
            nOSError = ::GetLastError();
    }
    else
        nOSError = ::GetLastError();

    return bRes;
}
4

0 回答 0