北笙ぐ 发表于 2021-5-30 15:12

关于Cocos2dx-js游戏的jsc文件解密(二)

## 前言
上一期**关于Cocos2dx-js游戏的jsc文件解密**教程后,有一些同学似乎遇到了一些新的问题,下面列举一些:
- 利用ASCII字符串Cocos Game来定位解密密匙在有些游戏中似乎行不通;
- 拿到了正确的Key后,利用解密工具解出来依然是乱码;
- 解密后的js文件用不用重新加密为jsc格式的文件然后打包回去;
- 解密的密匙还能在哪里获取;
- ······

<!-- more -->

诸如此类的问题很多,希望看了下面的一些简单分析能为大家提供一些答案。

## 初步分析
研究逆向先看正向,从官网上下载CocosCreator开发工具,使用案例js工程尝试构建编译,在构建发布页面很清楚的看到了脚本加密选项。

![密匙选项](https://i.loli.net/2021/05/24/bkChvPD12FpItTY.png)

按流程构建编译后得到简单的样本APK。关于APK内各个文件夹的作用和内容,这里不在多说,感兴趣的同学可以结合Cocos2dx源码进行分析。

![样本APK的jsc文件结构](https://i.loli.net/2021/05/25/F9r3NqaYmWxLdz8.png)

先拿样本APK做简单的分析,先用Jadx-gui去java层稍微读下源码,了解下assets目录下二进制源代码的加载情况,在入口**Cocos2dxActivity**处我们看到有一个**onLoadNativeLibraries**函数,跳转到其声明发现加载了一个叫**android.app.lib_name**的字符串资源。

!(https://i.loli.net/2021/05/25/rHu2dXaPs9FBK7h.png)

![加载声明](https://i.loli.net/2021/05/30/PIhfe867zYZkjqT.png)

在AndroidManifest.xml下找到其定义为**cocos2djs**,即加载了**libcocos2djs.so**文件。

!(https://i.loli.net/2021/05/30/pYolcxA34CumLO9.png)

明确了加载Assets目录资源的操作大概率不在java层后,再结合非虫前辈的“jsc反编译工具编写探索之路”,研究对象随即转移到libcocos2djs.so上。


## 构建过程
通过阅读Cocos2dx源码发现,其脚本加解密用的就是 **xxtea** 加密和解密(和Cocos2dx-lua加解密相似)。进而结合CocosCreator了解到其构建项目的过程为:
1. 工程用到的所有js脚本聚合为project.js等几个脚本
2. 如果勾选“Zip 压缩”选项,会进行压缩project.js,会减少很多体积,进而可以减少包大小
3. 使用xxtea进行加密上述文件,生成project.jsc
4. 将project.jsc打包到apk、ipa等安装包中

在程序运行时,正好做了相反操作:
1. 使用xxtea进行解密
2. 如果勾选“Zip 压缩”选项,进行解压缩
3. 调用js代码

## 实例分析
通过以上初步分析和构建过程的了解,怎么去获得Key值似乎就有些思路了。这里用两个游戏案例做分析,某Tap平台可下载:
- 某书院模拟器(A)
- 某公传承(B)

先拿游戏A分析,按上个帖子中的方法把安装包lib目录下的libcocos2djs.so拖进十六进制编辑器,搜索ASCII字符串:**Cocos Game**,结果没有搜索到相关信息。

!(https://i.loli.net/2021/05/27/c1EuZsdAqOGH9hx.png)

直接上IDA分析libcocos2djs.so文件,导出函数名很整洁看起来没有加什么奇怪的东西,说明没有做一些安全手段。搜索xxtea / key之类的函数名得到这几个相关函数:

![游戏A的so层关键函数](https://i.loli.net/2021/05/25/P8I2w4TktFsZMeL.png)

先尝试直接在so层寻找明文的Key,函数 **jsb_set_xxtea_key** 看着简单,似乎直接设置了key,去看看有没有希望的Key值。F5伪代码看下,传入了一个字符串化的指针参数,大概率可能是Key。

!(https://i.loli.net/2021/05/25/lizos5YmI8BaRPu.png)

回溯调用该函数的地方,看下传入的参数值。

!(https://i.loli.net/2021/05/25/DGUiMXaewgmzuxp.png)

很明显的得到了可疑的Key值(关键参数**v26**),尝试拿去解密jsc文件,解密成功。

![游戏A解密成功](https://i.loli.net/2021/05/25/za4rYwU5M7ldBcL.png)

此时再去分析下游戏B的libcocos2djs.so文件,IDA打开发现似乎是和游戏A相似的结构。

![游戏B的so层关键函数](https://i.loli.net/2021/05/25/TMQteldCV1yipxs.png)

同样,回溯关键函数 **jsb_set_xxtea_key** 同样来到了 **applicationDidFinishLaunching** 这个函数内,但似乎这次Key值(关键参数**v10**)不像游戏A中那样明文显示出来

!(https://i.loli.net/2021/05/25/onxW8vQFS3K7Rs1.png)

去附近的字符串看看有什么可疑的,双击**jsb-adapter/jsb-builtin.js**字符串。

!(https://i.loli.net/2021/05/25/VMEshj7PvGWmxXf.png)

却看到了可疑的Key值和常规的Cocos Game,再尝试拿这个Key值去解密,同样的解密成功。

此时返回游戏A中的同一位置,观察密匙附近的字符串。对比下,似乎只有 **main.js**这一个相同的地方,并且都在**applicationDidFinishLaunching**函数内部,或许是新的找Key值的关键?大家日后可以试试。

!(https://i.loli.net/2021/05/25/VIdEFj4UGha1PKy.png)

同时两个游戏的密匙都在函数 **applicationDidFinishLaunching** 中所体现出来,这就不得不促使我们了解下该函数。阅读下相关源码,了解到在一个Cocos2d-x的应用入口中,当应用环境加载完成会回调以下方法:

!(https://i.loli.net/2021/05/25/h64GYagTUtNXfiH.png)

此时再结合CocosCreator构建项目的过程就不难理解了,当游戏应用环境加载完毕后,该函数内把Key值传入到解密的函数中去,进而解密函数将jsc文件化为js文件,并拷贝到内存中去,游戏开始调用js文件,进入游戏界面。

## 其他关键函数的分析
以上的实例分析只是拿简单的 **jsb_set_xxtea_key** 函数入手,当然也可以拿其他的关键函数入手,依然拿游戏A举例。去其他相关函数看下,在 **xxtea_decrypt** 这个函数里看到有memcpy和memset操作,很像在开内存拷贝数据,

!(https://i.loli.net/2021/05/29/yYIoZQhw8GLgD5S.png)

并且 **do_xxtea_decrypt** 这个函数里大量的计算很像解密算法,

!(https://i.loli.net/2021/05/29/A98S5fYloy4hi3R.png)

再结合CocosCreator源代码(https://github.com/cocos-creator/engine-native/blob/f4a387d614691101c79ef75d1dbce705c834cad3/cocos/scripting/js-bindings/manual/jsb_global.cpp#L181),就不难知道传入 **xxtea_decrypt** 函数的参数中,第三个参数即为解密的Key值。

!(https://i.loli.net/2021/05/29/dM3pFUePcngjShl.png)

所以当下考虑直接在游戏运行时Hook这个函数打印出key值,由于是Native层,所以这里用简单的 **Frida** 脚本来Hook,关于Frida框架的使用这里就不说了,再说就多了emm······

adb连接测试机,终端输入 **frida-ps -U** 查看当前手机上的进程,以测试是否连通;

!(https://i.loli.net/2021/05/29/w1uSdPKiC2RFzMW.png)

接着编写一个简单的js脚本,当libcocos2djs.so文件加载时,直接hook xxtea_decrypt函数:

!(https://i.loli.net/2021/05/29/xXqkHYeGNDLroIE.png)

终端输入 **frida -U -f 包名 -l key.js --no-pause** ,拉起对应app进行hook,此时游戏会重新启动,重新加载运行游戏需要的环境,并保持运行。

!(https://i.loli.net/2021/05/29/Q1bNckv4rUfEpdx.png)

成功拿到了Key值,接下来就可以解密分析相关文件了。

## 关于解密工具
其实拿到Key值后,解密的逻辑直接参照CocosCreator源代码xxtea_decrypt部分,抄一份对应实现即可,自己也尝试写了一份,但操作较为繁琐,对不同的Cocos2dx版本有不同的处理。同时在不同的机子上测试也得到了不同的结果emm···还没有时间进行修复,当然后面有时间改完封装也会拿出来供大家测试的。

另外,也在一些论坛上也寻找了一些封装好的加解密程序,比如(https://beisheng.lanzoui.com/iSxKhplgnch),似乎能满足现在Cocos2dx版本的文件加解密,操作也较为简单,大家可以尝试食用。

![加解密工具](https://i.loli.net/2021/05/29/FuHqP9416a3e8Ez.png)

## 总结
1. 常规在libcocos2djs.so文件中搜索Ascil字符串“Cocos Game”、“main.js”、"jsb-adapter/jsb-builtin.js"等一些常规的普遍关键词来尝试定位Key。
2. 如果无法寻得,就上IDA看下so文件做没做过加密混淆,没有的话就结合applicationDidFinishLaunching函数等来寻找明文的Key值,或者hook关键函数来打印Key值。
3. 当然,游戏做了一些混淆或者其他安全手段时就需要先处理其他加密了emm···
4. 另外,Cocos2dx-js引擎做的游戏在运行时会先检测内存里面有没有js文件,有的话就直接运行js文件,没有的话就从jsc转换出js文件,所以解密后的js文件直接丢入原包就行。当然,除了一些做了文件验证形式的安全手段的游戏。

好了,到这里基本的教程也已经结束了,大家有什么好的方法和见解也欢迎交流,谢谢大家。

正己 发表于 2021-5-30 15:34

部分jsc解密后,还得在同目录下的index.json文件把encrypt改成flase,不然会打不开

北笙ぐ 发表于 2022-3-31 12:39

success666 发表于 2022-3-20 10:48
so里边找不到xxtea相关的函数可能是什么原因

如果搜索xxtea \ key 之类的关键词的相关函数,可以从入口函数哪里看下,或者作者对加解密函数进行了重写

lbue 发表于 2021-5-30 15:18

谢谢楼主

小猫猫 发表于 2021-5-30 17:02

学习了。

wujl82 发表于 2021-5-30 17:28

借一步学习知识:lol

dddl 发表于 2021-5-30 20:13

真是大佬啊,太厉害了。

hhthzd 发表于 2021-5-31 05:34


借一步学习知识

lyghost 发表于 2021-5-31 07:17

这是解密cocos create还是cocos-js?

北笙ぐ 发表于 2021-5-31 10:06

lyghost 发表于 2021-5-31 07:17
这是解密cocos create还是cocos-js?

cocos2d-js打包生成的jsc脚本文件

兴起 发表于 2021-5-31 10:21

学习一下下
页: [1] 2 3 4 5
查看完整版本: 关于Cocos2dx-js游戏的jsc文件解密(二)