在游戏逆向中我们需要在某个执行函数的地方添加自己的代码。
案例:HackMe.exe
每按一次空格扣两滴血
目标:hook扣血函数,改为double加血

拉进Od后定位到扣血的函数如下图
00BB2740 55 push ebp
00BB2741 8BEC mov ebp,esp
00BB2743 81EC CC000000 sub esp,0xCC
00BB2749 53 push ebx
00BB274A 56 push esi ; HackMe.<ModuleEntryPoint>
00BB274B 57 push edi ; HackMe.<ModuleEntryPoint>
00BB274C 51 push ecx ; HackMe.<ModuleEntryPoint>
00BB274D 8DBD 34FFFFFF lea edi,dword ptr ss:[ebp-0xCC]
00BB2753 B9 33000000 mov ecx,0x33
00BB2758 B8 CCCCCCCC mov eax,0xCCCCCCCC
00BB275D F3:AB rep stos dword ptr es:[edi]
00BB275F 59 pop ecx ; kernel32.771F6359
00BB2760 894D F8 mov dword ptr ss:[ebp-0x8],ecx ; HackMe.<ModuleEntryPoint>
00BB2763 8B45 F8 mov eax,dword ptr ss:[ebp-0x8]
00BB2766 8B08 mov ecx,dword ptr ds:[eax]
00BB2768 2B4D 08 sub ecx,dword ptr ss:[ebp+0x8]
00BB276B 8B55 F8 mov edx,dword ptr ss:[ebp-0x8]
00BB276E 890A mov dword ptr ds:[edx],ecx ; HackMe.<ModuleEntryPoint>
00BB2770 8B45 F8 mov eax,dword ptr ss:[ebp-0x8]
00BB2773 8338 00 cmp dword ptr ds:[eax],0x0
00BB2776 7F 07 jg short HackMe.00BB277F
00BB2778 8B45 F8 mov eax,dword ptr ss:[ebp-0x8]
00BB277B C640 08 01 mov byte ptr ds:[eax+0x8],0x1
00BB277F 5F pop edi ; kernel32.771F6359
00BB2780 5E pop esi ; kernel32.771F6359
00BB2781 5B pop ebx ; kernel32.771F6359
00BB2782 8BE5 mov esp,ebp
00BB2784 5D pop ebp ; kernel32.771F6359
00BB2785 C2 0400 retn 0x4
地址00BB2768 sub ecx,dword ptr ss:[ebp+0x8]
我们想要把该指令改为jmp [ourFunc]然后在ourFunc中在jmp回来。

代码实现
#include <Windows.h>
bool Hook(void* toHook, void* ourFunct, int len) {
if (len < 5) {
return false;
}
DWORD curProtection;
VirtualProtect(toHook, len, PAGE_EXECUTE_READWRITE, &curProtection);
memset(toHook, 0x90, len);
DWORD relativeAddress = ((DWORD)ourFunct - (DWORD)toHook) - 5;
*(BYTE*)toHook = 0xE9;//jmp
*(DWORD*)((DWORD)toHook + 1) = relativeAddress;
DWORD temp;
VirtualProtect(toHook, len, curProtection, &temp);
return true;
}
DWORD jmpBackAddy;
void __declspec(naked) ourFunct() {
__asm {
add ecx, ecx
mov edx, [ebp - 8]
jmp[jmpBackAddy]
}
}
DWORD WINAPI MainThread(LPVOID param) {
int hookLength = 6;
DWORD hookAddress = 0xBB2768;
jmpBackAddy = hookAddress + hookLength;
Hook((void*)hookAddress, ourFunct, hookLength);
while (true) {
if (GetAsyncKeyState(VK_ESCAPE)) break;
Sleep(50);
}
FreeLibraryAndExitThread((HMODULE)param, 0);
return 0;
}
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD dwReason, LPVOID lpReserved) {
switch (dwReason) {
case DLL_PROCESS_ATTACH:
CreateThread(0, 0, MainThread, hModule, 0, 0);
break;
}
return TRUE;
}
由于jmp指令最少占5字节,所以我们必须覆写连同目标指令下一条指令

连起来为6字节
运行HackMe 并注入dll

跳转成功


博客围绕游戏逆向展开,以HackMe.exe为例,介绍在游戏逆向中于执行函数处添加代码的方法。目标是hook扣血函数,将其改为double加血。通过Od定位扣血函数,把指令改为jmp [ourFunc]并在其中跳转回来,还说明了代码实现需覆写指令,最后运行游戏并注入dll实现跳转。
341

被折叠的 条评论
为什么被折叠?



