CGSS 核心反向过程实录 | 二、内容提取初试

文章目录
  1. 1. 一、声明
  2. 2. 二、文件结构猜测
  3. 3. 三、曙光:AFS2
  4. 4. 四、vgmtoolbox 的拯救
  5. 5. 五、谱面的出现

索引

2017年5月追记:

我探索这些的目的,是以一个玩家的身份,让 CGSS 变得更好玩。私下里我类比过普罗米修斯,将天火——谱面的制作和玩的能力从“天上”分一点出来。其实,修改 CGSS 去作弊是很简单的,无论是客户端还是 MITM。但是我不会去作弊,也不希望这系列文章的读者们将文章内容用在歪门邪道上,不希望去作弊、破坏平衡性。玩过 LLSIFSB69GF(note)Arcaea 之后,我仍然认为 CGSS 的综合指标(游戏性、操作体验、曲目等等)是行业内翘楚,Cy这次比较用心。那么作弊还有什么意思嘛!对了,我不氪金,不冲分,只是闲暇时间来两局,玩得舒心。

当然,まゆさまが見ています。

(3月2日23时-3月3日2时)


一、声明

The Idolmaster Cinderella Girls Starlight Stage 软件和相关媒体的著作权为 Bandai Namco Entertainment Inc. 所有。本系列文章仅从兴趣出发,研究数据反向过程。在此不会给出完整的反向过程、反向结果和源代码,只给出思路和部分非关键数据。

我相信大牛即使是没有看过我写的这些玩意儿也能上的。

二、文件结构猜测

上次我们讲过,歌曲文件的大小在 2M 以上。根据这个准则大致浏览一下各目录,就能发现目录 l 下聚集着一些 3.5M 左右的文件,数量不算多也不算少。推测这些是音频文件,而且是打歌用的音乐。我随机选择了一个 8a79c100465ec1c6ffbfdb45cf86af36bf6425cf,开始查看。

首先我以为是简单的音乐,就试着用 foobar2000 配合各种解码器来播放,都失败了。文件识别如何呢?TrIDNet 败下阵来,直接就报无法识别了,连推荐选项都没有。于是只好手工分析了。

由于几乎不可能是文本文件,所以最好的工具无非就是16进制查看器啦。这里我选用的是 Hex Editor Neo

这个文件头就很有意思:

`@UTF` 是很明显的特征

然后往下看,能看到一些可读的东西,例如 CueWafeformSamplingRate 等等。不过还有一个很有意思的现象,这个 @UTF 总是在4字节对齐(或者更高,例如16,我没仔细算)开头的地方出现。这就说明,@UTF 很可能是一个节(section)的开始标志。考虑到现在很多文件格式是针对32位机器的,对齐和数据首选32位(4字节)是很正常的。在@UTF 之前的那些字节,很多都是 0x00,说明这个文件结构是固定填充,带 padding 的。

考虑到一般分节的文件结构会记录数据偏移,而且很可能出现在头部,我们就来试试。第二个 DWORD0x0036caf8(Big Endian,大端序),等于十进制的 3590904,而该文件的大小是 3590912 字节,跳转到偏移 0x0036caf8,果然接下来8个字节都是 0x00,说明 @UTF 后紧跟着的4字节存放的是文件有效大小。

按照这样的思路抓几个节来分析,能得出下面一个简陋的结构:

struct {
   int32 magic; // "@UTF"
   int32 length; // 不包含"@UTF"头和4字节的长度
   int32 ???;
   int32 desc_offset; // 文字描述段(含段flag)距离本节的偏移
   int32 unknown_payload_length; //
   ??? ???;
   char field_desc[N]; // 文字描述段,C样式字符串,NULL结尾
   int32 end_signature = 0x00000000; // 固定的全零结尾
}

没错,对实际解析没什么用。然后注意到一个段(segment)SamplingRate,这个值应该不是随便取的。一般的设备也就是 11025 Hz、22050 Hz、44100 Hz、48000 Hz 这几种规格,如果播放时还要进行转换,就可能满足不了音游的实时性要求了。我们来看看:

推断 `SamplingRate` 的值

从后往前推,SamplingRate 是倒数第三个段,如果前面是数据,那么应该接近数据的末尾。慢慢推就发现,ac 44(十进制 44100)应该就是了。至于前后的字节,猜测是类型说明。

但是分析也就到此为止了,简单的挖掘挖不出新东西。

三、曙光:AFS2

继续看文件有没有什么有意思的。我发现,在最大段的数据(猜测是音频本体)前的节并不是 @UTF,而是 AFS2。为什么我这么肯定呢?因为 AFS2@UTF 一样,享受4字节对齐的“特殊待遇”。

这个 AFS2 并不像 @UTF 所指的那么泛,很可能是这个文件类型的指示。于是 Google 一下“AFS2 Format”,去掉那些明显是水军的链接,又有一个东西进入了视野:AWB。更多的时候,是这么写的:“AWB AFS2”——几乎是不可分割的。

首先我点入了这个链接,然后是这个。然后我知道了解包工具 QuickBMS 的存在,和对应的 AWB 解包脚本

我把 AFS2 节提取出来进行解包,但是什么都没出来。本来想结合推导出的结构手写 QuickBMS 脚本的,还找了一下使用方法,但是结构不完整也没法写了。

附:这个时期找到的 AFS 格式描述,不过和我观察到的不一致。

这条线暂时搁到一旁。

四、vgmtoolbox 的拯救

我继续阅读搜索结果。又一个东西吸引了我的注意:vgmtoolbox,有人说这个可以解 ACB/AWB 包。

什么是 ACB/AWB?仔细看索引数据库就会发现一些 .acb 文件,以及刚才抓的文件的文件头中的 ACB Format/PC Ver.1.23.01 Build:,都在提示我们这是个 ACB 包。

于是我下载了 vgmtoolbox,在 Extraction Tools\Common Archives 下找到了解包的界面。尝试后我发现,整个文件就是一个 ACB 包,AFS2 节只是其中的一部分。

然而,解包之后发现,解出来的是一个后缀名为 .hca 的文件。Google 之后,一团线出现在我眼前。

处在核心的,是一家名为 CRI Middleware 的日本软件公司。这家公司出品过游戏,不过在现在,其主业是提供音频解决方案。它开发了一款音频格式 ADX,也提供了相应的封包方案 ACB/AWB。

ADX 支持加密,维基百科上是这么说的:

A.D.X. supports a simple encryption scheme which XORs values from a linear congruential pseudorandom number generator with the block scale values. This method is computationally inexpensive to decrypt (in keeping with A.D.X.’s real-time decoding) yet renders the encrypted files unusable. The encryption is active when the “Flags” value in the header is 0x08. As XOR is symmetric the same method is used to decrypt as to encrypt. The encryption key is a set of three 16-bit values: the multiplier, increment, and start values for the linear congruential generator (the modulus is 0x8000 to keep the values in the 15-bit range of valid block scales). Typically all A.D.X. files from a single game will use the same key.

也就是说,解出来的是音频文件应该是 ADX 一类的。考虑到 BNEI 是日本企业,涉足游戏,和 CRI 是可能合作的,这进一步增加了可信度。

如何证明呢?CGSS 的启动画面就有 CRI 的logo(右上角):

CGSS 启动画面

以前我还不知道,现在我知道了。

然后我搜索 ADX 的播放器,找到一个 CriAtomPlayer(从名字就可以看出来源)。虽说是在国内网站上找到的,不过根据后来看到的资料,应该来自于限定日本国内使用的免费 ADX LE 开发套件。正当我满心欢喜地敲下回车的时候,一播放,完全是噪音。加密?你要我去试3×16位的密钥?这条线在这里断了。

五、谱面的出现

百无聊赖之中,我随意翻找 a 目录下的文件,拖到 vgmtoolbox 的窗口中看能不能解压,从最大的文件开始尝试。

第一个,不行。用 Notepad++ 一看就是编译后的 Unity3D shader。

第二个,不行。用 Notepad++ 一看……等等,这也是一个 SQLite 数据库!

话不多说,再次查看里面的内容。哇,这次挖到了东西,所有的对话文字、卡片说明、特技说明、载入画面的“八卦”(ウワサ)等等,都展现在了眼前。

于是我意识到,在 a 目录的 Unity3D shader 之海中,一定还存在其他的数据库。于是又写了一个小程序,在所有文件中搜索 SQLite 数据库。果不其然,我所保存的数据中,除了索引数据库,还有另外44个文件是 SQLite 数据库,打开看看是什么吧。有房间物品说明、PLv(Producer Level)说明等等,不过最有价值的,还是很容易解析的谱面(你看到了第一眼也会懂的,开发人员太贴心了www),和额外的谱面说明。


这一趟下来,音频这一关还没法过,但是谱面拿到了。

分享到 评论