Cheat Engine(CE)游戏修改例程-《我的朋友佩德罗》
一、前言
一,本教程属于低水平重复无提高的修改水平,主要是与想用CE进行游戏修改入门的朋友进行交流。汇编高手请勿笑。
二,本篇心得体会主要修改游戏教程阶段的机炮,对其进行一击必杀。游戏中机炮大约需要用手枪攻击6-7次才能解决,比较烦人,因此有必要对其一击必杀。
这个机炮的出现大约在游戏开始后游玩约7-8分钟时候,这一关的游戏存档文件在本文章最后附件中提供。
三,CE修改游戏(使用CEAA用汇编修改)的一般过程是这样的:
1,查找并找到某个你想修改的游戏中的某数值地址
2,将该地址加入地址列表,试验并确认就是该地址
3,对该地址按鼠标右键,选“找出是什么访问(或改写)了这个地址”,快捷键F5和F6
4,在游戏中进行操作,CE会截获涉及该地址的代码
5、找顺眼的代码,进行代码注入
6、完成修改
至于游戏数值基址,对于我们这些大多数不会写程序(如C,如易语言等高级语言)进行注入的用户,找基址用处不大。
但是,通过代码注入,我们可以通过自制指针,达到控制游戏数值的目的。这样得到的数值自制指针,可保存使用。
二、查找机炮HP地址及修改
为达到一击必杀,首先要找到机炮健康值(HP)的地址。那么,下面先CE找一找。
1搜索:
设置数值类型为:单浮点,扫描类型为:未知初始值。首次搜索找到3亿地址。
(为什么是单浮点,这是猜测的。目前较多的游戏特别是大型游戏或者u3d开发的游戏基本上数值都是单浮点类型。)
之后对机炮开枪搜减少,人物动一动不开枪搜不变。。。。。
开枪5次后,找到11个值,发现有一个值的初始值为工工整整的值2,其他的都是一堆小数点的值。估计是它(因为程序员一般会设置整数初始值)。
2验证:
拉下这个地址到地址列表,锁定该值,果然机炮遭受多少枪击都不会被击毁!在取消锁定改值为100,开枪打它,可以看到值挨一枪减少一点(每次减少0.35是手枪的攻击力)!
这就验证了这个地址确实是我们要找的机炮hp地址。
3找访问代码和写入代码:
对该地址按鼠标右键,选“找出是什么访问(或改写)了这个地址”,快捷键F5和F6。
则CE分别打开2个窗口,一个是访问xxxxx,一个是写入到xxxxx。
这时候可以看到:
访问该地址的代码中,有一句“快速、不停”的读取该地址的代码。其余7条代码都是开一枪计数增加一次的代码。
写入该地址的代码,只有一条。是开一枪写一次。
图
图
图
图
图
4写一击必杀脚本
图
图
图
图
图
1,注销原语句
2,写新语句
3、分配到当前CT表
图
图
运行完美。一枪击毙机炮。
图
但是!可是但是!!关闭游戏再次打开进行到机炮这里,试图勾选脚本,发现无法勾选。嗯?脚本写错了?!脚本有错误?!
呵呵,这里有个小问题。Unity3D引擎游戏,它的一些代码是需要才生成,因此,当游戏代码没有运行到某个地方时候,一些代码没有在内存中自动生成。当条件成熟,程序会自动在内存生成相关代码,供游戏调用。
于是,试着对机炮开一枪,回到CE,再试试勾选脚本,呵呵,这次可以勾选了,回到游戏,一枪毙命!!!
5多加了几句的一击必杀脚本
虽然这个脚本可用,但是修改了原始代码,对于有洁癖(或者说有执拗原则)的人无法忍受。
那么,下面就进行脚本修订---不改变原始代码,而写一击必杀脚本。
这里,介绍一个CEAA中的朋友Alloc函数。
ALLOC(分配的内存标签名, 字节数):
分配指定字节数的内存,并用标签名指向被分配的内存地址。
好,这里我申请一个4字节内存,地址名命名为:JiPaoKill_Zero
alloc(JiPaoKill_Zero,4) //申请一个4字节内存,地址名命名为:JiPaoKill_Zero
registersymbol(JiPaoKill_Zero) //注册这个名称,以便后面可用
(知识点:单浮点值占用4字节,双浮点值占用8字节。所以这里申请了4字节内存。)
下面写newmem中的语句:
mov [JiPaoKill_Zero],(float)0.01 //将一个非常小的值存入地址
movss xmm5,[JiPaoKill_Zero] //将该地址的值赋值给寄存器
解释:1,之所以给一个非常小的值而不是给0值,是因为有的游戏程序后面会判断该值,是0会直接倒毙。这个游戏我没有测试,不知道直接给0值会如何,为了达到一击必杀的娱乐效果,和避免不击就杀,所以给了一个特别小的值。这样一来,机炮既不会自行倒毙,也会被我们一击必杀(理论上给的值小于手枪伤害即可,例如手枪伤害值是0.35,因此给机炮HP赋值小于0.35,都会被一枪击杀。)
当然,这里还有一个办法,就是在xmm0-xmm15中,找一个值小于0.35的,将它的值直接赋值给xmm5,也能达到目的。但有时候找不到合适的值。
2,赋值语句mov可用于第一句,但是第二句给浮点寄存器赋值必须用movss或movsd(双浮点)
3,给寄存器赋值,必须是内存对寄存器或者寄存器对寄存器,不能使用立即数赋值。因此需要在内存中申请地址JiPaoKill_Zero,用JiPaoKill_Zero这个内存中转。但是给内存赋值可以是立即数。
好,大功告成!
注意这里是新编辑修改内容:[b]这里有误!2个搜索结果中第一个是起效代码,第二个是无效代码。)))">6多收了三五斗((([b]注意这里是新编辑修改内容:[b]这里有误!2个搜索结果中第一个是起效代码,第二个是无效代码。)))
关闭游戏程序,重写开启并继续游戏,游戏到机炮处,开了1枪!勾选脚本,再开一枪!!
啥???!!!没有一击毙命,没有一击必杀!!!。再开几枪,机炮才爆炸完蛋!怎么回事儿?
回到CE,取消一击必杀脚本的勾选。
打开脚本看看,看 aobscan 命令这里。CE搜索的是“F3 0F 11 AE D0 00 00 00 48”这些字节。好,手动用CE找找看。
在CE界面搜索,数值类型选:字节数组;然后勾选数值输入框旁“十六进制”单选框。粘贴“F3 0F 11 AE D0 00 00 00 48”。
搜索,找到2个结果!!
再次勾选一击必杀脚本,之后打开这2个地址汇编区域看看。CE在第一个结果位置进行了注入,既然这里没有达到注入效果,那第二个结果肯定是有实效的地址(验证过程略:大概就是下断点,看开枪射击机炮后游戏断在哪里)。注意这里是新编辑修改内容:[b]:这里有误!2个搜索结果中第一个是起效代码,第二个是无效代码。大家看思路即可,谢谢。)">size=5)
CE的aob函数,在内存中搜索到一个结果就返回,不考虑是不是还有相同结果的问题。(aob函数lua脚本,可以指定返回第n个结果。)
既然这样,那么怎么才能让aobscan函数返回正确的汇编代码地址呢?
通常的方法有2:
1、比较2处地址的代码,直到找到不同代码为止,然后把搜索的代码中一直加到不同字节为止。之后将其粘贴到脚本中,替换原来的字节码。但是经过试验,一是相同字节码段落太长,很难找到不同点。二是起效的字节段中会发生变化(也就是第一次找到的代码段,程序会自己改写其中内容,导致字节码无用)。所以加长字节码段进行搜索方法不可行。
2、aob函数lua脚本,指定返回第n个结果的方法。经试验,不知道哪里的问题,脚本总是返回第一个伪结果。
注意这里是新编辑修改内容:[b]aob函数lua脚本,返回第n个结果的方法过去成功使用过,已经忘记了。今天返回去研究了一下,发现这个办法可行,脚本可以完美返回自己需要的第n个结果地址)">size=5)
那么,怎么办?下面是我的邪门歪道的办法:
3、脚本复制法:
在CE的地址栏复制该脚本,之后粘贴,现在有2个完全相同脚本。
2个脚本一起勾选,就可以达到2处搜索结果都被更改注入的效果!!
实测有效!!!
三、升级脚本
打算做2件事:
1、增加机炮HP地址指针。
2、在频繁访问机炮HP地址位置注入代码,达到不开枪射击机炮,就可以控制机炮hp值的目的。
附件:
1游戏存档
mfp_save-2024年03月31日195935.rar
(1.11 KB, 下载次数: 22)
2简要的ct脚本
My Friend Pedro - Blood Bullets Bananas-2024年03月31日200309.rar
(2.51 KB, 下载次数: 51)