#include "pch.h"
#include <iostream>
#include <Windows.h>
#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
", regs->rax);
printf("rbx: %x
", regs->rbx);
printf("rcx: %x
", regs->rcx);
printf("rdx: %x
", regs->rdx);
regs->eax = 100;
*(DWORD*)(regs->rbx + 0x7F0) = regs->eax;
#else
printf("eax: %x
", regs->eax);
printf("ebx: %x
", regs->ebx);
printf("ecx: %x
", regs->ecx);
printf("edx: %x
", 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
");
// 钩住这里
//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<BYTE> 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<BYTE> 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
// 使用堆栈大小
// 4*8=32=0x20
// 16*8=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
" // sub rsp,0xA0
"48 89 44 24 20
" // mov [rsp+0x20],rax
"48 89 5C 24 28
" // mov [rsp+0x28],rbx
"48 89 4C 24 30
" // mov [rsp+0x30],rcx
"48 89 54 24 38
" // mov [rsp+0x38],rdx
"48 89 74 24 40
" // mov [rsp+0x40],rsi
"48 89 7C 24 48
" // mov [rsp+0x48],rdi
"48 89 6C 24 50
" // mov [rsp+0x50],rbp
"48 89 64 24 58
" // mov [rsp+0x58],rsp
"4C 89 44 24 60
" // mov [rsp+0x60],r8
"4C 89 4C 24 68
" // mov [rsp+0x68],r9
"4C 89 54 24 70
" // mov [rsp+0x70],r10
"4C 89 5C 24 78
" // mov [rsp+0x78],r11
"4C 89 A4 24 80 00 00 00
" // mov [rsp+0x80],r12
"4C 89 AC 24 88 00 00 00
" // mov [rsp+0x88],r13
"4C 89 B4 24 90 00 00 00
" // mov [rsp+0x90],r14
"4C 89 BC 24 98 00 00 00
" // mov [rsp+0x98],r15
// 2
"48 8D 4C 24 20
" // lea rcx,[rsp+0x20]
"48 B8"; // mov rax,
vector<BYTE> 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
" // call rax
"48 8B 44 24 20
" // mov rax,[rsp+0x20]
"48 8B 5C 24 28
" // mov rbx,[rsp+0x28]
"48 8B 4C 24 30
" // mov rcx,[rsp+0x30]
"48 8B 54 24 38
" // mov rdx,[rsp+0x38]
"48 8B 74 24 40
" // mov rsi,[rsp+0x40]
"48 8B 7C 24 48
" // mov rdi,[rsp+0x48]
"48 8B 6C 24 50
" // mov rbp,[rsp+0x50]
"48 8B 64 24 58
" // mov rsp,[rsp+0x58]
"4C 8B 44 24 60
" // mov r8,[rsp+0x60]
"4C 8B 4C 24 68
" // mov r9,[rsp+0x68]
"4C 8B 54 24 70
" // mov r10,[rsp+0x70]
"4C 8B 5C 24 78
" // mov r11,[rsp+0x78]
"4C 8B A4 24 80 00 00 00
" // mov r12,[rsp+0x80]
"4C 8B AC 24 88 00 00 00
" // mov r13,[rsp+0x88]
"4C 8B B4 24 90 00 00 00
" // mov r14,[rsp+0x90]
"4C 8B BC 24 98 00 00 00
" // mov r15,[rsp+0x98]
"48 81 C4 A0 00 00 00"; // add rsp,0xA0
vector<BYTE> 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
" // push esp
"55
" // push ebp
"57
" // push edi
"56
" // push esi
"52
" // push edx
"51
" // push ecx
"53
" // push ebx
"50
" // push eax
"54"; // push esp
vector<BYTE> 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
" // pop eax
"5B
" // pop ebx
"59
" // pop ecx
"5A
" // pop edx
"5E
" // pop esi
"5F
" // pop edi
"5D
" // pop ebp
"83 C4 04"; // add esp,0x04
vector<BYTE> 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 开启/关闭
");
while (!GetAsyncKeyState(VK_F12))
{
if (GetAsyncKeyState(VK_F4) & 1)
{
bEnable = !bEnable;
if (bEnable)
{
printf("挂钩
");
// 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("脱钩
");
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;
}