CE教程:一个简单的迷宫游戏
本帖最后由 Ganlv 于 2018-4-16 13:39 编辑这个游戏是由论坛里 (https://www.52pojie.cn/home.php?mod=space&uid=512961&do=thread&view=me&from=space&type=thread) 大神发布的一个小游戏,《[迷宫游戏,大家来挑战一下吧](https://www.52pojie.cn/thread-724334-1-1.html)》。
闲着无聊就拿来玩玩,顺便做个 CE 的教程,当然这个小游戏的代码甚至比 CE 的 Tutorial 的还简单,没有什么增加难度的地方,大部分的变量都在全局或静态变量区,可以作为一个入门级的练习。
## 过程
### 找到储存坐标的地址
我的想法是,应该在上下左右移动的时候会有一个变量记录当前的 X Y 坐标的内存地址会变动,或者是记录整个迷宫形状的一块方形的内存区域中的某一位会改变(当然这个可能性较小)。然后我们就开始模糊搜索吧。
我首先尝试 4 字节整数型,未知的初始值,进行首次扫描。然后改变一下当前位置(比如向右移动 1 格),选择改变了的数值,然后再次扫描。然后再向左移动 1 格,再次扫描。反复进行这个步骤,直到剩余的个数基本不变了。
在搜索过程中可以不改变位置(先向右 1 格,再向左 1 格),选择未改变的数值,然后再次扫描,这样可以去除一些本身就是不断变动的数值。
* 如果只剩了 1 个,那么算你幸运,改一下这个试试,如果可行的话那么恭喜你,你学会了 CE 的最基础的用法。
* 如果剩下了好几个,除了其中的 1 个或几个看上去像个坐标,其他几个都是成千上万的,或者不断变动的,或者是奇怪的负数,那么其他那些基本都可以排除在外了。可以尝试移动一下位置,然后看坐标是否 +1 或 -1,来验证自己的猜想。
* 如果剩下了几百个(当然这款游戏不可能,这种情况大部分都是大型3D游戏之类的,很多坐标都会跟随当前人物一起移动),具体请参考 [【原创】CE教程:实战篇](https://www.52pojie.cn/thread-692068-1-1.html)。
这款小游戏可以很轻松的找到 X Y 坐标的位置,而且都是全局变量,内存地址都是静态的(重启游戏之后地址不会改变),非常容易修改。
我们可以轻松地找到这两个内存地址
```plain
Y坐标 MazeGame.exe+1E340
X坐标 MazeGame.exe+1E344
```
把他们改成 50 和 50,再稍微移动一下当前位置,重新触发一下程序中的判断,可以发现这个地址就是我们想要的。
这样一个简单的外挂就做完了。
### 穿墙?
穿墙是什么原理?把碰撞检测去掉不就可以穿墙了吗~(对于 3D 游戏要小心,去除碰撞检测之后可能会掉入地下,可能需要自己重写算法)
选中这个地址,右键,查找是什么访问了这个地址。然后随意移动一下。可能会出现好几条指令,一定要注意指令的顺序和计数器。
我们分析一下:首先读取这个地址进行碰撞检测,如果可以移动,那么还会再写回这个地址,然后绘图的程序又会再次访问这个地址。
按我们的分析第一条应该是碰撞检测,我们再周围找一下判断跳转指令,nop 掉试试。
选择“在反汇编器中显示”
```asm
MazeGame.exe+2262 - mov ecx, { }
MazeGame.exe+2268 - mov edx, { }
MazeGame.exe+226E - imul eax,ecx,000000CB { 203 }
MazeGame.exe+2274 - cmp byte ptr ,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 ,ecx { }
MazeGame.exe+2288 - call dword ptr { ->->win32u.NtUserInvalidateRect }
MazeGame.exe+228E - mov edx, { }
MazeGame.exe+2294 - mov ecx, { }
MazeGame.exe+229A - imul eax,ecx,000000CB { 203 }
```
分析一下这个代码,伪代码大概就是
```c
ecx = Y坐标;
edx = X坐标;
eax = ecx * 0xCB;
if (*((byte *)(eax+edx+MazeGame.exe+1E423)) != 0x01) {
++ecx;
Y坐标 = ecx;
绘图();
}
```
`MazeGame.exe+1E423` 这块内存中应该就是迷宫地图,再化简一下就是
```c
if (迷宫地图 != 0x01) { // 数组宽度是 0xCB
++Y坐标;
绘图();
}
```
我们需要的只是修改一下 je 这条语句
```asm
MazeGame.exe+227C - 74 1C - je MazeGame.exe+229A
```
* 方法1:改成 `90 90`(NOP掉)
* 方法2:改成 `74 00`(跳转到下一条指令,这样无论条件是否成立都会继续运行)
第一种方法最简单了,直接右键这条指令,选择“替换成什么也不做”。
回到游戏中测试一下,成功,把上下左右的碰撞检测都去掉,你就可以为所欲为了。
最后记得保存哦。
## 相关链接
* [迷宫游戏,大家来挑战一下吧](https://www.52pojie.cn/thread-724334-1-1.html)
* [【原创】CE教程:实战篇](https://www.52pojie.cn/thread-692068-1-1.html)
* [【原创】CE教程:基础篇](https://www.52pojie.cn/thread-691615-1-1.html)
* (http://cheatengine.org/)
* (http://cheatengine.org/download/ch_cn.zip) [使用方法](https://www.52pojie.cn/thread-691615-1-1.html#18713591_使用中文翻译文件)
* (https://github.com/cheat-engine/cheat-engine/releases)
* [爱盘下载](https://down.52pojie.cn/Tools/Debuggers/Cheat%20Engine%20v6.7.exe)
## 附件
请问方括号里面的是基址吗
如果是的话前面MazeGame.exe会变动的,能教下怎么解决吗
我是新手,问的问题很低级,望解答{:1_923:} 墨辰 发表于 2018-4-23 11:09
请问方括号里面的是基址吗
如果是的话前面MazeGame.exe会变动的,能教下怎么解决吗
我是新手,问的问题 ...
MazeGame.exe是模块地址,通过 GetModuleInformation 获取(相关API:GetModuleHandle EnumProcessModules)。
感谢分享,学习了··· CE教程呢楼主? {:301_975:}感谢楼主分享 学习了{:301_978:} 学习一下,看看能弄懂多少~{:301_978:} 试一试,
楼主学习了 学习加强己我{:1_921:} 看懂了 谢谢