安卓Unity3d游戏<旅行青蛙>简单逆向

对安卓Unity3d游戏<旅行青蛙>的简单逆向分析。

1.背景知识

第一次接触这类android app的逆向分析,发现还是有相关的开发经验之后,逆向分析起来才能比较熟悉,易于上手。介于我只有普通类型的app的开发经历,并没有这类游戏app的开发经验,就需要先补一下相关的基础知识。

A.Unity (游戏引擎)/#%E6%B8%B8%E6%88%8F)

  • Unity 是一款由 Unity Technologies 研发的跨平台2D/3D 游戏引擎。
  • 可用于开发 Windows、MacOS 及 Linux 平台的单机游。戏,PlayStation、XBox、Wii、3DS 和 任天堂Switch 等游戏主机平台的视频游戏,或是 iOS、Android 等移动设备的游戏。
  • Unity 所支持的游戏平台还延伸到了基于 WebGL 技术的 HTML5 网页平台,以及 tvOS、Oculus Rift、ARKit 等新一代多媒体平台。
  • 除可以用于研发电子游戏之外,Unity 还是被广泛用于建筑可视化、实时三维动画等类型互动内容的综合型创作工具。

游戏引擎是指一些已编写好的可编辑电脑游戏系统或者一些交互式实时图像应用程序的核心组件。这些系统为游戏设计者提供各种编写游戏所需的各种工具,其目的在于让游戏设计者能容易和快速地做出游戏程序,而不用由零开始。大部分都支持多种操作系统平台,如Linux、Mac OS X、Windows。大多数游戏引擎包含以下系统:渲染引擎(即“渲染器”,含二维图像引擎和三维图像引擎)、物理引擎、碰撞检测系统、音效、脚本引擎、电脑动画、人工智能、网络引擎以及场景管理等。

B.Unity编译Android apk

Unity 发布成android包的环境搭建步骤(详细,适合小白)
Unity编译Android的原理解析和apk打包分析

如何区分普通APK和Unity编译生成的APK?

与普通APK相比,多了assert/bin目录,在这个目录之下,可以看到unity相关dll库,游戏主要功能大部分都是用C#语言在这些dll库中实现的。

所以如果在分析apk时解压后看到如上图所示路径,则此apk很有可能是一个Unity游戏apk。

C.dll逆向工具dnSpy

神器如 dnSpy,无需源码也能修改 .NET 程序

2.逆向破解

实现游戏主要功能的重点分析对象:Assembly-CSharp.dll。 这个我觉得只有在各个dll文件中搜索关键字符串,最终定位到主要的功能dll。因为不像普通Apk一样,在manifest文件中可以找到入口Activity,所以我感觉是只有一个一个dll的查看和排除了(当然,如果能从dll文件的名字上看出点什么是最好的)。

A.三叶草无限

找到关键方法(查询三叶草数量)如下图所示,并将其返回值改为固定值,这样每次查询的三叶草数量都为我们修改后的10000,从而达到无限购买的目的。


这里我是通过搜索关键字符串如三叶草不足分析定位到关键方法的,所以逆向分析一定要有目的和入手点,不然效率很低,而且也不知道到底要干啥。

B.无限抽奖

与上述分析类似,找到关键函数并改变其返回值。


C.补充说明

dnSpy中搜索字符串时,如果选择以上所有是搜索不出结果的,只有选择数字/字符串才能成功搜索到dll文件中的对应字符串位置。

D.apk重打包

与普通的apk重打包流程相同,apktool b xxx之后签名即可,此app并没有签名校验。

很久没用过apktool重打包,居然忘记了重打包之后的apk的存放位置了(捂脸~),在被打包的xxx目录下的dist文件夹中。

E.遗留问题

在分析问题A时,找到了初始化定义三叶草数量的变量如下图所示,但是在修改其值的时候遇到了问题,并不知道修改哪个值才能成功修改该变量。


这里附上一张其他教程中修改变量值的图,为啥到我这里就不一样了233

介于不是主攻方向,以后有时间可以研究研究unity相关知识,应该会对此问题有更多的了解。

3.思路分析

接下来对其中的部分功能实现机制进行简单分析。

A.抽奖奖品的出现机制

在游戏过程中,我们可以发现抽奖的时候可能会出现白玉、青玉、绿玉、红玉、黄玉,那么这些玉的出现机制是怎样的呢?是简单的随机数吗?

我们在如下图所示代码中可以看到各种玉之间的数量占比(60+27+9+3+1=100)

具体的判断出什么球的思路如下:

  • 先从0-100中取一个随机数;
  • 返回结果的初始值为白玉;
  • 程序定义了一个枚举ENUM,枚举的value从0-4分别对应上图所示从white-gold的name;
  • 然后进行while循环While i < 5;
  • 在while循环中根据i的值,取对应的name,再去上图中PrizeBalls中取name对应的具体数值(如white对应的60),如果该数值大于之前取的随机数,则返回结果为对应的name;如果不满足条件,则继续循环,取下一个name并将其具体数值和之前的数值相加,直到满足条件并获得对应的返回结果(此时返回结果取得是最后取到的name值)。

所以可以看到并不是简单的取随机数判断,整个思路设计还是比较巧妙的。

B.更多分析

关于小青蛙旅行的过程(包括目的地决定、明信片、耗时等等),主要在class TravelSimulator中,由于时间有限,没有分析完整个类,只分析了一部分代码,这里就不列出来了,以后有时间的话可以完整的分析一下整体的设计思路和判断机制。

总结

在分析过程中可以明显看到,程序中较多的使用了枚举ENUM这一数据结构,可以简化很多对应的switch-case操作。

.vb.net中三种转换【CType/DirectCast/TryCast】
C#中的枚举(Enum)你知道多少呢?

4.参考

青蛙旅行 — Unity3d类安卓游戏逆向分析初探
Unity3d类安卓游戏逆向分析初探
玩《旅行青蛙(旅かえる)》有哪些体验