c++ x86_x64挂钩函数 传递寄存器表
阅读原文时间:2023年07月11日阅读:1
  • https://github.com/januwA/GameCheat

    #include "pch.h"
    #include
    #include
    #include "GameCheat.h"

    using namespace std;

    struct Regs
    {
    #ifdef _WIN64
    union
    {
    uint64_t rax;
    DWORD eax;
    WORD ax;
    // BYTE ah; // (BYTE)((BYTE*)(&r.ax) + 1)
    BYTE al;
    };
    uintptr_t rbx;
    uintptr_t rcx;
    uintptr_t rdx;
    uintptr_t rsi;
    uintptr_t rdi;
    uintptr_t rbp;
    uintptr_t rsp;
    uintptr_t r8;
    uintptr_t r9;
    uintptr_t r10;
    uintptr_t r11;
    uintptr_t r12;
    uintptr_t r13;
    uintptr_t r14;
    uintptr_t r15;
    #else
    uintptr_t eax;
    uintptr_t ebx;
    uintptr_t ecx;
    uintptr_t edx;
    uintptr_t esi;
    uintptr_t edi;
    uintptr_t ebp;
    uintptr_t esp;
    #endif // _WIN64

    };

    void __stdcall myHook(Regs* regs)
    {
    #ifdef _WIN64
    printf("rax: %x\n", regs->rax);
    printf("rbx: %x\n", regs->rbx);
    printf("rcx: %x\n", regs->rcx);
    printf("rdx: %x\n", regs->rdx);
    regs->eax = 100;
    (DWORD)(regs->rbx + 0x7F0) = regs->eax;
    #else
    printf("eax: %x\n", regs->eax);
    printf("ebx: %x\n", regs->ebx);
    printf("ecx: %x\n", regs->ecx);
    printf("edx: %x\n", regs->edx);
    regs->eax = 99;
    (DWORD)(regs->ebx + 0x4AC) = regs->eax;
    #endif // _WIN64
    }

    DWORD WINAPI MyThread(HMODULE hModule)
    {

    #ifdef _WIN64
    GameCheat gc{ "Tutorial-x86_64.exe" };
    #else
    GameCheat gc{ "Tutorial-i386.exe" };
    #endif // _WIN64

    FILE* f;
    gc.openConsole(&f);
    printf("INJECT OK\n");

    // 钩住这里
    //x64 Tutorial-x86_64.exe+2B08C - 29 83 F0070000 - sub [rbx+000007F0],eax
    //x86 Tutorial-i386.exe+2578F - 29 83 AC040000 - sub [ebx+000004AC],eax

    #ifdef _WIN64
    BYTE* addr = (BYTE)gc.mi.lpBaseOfDll + 0x2B08C; vector copyBytes = GameCheat::byteStr2Bytes("29 83 F0 07 00 00"); BYTE lpAddress = (BYTE)gc.mi.lpBaseOfDll - 0x10000; #else BYTE addr = (BYTE)gc.mi.lpBaseOfDll + 0x2578F; vector copyBytes = GameCheat::byteStr2Bytes("29 83 AC 04 00 00"); BYTE lpAddress = 0;
    #endif // _WIN64

    BYTE* newHook = (BYTE*)VirtualAlloc(lpAddress, 500, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    size_t position = 0;

    #ifdef _WIN64
    // 使用堆栈大小
    // 48=32=0x20 // 168=128=0x80
    // 32+128=160=0xA0

    /*
    global Start
    section .text
    ; 1
    sub rsp,0xA0
    mov [rsp+0x20],rax
    mov [rsp+0x28],rbx
    mov [rsp+0x30],rcx
    mov [rsp+0x38],rdx
    mov [rsp+0x40],rsi
    mov [rsp+0x48],rdi
    mov [rsp+0x50],rbp
    mov [rsp+0x58],rsp
    mov [rsp+0x60],r8
    mov [rsp+0x68],r9
    mov [rsp+0x70],r10
    mov [rsp+0x78],r11
    mov [rsp+0x80],r12
    mov [rsp+0x88],r13
    mov [rsp+0x90],r14
    mov [rsp+0x98],r15

    ; 2
    lea rcx,[rsp+0x20]
    mov rax,myHook
    call rax

    ; 3
    mov rax,[rsp+0x20]
    mov rbx,[rsp+0x28]
    mov rcx,[rsp+0x30]
    mov rdx,[rsp+0x38]
    mov rsi,[rsp+0x40]
    mov rdi,[rsp+0x48]
    mov rbp,[rsp+0x50]
    mov rsp,[rsp+0x58]
    mov r8,[rsp+0x60]
    mov r9,[rsp+0x68]
    mov r10,[rsp+0x70]
    mov r11,[rsp+0x78]
    mov r12,[rsp+0x80]
    mov r13,[rsp+0x88]
    mov r14,[rsp+0x90]
    mov r15,[rsp+0x98]
    add rsp,0xA0

    myHook:
    */

    // 1
    string bytesStr1 = "48 81 EC A0 00 00 00\n" // sub rsp,0xA0
    "48 89 44 24 20\n" // mov [rsp+0x20],rax
    "48 89 5C 24 28\n" // mov [rsp+0x28],rbx
    "48 89 4C 24 30\n" // mov [rsp+0x30],rcx
    "48 89 54 24 38\n" // mov [rsp+0x38],rdx
    "48 89 74 24 40\n" // mov [rsp+0x40],rsi
    "48 89 7C 24 48\n" // mov [rsp+0x48],rdi
    "48 89 6C 24 50\n" // mov [rsp+0x50],rbp
    "48 89 64 24 58\n" // mov [rsp+0x58],rsp
    "4C 89 44 24 60\n" // mov [rsp+0x60],r8
    "4C 89 4C 24 68\n" // mov [rsp+0x68],r9
    "4C 89 54 24 70\n" // mov [rsp+0x70],r10
    "4C 89 5C 24 78\n" // mov [rsp+0x78],r11
    "4C 89 A4 24 80 00 00 00\n" // mov [rsp+0x80],r12
    "4C 89 AC 24 88 00 00 00\n" // mov [rsp+0x88],r13
    "4C 89 B4 24 90 00 00 00\n" // mov [rsp+0x90],r14
    "4C 89 BC 24 98 00 00 00\n" // mov [rsp+0x98],r15
    // 2
    "48 8D 4C 24 20\n" // lea rcx,[rsp+0x20]
    "48 B8"; // mov rax,

    vector bytes1 = GameCheat::byteStr2Bytes(bytesStr1);
    memcpy_s(newHook + position, bytes1.size(), bytes1.data(), bytes1.size());
    position += bytes1.size();

    (uintptr_t)(newHook + position) = (uintptr_t)myHook; // myHook
    position += sizeof(uintptr_t);

    // 3
    string bytesStr2 = "FF D0\n" // call rax
    "48 8B 44 24 20\n" // mov rax,[rsp+0x20]
    "48 8B 5C 24 28\n" // mov rbx,[rsp+0x28]
    "48 8B 4C 24 30\n" // mov rcx,[rsp+0x30]
    "48 8B 54 24 38\n" // mov rdx,[rsp+0x38]
    "48 8B 74 24 40\n" // mov rsi,[rsp+0x40]
    "48 8B 7C 24 48\n" // mov rdi,[rsp+0x48]
    "48 8B 6C 24 50\n" // mov rbp,[rsp+0x50]
    "48 8B 64 24 58\n" // mov rsp,[rsp+0x58]
    "4C 8B 44 24 60\n" // mov r8,[rsp+0x60]
    "4C 8B 4C 24 68\n" // mov r9,[rsp+0x68]
    "4C 8B 54 24 70\n" // mov r10,[rsp+0x70]
    "4C 8B 5C 24 78\n" // mov r11,[rsp+0x78]
    "4C 8B A4 24 80 00 00 00\n" // mov r12,[rsp+0x80]
    "4C 8B AC 24 88 00 00 00\n" // mov r13,[rsp+0x88]
    "4C 8B B4 24 90 00 00 00\n" // mov r14,[rsp+0x90]
    "4C 8B BC 24 98 00 00 00\n" // mov r15,[rsp+0x98]
    "48 81 C4 A0 00 00 00"; // add rsp,0xA0
    vector bytes2 = GameCheat::byteStr2Bytes(bytesStr2);
    memcpy_s(newHook + position, bytes2.size(), bytes2.data(), bytes2.size());
    position += bytes2.size();

    #else
    // 使用堆栈大小

    /*
    global Start
    section .text
    ; 1
    push esp
    push ebp
    push edi
    push esi
    push edx
    push ecx
    push ebx
    push eax

    ; 2
    push esp
    call myHook

    ; 3
    pop eax
    pop ebx
    pop ecx
    pop edx
    pop esi
    pop edi
    pop ebp
    add esp,0x04

    myHook:

    */

    // 1
    string bytesStr1 = "54\n" // push esp
    "55\n" // push ebp
    "57\n" // push edi
    "56\n" // push esi
    "52\n" // push edx
    "51\n" // push ecx
    "53\n" // push ebx
    "50\n" // push eax
    "54"; // push esp

    vector bytes1 = GameCheat::byteStr2Bytes(bytesStr1);
    memcpy_s(newHook + position, bytes1.size(), bytes1.data(), bytes1.size());
    position += bytes1.size();

    // call myHook
    DWORD callMyHookBytes = (BYTE*)myHook - (newHook + position) - 5;
    *(newHook + position) = 0xE8;
    position += sizeof(BYTE);
    (DWORD)(newHook + position) = callMyHookBytes;
    position += sizeof(DWORD);

    // 3
    string bytesStr2 = "58\n" // pop eax
    "5B\n" // pop ebx
    "59\n" // pop ecx
    "5A\n" // pop edx
    "5E\n" // pop esi
    "5F\n" // pop edi
    "5D\n" // pop ebp
    "83 C4 04"; // add esp,0x04

    vector bytes2 = GameCheat::byteStr2Bytes(bytesStr2);
    memcpy_s(newHook + position, bytes2.size(), bytes2.data(), bytes2.size());
    position += bytes2.size();

    #endif // _win64

    // 拷贝盗取的字节,看情况也可以不要
    /*
    memcpy_s(newHook + position, copyBytes.size(), copyBytes.data(), copyBytes.size());
    position += copyBytes.size();
    */

    // return
    DWORD jmpReturnBytes = (addr + copyBytes.size()) - (newHook + position) - 5;
    *(newHook + position) = 0xE9;
    position += sizeof(BYTE);
    *(DWORD*)(newHook + position) = jmpReturnBytes;

    DWORD jmpHookBytes = newHook - addr - 5;
    bool bEnable = false;
    printf(" F4 开启/关闭\n");
    while (!GetAsyncKeyState(VK_F12))
    {
    if (GetAsyncKeyState(VK_F4) & 1)
    {
    bEnable = !bEnable;
    if (bEnable)
    {
    printf("挂钩\n");
    // Tutorial-x86_64.exe+2B08C >> jmp newHook
    DWORD oldProc;
    VirtualProtect(addr, copyBytes.size(), PAGE_EXECUTE_READWRITE, &oldProc);
    memset(addr, 0x90, copyBytes.size());
    *addr = 0xE9;
    *(DWORD*)(addr + 1) = jmpHookBytes;
    VirtualProtect(addr, copyBytes.size(), oldProc, 0);
    }
    else
    {
    printf("脱钩\n");
    DWORD oldProc;
    VirtualProtect(addr, copyBytes.size(), PAGE_EXECUTE_READWRITE, &oldProc);
    memcpy_s(addr, copyBytes.size(), copyBytes.data(), copyBytes.size());
    VirtualProtect(addr, copyBytes.size(), oldProc, 0);
    }
    }
    Sleep(10);
    }

    VirtualFree(newHook, 0, MEM_RELEASE);
    gc.closeConsole(f);
    FreeLibraryAndExitThread(hModule, 0);
    return 0;
    }

    BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD ul_reason_for_call,
    LPVOID lpReserved
    )
    {
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    CloseHandle(CreateThread(0, 0, (LPTHREAD_START_ROUTINE)MyThread, hModule, 0, 0));
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
    break;
    }
    return TRUE;
    }