一、工具及游戏介绍
使用工具:Ollydbg,PEID,Cheat Engine
实现功能:玩家无敌
目标:找到全局数据,或关键代码块。
游戏版本:合金弹头1-5代珍藏版
二、逆向逻辑
1、初始判断【CE数据】
通过游戏试玩,发现玩家是一次性死亡,但在复活开始阶段,有闪光的无敌状态。
可利用这点,实现无敌。
刚开始先通过CE找到类似秒数的 复活状态信息数据,并找到修改数据的代码段。
2、OD调试【OD追踪关键代码块】
在秒数数据下硬件写入断点,得到修改数据的代码。
回溯跟踪分析,分析DL的来源,追踪关键代码块。
在函数入口处下条件断点。
往上分析,发现削减数据,DL来源于【EBX*4+0x5FE0A8】,
经多次验证,EBX == 0x0,所以数据来源0x5FE0A8
此地址数据一直在变化,下硬件写入断点,得到相关计算的功能代码。
跟踪分析,发现此函数返回未削减的数值,并准备调用削减功能代码。
进入分析。
发现函数从固定地址0x711470 + EAX偏移(模块内),取出中间堆数据地址(堆内)。
再通过 中间堆数据地址 + ECX偏移,得到放在 堆中的无敌状态数值。
通过得到无敌状态数值,调用削减功能代码,进行削减后,
再发往0x5FE0A8处,再赋回堆0x39C60CB处。
3、分析和实现
所以,此处可对 EAX偏移,ECX偏移,进行判断。
准确锁定状态数据,并进行Hook代码。
实现内联HOOK,完成无敌。
三、总结:
1、总体逻辑
﹒﹒﹒﹒﹒﹒﹒﹒﹒Hook中间代码实现 ↓ 实现数据恒定
﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒(取出修改)
﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒↓↓↓--------------↑↑↑
固定数据------------>>>中间数据--------->>>中间堆数据
(复活初始赋值) ﹒(多种数据临时存放点) ﹒(无敌状态数据)
﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒(0x5FE0A8) ﹒﹒﹒﹒﹒(0x39C60CB)
﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒↓↓↓----------------↑↑↑
﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒﹒(修改存放)
2、Hook Opcode
83 F1 01 3D 70 1C 71 00 75 0B 81 F9 84 04 10 00 75 03 B0 99 C3 8A 04 11 C3
3、功能代码
//找到进程 HANDLE ReProcess = 0; PROCESSENTRY32 pe32; pe32.dwSize = sizeof(pe32); HANDLE hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); BOOL bMore = ::Process32First(hProcessSnap, &pe32); //多字节转宽字节 WCHAR proname[20] = {}; MultiByteToWideChar(CP_ACP, MB_COMPOSITE, "WinKawaks.exe", 20, proname, 20); while (bMore) { if (wcscmp(pe32.szExeFile, proname) == 0) { ReProcess = ::OpenProcess(PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID); printf("找到了\\n"); break; } bMore = Process32Next(hProcessSnap, &pe32); } HANDLE process; process = OpenProcess(PROCESS_ALL_ACCESS, FALSE, 0xeb4); //Hook 地点 DWORD attibute; VirtualProtectEx(ReProcess, (LPVOID)0x00444779, 0x6, PAGE_READWRITE, &attibute); //jmp HookOpcode BYTE OPecode1[] = { ‘\\xE9‘, ‘\\xB8‘, ‘\\xC2‘, ‘\\x07‘, ‘\\x00‘, ‘\\x90‘ }; DWORD num; WriteProcessMemory(ReProcess, (LPVOID)0x00444779, OPecode1, 6, &num); VirtualProtectEx(ReProcess, (LPVOID)0x00444779, 0x6, attibute, &attibute); //Hook Opcode VirtualProtectEx(ReProcess, (LPVOID)0x004c0a36, 0x25, PAGE_READWRITE, &attibute); //HookOpcode BYTE OPecode2[] = { ‘\\x83‘, ‘\\xF1‘, ‘\\x01‘, ‘\\x3D‘, ‘\\x70‘, ‘\\x1C‘, ‘\\x71‘, ‘\\x00‘, ‘\\x75‘, ‘\\x0B‘, ‘\\x81‘, ‘\\xF9‘, ‘\\x84‘, ‘\\x04‘, ‘\\x10‘, ‘\\x00‘, ‘\\x75‘, ‘\\x03‘, ‘\\xB0‘, ‘\\x99‘, ‘\\xC3‘, ‘\\x8A‘, ‘\\x04‘, ‘\\x11‘, ‘\\xC3‘ }; WriteProcessMemory(ReProcess, (LPVOID)0x004c0a36, OPecode2, 25, &num); VirtualProtectEx(ReProcess, (LPVOID)0x004c0a36, 0x25, attibute, &attibute); CloseHandle(ReProcess);
四、效果
完成无敌:
个人总结:
虽然只是个小外挂,但找出了类似储存游戏数据的地方。虽然不太确定,但往这条路分析下去,以此达到其它功能,潜力还是蛮大的。
附件:
KID