[原创]少前2逆向经验分享

查看 144|回复 11
作者:iuwerury   
免责声明:本篇文章仅作个人逆向分析经验记录与学习之用,所获得的一切资产恕不作任何分享。实践本文章记录的任何操作所产生的一切后果均与本人无关。侵删

本文的撰写离不开 @DNLINYJ 前辈开路,也是前辈的帖子带我认识了Process Monitor这一神器,前辈帖子指路:https://bbs.kanxue.com/thread-279118.htm 和 https://www.52pojie.cn/thread-1840843-1-1.html

1. global-metadata.dat 及 AssetBundle
跟着前辈的文章一步步走就行了,具体怎么操作就请诸位大佬各显神通了,在此略过
2. 植入UnityExplorer
简单介绍一下:UnityExplorer (https://github.com/sinai-dev/UnityExplorer) 是一个十分方便且开源的Unity游戏内调试辅助工具,提供了Inspector、Object Explorer、Console和Hook等诸多强大功能。(可惜的是该项目不知出于何种原因已经archived不再更新)
[ol]
  • 在上一步中得到解密的global-metadata.dat后,先将BepinEx或者MelonLoader框架安装到游戏上,这里根据我的经验il2cpp最好选择MelonLoader 0.5.7版。
    [/ol]

    MelonLoader官方安装教程: https://github.com/LavaGang/MelonLoader?tab=readme-ov-file#how-to-use-the-installer



    Snipaste_2023-12-28_10-08-18.png (99.87 KB, 下载次数: 0)
    下载附件
    安装MelonLoader 0.5.7
    2023-12-29 11:29 上传

    (这里我已经安装过了所以显示为RE-INSTALL,正常安装应该只有一个INSTALL按钮)
  • 安装MelonLoader后,依照UnityExplorer的Readme安装UnityExplorer
    [/ol]

    https://github.com/sinai-dev/UnityExplorer?tab=readme-ov-file#melonloader



    Snipaste_2023-12-28_10-08-26.png (189.45 KB, 下载次数: 0)
    下载附件
    选择UnityExplorer版本
    2023-12-29 11:30 上传

    (其实就是将解压出来的 Mods 文件夹和 UserLibs 文件夹复制到游戏对应目录就行了)
    3. 替换global-metadata.dat
    安装MelonLoader启动后会在终端发现Cpp2IL报错导致游戏无法正常启动,这是因为原版加密的global-metadata.dat依然在 il2cpp_data\Metadata 文件夹中,需要凭借单身多年的手速将其替换。
    替换之前记得将dump出来的global-metadata.dat的第4-8字节的版本号patch正确,经过一遍遍在il2cppDumper中试错后确认为 0x18
    偷梁换柱具体步骤如下:
    [ol]

  • 在 Game 文件夹中直接启动游戏,不通过启动器启动

  • 立即切换到终端窗口,当 Loading Plugins from ... 字样出现时立即选中终端内任意范围冻结进程,此时游戏窗口应刚好出现并冻结于如图所示白屏状态
    [/ol]


    Snipaste_2023-12-28_10-10-12.png (152.73 KB, 下载次数: 0)
    下载附件
    通过终端选中冻结进程
    2023-12-29 11:30 上传

  • 复制并备份好原版global-metadata.dat (这一步和接下来的几步理应不会出现“文件被占用”、“无法启动”、游戏崩溃之类的任何错误,如果遇到了说明上一步冻结时机过晚、过早)

  • 将dump并patch好版本(再强调一次,十分甚至九分重要)的global-metadata.dat替换过去

  • 切换至终端窗口,按 Esc 取消选中,解冻进程

  • 退出游戏,将第3步备份好的原版global-metadata.dat替换回来,之后在遇到游戏更新时重新走一遍以上步骤即可
    [/ol]
    4. 解密其它未封装进AssetBundle的资源
    在成功安装UnityExplorer之后,我们应当已经拥有了il2CppDumper提供的dump.cs文件,以及UnityExplorer提供的强大hook功能。至此我们终于可以进入正题,解密其它资源。
    4.1 解密.acb、.awb音频
    根据以往解galgame的经验,特殊格式必有特殊工具。通过万能的搜索引擎,我最终找到了 vgmstream 这个强大工具。
    通过阅读 USAGE.md 的 Decryption keys 这节可以发现解码.acb和.awb需要 .hcakey 。经过测试发现确实如此,没有.hcakey解码出来的.wav文件就是一坨答辩。


    Snipaste_2023-12-28_10-10-25.png (119.47 KB, 下载次数: 0)
    下载附件
    解密.awb/.acb可能需要.hcakey
    2023-12-29 11:30 上传

    再次借助万能搜索引擎の抛瓦,我找到了@头蟹床大佬的这篇分析.hca的顶级文章。

    https://blog.mottomo.moe/categories/Tech/RE/zh/2018-10-12-New-HCA-Encryption/

    这里我就直奔主题跳到初步分析密钥设置流程这一节,发现了 criWareUnity_SetDecryptionKey() 这一关键函数。然而在IDA或者il2CppDumper的dump.cs中都搜索不到 SetDecryptionKey 这一函数。


    Snipaste_2023-12-28_10-10-35.png (33.1 KB, 下载次数: 0)
    下载附件
    搜索SetDecryptionKey无结果
    2023-12-29 11:31 上传

    因此我退而求其次,搜索 Decrypt 关键词,这次在IDA中发现了一些跟CriWare有关的目标函数。


    Snipaste_2023-12-28_10-10-46.png (209.92 KB, 下载次数: 1)
    下载附件
    IDA函数搜索Decrypt
    2023-12-29 11:31 上传

    其中包括两个跟acb有关的目标函数:
    [ol]
  • CriWare.CriAtomExAcb::Decrypt()
  • CriWare.CriAtomPlugin::DecryptAcb()
    [/ol]
    重启游戏,在点击开始屏幕进入游戏之前的界面尝试用UnityExplorer hook住这两个函数。


    Snipaste_2023-12-29_11-34-45.png (70.01 KB, 下载次数: 0)
    下载附件
    UnityExplorer hook
    2023-12-29 11:34 上传

    点击开始屏幕,切换到终端查看打印输出,发现成功打印出key,调用的函数是 CriWare.CriAtomExAcb::Decrypt() 。
    [13:15:16.183] [UnityExplorer] --------------------
    void CriWare.CriAtomExAcb::Decrypt(ulong key, ulong nonce)
    - __instance: CriWare.CriAtomExAcb
    - Parameter 0 'key': 密钥在这里
    - Parameter 1 'nonce': 0
    [13:15:22.939] [UnityExplorer] --------------------
    void CriWare.CriAtomExAcb::Decrypt(ulong key, ulong nonce)
    - __instance: CriWare.CriAtomExAcb
    - Parameter 0 'key': 密钥在这里
    - Parameter 1 'nonce': 0
    [13:15:22.966] [UnityExplorer] --------------------
    void CriWare.CriAtomExAcb::Decrypt(ulong key, ulong nonce)
    - __instance: CriWare.CriAtomExAcb
    - Parameter 0 'key': 密钥在这里
    - Parameter 1 'nonce': 0
    [13:15:23.574] [UnityExplorer] --------------------
    void CriWare.CriAtomExAcb::Decrypt(ulong key, ulong nonce)
    - __instance: CriWare.CriAtomExAcb
    - Parameter 0 'key': 密钥在这里
    - Parameter 1 'nonce': 0
    根据vgmstream的Readme,将得到的 ulong key 转换为hex bytes。注意.net的BigEndian编码问题。go代码如下:
    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音频了


    Snipaste_2023-12-28_10-27-57.png (172.43 KB, 下载次数: 0)
    下载附件
    音频解密结果
    2023-12-29 11:35 上传

    4.2 转换.usm视频
    相较而言,.usm视频的解码对我而言就简单多了(当然还是因为解galgame的经验)
    [ol]
  • 使用vgmtoolbox解码.usm为.m2v和.hca
    [/ol]

    vgmtoolbox官方地址:https://sourceforge.net/projects/vgmtoolbox/



    Snipaste_2023-12-28_10-22-41.png (89.94 KB, 下载次数: 0)
    下载附件
    vgmtoolbox打开video demultiplexer
    2023-12-29 11:35 上传
  • 静静等待vgmtoolbox完成它的工作
    [/ol]


    Snipaste_2023-12-28_10-25-26.png (159.81 KB, 下载次数: 0)
    下载附件
    vgmtoolbox解码中
    2023-12-29 11:36 上传
  • 使用vgmstream转换.hca为.wav
    [/ol]


    Snipaste_2023-12-28_10-29-21.png (191.12 KB, 下载次数: 0)
    下载附件
    vgmstream转换.hca为.wav
    2023-12-29 11:37 上传
  • 直接用potplayer播放(注意音轨数量,有的两条有的一条)
    [/ol]


    Snipaste_2023-12-28_10-08-395ed87398087ae1d6.png (1.72 MB, 下载次数: 0)
    下载附件
    potplayer载入音频
    2023-12-29 11:37 上传



    Snipaste_2023-12-28_10-08-479e2ff6f2d3ad1736.png (122.21 KB, 下载次数: 0)
    下载附件
    potplayer选中两条音轨
    2023-12-29 11:37 上传
  • 如需合并音视频为一个文件,先用everything处理一下文件名
    [/ol]


    Snipaste_2023-12-28_10-09-266466c08353b7b4a2.png (32.16 KB, 下载次数: 0)
    下载附件
    everything重命名.m2v文件
    2023-12-29 11:38 上传



    Snipaste_2023-12-28_10-09-01b337c5c18181b48b.png (34.3 KB, 下载次数: 0)
    下载附件
    everything重命名.wav文件
    2023-12-29 11:38 上传
  • 再使用ffmpeg合并
    [/ol]
    @rem 单音轨
    FOR %%a IN (*.m2v) DO ffmpeg -i "%%a" -i "%%a_0.wav" -map 0:v -map 1:a -c copy "%%a.mov"
    @REM 双音轨
    FOR %%a IN (*.m2v) DO ffmpeg -i "%%a" -i "%%a_0.wav" -i "%%a_1.wav" -map 0:v -map 1:a -map 2:a -c copy "%%a.mov"
    4.3 解码Table
    这一部分其实说简单也不行说难也不行。
    不能说它难是因为这就是一个加了长度前缀的protobuf,通过 08 0A 这种极具protobuf特点的字节可以看出。因此解码前只需删掉前4字节即可正常解码。

    关于长度前缀详见protobuf官方文档:https://protobuf.dev/programming-guides/encoding/#length-types



    Snipaste_2023-12-28_10-09-372709f2565e3eac83.png (252.25 KB, 下载次数: 0)
    下载附件
    table文件sample
    2023-12-29 11:38 上传

    不能说它简单是由于游戏使用了HybridCLR,global-metadata.dat和DummyDLL中的类型信息都不全,暂时无法自动化地导出.proto用来解析,因此在这部分如果想要获得到.json需要人工去对照CheatEngine得到的mono信息猜出字段名,十分麻烦,故在此略过,直接使用python的 protod 包解码raw wire
    protod --file XXXXXXXX.bytes


    Snipaste_2023-12-28_10-09-45d7d12f4fb83f794f.png (514.49 KB, 下载次数: 0)
    下载附件
    table文件sample解码
    2023-12-29 11:39 上传

    (找错别字环节)
    结语
    在这次实战中,遇到的最大阻力其实并不是易盾反作弊的保护,反而是HybridCLR的特殊指令集,导致解码Table时由于缺少.proto又不能通过DLL直接生成,需要手动一个个字段地猜,不是很偷懒优雅。希望之后有大佬能写出将HybridCLR指令集转换回IL指令集的工程,这样就可以开摆了嘻嘻(bushi

    下载次数, 下载附件

  • iuwerury
    OP
      


    alicc 发表于 2024-1-3 12:16
    大佬请问下 UnityExplorer 有没学习基础等文章
    我是通过这里接触到UnityExplorer的:https://framedsc.com/GeneralGuides/universal_unity_freecam.htm#starting-unity-explorer
    这网站里面也有其他很不错的教程,比如另一个虚幻4相关的工具:https://framedsc.com/GeneralGuides/universal_ue4_consoleunlocker.htm
    使用UnityExplorer更高级的功能(比如console、hook、inspector)需要稍微熟悉一下unity的基础知识,比如各种Asset类型、Unity的Transform类、C#
    它自己的Readme (https://github.com/sinai-dev/UnityExplorer?tab=readme-ov-file#features) 写得也比较详尽可以参考
    iuwerury
    OP
      


    AH225D 发表于 2024-3-5 11:04
    菜鸡斗胆问问大佬,那要怎么把他从内存dump global-metadata.dat那步要怎么做啊。看了帖子里的连接没看明白

    建议通篇阅读这篇文章https://bbs.kanxue.com/thread-278275.htm#msg_header_h2_1,有条件也可以去读一下英语原文https://katyscode.wordpress.com/2021/02/23/il2cpp-finding-obfuscated-global-metadata/。
    当你在ida中找到形如以下形式的代码时,红框中的182B7C2D8就是解密后的global-metadat.dat地址:


    image.png (155.61 KB, 下载次数: 0)
    下载附件
    2024-3-5 12:41 上传

    之后再用任意工具从这一地址dump内存就行了(Windows上我习惯用Cheat Engine,Android上Frida/GameGuardian均可)。
    如果你想问dump内存的具体操作建议问gpt/同义千问/文心一言等老师
    Raincccup   

    太强了,膜拜大佬
    DNLINYJ   

    其实IL层根本没改(写完文章了但是不太想发)写的不错 (^^ゞ
    zfajun   

    感谢分享。。。。。
    iuwerury
    OP
      


    DNLINYJ 发表于 2023-12-30 22:35
    其实IL层根本没改(写完文章了但是不太想发)写的不错 (^^ゞ

    主要是我在一个code文件夹里发现了Assembly-CSharp.dll.bytes(好像叫这个),里面有GF2命名空间,其中有大量缺少内容的游戏逻辑函数。然后就尝试了一下在游戏内用unity explorer、il2cppdumper给的dump.cs和CheatEngine找“GF2”,最终只有CheatEngine找到了,但是定位函数后会发现CE给到的是进入HybridCLR解释执行过程的函数(就是那一大坨switch case)。再结合百度上一些使用HybridCLR的教程和GitHub上类似的demo都说HybridCLR处理的hotupdate都以.bytes结尾,就说明它还是把这些核心逻辑用HybridCLR保护起来了
    DNLINYJ   


    iuwerury 发表于 2023-12-31 11:06
    主要是我在一个code文件夹里发现了Assembly-CSharp.dll.bytes(好像叫这个),里面有GF2命名空间,其中有 ...

    HybridCLR的社区版其实那玩意就是裸奔的,商业版有标准加固和高级加固,标准加固其实也就那样,几天就搞好了,高级估计由于ym没钱没上 (ˉ﹃ˉ)
    0xUYR7s   

    学习了。
    Sugarmapler   

    牛哇,虽然搞不懂,但是大受震撼
    您需要登录后才可以回帖 登录 | 立即注册

    返回顶部