ai474427793 发表于 2025-2-17 18:27

某手游cocos2djs逆向分享之分析思路及切入方法

# 某手游cocos2djs逆向分享之分析思路及切入方法

## 一,初探

###### 目标APP :        0bC1wLTzx6c=

拿到APP,先解压查看下加固情况,因为游戏类app一般都是使用cocos2d或者unity框架开发,先初步确定app开发框架,方便后续寻找大佬的成功经验,可以使用关键词做相关搜索.



可以在**./lib/arm64-v8a/**路径下,看到最大的so文件为**libcocos2djs.so**,可以初步确定本样本为cocos2djs开发.

## 二,需求

某个接口有个sign算法需要确定其计算的方式,先抓包看看

## 三,抓包

直接使用root真机,安装样本app,尝试使用postern全局代理,发现app会出现断网的情况.改用proxydroid,还是断网.最后使用WIFI代理,成功抓取到对应的数据包.



可以看到sign的位置,以及其他一些线索关键词:**create_order_v2**,**apipayh5**

## 四,分析

解压app到文件夹,直接cmd命令通过grep工具搜索关键词



可以看到在classes.dex里面有线索,jadx-gui直接拖入dex文件进行搜索



通过交叉引用一直往上找,最终定位到



尝试hook,查看一下调用堆栈.

```javascript
let YqSdkMgr = Java.use("org.cocos2dx.javascript.plugin.YqSdkMgr");
YqSdkMgr["sdkVip"].implementation = function (str) {
    console.log(`YqSdkMgr.sdkVip is called: str=${str}`);
    this["sdkVip"](str);
};
```



可以看到sign是作为参数传入的,咨询AI可知在cocos2djs框架开发的app中jsc文件里面才有对应的线索.在/assets里面随便找一个后缀jsc的文件打开看看先



不出意外,核心代码做了加密,那么接下来就是寻找jsc的解密方法.

## 五,尝试

1,根据经验,先将libcocos2djs.so拖入到winhex中搜索main.js,结果如下



附近找到一个目测有点奇怪的字符串:c03ef3b<$21a4)11,长度也和之前研究过的jsc的key长度一样,填入解密工具,并拖入jsc文件尝试解密.



解密失败.看来得上强度了.

## 六,动手

根据大佬的分享可知jsc文件一般是使用xxtea算法进行加解密.以下是frida脚本

```js
var so_name = "libcocos2djs.so";
var fun_name = "xxtea_decrypt";
function do_hook() {
var addr = Module.findExportByName(so_name, fun_name);
console.log(addr);
Interceptor.attach(addr, {
      onEnter: function (args) {
                console.log('key: ' + Memory.readCString (args));
      },
      onLeave: function (retval) {
      }
})
}
function load_so_and_hook() {
var dlopen = Module.findExportByName(null, "dlopen");
var android_dlopen_ext = Module.findExportByName(null, "android_dlopen_ext");
Interceptor.attach(dlopen, {
      onEnter: function (args) {
          var path_ptr = args;
          var path = ptr(path_ptr).readCString();
          console.log("", path);
          this.path = path;
      }, onLeave: function (retval) {
          if (this.path.indexOf(so_name) !== -1) { // 如果包含我想要的so文件
            console.log("", this.path);
            do_hook();
          }
      }
});
Interceptor.attach(android_dlopen_ext, {
      onEnter: function (args) {
          var path_ptr = args;
          var path = ptr(path_ptr).readCString();
          this.path = path;
      }, onLeave: function (retval) {
          if (this.path.indexOf(so_name) !== -1) {
            console.log("\nandroid_dlopen_ext加载:", this.path);
            do_hook();
          }
      }
});
}
load_so_and_hook();
```

通过spwan方式启动app,并且在加载对应的so后执行xxtea_decrypt的解密,可以hook到对应的秘钥



可以看到已经hook到对应的秘钥,再次尝试拖入JscDecodeCsharp进行解密:



可以看到,已经解密得到核心js代码.但是还有一个问题,assets里面的jsc文件很多,一个一个解密定位很浪费时间.尝试寻找有没有批量解密的工具或者代码

最终在万能的github找到

```js
https://github.com/MikaCybertron/Tool-Encryption-Decryption-JSC-Files-for-Cocos2djs-Games
```

里面有两份工具,一份是exe格式的,经测试,无法解密.还有一份是python代码,尝试在window10上面根据流程安装依赖库并执行,提示缺少C++14,无法运行.

于是更换使用ubuntu系统,成功批量解密所有jsc文件.

然后使用grep最终定位到核心代码位置如下



可以看到sign是通过protobuf,服务器下发的,signParam应该就是用来签名的原始文本,但是具体算法在服务器执行,无法本地还原.

至于分析protobuf协议,看着头大,直接拖回收站去吧 -_-

## 七,后记

分析到此结束,侵权请联系我删贴.

记得之前分析过一个LuaJIT的样本,所有核心代码,都是字节码的形式,感觉安全系数要高得多.

最后,如果你看到了这里,麻烦伸出你发财的右手,帮我转评赞来一套,也欢迎小伙伴一起学习交流,完结,撒花!

ps:不接单,谢谢.

chenquanjun 发表于 2025-2-18 16:26

已经上了frida的话,也可以直接hook加载文件解密的接口,这样可以直接转存解密完的文件

tyrell 发表于 2025-3-14 12:03

太强了吧,谢谢分享

yhys 发表于 2025-3-22 12:04

谢谢大佬分享
页: [1]
查看完整版本: 某手游cocos2djs逆向分享之分析思路及切入方法