diff --git a/content/posts/2024-10-24 PJSK Reversing.md b/content/posts/2024-10-24 PJSK Reversing.md new file mode 100644 index 0000000..b6483d2 --- /dev/null +++ b/content/posts/2024-10-24 PJSK Reversing.md @@ -0,0 +1,99 @@ +--- +title: 世界计划 缤纷舞台!feat. IL2Cpp +title_image: +subtitle: 从零开始解密 pjsk 的网络请求 +tags: + - ctf + - 教程 +--- +玩了这么久プロセカ,有点想分析一下游戏的排行数据,做一些自动化,比如让自己一直停留在整两百名之类的。这种手游抓抓包模仿请求一定不会很难吧——装上 Reqable 连上模拟器抓抓包偷吃几块饼干之后发现,请求负载和返回内容都依然是乱码... + +![[Screenshot 2024-10-24 062606.png|只偷吃到了饼干渣]] + +看到乱码的第一反应是编码不对,或者过了某种基础混淆,总之先丢给 CyberChef 看看魔法糊糊器能不能把答案糊出来,发现不行。去群里问问之后 Menci 和我说是 AES 加密过的,还告诉我了加密密钥在 APIManager 里面,那就试着找找吧 + +## 1 从拆开 APK 开始 + +因为プロセカ的客户端能够解密,那么解密密钥一定就在客户端里。首先下载了プロセカ 4.0.0 的 XAPK 包。所谓的 XAPK 其实就是把多个 APK 压缩在一起啦,其中一个包含了所有架构共享的文件,另一个包里放了 arm64 平台专属的二进制(虽然这个游戏好像还没有编译过除了 arm64 以外的平台,不知道为什么还要这样分包) + +解压缩之后单独用 apktool 把两个安装包的文件拆出来看一看吧。目录结构看上去就是一个一般的 IL2Cpp Unity 项目,没有什么特别的。编译过的游戏二进制在 lib/arm64-v8a/libil2cpp.so 里面,然后运行它、让它能够和 C# 那边的程序对接需要的元信息在 assets/bin/Data/Managed/Metadata/global-metadata.dat 里面。 + +![[2024-10-24 15-24.png|两个重要的文件]] + +如果想要快速找到代码的话,只看 IL2Cpp 编译好的的二进制肯定不行。这个文件里一共有 44 万个没有名字的函数指针,IDA 把这些分析出来都花了快一个小时,从这里一个一个找肯定是不行的。所以我搜索了一下 IL2Cpp 反编译,找到了 Perfare/IL2CppDumper 这个工具,试了一下发现报错说 "Metadata file supplied is not valid metadata file" + +![[2024-10-24 16-06 1.png|正常的元文件的文件头]] + +为什么呢?看了一下,一般的 global-metadata 的文件头是 0xAF1BB1FA,而我拿到的这个不是,也就说明它很可能被加了壳。 + +## 2. 脱壳元文件 + +怎样解密呢?首先试了同一个作者的另一个工具 Zygisk-IL2CppDumper,是一个据说可以自动解密元文件的 Magisk 模块,但是构建好装上之后打开游戏发现什么都没有发生,说会解包到 /data/data 里面但是也没有,还是试试别的方法吧。 + +既然上次用 Cheat Engine 在电脑上从内存中脱壳了 maimai 的 Assembly-CSharp,我觉得应该也可以用同样的方式脱壳プロセカ的元文件,所以就下载了一份 Game Guardian 试了一下。打开游戏,挂载上 GG,内存搜索 "H AF1BB1FA" 之后马上就找到了! + +![[Screenshot 2024-10-24 073615.png|搜索到了内存]] + +把地址复制下来,去第四个 Tab 把地址粘贴进去之后点旁边的选择器选中这个区域的头到尾,导出成文件之后重命名成新的 global-metadata.dat 就可以了。之后重新试了一下用 IL2CppDumper 反编译就没有报错了! + +![[2024-10-24 16-03.png|反编译成功了!]] + +虽然还是有 "This file may be protected" 的报错,原本还以为 libil2cpp.so 也被套了壳,结果发现并没有,只是识别到了 JNI_OnLoad 预警性地报了一个错而已,也就是说已经成功啦。看了一眼 Dumper 输出的 `dump.cs`,里面确实有 APIManager,里面也确实用到了 AES 加密,但是因为实现的部分被转成二进制了,这里只能看到定义。 + +## 3. 找钥匙! + +接下来就是找钥匙的环节,但是怎么找呢?如果要找到钥匙的话,大概需要看一下 APIManager 的代码实现,可是 `dump.cs` 里面只有空壳没有实现,可是只看 libil2cpp.so 又没办法知道 APIManager 在哪... 怎么办呢?看了一下 Dumper 仓库里面写的文档,看起来像是能和 IDA 联动让实现和空壳结合在一起的样子,那就下载一个 IDA 试试吧。 + +下载了 IDA 9.0,其实不太会用,我只懂得基础操作比如用 F5 切换反编译代码和汇编之类的,但是总之先打开二进制 libil2cpp.so 看看吧。刚打开的时候什么都没有,只有不到一百个函数,我还在怀疑是不是打开错文件了,但是等了十分钟又出现了很多函数,发现原来它只是还没有分析完... 可能 150MB 大的二进制对于 IDA 来说也太大了吧,完整分析完花了差不多一个小时,存的数据库有 2 GB 大 (╯’ – ‘)╯︵ ┻━┻ + +![[2024-10-24 16-26.png|好大文件]] + +分析完之后依然没有函数名,全部都是 sub_1234567 这样的数字编号。看着 Dumper 的文档试着用 File > Script file 跑了一下那个 ida_py3 的脚本,选中了 script.json 之后函数名确实出现了!不过这只是第一步。 + +看了 `dump.cs` 里面的函数定义之后,我觉得 CreateCrypt 这个函数比较像是我们要找的,因为是一个静态函数,调用了之后会凭空造出来一个 FastAES 的实例,而 FastAES 需要传入两个钥匙才能创建实例,所以无论怎样这里都会用到钥匙吧? + +![[2024-10-24 16-45.png|APIManager 的函数定义]] + +看看反汇编的二进制代码发现确实用到了密钥。虽然变量全都被打乱了,但是从 FastAES 的构造器参数可以看出来 v3 v4 是 AES128 的两个钥匙 (key, iv),然后规格是 AES128,密文模式 1 (CBC),补格模式 2 (PKCS7)。那么这两个变量是从哪里来的呢?从代码里也能看到,v2 是从 v1 + 184 的指针地址读过来的,v3 是 v2 的值,v4 是 v2 的下一个值也就是 v1 + 192,而 v1 是 APIManager_TypeInfo 的地址。 + +![[2024-10-24 16-48.png]] + +从 C# 的逻辑上想的话,TypeInfo 应该是一个类附带的常量或者变量类型的地方,从 `dump.cs` 里面可以看到它定义的变量指针偏差从 0 加到 8 加到 0x20, 0x28... 可是这里面没有 +184 = 0xb8 这个位置,为什么呢? + +![[2024-10-24 19-27.png|APIManager 类的变量偏差最高到了 0x38]] + +我在这里卡了超级久,然后看了一下构造器发现 +184 这个偏差原来是在调用构造器的时候动态写进去的,是代码里面没有定义的,也许是某种编译器优化吧。打开 `APIManager$$.cctor` 构造器首先发现的是它写入了指向 +184 的地方 (L23 行),写入的是 v3 的值。向前读可以看到 v3 就是 v1,是一个空的 16 字节数组,然后把 v2 的数据复制到了 v1,而 v2 是 `Field__` 开头的这一长串。 + +![[2024-10-24 19-32.png|cctor 构造器的反编译代码]] + +回到 `dump.cs` 里面查找这个字段,发现它是一个编译器生成的只读项,上面下面也有类似的东西,看这个 "Static Array Init Type Size" 的话这些应该就是代码里用到的数组常量被转移到的位置了。但是这一长串的十六进制似乎只是某种指针,数值似乎不在这里——因为如果是数值的话,数组的长度对不上——我们要找的 AES128 密钥是 128 位也就是 16 字节,但是这一长串每个都有 32 字节,和前面的 Array Size 也对不上。那么数值在哪呢? + +![[2024-10-24 19-37 1.png|十六进制 offset 在编辑器里五颜六色]] + +看到后面五颜六色的 offset 那里写了注释 "Metadata offset",我就在想难道它会在 global-metadata 里面吗?用 hexed.it 打开了这个文件然后把 offset 复制到 Go to 栏里面转向,发现那里真的有一个 16 位的钥匙!接下来又按同样的方式找到了 16 位的 iv,整个 AES 加密就被破解啦(在这里打一下码,需要的话看完这篇肯定就能够自己找到了 quq) + +![[2024-10-24 20-03 1.png|找到了 16 位的钥匙]] + +## 4. 可以解密了! + +接下来就是解密的过程了,把请求内容和返回内容都导出成文件,再随手用搓两行 python 脚本就可以解密啦: + +```python +import sys +from Crypto.Cipher import AES +from Crypto.Util.Padding import unpad +from pathlib import Path + +aes = AES.new(b"g2fcC0ZczN9MTJ61", AES.MODE_CBC, b"msx3IV0i9XE5uYZ1") +dec = lambda x: unpad(aes.decrypt(x), AES.block_size, style='pkcs7') + +[f.with_suffix(".dec").write_bytes(dec(f.read_bytes())) + for f in Path(sys.argv[1]).glob("*")] +``` + +解密之后似乎是一个 pjsk 自己的二进制序列化格式,看起来还需要一些时间研究怎样把它转换成 json 呢,不过今天就到这里好啦,累累睡睡(x) + +![[2024-10-24 21-02.png|解密之后的明文]] + + + diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 15-24.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 15-24.png new file mode 100644 index 0000000..7b3ad18 Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 15-24.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-03.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-03.png new file mode 100644 index 0000000..e982aad Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-03.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-06 1.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-06 1.png new file mode 100644 index 0000000..f85b3ea Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-06 1.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-06.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-06.png new file mode 100644 index 0000000..f85b3ea Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-06.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-26.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-26.png new file mode 100644 index 0000000..99ce04f Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-26.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-45.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-45.png new file mode 100644 index 0000000..9d5a7bd Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-45.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-48.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-48.png new file mode 100644 index 0000000..1803db1 Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 16-48.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-27.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-27.png new file mode 100644 index 0000000..a3c4981 Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-27.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-32.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-32.png new file mode 100644 index 0000000..e556396 Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-32.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-37 1.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-37 1.png new file mode 100644 index 0000000..f1c4659 Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-37 1.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-37.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-37.png new file mode 100644 index 0000000..3b0f4b2 Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 19-37.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 20-03 1.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 20-03 1.png new file mode 100644 index 0000000..740b3dd Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 20-03 1.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 20-03.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 20-03.png new file mode 100644 index 0000000..8d64931 Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 20-03.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 21-02.png b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 21-02.png new file mode 100644 index 0000000..dec5499 Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/2024-10-24 21-02.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/Screenshot 2024-10-24 062606.png b/content/posts/Assets/2024-10-24 PJSK Reversing/Screenshot 2024-10-24 062606.png new file mode 100644 index 0000000..9a1bd6c Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/Screenshot 2024-10-24 062606.png differ diff --git a/content/posts/Assets/2024-10-24 PJSK Reversing/Screenshot 2024-10-24 073615.png b/content/posts/Assets/2024-10-24 PJSK Reversing/Screenshot 2024-10-24 073615.png new file mode 100644 index 0000000..157afd5 Binary files /dev/null and b/content/posts/Assets/2024-10-24 PJSK Reversing/Screenshot 2024-10-24 073615.png differ