逆流而上的小船头像

Unity手游逆向实战:从Assembly-CSharp.dll到游戏逻辑修改

1. 逆向工具链全解析

做Unity手游逆向就像玩解谜游戏,关键是要选对工具。我这些年折腾过不下20款工具,最后沉淀下来的这套组合拳能解决90%的未加密Unity单机手游。先说个真实案例:去年有个独立开发者朋友想研究竞品游戏机制,用这套工具三天就摸清了核心算法。

Android Killer 绝对是APK拆解界的瑞士军刀。它最厉害的不是反编译,而是能自动处理各种资源文件冲突。有次我遇到个游戏用了特殊资源压缩格式,其他工具都报错,只有Android Killer能完整解包。最新版还支持实时调试smali代码,改完直接热重载,省去了反复打包测试的时间。

针对Unity的ILSpy 有个隐藏技巧:按住Ctrl点击方法名可以追溯调用链。有次分析抽卡概率算法,我就是用这个功能追了12层调用,最终在GameManager类里找到了伪随机数种子。建议装个插件版,反编译速度比独立版快3倍,还能保存工程进度。

ILDasm/ILasm 这对黄金搭档要注意版本匹配。我踩过的坑是:用VS2022的ILDasm反编译,再用VS2019的ILasm打包,结果游戏直接闪退。后来发现是元数据处理方式不同,现在我都固定用VS2019的28.0版本工具链。

2. 实战:从解包到定位关键代码

最近逆向的一款模拟经营类游戏特别典型。用压缩软件解压APK后,在assets/bin/Data/Managed里发现了7个dll文件。这里有个筛选技巧:先按文件大小排序,通常Assembly-CSharp.dll是最大的,因为包含了主要游戏逻辑。其他像UnityEngine.dll这种系统库不用管。

用十六进制编辑器查看文件头是个好习惯。有次我发现某个dll开头是"UPX!",才知道开发商用了UPX加壳。不过现在很多Unity手游连这种基础保护都懒得做,直接就能看到明文IL代码。

ILSpy分析阶段 最重要的是搜索策略。不要一上来就搜"money"这种常见词,先找游戏特有的术语。比如那款农场游戏里,货币变量叫"farmDollar"而不是"gold"。我通常先用反射查看所有类名,把带Game、Manager、Controller后缀的类优先排查。

找到可疑类后,重点看这两类方法:

  1. 以Get/Set开头的方法
  2. 带有Update/FixedUpdate/LateUpdate的方法

上次改人物移动速度,就是在PlayerController类的FixedUpdate里发现的。有个细节:Unity物理计算都在FixedUpdate里,所以改移动参数要优先查这里。当时找到这行代码:

rigidbody.velocity = new Vector3(inputX, 0, inputZ) * moveSpeed;

把moveSpeed从3改到10,角色就跑得飞快了。

3. IL指令修改的魔鬼细节

用ILDasm导出的.il文件可能有上万行,我有个快速定位技巧:先用文本编辑器搜索"ldc.r4"(加载float常量)或"ldc.i4"(加载int常量)指令。上次改游戏里的物品售价,就是找到所有包含"ldc.i4"和"price"的代码块。

关键修改原则:

  1. 改数值常量比改逻辑安全
  2. 优先改乘法系数而非固定值
  3. 注意保持栈平衡

有次手贱改了方法调用顺序,游戏直接崩了。后来才明白IL代码必须严格维持栈状态,比如这个典型错误:

ldloc.0    // 加载局部变量0
ldc.i4 100 // 加载常量100
mul        // 相乘

要是把mul改成add,虽然语法没错,但游戏逻辑就乱套了。

ILasm重编译 常见报错处理:

  • 遇到"Token 0x0200001F未定义",通常是元数据损坏,需要先用ildasm /metadata=full重新导出
  • "无法解析程序集引用"错误,要把所有依赖dll放在同目录
  • 最好保留原dll的manifest信息,我习惯加/resource参数:
ilasm Assembly-CSharp.il /output=Modified.dll /dll /resource=Assembly-CSharp.res

4. 重打包的避坑指南

用Android Killer替换dll时,有两点特别容易翻车:

  1. 必须删除META-INF目录,否则签名冲突
  2. assets目录下的资源ID不能变

最近遇到个棘手情况:替换dll后游戏能运行,但所有UI贴图都错乱了。后来发现是Unity版本兼容问题,原游戏用2019.4.21开发,我用2021.3.1的工具链处理过dll。解决办法是用Unity自带的命令行工具处理:

Unity.exe -batchmode -nographics -quit -manualLicenseFile 
-projectPath "空工程路径" -exportPackage "Assets" "output.unitypackage"

签名验证 也是个暗坑。有些游戏会校验自身签名,直接替换dll会导致闪退。这时候要么用Xposed hook签名校验方法,更简单的办法是修改AndroidManifest.xml里的android:debuggable="true",大部分校验逻辑在debug模式下会跳过。

测试阶段建议用模拟器,我常用MuMu模拟器的开发者模式,能直接看到崩溃日志。有个取巧的方法:在关键代码处插入Log输出,这样即使游戏崩溃也能定位到问题点。比如在dll里加个Debug.Log("Reached Point A"),用adb logcat | grep Unity就能看到执行轨迹。

转载自 CSDN-专业IT技术社区

原文链接:https://blog.csdn.net/weixin_29281915/article/details/159061113

文章来源转载

评论

评论列表

微信小程序
QQ小程序

关于作者

点赞数:0
关注数:0
粉丝:0
文章:0
关注标签:0
加入于:--