首页
社区
课程
招聘
[原创]关于Cocos2dx-js游戏的jsc文件解密
发表于: 2021-6-1 21:42 29042

[原创]关于Cocos2dx-js游戏的jsc文件解密

2021-6-1 21:42
29042

上一期关于Cocos2dx-js游戏的jsc文件解密教程后,有一些同学似乎遇到了一些新的问题,下面列举一些:

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

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

密匙选项

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

样本APK的jsc文件结构

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

Coscos2dxActivity入口处

加载声明

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

xml文件中的定义

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

通过阅读Cocos2dx源码发现,其脚本加解密用的就是 xxtea 加密和解密(和Cocos2dx-lua加解密相似)。进而结合CocosCreator了解到其构建项目的过程为:

在程序运行时,正好做了相反操作:

通过以上初步分析和构建过程的了解,怎么去获得Key值似乎就有些思路了。这里用两个游戏案例做分析,某Tap平台可下载:

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

Cocos Game定位Key失效

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

游戏A的so层关键函数

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

jsb_set_xxtea_key函数

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

A-applicationDidFinishLaunching函数

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

游戏A解密成功

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

游戏B的so层关键函数

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

B-applicationDidFinishLaunching函数

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

B-附近字符串

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

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

A-附近字符串

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

applicationDidFinishLaunching函数

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

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

xxtea_decrypt函数

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

do_xxtea_decrypt函数

再结合CocosCreator源代码jsb_global.cpp,就不难知道传入 xxtea_decrypt 函数的参数中,第三个参数即为解密的Key值。

jsb_global.cpp源码确认

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

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

Frida连接测试

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

hook脚本

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

hook拿到Key值

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

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

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

加解密工具

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

 
 
 
 
 
 
 

[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 10
支持
分享
最新回复 (11)
雪    币: 116
活跃值: (1012)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
支持一下 文章很不错
2021-6-2 03:33
0
雪    币: 298
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
3
支持一下 文章很不错
2021-6-2 08:42
0
雪    币: 6573
活跃值: (3888)
能力值: (RANK:200 )
在线值:
发帖
回帖
粉丝
4
支持一下,文章很不错
2021-6-2 10:25
0
雪    币: 1743
活跃值: (1375)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
支持 之前接触过一些 很有收获
2021-6-2 10:55
0
雪    币: 3836
活跃值: (4142)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
支持一下,文章很不错
2021-6-2 14:55
0
雪    币: 8764
活跃值: (5718)
能力值: ( LV13,RANK:296 )
在线值:
发帖
回帖
粉丝
7
支持, 鄙人也略微探究过一二
https://blog.shi1011.cn/re/android/1422
2021-6-3 12:26
0
雪    币: 102
活跃值: (2050)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
mark
2021-6-11 22:51
0
雪    币: 4311
活跃值: (2662)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
9
好文
2021-8-3 09:38
0
雪    币: 394
活跃值: (617)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
有没有jsc 批量解密的 
2021-9-11 04:59
0
雪    币: 67
活跃值: (369)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
道理我都懂,你干嘛抄我写的附图
2021-11-7 12:13
0
雪    币: 116
活跃值: (1012)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
sunfishi 支持, 鄙人也略微探究过一二 https://blog.shi1011.cn/re/android/1422
大佬写得不错 只是我有个疑问 最后替换脚本的时候 为啥不能用Memory.alloc重新分配内存空间来突破原有的大小限制呢
2022-1-25 11:27
0
游客
登录 | 注册 方可回帖
返回
//