本文的撰写离不开 @DNLINYJ 前辈开路,也是前辈的帖子带我认识了Process Monitor这一神器,前辈帖子指路:https://bbs.kanxue.com/thread-279118.htm 和 533K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3f1#2x3Y4m8G2K9X3W2W2i4K6u0W2j5$3&6Q4x3V1k6@1K9s2u0W2j5h3c8Q4x3X3b7I4z5o6b7H3z5o6b7K6i4K6u0V1x3g2)9J5k6o6q4Q4x3X3g2Z5N6r3#2D9
跟着前辈的文章一步步走就行了,具体怎么操作就请诸位大佬各显神通了,在此略过
简单介绍一下:UnityExplorer (de9K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6K6K9h3&6S2K9g2)9J5k6r3c8W2N6W2)9J5c8W2g2F1K9i4c8&6c8i4S2H3L8r3!0J5k6i4t1`.) 是一个十分方便且开源的Unity游戏内调试辅助工具,提供了Inspector、Object Explorer、Console和Hook等诸多强大功能。(可惜的是该项目不知出于何种原因已经archived不再更新)
MelonLoader官方安装教程: 0c4K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6x3j5i4k6S2c8$3q4F1k6#2)9J5c8V1#2W2L8r3!0F1e0r3!0S2k6r3g2J5i4K6y4r3N6r3q4T1i4K6y4p5M7X3g2S2k6r3#2W2i4K6u0V1L8%4k6Q4x3X3c8X3K9h3I4W2i4K6t1K6K9r3!0%4i4K6u0V1N6r3!0Q4x3X3c8#2M7$3g2Q4x3X3c8@1K9r3g2Q4x3X3c8A6L8Y4y4@1j5h3I4D9k6i4t1`.
(这里我已经安装过了所以显示为RE-INSTALL,正常安装应该只有一个INSTALL按钮)
9ecK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6K6K9h3&6S2K9g2)9J5k6r3c8W2N6W2)9J5c8W2g2F1K9i4c8&6c8i4S2H3L8r3!0J5k6i4u0Q4x3@1k6@1j5h3u0Q4x3@1c8J5k6h3q4V1L8h3g2Q4x3X3c8G2N6W2)9J5k6r3k6A6L8r3g2Q4x3U0y4E0k6h3I4G2L8X3I4G2j5h3c8W2M7R3`.`.
(其实就是将解压出来的 Mods 文件夹和 UserLibs 文件夹复制到游戏对应目录就行了)
Mods
UserLibs
安装MelonLoader启动后会在终端发现Cpp2IL报错导致游戏无法正常启动,这是因为原版加密的global-metadata.dat依然在 il2cpp_data\Metadata 文件夹中,需要凭借单身多年的手速将其替换。
il2cpp_data\Metadata
替换之前记得将dump出来的global-metadata.dat的第4-8字节的版本号patch正确,经过一遍遍在il2cppDumper中试错后确认为 0x18 。
0x18
偷梁换柱具体步骤如下:
在 Game 文件夹中直接启动游戏,不通过启动器启动
Game
立即切换到终端窗口,当 Loading Plugins from ... 字样出现时立即选中终端内任意范围冻结进程,此时游戏窗口应刚好出现并冻结于如图所示白屏状态
Loading Plugins from ...
复制并备份好原版global-metadata.dat (这一步和接下来的几步理应不会出现“文件被占用”、“无法启动”、游戏崩溃之类的任何错误,如果遇到了说明上一步冻结时机过晚、过早)
将dump并patch好版本(再强调一次,十分甚至九分重要)的global-metadata.dat替换过去
切换至终端窗口,按 Esc 取消选中,解冻进程
Esc
退出游戏,将第3步备份好的原版global-metadata.dat替换回来,之后在遇到游戏更新时重新走一遍以上步骤即可
在成功安装UnityExplorer之后,我们应当已经拥有了il2CppDumper提供的dump.cs文件,以及UnityExplorer提供的强大hook功能。至此我们终于可以进入正题,解密其它资源。
根据以往经验,特殊格式必有特殊工具。通过万能的搜索引擎,我最终找到了 vgmstream 这个强大工具。
vgmstream
通过阅读 USAGE.md 的 Decryption keys 这节可以发现解码.acb和.awb需要 .hcakey 。经过测试发现确实如此,没有.hcakey解码出来的.wav文件就是一坨答辩。
USAGE.md
.hcakey
再次借助万能搜索引擎の抛瓦,我找到了@头蟹床大佬的这篇分析.hca的顶级文章。
813K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6T1L8r3!0Y4i4K6u0W2L8h3!0@1N6r3!0E0L8#2)9J5k6h3#2G2k6g2)9J5c8X3y4S2N6r3g2Y4L8%4u0A6k6i4y4Q4x3V1k6f1k6h3y4Z5i4K6u0r3f1V1g2Q4x3V1k6*7K9q4)9J5c8U0t1H3x3e0S2Q4x3X3b7I4x3q4)9J5k6o6p5J5i4K6u0V1e0X3g2%4i4K6u0V1d9p5y4m8i4K6u0V1c8h3&6U0M7Y4W2H3N6r3W2G2L8W2)9J5c8R3`.`.
这里我就直奔主题跳到初步分析密钥设置流程这一节,发现了 criWareUnity_SetDecryptionKey() 这一关键函数。然而在IDA或者il2CppDumper的dump.cs中都搜索不到 SetDecryptionKey 这一函数。
criWareUnity_SetDecryptionKey()
SetDecryptionKey
因此我退而求其次,搜索 Decrypt 关键词,这次在IDA中发现了一些跟CriWare有关的目标函数。
Decrypt
其中包括两个跟acb有关的目标函数:
CriWare.CriAtomExAcb::Decrypt()
CriWare.CriAtomPlugin::DecryptAcb()
重启游戏,在点击开始屏幕进入游戏之前的界面尝试用UnityExplorer hook住这两个函数。
点击开始屏幕,切换到终端查看打印输出,发现成功打印出key,调用的函数是 CriWare.CriAtomExAcb::Decrypt() 。
[
13
:
15
16.183
] [UnityExplorer]
-
void CriWare.CriAtomExAcb::Decrypt(ulong key, ulong nonce)
__instance: CriWare.CriAtomExAcb
Parameter
0
'key'
: 密钥在这里
1
'nonce'
22.939
22.966
23.574
根据vgmstream的Readme,将得到的 ulong key 转换为hex bytes。注意.net的BigEndian编码问题。go代码如下:
ulong key
package main
import
(
"encoding/binary"
"fmt"
)
func main() {
bytes :
=
make([]byte,
8
binary.BigEndian.PutUint64(bytes, <替换为密钥>)
fmt.Printf(
"%X\n"
, bytes)
}
将转换后的hex bytes保存为.hcakey并复制到与.acb相同的目录,就可以愉快地用vgmstream解密.acb和.awb音频了
相较而言,.usm视频的解码对我而言就简单多了
vgmtoolbox官方地址:0bdK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6K6L8%4g2J5j5$3g2X3L8%4u0Y4k6g2)9J5k6h3&6W2N6q4)9J5c8Y4m8J5L8$3A6W2j5%4c8K6i4K6u0r3N6X3N6E0N6r3!0G2L8r3u0G2P5q4)9J5c8R3`.`.
@REM
单音轨
FOR
%
a IN (
*
.m2v) DO ffmpeg
i
"%%a"
"%%a_0.wav"
map
:v
:a
c copy
"%%a.mov"
双音轨
"%%a_1.wav"
2
这一部分其实说简单也不行说难也不行。
不能说它难是因为这就是一个加了长度前缀的protobuf,通过 08 0A 这种极具protobuf特点的字节可以看出。因此解码前只需删掉前4字节即可正常解码。
08 0A
关于长度前缀详见protobuf官方文档:b13K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6H3M7X3!0@1L8$3u0#2k6W2)9J5k6h3c8W2N6W2)9J5c8Y4m8J5L8$3N6J5j5h3#2E0K9h3&6Y4i4K6u0V1k6%4g2A6k6r3g2K6i4K6u0r3k6h3&6U0L8$3c8A6L8X3N6Q4x3V1k6Q4x3U0y4D9k6h3&6Y4N6r3S2Q4x3X3c8@1P5i4m8W2M7H3`.`.
不能说它简单是由于游戏使用了HybridCLR,global-metadata.dat和DummyDLL中的类型信息都不全,暂时无法自动化地导出.proto用来解析,因此在这部分如果想要获得到.json需要人工去对照CheatEngine得到的mono信息猜出字段名,十分麻烦,故在此略过,直接使用python的 protod 包解码raw wire
protod
file
XXXXXXXX.bytes
(找错别字环节)
在这次实战中,遇到的最大阻力其实并不是易盾反作弊的保护,反而是HybridCLR的特殊指令集,导致解码Table时由于缺少.proto又不能通过DLL直接生成,需要手动一个个字段地猜,不是很优雅。希望之后有大佬能写出将HybridCLR指令集转换回IL指令集的工程,这样就可以开摆了嘻嘻(bushi
[培训]科锐逆向工程师培训第53期2025年7月8日开班!