安卓unity(il2cpp)游戏破解之阿x斯病毒破解背包上限
# 样本原件- taptap上下载最新的:阿xx病毒_1.0.17.apk
- 论坛里可以发外链的样本原件下载吗?望告知,先不发了。
# 工具清单
- Il2CppDumper-v6.6.2
- 用于dump出游戏的函数信息
- 工具下载地址:https://github.com/Perfare/Il2CppDumper/releases/download/v6.6.2/Il2CppDumper-v6.6.2.zip
- 这软件只能在windows下运行,mac电脑可以用windows虚拟机运行
- ida pro 7.0
- 分析代码执行流程
- 手写汇编转二进制代码
- MT管理器
- 签名破解
- so文件二进制修改
- 打包签名
# 一、破解签名验证
使用MT管理器一键去除签名验证,获取到破解签名的后的apk
# 二、dump出游戏的函数信息
1. 从apk中取出需要的源文件:
- libil2cpp.so 文件路径:lib/armeabi-v7a/libil2cpp.so
- global-metadata.dat 文件路径:assets/bin/Data/Managed/Metadata/global-metadata.dat
2. 打开Il2CppDumper,依次选择libil2cpp.so和global-metadata.dat文件, 出现如下结果表示操作成功!(https://attach.52pojie.cn//forum/202105/19/163011worrj0tr2jartl0t.jpg)
3. 上步操作将得到几个重要文件
- dump.cs 里面包含了游戏的函数和对应的地址信息
- script.json 后面ida需要用到
# 三、 ida分析的准备工作
1. 打开ida32位,选择new,拖入libil2cpp.so,等待加载完成,时间有点久先去玩会吧
2. 加载脚本文件,先选ida.py,再选上面dump出来的script.json!(https://attach.52pojie.cn//forum/202105/19/164417gm6m5cf9c9fgvzff.jpg)
等待脚本运行完成
# 四、分析dump.cs
用文本软件打开dump.cs,这里要破解背包,背包的常用单词bag,在dump.cs里搜索bag,提一下我是怎么猜到用bag搜索的,在玩游戏的时候,里面有个广告,广告看完会给我解锁几格背包,通过这个线索去分析smali代码里相关逻辑可以看到代码里有bag这种关键词
发现有以下可以的代码:
```
// RVA: 0x39A3E8 Offset: 0x39A3E8 VA: 0x39A3E8
public int GetCurBagSize() { }
```
翻译过来就是获取当前的背包格数,尝试修改这个函数的返回值。可以看到函数上面有该函数的地址:0x39A3E8
回到ida软件,按快捷键g定位到0x39A3E8
!(https://attach.52pojie.cn//forum/202105/19/164804hp1r0kzyyd9ksfnk.png)
跳转后右键选择图视图,先按p键添加函数,然后右键选择graph view视图查看流程图,
!(https://attach.52pojie.cn//forum/202105/19/164808mralp8z13rehz3v3.jpg)
直接拉到底,查看流程的最终路径,重点关注R0寄存器,因为R0寄存器是用来存函数的返回结果。
光标定位MOV R0, R5这行代码,使用keypatch插件(如何安装请百度或者论坛里找),快捷键ctrl+alt+k
!(https://attach.52pojie.cn//forum/202105/19/164811j1l511h82hb4wm1w.jpg)
这里我要500个背包格子,所以给R0寄存器赋值500对应的16进制为0x1f4(注意:不要搞太多,否则游戏直接卡死),获取到7D 0F A0 E3这条指令,然后用MT编辑libil2cpp.so,用16进制编辑器打开,跳转到地址0039A4EC,然后将指令改成7D 0F A0 E3。修改后保存退出并在mt里保存并重签名,再安装处理后的apk。
打开游戏,发现游戏里的背包格子已经变成了500格,但是实际测试还是只能带10个格子的物品,这里的修改至少修改了显示效果。
# 五、如法炮制、继续分析
按上面的思路,继续搜索dump.cs里可疑的函数,发现以下代码很可疑
```java
// Namespace:
public class CContainerBag : CContainerBase // TypeDefIndex: 5556
{
// Methods
// RVA: 0x4FB4D0 Offset: 0x4FB4D0 VA: 0x4FB4D0
public void .ctor() { }
// RVA: 0x4FB580 Offset: 0x4FB580 VA: 0x4FB580 Slot: 6
public override bool AddMateriel(ulong UID) { }
// RVA: 0x4FBFAC Offset: 0x4FBFAC VA: 0x4FBFAC Slot: 10
public override int GetCanAddNum(int nModelId) { }
}
```
CContainerBag里的GetCanAddNum,这个意思是获取可以添加的数量,我猜测这是指可以放进背包里的物品数量,结果证明我猜的是对的。把这个数量调的很大就可以。剩下的我先不说了,你们自己按上面的思路去改吧~
还有几个函数需要改的,提前透露下:
- CContainerBase里的GetGridSize, 改这个是野外的时候背包的数量正确显示作用
```
// RVA: 0x4FE428 Offset: 0x4FE428 VA: 0x4FE428
public int GetGridSize() { }
```
- GetGridLeft 改这个是解决一个bug,武器放到身上,在野外脱不下来即使背包里显示有格子
# 六、修改清单
1. 0039A4EC处修改为7D 0F A0 E3
- 对应函数:GetCurBagSize (获取家中当前背包格子数量)
- arm指令:MOV R0, #0x1f4
- 16进制指令:7D 0F A0 E3
- 作用:家中背包格子显示数量,这个只是个显示作用
2. 004FC6AC处修改为FF 0F 0F E3
- 对应函数:GetCanAddNum (获取家中当前可以添加的物品数量)
- arm指令:MOV R0, #0xffff
- 16进制指令:FF 0F 0F E3
- 作用:真正的可以添加无限的物品
3. 004FE428处修改为 7D 0F A0 E3
- 对应函数:GetGridSize (获取野外当前背包格子数量)
- arm指令:MOV R0, #0x1f4
- 16进制指令:7D 0F A0 E3
- 作用:野外正确显示背包格子,显示作用
4. 004FE408处修改为 7D 0F A0 E3
- 对应函数:GetGridLeft (获取野外剩余的背包数量)
- arm指令:MOV R0, #0x1f4
- 16进制指令:7D 0F A0 E3
- 作用:防止武器卸下时出现背包已满的情况
# 七、关键思路总结
之前都是破解smali层的代码,so层这是第一次尝试,ida也是第一次用,基本是靠参考论坛里的帖子和百度的。我这个破解过程主要是看流程图,对汇编代码没有看(也看不懂...), 因为我定位的这些函数都比较简单,函数的作用都是获取什么数值结果(getxxx),所以我主要是分析流程视图,重点关注路线的重点,有时候就1个终点,有时候有2个甚至多个,这种情况可以先关注到达终点路径比较多的那个终点(有点绕)。然后终点关注R0寄存器,使用MOV指令强行修改R0寄存器的值。要多试,不要怕失败。 2370177068 发表于 2021-5-20 00:50
哇,你这个叫第一次????
真的是第一次 都是参考论坛里的帖子弄的 原件是可以发的 没问题 CrazyNut 发表于 2021-5-19 17:39
原件是可以发的 没问题
好的谢谢 学习一下 现在u3d游戏越来越难破解了 哇,你这个叫第一次????{:1_937:}{:1_937:}{:1_937:} 有点流弊流弊 学习了,谢谢 学习了,谢谢