简单利用Cheat Engine的mono功能修改Unity游戏
前言
今天说的游戏指:Unity框架开发的游戏(或者有说MONO系游戏).
Unity框架游戏使用C#开发,主要利用它跨平台的特性,这里面跨平台的不是C#,而是C#生产的中间代码CIL,这种代码只要放在支持CLR的平台上就都可以编译执行. 而MONO就是Unity所使用的开源CLR实现. 这样你就明白了Unity和Mono的关系,更多可参详这篇文章
总结:使用Cheat Engine的mono功能可以快速修改Unity游戏的源码
测试游戏地址:
https://www.cracked-gamespc.com/games/back-to-the-dawn
1.简单修改作者留的后台的GM代码
1.1 ce附加进程并开启mono
如果是unity的游戏会有mono这个选项, 此时点击 Active mono(可以看出这个一个feature的功能), 然后我们打开.Netinfo,
1.2 .Netinfo
因为.Net的原因,所有函数都是明参数和返回值的
所有游戏的代码都是在Assembly-CSharp下的, 这里我们搜索GM,发现有很多东西可以修改,这里只举两个例子:
GMThrowDice1value
,GMThrowDice2value
, 修改这两个可以修改游戏中roll的点数
2.修改彩票中奖函数
上面是一个作者留的后台,下面我们进行一个普通函数的修改
这里以买彩票为例,彩票的英文是lottery ticket
,在classes 中搜索lottery
我们可以看到所以有的相关类以及类的静态成员和方法
这里可以看到有一个LotteryTicketBounsLogic
是彩票相关的逻辑类 里面有一个方法SetL otteryTicketNumber
,这个就是生成彩票号码的函数,但是他没有传参,双击进去,就是内存的代码,
2.1.如果简单的话可以直接修改
2.2 在ce中更推荐用脚本修改
2.2.1 lua&C
在函数上右键 Generate patch template for method
我们可以看到这是一个lua脚本,红色的内容是C#的脚本,重载了改函数
,直接修改C#中的函数:
原本:
复制代码 隐藏代码
public System.String newSetLotteryTicketNumber()
{
//you have access to public fields. Use reflection if you wish to access private fields
return oldSetLotteryTicketNumber();
}
修改为:
复制代码 隐藏代码
public System.String newSetLotteryTicketNumber()
{
//you have access to public fields. Use reflection if you wish to access private fields
return "88888";
}
这样这个返回值就一直是88888了
这个时候不要点击Execute, 点击file-Assign to current cheat table
这样就是一个可以随时开启/关闭的状态,就是我们普通的脚本
2.2.2 除了上面的lua&C#的方式,还有其他很多方式,ce都给出了模板:
这里简述两个模式:
2.2.3 Code Injectien
代码模板如下:
复制代码 隐藏代码
alloc(newmem,2048,LotteryTicketBounsLogic:SetLotteryTicketNumber)
label(returnhere)
label(originalcode)
label(exit)
newmem: //this is allocated memory, you have read,write,execute access
//place your code here
originalcode:
push rbp
mov rbp,rsp
sub rsp,40
exit:
jmp returnhere
LotteryTicketBounsLogic:SetLotteryTicketNumber:
jmp newmem
nop 3
returnhere:
因为是通过mono的函数名定位的,所以这个需要开启 mono, 即Active mono
2.2.4 AOB Injection
代码模板如下:
复制代码 隐藏代码
[ENABLE]
aobscan(INJECT,55 48 8B EC 48 83 EC 40 48 89 75 F0 48 89 7D F8 C7 45 E8) // should be unique
alloc(newmem,$1000,INJECT)
label(code)
label(return)
newmem:
code:
push rbp
mov rbp,rsp
sub rsp,40
jmp return
INJECT:
jmp newmem
nop 3
return:
registersymbol(INJECT)
[DISABLE]
INJECT:
db 55 48 8B EC 48 83 EC 40
unregistersymbol(INJECT)
dealloc(newmem)
可以看到是通过特征码定位的,所以是不需要开启mono的, 但是会搜索特征码会很慢
3.如何调试函数
上面修改了某一个函数,如果看他是否生效呢?
3.1 可以在游戏内直接看
3.2 如果游戏很麻烦,,或者写错了崩溃,可以使用 mono_invoke_method调试
官网如下:
https://wiki.cheatengine.org/index.php?title=Mono:Lua:mono_invoke_method
里面有示例.我自己测试的脚本如下:
复制代码 隐藏代码
LaunchMonoDataCollector()
function my_mono_invoke_method(AddrMethod)
if AddrMethod==nil or AddrMethod==0 then
print('没有找到方法')
return
end
local AddrClass=mono_method_getClass(AddrMethod)
printf('AddrClass:%s', AddrClass)
local instances = mono_class_findInstancesOfClassListOnly(domain,AddrClass)
instance=instances[1]
printf('instance:%s', instance)
local r=mono_invoke_method('', AddrMethod, instance,{})
print(r)
return r
end
local domain=''
local AddrIssu = mono_findMethod(domain, 'LotteryTicketBounsLogic', 'CurrentIssue')
local AddrNum = mono_findMethod(domain, 'LotteryTicketBounsLogic', 'SetLotteryTicketNumber')
printf('第%d期的彩票号是:%s',my_mono_invoke_method(AddrIssu),my_mono_invoke_method(AddrNum))
3.如何快速写汇编
上面修改了LotteryTicketBounsLogic.SetLotteryTicketNumber
这个函数, 但是需要用户输入特定的数字,有没有不需要输入特定数字的方法呢?
可以同时修改
是否中奖函数LotteryTicketBounsLogic:isWinningLottery
对几个数字函数LotteryTicketBounsLogic:GetBounscCount
如果不想写汇编可以使用这个在线网站, 把任意一个语言的代码,通过不同的编译器转为汇编
如LotteryTicketBounsLogic:GetBounscCoun
直接返回5(即所有数字都对)
一旦您浏览本站,即表示您已接受以下条约:
1.使用辅助可能会违反游戏协议,甚至违法,用户有权决定使用,并自行承担风险;
2.本站辅助严禁用于任何形式的商业用途,若被恶意贩卖,利益与本站无关;
3.本站为非营利性网站,但为了分担服务器等运营费用,收费均为赞助,没有任何利益收益。
死神科技 » 简单利用Cheat Engine的mono功能修改Unity游戏