我一直试图写一个蹦床钩在退出过程中的乐趣。钩子的代码(消息框)执行得很好,但是当返回EXIT进程的时候,我得到了一个访问冲突。我已经读了好几遍自己的代码,看不出有什么问题我将旧的函数序言存储在字节数组中,并将jmp添加到我修补的地址之后的地址中我是不是走错了路?

#include "main.h"

PVOID TrampolineAddress;
BYTE TrampolineBytes[10] = { 0, 0, 0, 0, 0, 0xE9, 0, 0, 0, 0 };

void ExitProcessNew(UINT uExitCode)
{
    MessageBox(NULL, "Exiting!", "Exiting!", 0);
    _asm
    {
        push uExitCode;
        call TrampolineAddress;
    }
}

int main()
{
    memcpy(&TrampolineBytes, &ExitProcess, 5);
    *(DWORD*)&TrampolineBytes[6] = (DWORD)((DWORD)&ExitProcessNew) - (DWORD)&ExitProcess;

    TrampolineAddress = VirtualAlloc(NULL, 10, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
    memcpy(TrampolineAddress, TrampolineBytes, 10);

    BYTE PatchBytes[] = { 0xE9, 0, 0, 0, 0 };
    *(DWORD*)&PatchBytes[1] = (DWORD)((DWORD)&ExitProcessNew) - (DWORD)&ExitProcess - 5;

    BOOL writeSuccess = WriteProcessMemory(GetCurrentProcess(), &ExitProcess, PatchBytes, sizeof(PatchBytes), NULL);

    ExitProcess(0);
    printf("%d", GetLastError());
    getchar();
}

最佳答案

我花了很长时间试图让你的代码工作,但最终还是放弃了,我觉得仅仅向你展示有效的代码比修复你的代码更容易你的逻辑是有道理的,但我认为有几个小错误导致了失败。
所以这是我很久以来一直使用的方法,它基于一个朋友和我分享的名为Solaire的代码:
常规挂钩/绕行功能:

bool Hook(BYTE* src, BYTE* dst, int len)
{
    if (len < 5) return false;

    DWORD  curProtection;
    VirtualProtect(src, len, PAGE_EXECUTE_READWRITE, &curProtection);

    uintptr_t  relativeAddress = ((uintptr_t)dst - (uintptr_t)src) - 5;

    *src = 0xE9;
    *(uintptr_t *)((uintptr_t)src + 1) = relativeAddress;

    VirtualProtect(src, len, curProtection, &curProtection);
    return true;
}

蹦床功能:
void * TrampolineHook(BYTE* src, BYTE* dst, int len)
{
    // Make sure the length is greater than 5
    if (len < 5) return 0;

    // Create the gateway (len + 5 for the overwritten bytes + the jmp)
    void* gateway = VirtualAlloc(0, len + 5, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

    //Write the stolen bytes into the gateway
    memcpy(gateway, src, len);

    // Get the gateway to destination addy
    uintptr_t  gatewayRelativeAddr = ((uintptr_t)src - (uintptr_t)gateway) - 5;

    // Add the jmp opcode to the end of the gateway
    *(BYTE*)((uintptr_t)gateway + len) = 0xE9;

    // Add the address to the jmp
    *(uintptr_t *)((uintptr_t)gateway + len + 1) = gatewayRelativeAddr;

    // Place the hook at the destination
    Hook(src, dst, len);

    return gateway;
}

你已经知道逻辑了,所以我不需要解释代码,注释就足够了。
下面我们将介绍一个与ExtPoalEngy函数匹配的函数指针,并将其与模板“T”前缀。
然后我们创建该类型的指针,并在其前面加上“o”作为original的前缀,因为在运行代码之后,我们将使用它调用“original”函数然后,我们重定向流到的实际函数的前缀是“h”表示“hooked”或其他。
主代码:
typedef void(__stdcall* tExitProcess)(UINT);
tExitProcess oExitProcess;

void __stdcall hExitProcess(UINT uExitCode)
{
    MessageBox(NULL, "Exiting!", "Exiting!", 0);
    Sleep(1000);

    return oExitProcess(uExitCode);
}

int main()
{
    oExitProcess = (tExitProcess)TrampolineHook((BYTE*)&ExitProcess, (BYTE*)&hExitProcess, 5);
    ExitProcess(0);
}

很标准的程序,试试看,也许可以和你的比较,希望能帮上忙

10-05 22:41