C++ 如何将DLL注入挂起的x64进程?

C++ 如何将DLL注入挂起的x64进程?,c++,winapi,dependency-injection,dll-injection,trampolines,C++,Winapi,Dependency Injection,Dll Injection,Trampolines,我正在尝试将我的DLL注入到我刚刚创建的64位进程中。我最初创建它是挂起的,这样我就可以在该进程中应用WinAPI补丁蹦床(从我注入的DLL)。但是如果我这样做,我就不能将我的DLL注入挂起的进程 因此,我提出了以下代码,遵循,但它没有走远。VirtualProtectEx失败,我得到一个错误代码error\u INVALID\u ADDRESS。我在下面的源代码中做了标记 知道我把事情搞砸了吗 PROCESS_INFORMATION pi = {0}; STARTUPINFO si = {0}

我正在尝试将我的DLL注入到我刚刚创建的64位进程中。我最初创建它是挂起的,这样我就可以在该进程中应用WinAPI补丁蹦床(从我注入的DLL)。但是如果我这样做,我就不能将我的DLL注入挂起的进程

因此,我提出了以下代码,遵循,但它没有走远。
VirtualProtectEx
失败,我得到一个错误代码
error\u INVALID\u 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;
}

我不能将我的DLL注入一个挂起的进程——绝对是胡说八道。例如,为什么不使用apc来为进程注入dll或任意外壳代码?@RbMm:我使用的外壳代码调用
LoadLibrary
,我将其注入目标进程,然后使用
CreateRemoteThread
执行,但问题是,当目标进程仍然挂起或尚未运行时,我可以这样做吗?是的,不专业,不胡说八道。我在这个话题上有丰富的经验,知道我说的是什么——将apc注入子进程是最好的选择。结果,shell代码(或LoadLibrary)将在入口点之前的第一个进程线程中执行。你为什么不用这个?对于您尝试的修补程序exe条目?为什么这么难看的代码会出现大量错误?您只需调用
QueueUserAPC
。你的线柄。如果您尝试修补程序exe入口点-所以在exe入口点之前执行代码对您来说必须是正确的。我不能将我的DLL插入挂起的进程-绝对是胡说八道。例如,为什么不使用apc来为进程注入dll或任意外壳代码?@RbMm:我使用的外壳代码调用
LoadLibrary
,我将其注入目标进程,然后使用
CreateRemoteThread
执行,但问题是,当目标进程仍然挂起或尚未运行时,我可以这样做吗?是的,不专业,不胡说八道。我在这个话题上有丰富的经验,知道我说的是什么——将apc注入子进程是最好的选择。结果,shell代码(或LoadLibrary)将在入口点之前的第一个进程线程中执行。你为什么不用这个?对于您尝试的修补程序exe条目?为什么这么难看的代码会出现大量错误?您只需调用
QueueUserAPC
。你的线柄。如果您尝试修补程序exe入口点-所以在exe入口点之前执行代码对您来说必须是正确的。