CE与mono模块_1
今天不想学习,想玩游戏,所以就打开了一个肉鸽游戏,尝试开挂。
参考:【CheatEngine基础教程】四、Unity3D游戏《晚上nano好》修改实战
先打开游戏目录,看看是哪类游戏
- rpgmaker:解包+编辑器用工程文件打开
- gamemaker:js反混淆得到源代码
- unity il :ce+dnspy
- unity il2cpp:恢复符号表ida改cpp代码+ce
在Managed文件夹中:
很明显可以看出是unity游戏
首先要明确目标:
这是一个卡牌rougelike游戏,玩家操作2~4个角色+一个主角打败复数的敌人
修改金钱,技能点(升级人物),人物血量,每回合费用
那么开始
修改基本数据
由于这个游戏是unity游戏,可以直接通过ce的mono分析模块来方便地检测内容并hook函数
这样打开这个功能,然后搜索金钱数量,直到找到对应的值
右键,查找是什么改写了这个值
得到:
详细分析一下这个代码,会发现这里的地址是写死的,以字面量直接放到内容里面,这是为什么呢?
由于unity是cs语言,cs在编译时只生成il中间代码,在CLR虚拟机中执行,相当于java里面的虚拟机。这样,它边执行边编译,直接把对应的值写死在编译出的代码里面,然后直接执行,这样当然可以每次都使用字面量而每次都可以不一样。
这也说明不能通过找多级指针来寻找基址,需要另一种方法。
由于开启了mono分析功能,在检测界面点击:显示反汇编程序:
可以看到已经把函数名翻译出来了,那么我们可以从函数名下文章直接找值,由于函数名是一定的,从函数名开始的偏移也是一定的,这样就可以直接找到对应的变量而不需要找基址。可以看到这里的方法是金币的set方法
在dnspy中查看
显然找get更好
在ce中ctrl+g跳转:PlayData:get_Gold
只有1c的长度
可以直接从11行取出rax+25c作为gold的值,但是get和set在这里都有rax+25c的偏移,可以怀疑这里有一个结构体,如果可以找到结构体开始的值,相当于整个内容都有了,只不过还有解决每个值对应的内容是什么的问题。这时mono分析功能又派上用场了:
ctrl+d:
把我们金钱的地址填进去-结构-定义新的结构:
它把所有信息显示出来了(还有偏移量):
一开始的值就是上面函数中的字面量,soul就是技能点,把这两个偏移记住
在内存查看中-工具-自动汇编-写自动汇编脚本:
1 | [ENABLE] |
这样我们保存后就保存了对应的结构体指针
然后根据偏移:
做出指针,后面的soul同理,不再赘述
在这个结构体中还有人物血量:
同理把找到的结构体开头作为基址来偏移就好
最后还有cost,每回合费用,它不在这个结构体里面,重新搜索,如法炮制:
先看结构体偏移8c
找到setAP函数和getAP函数,这两个函数似乎都没有硬编码的地址,也比较合理,每次开一个战斗都要重新生成一次,但是可以看到:
明显结构体开头在r15,但是拿不到值,干脆直接注入代码:
1 | [Enable] |
这样就拿到结构体头了,不过因为是代码注入,必须要调用一次这个函数之后才可以得到值。
同理就得到AP的值了。
锁血和秒杀
角色信物
这个游戏有一个设定,解锁角色需要一些条件。然后如果想要看后日谈,需要解锁所有角色,然后用对应的礼物给对应的角色3次,并在最后打最终boss的时候带上他们并通关,这需要花费的时间太长了,很离谱,所以准备修改一下。
在dnspy中搜索角色数据,任意搜索一下,找到了一个用于返回这一个角色数据的函数:
通过这个查找被什么使用
找到给礼物的函数:
这个函数表明可以通过charid来查找对应的charData