一、背景
最近玩CE的时候,突然发现Help菜单里面居然还藏着一个小游戏,花了半天时间,终于使用CE完成了所有关卡,现在分享给大家,也可以和大家共同加深CE功能的学习。
二、环境
系统:windows 10
调试器:Cheat Engine 7.1
目标游戏:CE自带的TutorialGame
三、游戏过关攻略
1.第一关
观察游戏:
首先,我们打开游戏,选择第一关,全通关后需要选择,没通关的话直接进去就是第一关,CE附加游戏。
观察游戏界面如下:
这里会有一个提示,每5次射击后,子弹会重装,之后目标会治疗,试着找出一种方式摧毁目标,经过我们的尝试,发现单纯射击,确实干不掉它。子弹打完它就满血了。
过关思路:我们可以找到放子弹的变量,然后将其锁定,即可让子弹永远打不完,从而绕过目标的治疗。
开始操作:
首先,搜索当前子弹数量,射击,再次搜索子弹数量,这是一种常见的变量搜索方法,也是CE里面最强大的一种方法。
这时候我们发现问题了,搜到后面,发现没有结果了?我们思路肯定出现了一点问题,或许子弹不是减少,而是增加?增加到5就重置?好的,打光子弹,从0开始搜索,搜索结果如下:
我们似乎找到了一个和我们预想差不多的变量地址,这里双击添加到我们的地址列表,选中后空格键锁定,在游戏中发现,不管我们怎么发射子弹,敌人血量都不重置了。
到目前为止,我们就能干掉这个目标了,但我们尝试用一种快乐的方法干掉他。
在地址列表中,右键,查找是什么改写了该变量。
在游戏中开一枪,我们看到改变此变量的指令,跳转到反汇编窗口
在反汇编窗口,可以看到,该指令是将这个变量加一,如果我们改为+0,或者nop,就可以实现无限子弹了。
选中该指令,ctrl+a出现自动汇编窗口,模板中选择AOB注入,更改掉当前指令,这里直接注释即可,然后File->Assign to current cheat table,添加到当前作弊列表中。
在地址列表选中脚本,可以看到相应的汇编指令已经改变,跳转到我们的代码执行了。
此时,应用我们的脚本,即可快乐度过第一关
2.第二关
观察游戏:
可以看到这里也是有提示的,我们有2个高血量高伤害的敌人,我们需要干掉他们。然后有一个警告,敌人和玩家是有关联的。
绕过思路:
首先,秦王绕柱走。走位走位,那个回手掏。然后发现操作太蛇皮了,反人类的移动,没办法,感兴趣的朋友们可以练练走位,然后干掉它俩。接下来介绍我个人的2种过关思路:
(1)我们锁血了,按道理说就能直接干掉他俩了。
(2)我们找到扣血代码,然后hook,在扣血前判断,如果是自己就不扣血,如果是敌人就秒杀。
开始操作:
先搜索自己的血量,这里方法和前面是一致的。根据屏幕上的显示进行搜索,或者根据被攻击的次数,选择减少的数值,也能找到自己的血量,操作过程如下:
更改数值,发现游戏内数值也改变,我们找到了血量变量地址
锁定该血量。干掉2个敌人。
血量掉的贼慢,开始第二种方法。
和第一关一样的操作,查找是什么改写了这个地址,然后进入游戏,让自己被打一枪。
进入反汇编窗口,查看代码,看到前后都是00 00,只有3条代码,可以猜测此处应当是血量扣除的代码。
右键,查看这条指令访问的地址,从而找出敌人的血量
会弹一个小框出来,我们进入游戏,和敌人相爱相杀,小框会记录每次该指令访问的地址。
因为游戏提示说,玩家和敌人其实是有关联的,所以我们分析一下数据结构,这里选中这3个地址,右键->打开指定地址并剖析数据。
一系列确定之后,可以看到,结构体窗口如下:
我们很快就在偏移0x60处找到了血量,并且在0x70处找到了阵营信息。
现在我们可以开始优雅的过关了。选中扣血代码,ctrl+a进入自动汇编,选择AOB注入模板。
现在我们新建一个标签,名为kill,表示立刻杀死当前对象,然后在代码入口处,判断当前阵营,如果为0,直接跳转到Kill,干掉,如果为1,则不进行任何操作。由于代码本身自带ret,所以我们后面的指令不会执行,不管他
现在试试结果吧,将脚本保存到CheapTable,运行脚本,完美过关
3.第三关
观察游戏:
游戏大概意思为把所有平板都变成绿色来解锁们,然后进入门就通关了。提示可以通过检测碰撞,或者利用坐标传送。
过关思路:
(1)找出坐标信息,由于是2D游戏,只要找到x,y即可,然后直接传送,把平台都变成绿色,最后传送到门里面
(2)找出碰撞代码,绕过它。
开始操作:
首先,我们来找人物的坐标信息。这里可以先找x,y根据编程逻辑,就跟在x的后边。而坐标一般为浮点数(PS:对于坐标原点,向右x增加,向左x减少,熟悉界面编程的应该不难理解。),查找过程如下:
至此,我们找到了正确的x值,然后我们在该地址后面+4即为y的偏移。
好的,看起来我们可以通过修改x,y的值过关了
当然,我们也要改一个优雅的方法,最好是能够hook代码的那种。
选择x的地址,右键,查看什么访问了这个地址
可以看到,坐标x在玩家对象中的偏移为baseAddr+24,在x处右键,内存中显示
更改显示模式为4字节整数
将首地址-偏移(0x24),跳转到对象首地址
进入游戏,不停死亡,观察该内存区域中的数值变化,发现图下方框的位置,当玩家死后,变为1,玩家存活变为0
将其添加到作弊表中。锁定该值,可以发现,人物无敌了
分别锁定,发现二者功能如下,第一个地址是表示人物是否显示,第二个地址表示人物是否死亡。
接下来我们怎么操作呢,找到访问该地址的代码,然后绕过它。在判断人物死亡的地址处右键,什么改写了该地址,然后进游戏死亡,查看到如下代码
进入反汇编,看到如下代码,若修改参数能实现无敌,但我们要的是避免碰撞,或者避免死亡检测。
这里我们用到CE的另一个功能,指令跟踪。
设置最大跟踪次数为10000,跳过系统模块和取消单步
进入游戏,死亡,得到如下结果,右键,全部展开
我们在第二层找到了调用这条语句的代码,双击到达反汇编代码
只要将je改为jmp即可绕过碰撞。选中je,ctrl+a,选择AOB注入模板,更改指令如下:
添加到作弊表,启用脚本,可以看到,我们已经不会和敌人碰撞了
接下来只要慢慢修改我们的坐标,把所有平台点绿,即可过关。
4.绕过Integrity Check
我们已经过关了,但是此时发现一个问题,每次我们运行脚本进行hook的时候,窗口顶部总会显示一个可恶的Integrity check error
现在我们来绕过它。
首先,打开游戏,CE附加进程,当我们运行脚本hook时,内存中我们hook的指令会被更改为jmp,所以我们先找到指令位置。搜索hook的特征码
这里解释一下,特征码就是指令在内存中的十六进制编码。通过该十六进制编码,可以在变动的内存中找到该指令地址,完成hook。AOB注入也是因为这个原理,所以稳如老狗,游戏基址随便变都能使用。
添加该地址到作弊列表,右键在内存窗口中查看
右键,给它下一个内存访问断点,查看是哪儿读取了该地址中的指令
现在我们看到,有3处检查了该地址处的代码
在反汇编窗口分析这3个访问指令,找到了如下的循环判断代码。
根据排查,发现将xx.exe+38E0C处的jg指令改为jmp指令,即可让检测失效,这里没有分析上下文,所以不清楚该处到底是如何实现代码检测的。
接下来的工作就是自动汇编(Ctrl+A)->AOB注入模板->将jg改为jmp
添加到作弊列表中,启用该脚本,此时用其他脚本发现,代码完整性检查已经被绕过了,接下来只要把作弊表保存一份,即可
四、总结
我们完成了3个关卡的作弊,以及完整性检查的绕过,但这还不够,我们应该将完整性检查的代码逆向出来,这里我就偷了一个懒,直接试出来如何绕过了,各位小伙伴感兴趣的可以继续追踪分析。
五、工具获取与源码
CE7.1工具,可以在官网上直接下载,百度或者其他搜索引擎搜索Cheap Engine即可到达官网。
演示用到的CT见附件。