《明日方舟:终末地》启动器config.ini解密记录

《明日方舟:终末地》启动器config.ini解密记录
misaka10843前言
在为《明日方舟:终末地》开发第三方启动器插件时,我发现鹰角不像米哈游的一样config.ini直接是明文保存的,而是直接将 config.ini 加密,导致必须要解密才能让第三方插件能够正确读取游戏版本号和 API 渠道信息。
这篇文章更多是为了重新走一遍反汇编的路,防止自己之后忘记x,利用 x64dbg 抓出真正的 AES-256-CBC 密钥的全过程。
静态 XOR 的错觉
起初我通过内存搜索抓到了解密后的明文([Game]\nversion=...),并天真地尝试用 密文 ^ 明文 反推密钥。算出来了一个 100 多字节的固定数组。 在更新之前完全ok,但这招在游戏更新后立刻失效了(也对,不可能用xor来,不然改一点点就要重新下发一下)
用 x64dbg 步过排雷
既然静态密码行不通,我决定重新用 x64dbg 动态调试,把官方到底用了什么加密算法给揪出来。
因为启动器使用了大量的底层框架(Qt),如果盲目跟进每一个函数,很容易迷失在数万行系统代码的汪洋大海里。所以我采取了最笨但也最稳妥的战术: “步过排雷法” 。
1.定位读取方法位置
首先,程序一定要读取这个文件。所以我在 x64dbg 的搜索范围->所有用户模块->字符串应用中全局搜索 config.ini。 然后将两个搜索出来的config.ini的两个方法都打上断点
2.死盯寄存器,F8揪出真凶
这是最考验眼力的一步。首先要在运行到上面打的断点的函数中先F7进入函数里,然后就F8让程序一行一行在外面跑。
并且还要死死盯着右侧的寄存器窗口(特别是 RAX) 和下方的内存数据窗口。 每按一次 F8,就检查一下内存里有没有出现配置文件的明文。
走着走着,在我按过某一个 CALL 指令的瞬间,原本一堆乱码的寄存器,突然赫然弹出了 "[Game]\nversion=70.0.1\nentry=..." 这段极其完美的明文
3.深入虎穴
既然知道是刚才那个 CALL 把密文变成了明文,那它就是核心解密算法的函数。
Ctrl+F2 重启程序,再次来到这里。但这一次,就把断点精准地打在了这个嫌疑 CALL 上。 当程序再次停在这里时,我不再按 F8而是按下F7,一头扎进了这个解密函数的内部然后再进行2中的操作。
进去之后,经过几步简单的追踪,真相水落石出,赫然看见call了OpenSSL的库
-
CALL <EVP_CIPHER_CTX_new> -
CALL <EVP_aes_256_cbc> -
CALL <EVP_DecryptInit_ex>
既然是 AES-256-CBC,解密就必须要两个硬性参数:32 字节的 Key 和 16 字节的 IV。
在调用 EVP_DecryptInit_ex 之前,程序必须将这两个参数传递进去。根据 x64 汇编的调用约定,我直接在那个 CALL 上方看谁给寄存器传了地址:
- 负责 IV 的地址:
7FF7AA2641C0 - 负责 Key 的地址:
7FF7AA2641D0
最终提取结果:
- IV (16 Bytes):
33 46 78 61 19 27 50 64 95 01 93 72 64 60 84 00 - Key (32 Bytes):
C0 F3 0E 1C E7 63 BB C2 1C C3 55 A3 43 03 AC 50 39 94 44 BF F6 8C 4A 22 AF 39 8C 0A 16 6E E1 43
总结与代码实现
拿到 Key 和 IV 后,一切就变成了最简单的调用系统自带加密库。 因为 AES 会自动处理文件大小补齐(Padding),我们不需要再去纠结之前猜测的“两字节文件头偏移”,直接将整个文件按 PKCS7 填充模式解密即可,出来就是完美的 [Game] 配置文件。
断点其实也打了挺多了,回想起来可能可以找到config.ini的密文地址之后直接打硬件访问断点应该就可以了
以及之前感觉应该不会直接调用openssl,所以也就是没有直接搜索对应的特征(就是EVP_CIPHER_CTX_new)
理论来说只要直接搜索EVP_CIPHER_CTX_new就可以找到解密信息,然后打个断点后直接看内存映射即可













