0x0 故事
那是2017年... 突然两张GIF刷爆了我加的多个群组。
大伙们都是LSP了,看到这哪还顶得住,纷纷开始寻找原游戏出处。然后发现是TapTap中还未上架的游戏《宝石研物语》,这还不得感觉关注一波?于是游戏关注度飞涨。然后...
不太妙的感觉...不过不碍事,游戏关注持续增加。一直到上线后一度挤爆服务器,后续多天也经常维护。
至于玩家们最关注的Live2D,则不出意外的惨遭和谐,掀裙子的动画直接消失了。
这哪能忍,那么就尝试看看资源文件,是否真的删掉了动画还是仅不播放此动画了。
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
,那么接下来的就是复制粘贴解密了。另外当时求助过浮冰大佬,他认识的大佬也有在研究这个解密,于是直接丢给了我一份成品。不用动手真的太爽了
。
解密程序大佬已开源:28598519a/bsydecrypt: a tool can decrypt the file from 寶石研物語 (github.com)
解密Live2D后发现没有删除动画,好耶,当时甚至拿Live2D官方模板搓了个APK丢群里玩。
11 条评论
大佬nb,想请教下那个apk是怎么做的,我倒是想可以用unity做,但现在貌似找不到2代的sdk了,都是4代和5代的,导入不了
https://imgse.com/i/pPn6S5F![](https://blog.hoshi.tech/usr/themes/handsome/assets/img/emotion/aru/crying.png)
大佬能试试宝石3吗
大概看了下,变化不大,而且已经有轮子了。
https://github.com/zths/gemtradeDecode/
选gemtrade2分支,测试伊恩之石资源能解密成功。
编译好的:https://blog.hoshi.tech/usr/uploads/2023/08/380048133.zip
好好好感谢大佬![](https://blog.hoshi.tech/usr/themes/handsome/assets/img/emotion/aru/thumb.png)
搞不懂![](https://blog.hoshi.tech/usr/themes/handsome/assets/img/emotion/aru/crying.png)
大佬我想问问宝石3文件加密开头跟这个一样还能接着用现成的的解密吗
不清楚哦,可以试一试,只接触过1.0版本![](https://blog.hoshi.tech/usr/themes/handsome/assets/img/emotion/aru/shy2.png)
发现是用不了了
![](https://blog.hoshi.tech/usr/themes/handsome/assets/img/emotion/aru/cryingface.png)