此文为补写,意为记录,已不适用于目前版本游戏

0x0 故事

那是2017年... 突然两张GIF刷爆了我加的多个群组。

magelite.gif lili.gif

大伙们都是LSP了,看到这哪还顶得住,纷纷开始寻找原游戏出处。然后发现是TapTap中还未上架的游戏《宝石研物语》,这还不得感觉关注一波?于是游戏关注度飞涨。然后...

gemtrades_clarification.png

不太妙的感觉...不过不碍事,游戏关注持续增加。一直到上线后一度挤爆服务器,后续多天也经常维护。

gemtrade_comment.jpg

至于玩家们最关注的Live2D,则不出意外的惨遭和谐,掀裙子的动画直接消失了。magelite_censor.gif

这哪能忍,那么就尝试看看资源文件,是否真的删掉了动画还是仅不播放此动画了。

0x1 资源解密

解压安装包,assets\res\下有live2d文件夹。

好耶,点开模型配置文件model.json

...

坏耶,被加密了,再看看动作文件,贴图文件等,发现全部被加密,且文件头为都为gemtrade。结合这游戏是Cocos2d-Lua开发的,盲猜一波是xxtea加密(?)。

掏出IDA,加载libcocos2dlua.so,定位到cocos2d::FileUtils::getDataFromFile(),伪代码:

cocos2d::Data *__fastcall cocos2d::FileUtils::getDataFromFile(cocos2d::Data *a1, cocos2d::FileUtils *a2, int a3, _BYTE *a4)
{
  int v8; // r2
  int v10[8]; // [sp+0h] [bp-20h] BYREF

  cocos2d::Data::Data(a1);
  v8 = *(_DWORD *)a2;
  v10[1] = (int)a1;
  v10[0] = (int)off_CD734C60;
  (*(void (__fastcall **)(cocos2d::FileUtils *, int, int *))(v8 + 28))(a2, a3, v10);
  if ( !cocos2d::Data::isNull(a1) )
    *a4 = cocos2d::FileUtils::decodeData(a2, a1);
  return a1;
}

发现多了一个FileUtils::decodeData()方法,那么它应该就是目标了,此方法中调用FileUtils::decodeBuffer()紧接着FileUtils::decodeXOR(),伪代码:

char *__fastcall cocos2d::FileUtils::decodeXOR(cocos2d::FileUtils *this, unsigned __int8 *a2, int a3, int *a4)
{
  unsigned int v8; // r4
  int v9; // r5
  int v10; // r8
  int v11; // r0
  unsigned int v12; // r6
  unsigned int v13; // r8
  unsigned int v14; // r10
  unsigned int v15; // r5
  char *v16; // r11
  int v17; // r0
  __int16 v18; // r12^2
  char *v19; // r3
  unsigned int v20; // r0
  unsigned int v21; // r2

  if ( a3 <= 19 )
    return 0;
  v8 = memcmp(&unk_CD6C15E8, a2, 8u);
  if ( v8 )
    return 0;
  v9 = cocos2d::FileUtils::char2uint(this, a2, 8);
  v10 = cocos2d::FileUtils::char2uint(this, a2, 12);
  v11 = cocos2d::FileUtils::char2uint(this, a2, 16);
  v12 = (unsigned int)(v11 + v10) >> 1;
  v13 = (unsigned int)(v10 - v11) >> 1;
  v14 = a3 - 20;
  *a4 = v14;
  v15 = v9 - v12 * v13;
  v16 = (char *)malloc(v14);
  memcpy(v16, a2 + 20, v14);
  while ( 1 )
  {
    v17 = cocos2d::FileUtils::char2uint(this, (unsigned __int8 *)v16, v8);
    v18 = HIWORD(v17) ^ HIWORD(v15);
    v16[v8] = v17 ^ v15;
    v19 = &v16[v8];
    v8 += 4;
    v20 = (v17 ^ v15) >> 8;
    v21 = v14 - v8;
    --v15;
    v19[1] = v20;
    *((_WORD *)v19 + 1) = v18;
    if ( v14 <= v8 || v21 <= 3 )
      break;
    if ( v12 <= v8 && v12 < v21 )
    {
      v8 += v13;
      if ( v14 < v8 || v12 > v14 - v8 )
        v8 = v14 - v12;
    }
  }
  return v16;
}

其中unk_CD6C15E8查看为gemtrade 竟然不是xxtea,那么接下来的就是复制粘贴解密了。另外当时求助过浮冰大佬,他认识的大佬也有在研究这个解密,于是直接丢给了我一份成品。image.png不用动手真的太爽了

解密程序大佬已开源:28598519a/bsydecrypt: a tool can decrypt the file from 寶石研物語 (github.com)

解密Live2D后发现没有删除动画,好耶,当时甚至拿Live2D官方模板搓了个APK丢群里玩

image.png

最后修改:2023 年 08 月 11 日
如果觉得我的文章对你有用,请随意赞赏