作者:dawu@知道创宇404实验室
时间:2019/02/25
英文版本:https://paper.seebug.org/943/

0x00 前言

这是一篇游戏引发的简单技术文。

起因是个人很喜欢玩 google play 上的一些数字类型(角色攻击是线性增长,怪物指数变强,到后期越打不过,通过重生增强属性变强)的小游戏。但是这种游戏仍旧存在一定缺陷,前期资源不多,玩的太慢、玩的时间长了,就感觉没意思,就不想玩了,所以在玩到游戏中期的时候,往往都会去网上搜索XXX破解版/内购版,快速进入后期然后放弃这款游戏。

这样的做法其实是很不安全的,因为无法判断XXX破解版/内购版在破解/内购之后还做了什么。所以我最后的解决办法是,逆向这些apk,修改游戏逻辑。让我在玩的时候,可以快速度过缓慢的前期。

逆向了几个玩过的游戏,发现这类游戏使用Unity3D开发的居多。因此本文将介绍简单Unity3D类安卓游戏的逆向修改思路。

0x01 准备工具

逆向最简单的Unity3D类安卓游戏建议使用安装好 JAVA 环境的Windows系统(涉及到dll文件的修改,所以Windows平台更加适合)。

1.1 安卓 APK 逆向三件套

一般 APK 逆向,常使用到 apktooldex2jarjd-gui。在逆向 Unity3D 安卓游戏时,仅仅只需要使用到 apktool

  • Apktool: 用于解压/重新打包安卓APK。
  • dex2jar: 将解压出来的dex文件变成jar,方便使用jd-gui查看
  • jd-gui: 查看dex文件逻辑

1.2 dll文件逆向三件套

因为一般的 Unity3D 安卓游戏的主逻辑都在 asserts/bin/data/Managed/Assembly-CSarp.dll 中,所以我们还需要 dll文件逆向/重新打包 的工具。

  • ILSpy: 用于查看dll程序逻辑
  • ILDASM: 用于反编译dll文件,生成il文件(存放了dll反编译后的指令)和res文件(反编译后的资源文件),可以安装Windows SDK或者从网上下载。
  • ilasm: .net4.0自带了,位置在 C:\Windows\Microsofr.NET\Framework\v4.0.30319\ilasm.exe

1.3 生成重新打包的自签名证书

修改完 apk 之后,需要对 apk 进行签名。该命令用于生成签名的证书。

keytool -genkey -v -keystore my-release-key.keystore -alias alias_name -keyalg RSA -keysize 2048 0validity 10000
# 记住设置的密码,最后自签名应用的时候需要输入密码

0x02 开发一个简单的 Unity3D 游戏

用Unity3D开发了一个简单小游戏作为本文的样例,逻辑十分简单:

  1. 英雄每过一关战斗力都会增加100.
  2. 怪物的战斗力为 Math.pow(2,当前关数)
  3. 当英雄战斗力小于怪物的战斗力时,英雄无法闯关。英雄可以考虑修炼或者重生提高战斗力。
  4. 英雄每次修炼战斗力都会增加1000.
  5. 英雄选择重生后,关卡数清零,需要重新闯关,但英雄初始战斗力会增加 2000 * 重生前闯关数。

具体代码可以参考 Github

0x03 游戏逆向步骤

1.使用 apktool 解压游戏安装包

java -jar apktool.jar d game.apk

2.提取出 game/assets/bin/data/Managed/Assembly-CSarp.dll ,使用 ILSpy 打开即可看到 dll 里面的逻辑。

注: Unity3D开发的安卓游戏,其核心代码都在这个 dll 文件中,所以逆向/修改这个 dll 文件就可以了。这也是 Unity3D 和 其它安卓逆向不同的地方。

在没有混淆的情况下,反编译出的函数内容和原内容十分相似:

ILSpy 反编译的 Click1 内容

Click1 的原始代码

3.找到关键函数、关键逻辑后,就可以尝试反编译 dll 文件并修改。使用 ILDASMdll 文件反编译成 il 文件。使用 ILDASM 打开 dll 文件后, File -> dump 就可以导出反编译结果了。

4.根据步骤2,就很容易理解逻辑了,然后根据速查表,就可以知道在步骤3导出的il文件中修改哪里了。例如步骤2中 Click1 就是游戏中 点击闯关 按钮绑定的逻辑。闯关的关键判断就在: info.hero_power + info.temp_power + info.add_power >= info.monster_power。所以打开步骤3中生成的 .il 文件,结合 .NET IL 指令速查表修改这部分对应的关键逻辑即可。

修改为 info.hero_power + info.temp_power + info.add_power != info.monster_power 就可以通过此处的逻辑判断。

5.修改关键逻辑后,通过重新编译 dll 文件、apk 文件、签名修改后的 apk 就可以在手机上安装运行了。

重新编译dll文件命令如下:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\ilasm.exe game.il /output=Assembly-CSarp.dll /dll

将重新编译的dll放回 game/assets/bin/data/Managed/ 目录下,使用apktool重新打包apk:

java -jar apktool.jar b game
cp game/dist/game.apk ./

自签名应用:

jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.keystore game.apk alias_name

6.修改成功,开局修炼一次后,就可以无限闯关。顺利到达第30关。

0x04 杂谈和总结

  1. Unity3D有一个较为明显的特征: 开局会显示游戏LOGO。这个可以作为判断一个游戏是不是Unity3D开发的小参考。
  2. 文中的demo到了31关,就会发生整型溢出,怪物战斗力变为负数。原因是怪物战斗力的值为int型。在以前玩过的某个后期极度不平衡的游戏中,我的确遇到过整型溢出的问题。造成花钱升级还能增余额的情况。
  3. 在修改游戏之前把游戏语言调整为英文有助于在逆向的时候理解各个函数的意义(对于没有混淆的应用)。
  4. 游戏修改之后,很容易丧失原本的乐趣,变成纯粹的数字游戏。谨慎修改!

0x05 参考链接

  1. Apktool
  2. ILSpy
  3. .NET IL 指令速查表
  4. Unity3d类安卓游戏逆向分析初探

Paper 本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/829/