beatmania IIDX ULTIMATE MOBILE 游戏资源解密

本博文之内容仅供技术交流、学习,请勿用于违法、盈利行为。博主对博文中内容的时效性不负责,也不保证能解答读者的一切问题。如需转载,请注明原作者信息,并附带本博文链接。继续阅读则默认您同意上述条款。若不同意,请立即关闭本页面。

游戏简介

众所周知,REFLEC BEAT plusjubeat plus 在一年前纷纷停止了曲包更新。而 KONMAI 居然在今年推出了将 IIDX、SDVX、DDR 三款街机音游移植到移动端的计划,令人惊讶(但我个人认为,移动端上这三款游戏的趣味远不如 REFLEC BEAT 和 jubeat)。

beatmania IIDX ULTIMATE MOBILE 在前几天正式上架,并在多个音游相关群引发了热烈的讨论。该游戏采取的是按月付费订阅制(980 日元 / 月),并且在正式付费前可以体验 7 天的超级(ULTIMATE)会员权限。试用模式下,用户可以游玩的次数、曲目、难度均有限制,而超级会员可以无限制游玩任意难度的任意曲目,并且能自由播放 SP/DP 谱面和历代 BEMANI 音游的 GST。

至于游戏的其他内容和特性,我在此不再赘述,毕竟本文的主要内容还是游戏资源的解密。

前言

这游戏刚上 App Store,就马上有大佬下载了下来,不过好像服务器是过了一天才正式开放。我打开游戏试玩几盘之后,(出于新鲜感)也毫不犹豫地买了日区 iTunes 礼品卡充了超级会员(然而后来发现 10 级以上的曲目内含大量多押和楼梯元素,打不来,走了)。

后来在某音游自制群水群的时候,有人提到想提取游戏内置音乐播放器里 DRS、钢琴机的 GST,但内录音质非常差。于是,我便开始了对游戏资源的研究。

顺带一提,这也是我第一次单人 独立逆向出加解密算法 的经历,令我获得了很大的成就感,值得纪念~

出于各种原因,本人仅对 iOS 软件的逆向工程有所了解,本博文的逆向对象将 仅限 iOS 版 的 beatmania IIDX ULTIMATE MOBILE。

砸壳 & 解包

用最方便的工具,给自己带来如丝般顺滑的逆向体验(然而事实上并不存在)。

把 iPad 连接到 Mac,iproxy,启动!frida-ios-dump,启动!bm2dx.ipa,解压!

进到 .app 包里一看,发现 Data/data.unity3d 这么个东西,可以确定是基于 Unity 开发的游戏了。看来 KONMAI 的 iOS 开发程序员在这 6 年间还是学了点新技术的。

既然是 Unity 游戏,那么:AssetStudio,启动!把 data.unity3d 扔进去,惊喜地发现 ipa 包里自带的游戏资源是没有加密的,因此直接拿到了部分游戏贴图素材和音频(并在自制群秀了一下)。

可惜的是,用 spek 看了一下导出的 wav 文件的频谱,似乎只有 mp3 128kbps 的质量。

接下来就是游戏的下载数据了,Apps Manager + Filza 打开 App 数据路径来一看,可以发现下载数据全部存放在 Documents/ab 这个文件夹里。

ablist.json 一看就知道是存储资源信息列表的文件,戳开来一看,乱码……果然还是加密了吗,那不得不逆向解密了。

(注:当然还有另一种思路,就是 Hook 解密函数,在 App 运行时把解密好的文件从内存中 Dump 出来。由于我个人只做过 Objective-C 函数的 Hook,而对 C/C++ 函数 Hook 中的内存、文件读写不是很熟悉,就没有走这条路。)

还原符号

既然选择了远方,便只顾风雨兼程。IDA,启动!把 ipa 包里的可执行 Mach-O 文件 bm2dxum 扔进去分析一番,可以看到少数带 Unity 关键字的 Objective-C 函数,和一堆……sub_函数。搜索了一波 crypt 之类的关键字,除了几个 Objective-C 的 hash 函数以外没有结果。看来 Unity 偷偷把游戏中用到的很多函数名都隐藏掉了,真是个小机灵鬼!

那么,我们有方法恢复这些函数符号吗?答案当然是 YES。Il2CppDumper,启动!把 bm2dxum 和 global-metadata.dat 放进去,随便填个 2018.4 之类的版本,让软件自动分析,就得到了 dump.cs(内含类与函数的声明、地址信息)、stringliteral.json(内含字符串常量及其地址)、script.py(IDA 专用脚本,用于还原函数名信息)。

在 IDA 中选择 File – Script File,载入 script.py,让它慢慢跑一会儿,之前那些被隐藏的函数名便重新浮出水面。至此,符号还原工作已经完成。

寻找加解密函数

既然函数名已经全部暴露,而且函数名完全没有混淆,接下来的逆向分析工作就简单不少了。直接搜索 assetbundle、crypt、cipher 之类的关键字,筛选出一些可能与资源加解密相关的函数(这里找 AssetBundleList 类的原因是,前面在资源文件夹中看到过 ablist.json 这个文件,还记得吗?):

为了确认,直接上动态调试,lldb,启动!配合 Unc0ver 越狱修改过权限的 debugserver,体验简直不要太好。IDA 里拿一下函数地址,lldb 里输出一下 ASLR 偏移,在两者相加的地址下断点。

似乎是游戏在 TAP TO START 后,会验证一下本地已下载资源的完整性。数次网络通信后,很快就来到了断点。看一下函数的参数,我立刻面露微笑——ablist.json!这种存储资源信息列表的文件一般比较关键,值得从内存中提取出来。拿出来一看,果然和我预想的一样。小明玩音游,我解密音游资源,我们都有光明的未来!

接下来再结合 IDA 静态分析与 lldb 动态调试,终于找到用于加解密的类的构造函数 AssetBundleCryptoStream$$.ctor_4306905664,并 结合 dump.cs 还原一下函数参数名

分析加解密函数

继续 IDA 静态分析,会发现刚才的函数先调用了一个MakeSalt,再将一堆参数传进CreateAesStream。不知道它的 salt 是怎么 make 的,不妨再动态调试看看函数返回值,结果发现所谓的 salt 就是字符串的 UTF-8 编码:

好的,那么接下来可以看它具体是如何实现这个 CreateAesStream 的了。从 IDA F5 结果中可以看到,首先是调用了 PasswordDeriveBytes$$.ctor 这个函数构造出来一个类的实例,然后我们看看实例的交叉引用:(*(*pdb_self + 376))(pdb_self, (v14 >> 3), *(*pdb_self + 384));……

WTF!?还让不让人好好分析了?看 dump.cs 似乎只能找到类变量的偏移,而看不出这个 +376 到底是调用的啥函数。

失望、苦恼之际,我突然想到:直接动态调试一遍,选择进入函数,然后把 lldb 里的地址减掉 ASLR,不就是真实的函数地址了吗?立刻行动,然后用类似的方法,把整个函数的逻辑找了出来,原来是先用 PasswordDeriveBytes 生成密钥,然后再使用 AES_128_ECB 模式进行加解密(做到这里我有点纳闷:为什么使用 ECB 这一不足够安全的模式呢?):

实现加解密函数(一)

接下来差不多可以实现加解密函数了吧。通过 Google 搜索,我发现,PasswordDeriveBytesAesManaged等都是微软的.NET Core 里的类,这意味着,咱们可以滴滴偷代码了。我之前没有 C# 开发经验,于是这次花了几个小时安装.NET Core 环境、学习 C# 基本语法、阅读 微软官方文档 ,然后 使用正确的 key、iv 和 mode 进行解密……

Boom!失败了。输出的文件依然是一团乱码。

噩梦才刚刚开始。我脑子里满是问号:为什么完全一样的参数,却不能成功解密?即使是 padding 的问题,根据 ECB 模式的算法,文件的前几个 chunk 也应该是明文才对啊?

实现加解密函数(二)

又重新读了一遍 IDA F5 出来的代码,我发现 CreateAesStream 也仅仅做了一个类似构造函数、初始化的工作,可能具体的加密方法并不如我所想的那么简单。

回到 AssetBundleList$$Load 函数去看一眼,有没有调用什么叫 Decrypt 之类的方法,很可惜,并没有:

看样子,CreateAesStream会直接返回一个具有 Stream 类特性的实例对象,并且能被 StreamReader 类实例直接读取成明文。从刚才的分析里可以看出,CreateAesStream似乎无需传入指定加密 / 解密操作的 flag 参数,难道这是一个流密码的实现吗?「Stream」这个词似乎也在暗示着什么……

果然,天无绝人之路!回到 AssetBundleCryptoStream 类去看看,马上找到一个可疑的函数cipher,配合 dump.cs 文件分析一下:

哈哈!这是一个 AES 的 CTR 模式 的实现。接下来只要把 IDA F5 出来的代码改成对应的 C# 代码,就能实现正确的加解密了,事实也是如此。下面是我用游戏中素材进行拼接得到的一个动图:

总结 & 展望

逆向工程确实是一件非常费时、费神的事,它非常考验各方面的技巧(搜索、静态分析、动态调试、ARM 汇编等),也需要一点好运气

成功来之不易,在这篇博文中,我将不会放出直接可用的解密程序。如果你也对 beatmania IIDX ULTIMATE MOBILE 的游戏资源感兴趣,某知名 BEMANI 相关 PT 站已有完整的解密文件可供下载。如果你也想探究它的加解密流程,希望本文能对你有所帮助。

此外,根据我在 iOS 设备上对 beatmania IIDX ULTIMATE MOBILE 进行的抓包测试,可以确认它开启了 SSL Pinning(SSL Kill Switch对它无效),并且加密了与服务器的通信的所有内容。我还没有开始研究这个游戏的通信协议的加解密方式,或许在将来有空时会去看看,也或许不会再回来看,毕竟人家新出的游戏,还是付费订阅一下比较合适吧😉。