这个游戏是由论坛里 CnCrypt 大神发布的一个小游戏,《迷宫游戏,大家来挑战一下吧》。
闲着无聊就拿来玩玩,顺便做个 CE 的教程,当然这个小游戏的代码甚至比 CE 的 Tutorial 的还简单,没有什么增加难度的地方,大部分的变量都在全局或静态变量区,可以作为一个入门级的练习。
过程
找到储存坐标的地址
我的想法是,应该在上下左右移动的时候会有一个变量记录当前的 X Y 坐标的内存地址会变动,或者是记录整个迷宫形状的一块方形的内存区域中的某一位会改变(当然这个可能性较小)。然后我们就开始模糊搜索吧。
我首先尝试 4 字节整数型,未知的初始值,进行首次扫描。然后改变一下当前位置(比如向右移动 1 格),选择改变了的数值,然后再次扫描。然后再向左移动 1 格,再次扫描。反复进行这个步骤,直到剩余的个数基本不变了。
在搜索过程中可以不改变位置(先向右 1 格,再向左 1 格),选择未改变的数值,然后再次扫描,这样可以去除一些本身就是不断变动的数值。
- 如果只剩了 1 个,那么算你幸运,改一下这个试试,如果可行的话那么恭喜你,你学会了 CE 的最基础的用法。
- 如果剩下了好几个,除了其中的 1 个或几个看上去像个坐标,其他几个都是成千上万的,或者不断变动的,或者是奇怪的负数,那么其他那些基本都可以排除在外了。可以尝试移动一下位置,然后看坐标是否 +1 或 -1,来验证自己的猜想。
- 如果剩下了几百个(当然这款游戏不可能,这种情况大部分都是大型3D游戏之类的,很多坐标都会跟随当前人物一起移动),具体请参考 【原创】CE教程:实战篇。
这款小游戏可以很轻松的找到 X Y 坐标的位置,而且都是全局变量,内存地址都是静态的(重启游戏之后地址不会改变),非常容易修改。
我们可以轻松地找到这两个内存地址
Y坐标 MazeGame.exe+1E340
X坐标 MazeGame.exe+1E344
把他们改成 50 和 50,再稍微移动一下当前位置,重新触发一下程序中的判断,可以发现这个地址就是我们想要的。
这样一个简单的外挂就做完了。
穿墙?
穿墙是什么原理?把碰撞检测去掉不就可以穿墙了吗~(对于 3D 游戏要小心,去除碰撞检测之后可能会掉入地下,可能需要自己重写算法)
选中这个地址,右键,查找是什么访问了这个地址。然后随意移动一下。可能会出现好几条指令,一定要注意指令的顺序和计数器。
我们分析一下:首先读取这个地址进行碰撞检测,如果可以移动,那么还会再写回这个地址,然后绘图的程序又会再次访问这个地址。
按我们的分析第一条应该是碰撞检测,我们再周围找一下判断跳转指令,nop 掉试试。
选择“在反汇编器中显示”
MazeGame.exe+2262 - mov ecx,[MazeGame.exe+1E340] { [00000002] }
MazeGame.exe+2268 - mov edx,[MazeGame.exe+1E344] { [00000001] }
MazeGame.exe+226E - imul eax,ecx,000000CB { 203 }
MazeGame.exe+2274 - cmp byte ptr [eax+edx+MazeGame.exe+1E423],01 { 1 }
MazeGame.exe+227C - je MazeGame.exe+229A
MazeGame.exe+227E - push edi
MazeGame.exe+227F - push edi
MazeGame.exe+2280 - inc ecx
MazeGame.exe+2281 - push ebx
MazeGame.exe+2282 - mov [MazeGame.exe+1E340],ecx { [00000002] }
MazeGame.exe+2288 - call dword ptr [MazeGame.exe+151B4] { ->->win32u.NtUserInvalidateRect }
MazeGame.exe+228E - mov edx,[MazeGame.exe+1E344] { [00000001] }
MazeGame.exe+2294 - mov ecx,[MazeGame.exe+1E340] { [00000002] }
MazeGame.exe+229A - imul eax,ecx,000000CB { 203 }
分析一下这个代码,伪代码大概就是
ecx = Y坐标;
edx = X坐标;
eax = ecx * 0xCB;
if (*((byte *)(eax+edx+MazeGame.exe+1E423)) != 0x01) {
++ecx;
Y坐标 = ecx;
绘图();
}
MazeGame.exe+1E423
这块内存中应该就是迷宫地图,再化简一下就是
if (迷宫地图[Y坐标][X坐标] != 0x01) { // 数组宽度是 0xCB
++Y坐标;
绘图();
}
我们需要的只是修改一下 je 这条语句
MazeGame.exe+227C - 74 1C - je MazeGame.exe+229A
- 方法1:改成
90 90
(NOP掉)
- 方法2:改成
74 00
(跳转到下一条指令,这样无论条件是否成立都会继续运行)
第一种方法最简单了,直接右键这条指令,选择“替换成什么也不做”。
回到游戏中测试一下,成功,把上下左右的碰撞检测都去掉,你就可以为所欲为了。
最后记得保存哦。
相关链接
附件
MazeGame.CT.zip
(659 Bytes, 下载次数: 60)