已知:.apk,Unity游戏,本质是单机游戏,但登陆时会有联网操作

手机只开流量时打开游戏的状态

手机无任何网络连接时打开游戏的状态

求:破解游戏中联网的部分,使其变为纯单机游戏


0. 解压并打开apk

参考了:Unity - Apk包的代码与资源提取 - Kaima - 博客园

Unity3D 游戏的基本了解

参考自:unity游戏生成与修改so文件教程 - 吾爱破解 - 52pojie.cn

1.如何识别u3d游戏?打开解压包,如果lib文件夹下有libunity.so就证明这是一个unity3d游戏。
2.要修改Unity3d游戏,首先就要对其游戏代码存放位置有一个基本的了解。Unity3d生成游戏的游戏主逻辑一般放在三个地方:libil2cpp.so、Assembly-CSharp.dll、lua脚本。
【对于libil2cpp.so来说:我们知道,unity3d最大的一个特点是一次制作,多平台部署,而这一核心功能是靠Mono实现的。但是在2014年年中的时候,Unity3D引出了IL2CPP的概念,IL2CPP,英文意思即Intermediate Language to cpp,就是把IL中间语言转换成CPP文件。】
上面所说的这三个地方通常来说是唯一的,即只会出现一种情况。这是由unity3d引擎的生成方式决定的。

拿到游戏本体.apk

修改后缀名为.zip

使用解压软件解压

各个部分的说明如下表:

1
2
3
4
5
6
7
8
9
10
AppName/
├── AndroidManifest.xml # Android应用清单文件
├── assets/ # 包含资源文件夹,如图像和声音
├── res/ # 包含资源文件夹,如布局和字符串
├── lib/ # 包含原生库文件夹,如armeabi-v7a和arm64-v8a
├── META-INF/ # 包含APK签名的META-INF文件夹
├── classes.dex # Android应用的主要DEX文件
├── resources.arsc # 包含资源表文件
├── AndroidManifest.xml # Android清单文件
├── res/ # 包含资源文件夹,如布局和字符串
assets Unity游戏里面的资源和代码
lib arm和x86需要的so文件
META-INF 信息包
res 存放icon等资源
AndroidManifest.xml 清单文件
classes.dex Android Dalvik字节码
resources.arsc 编译后的二进制资源文件

1. 判断类型

参考了:某unity游戏逆向破解 - 吾爱破解 - 52pojie.cn

解压apk之后看一下一些关键目录

  • lib
  • assets\bin\Data\Managed

如果assets\bin\Data\Managed 出现了 Assembly-CSharp.dll,那么说明是mono类型的,游戏逻辑就在 Assembly-CSharp.dll 和其它同路径下的文件里,此时用 dnspy 逆向

如果没有看到Assembly-CSharp.dll, 但是在 lib 下看到了 libil2cpp.so 那么说明运行时是 IL2CPP,需要使用 Il2CppDumper + ida + 其它 逆向


分析为 该游戏 是 IL2CPP 类型

2. 利用工具 Il2CppDumper 将so里的所有函数名进行提取

参考了:去除Steam中Unity单机游戏的联网登录验证(Mono&IL2CPP) - 思泉 | Jev0n

[初探Unity3d+il2cpp.so网游修改新手教程篇内附所有相关工具下载地址和说明介绍】 - 吾爱破解 - 52pojie.cn

dnspy 下载地址:dnSpy/dnSpy: .NET debugger and assembly editor

Il2CppDumper 下载地址:Perfare/Il2CppDumper: Unity il2cpp reverse engineer

打开 Il2CppDumper.exe,依次导入 libil2cpp.soglobal-metadata.dat,运行,

Il2CppDumper 执行之后,得到了一些输出文件

  • dump.cs
    c#类和方法的签名和偏移,无具体代码
  • script.json
    可以导入到ida,进行方法名关联
  • il2cpp.h
    可以导入到ida,进行结构体关联

使用 VSCode 打开 dump.cs,在其中寻找相关逻辑,搜索与网络请求相关的类名或方法名

参考unity3d官方用户手册(2019.4 LTS) - UnityWebRequest - Unity 手册 - 创建 UnityWebRequest - Unity 手册

认为与 UnityWebRequest 模块的 SendWebRequest 方法有关

在 dump.cs 中找到

1
2
// RVA: 0x1D7A1A0 Offset: 0x1D7A1A0 VA: 0x1D7A1A0
public UnityWebRequestAsyncOperation SendWebRequest() { }

1
2
3
[NativeThrowsAttribute] // RVA: 0x678148 Offset: 0x678148 VA: 0x678148
// RVA: 0x1D7A0FC Offset: 0x1D7A0FC VA: 0x1D7A0FC
internal UnityWebRequestAsyncOperation BeginWebRequest() { }

得到 SendWebRequest 的偏移地址 0x1D7A1A0

使用 IDA Pro,导入 libil2cpp.so,按 G 输入偏移地址 0x1D7A1A0 搜索其位置,这个sub_1D7A1A0 就是 SendWebRequest方法。

IDA32位的和64位两个exe,要根据你反编译的文件运行对应的exe
Unity使用IL2CPP打包时,选择的CPU架构可以选择ARMv7ARM64,由于我上面拿的libil2cpp.soarmeabi-v7a的,也就是32位的,所以我运行的32位IDA

可能遇到问题:IDA 找不到python

解决问题:最新IDA8.3安装后需要做的一些完善工作(包括IDAPython报错、ChatGPT的模块安装、中文字符串的显示,各种问题解决方法合集)_ida pro 8.3-CSDN博客

选中BL sub_1D7A0FC行,左上方菜单栏选择”编辑”-“补丁程序”-“汇编”,出现警告:抱歉,此处理器模块不支持汇编程序。IDA Pro 的某些处理器模块(如ARM)可能未集成汇编功能,导致无法直接修改指令。但可以通过 手动计算机器码 + 十六进制编辑 绕过此限制。

使用 010Editor

  1. 在 IDA 中定位到地址 0x1D7A1AC
  2. 右键选择 编辑 -> 补丁程序 -> 更改字节
  3. 将原始值 D2 FF FF EB 修改为 00 00 A0 E1
  4. 确认修改后按 确定

编辑 -> 补丁程序 -> 应用补丁到输入文件,确定(同时备份一份libil2cpp.so.bak)。将修改完的 libil2cpp.so 覆盖入在 7-Zip 中展开的原zip(apk改后缀而来)包,再改后缀会.apk,导回手机,安装。


STEAM联网破解

从安卓逆向限制太多,所以转从电脑版入手:

(为STEAM平台游戏,Unity引擎开发)

游戏根目录如下:

发现 Assembly-CSharp.dll,初步判断为使用 Mono虚拟机 的 Unity游戏

将 Assembly-CSharp.dll 单独复制一份出来,拖入dnSpy:

dnspy 下载地址:[dnSpy/dnSpy: .NET debugger and assembly editor