有什么方法能从cocos creator构建的游戏里还原出live2d或spine动画资源?

那个cocos creator构建的游戏是zgirls3,初步拆包出来有单纯的png及webp图片文件、ogg音频文件、以及将png转码成pkm纹理文件
内容不止zgirl3本体,还包括top war及页游vivid army(那个日文片假名不会写)
从data/data里找到了一堆json文件,没有见到skel二进制文件,以及发现有altlas/live2d有关的index.jsc文件
现在那个游戏运营两个月没活动,一帮玩家没地方消磨了,不绑定找不回自己的帐号 日常登录数明显少了
其live2d/spine动画视频有官方号宣传过,希望我这个话题讨论不是关于窃据他人知识产权(软件、视频、音频和图像)的任何简介、链接或方法 只是打开游戏后手机发烫… 用过搜索引擎才知道cocos creator会将live2d文件转成专属的动画…

1 个赞

多谢分享IDA分析屏幕截图
只不过zgirls3的pkm纹理文件基本没xxtea加密的,我己经转成了png图片文件
并看到相关cg,相关工具已经发过 关于苍雾残响和少女战争:幻想天下统一战解包求助 - #2,来自 diedye
比起查pkm文件的sign,我建议你顺便res目录下是不是还有个import文件夹(里头一堆json),参考 cocos creator APK解包 资源还原 - 哔哩哔哩 ,还有data.bin不知道会起什么作用
我自己用AstroGrep(只有32位应用,建议试试其他64位替代应用)搜索import文件夹下的json有明文出png图片素材,不知道如何还原文件名…
我自己只做起这一步,接下来我的32位系统机器不知道能做什么…

1 个赞

哈哈草,居然不是cocos加密嘛,长见识了,我拆过这种固定标头的cocos游戏一般都是xxtea加密(

好,我再看看这篇文章

1 个赞

看到了 Cocos Creator 3.8 手册 - 资源管理注意事项 - meta 文件 指raw-assets下的文件名就是游戏资源的uuid
是时候要更新一下方向
已知live2d十分不支持pkm纹理文件,基本上只支持webp及png文件作为纹理文件(那些png文件第一眼感觉不像是live2d或spine动画纹理)
打算先按那些webp文件名逆向从import文件夹里找到相关json文件 剩下的json文件再找到SkeletonData字串当spine动画相关,暂时想到这一步…

2 个赞

感谢楼主分享的思路 目前已经成功恢复了人物的spine动画部分 对于ogg语音和webp图片暂时还没有找到恢复的方法 希望可以提供点思路

1 个赞

恭喜你恢复到人物的spine动画部分
******而我还要请教从那些sp.SkeletonData开头的json文件还原成altas文件及json骨骼动画文件 spine动画版本也明码写出,顺便放个查看spine动画的网页应用 chibi-gif 0.1.32.2
那个uuid及FileID的值不是16进制的,让我对不上那些pkm纹理16进制的文件名,webp及ogg文件也因此我找不下去… 也证实了文件名跟base64转换无关,目前不知道如何转换…
对cocos creator导入了live2d,我用agent ransack代替AstroGrep来搜一下"cc.animation live2dcomponent" 除了依然不知道如何还原出live2d项目,而且还发现这游戏是可能不复用一套live2d
******暂时编辑回复到这[date=2023-11-04 time=20:59:00 timezone=“Asia/Shanghai”]:melting_face:

1 个赞

这个游戏lIve2d里面的文件是二进制的 不清楚怎么提取 文件为bin类型 文头标识是live2d webp文件是l2d的贴图 至于uuid以及FiledID不是十六进制的转换 也不是base64转换 base64文件结尾多为== uuid的是cocos2d作为文件唯一标识的一种方法 uuid的转换的算法我找了很多网站才找到 我分享下 python代码

def uuid2uuid(base64):
    BASE64_KEYS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
    BASE64_VALUES = [0 for i in range (123)]
    for i in range (123):
        BASE64_VALUES[i] = 64
    for i in range (64):
        BASE64_VALUES[ord(BASE64_KEYS[i])] = i
    BASE64Values = BASE64_VALUES
    HexChars = "0123456789abcdef"
    _t = ["","","",""]
    _tt = ["-"]
    UuidTemplate = _t +_t +_tt  +_t +_tt +_t +_tt +_t  +_tt +_t +_t +_t
    Indices = []
    _index = 0
    for v in UuidTemplate:
        if v == "":
            Indices.append(_index)
        _index += 1
    if len(base64) != 22:
        return base64
    UuidTemplate[0] = base64[0]
    UuidTemplate[1] = base64[1]
    i = 2
    j = 2
    while i < 22 :
        lhs = BASE64Values[ord(base64[i])]
        rhs = BASE64Values[ord(base64[i + 1])]
        UuidTemplate[Indices[j]] = HexChars[lhs >> 2]
        j += 1
        UuidTemplate[Indices[j]] = HexChars[((lhs & 3) << 2 )| rhs >> 4 ]
        j += 1
        UuidTemplate[Indices[j]] = HexChars[rhs & 0xF ]
        j += 1
        i += 2
    print("".join(UuidTemplate))
    return "".join(UuidTemplate)

if __name__ == '__main__':
    base64 = "a2dtc80E1EpJt286jHHckG"
    uuid2uuid(base64)


def compressUuid(fullUuid):
    BASE64_KEYS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="
    HexChars = "0123456789abcdef"

    if len(fullUuid) != 36:
        return fullUuid

    strs = fullUuid.split('@')
    uuid = strs[0]

    zipUuid = []
    zipUuid.append(uuid[0])
    zipUuid.append(uuid[1])
    cleanUuid = uuid.replace("-","")


    HexMap = {}
    for i in range(len(HexChars)):
        char = HexChars[i]
        HexMap[char] = i
    zip_uuid = []
    for i in range(2, 32, 3):
        left = HexMap[chr(ord(cleanUuid[i]))]
        mid = HexMap[chr(ord(cleanUuid[i + 1]))]
        right = HexMap[chr(ord(cleanUuid[i + 2]))]

        zipUuid.append(BASE64_KEYS[(left << 2) + (mid >> 2)])
        zipUuid.append(BASE64_KEYS[((mid & 3) << 4) + right])

    print("".join(zipUuid))
    return fullUuid.replace(uuid, ''.join(zip_uuid))

if __name__ == '__main__':
    fullUuid = "e0a3869f-1819-475a-b226-1a3286036488"
    compressUuid(fullUuid)

方法uuid2uuid是将22位不带-符号的uuid转换为36位带-符号的uuid
方法compressUuid则是进行相反操作 uuid名称转换可逆
通过这个转换按照json里面的uuid进行还原 不同版本coco2d的json配置不一定相同 这个游戏的spine文件的atlas以及骨骼都在json配置里面 关键字搜索"sp.SkeletonData" 需要按照uuid转换的uuid查找相应的贴图 不过文件很混乱有的是pkm格式的有的是png格式的还有的是压缩包 所以我写的脚本也有些问题就不分享了

1 个赞

live2d文件我找到解法了,将bin文件拖入十六进制查看器会发现有些bin文件的头部标识是live2d字样如图


认定这些就是l2d的模型文件和配置文件,因为找不到moc3之类的l2d的特征信息,认为文件被处理过了,一开始认为是用xxtea加密的,用了楼上的密钥尝试解密没成功就放弃了,后来在这篇文章中找到了点思路https://www.52pojie.cn/thread-1746028-1-1.html,发现live2d后的字节为1f 8b 08 符合文章后面讲的gzip压缩特征,就使用python将文件尝试解压一下 代码如下 记得换下路径

import os
import gzip

path = r"C:\Users\zjbook\Desktop\新建文件夹 (4)"
for root, dirs, files in os.walk(path):
    for file in files:
        if file.endswith(".bin") :
            file_path = os.path.join(root, file)
            print(file_path)
            with open(file_path, 'rb') as f:
                compressed_content = f.read()
                f.close()
            decompressed_content = gzip.decompress(compressed_content[6:])
            with open(file_path, 'wb') as f:
                 f.write(decompressed_content)

结果如下图,出现了moc3这个特征 说明解压成功 是采用的标准解压库的解压方法


根据json文件搜索texture_ 可以搜索到l2d的贴图对应信息 moc3可以搜到moc3模型文件对应 model3可以搜索到动作对应信息 这两个json名称前面半部分加上.bin就是对应的配置信息的名称 然后将webp转为png图片 将model3里面的动作和物理信息提出来 就可以使用live2dexviewer打开了 如图

不过通过json配置文件只还原了几个l2d模型 有很多好像不在配置文件中 暂不清楚怎么还原名称 实在不行就像解神者那样一个一个试吧 暂时就想到这么多 有空再研究研究

1 个赞
  • 是不是可以直接用windows平台下的7zip来解压gzip特征的data.bin文件来获得moc3模型文件,python脚本一时之间不知道拿什么来运行…是windows power shell还是cmd命令行…(看来我自已没懂如何配置python环境)

  • 如果要一个个试l2d模型,我建议先用一张1024*1024的黑色图片当纹理(因为见到你的EX Studio用白色背景,如果用黑色背景则不用纹理来它会显示轮廓
    这是我拆少女前线-汉阳某个皮肤得来的经验).
    注意一下这时候l2d模型角色头部有正方型的样子…

  1. 这个游戏可能只有8~9个l2d模型可能只是单纯换纹理/皮来实现换装效果

  2. 在我没打算还原live2d或spine动画资源,我直接用pkm文件转png图片,当中有几张是这些l2d模型的预览图打包(包括了旧版本,甚至混入了其他), 是否需要发上来方便参考?

刚刚试了 可以使用zip解压软件对bin进行解压 解压之前先用16进制编辑器把live2d这个标识头部分删掉 改成zip这样的后缀 方便软件识别 就可以解压出来了 这个游戏的文件混乱的不行 贴图很多相同的 只是尺寸不同 估计很多老更新又叠加着新更新的 还不把没有用的删掉 都下到文件夹里面了 可能我之前把同名的配置文件覆盖了 所以少了 下次有空 我去抓个包看看

还是发张预览图,方便有心人一个一个试吧 (注意除了混入背景图,左下角第二张不是l2d的)


讲起老更新又叠加着新更新的事, :lying_face: 深挖下去的意外估计是惊吓…

1 个赞

更新一下,

还原live2d名称的思路是从import文件夹里的json文件里搜索prefabs或者AnimationClips来找那些UuID或FileID之类的…

(只不过这游戏不弄加密,光这些UuID或FileID对应关系够加密 :smiling_face_with_tear:)

xxxxxxxxxxxxxx

只不过从sp.SkeletonData里分离出altas+json文件希望不大,其spine动画很大可能只有待机+活动两种,还有可能zgirls3广告宣传已经播放过了,剩下的…

只是今天无聊手动hex编辑器去掉那些bin文件的live2d头部标识,然后7zip解压后,想找个EX studio以外的live2d播放器就顺便找到个官方说明文档…

#########
2023-11-21T16:00:00Z
如果有办法将sp.SkeletonData里分离出altas+json文件,会方便恢复的spine动画部分,至少可以一张张去试spine动画贴图/纹理,我就是不知道如何将这个sp.SkeletonData的json裁剪出altas及json动画部份

现在我拆了zgirls3上一个版本的应用安装包,按上面的方法解bin文件,得到moc3文件与json格式文件各36个…统计出72个webp图像文件 个人猜测有36个live2d模型,各个live2d模型准备了一个高清的webp纹理及一个低分辨率的webp纹理… 希望有机会还原最新版本的资源 :innocent:

  • SpecialSpine_Yumi_Cake.zip (720.9 KB)
    那我发个样本,问一下sp.SkeletonData的json文件是怎么还原成altas及json动画文件?

  • live2d动画找到38套(4套卡面立绘…)

    • 值不值得进行逆向工程彻底查找Uuid跟原文件名的关系?
1 个赞

正在上传:SpecialSpine_Yumi_Cake.rar…
spine of the chibi version, which you sent, everything is ok

open live2dEx

我在群里找了个cocos2d还原教程 里面的代码需要Java环境才能运行 虽然和这个游戏的配置有些区别 但都差不多 可以参考下 [cocos2d还原教程](链接:https://pan.baidu.com/s/1YCegbXb3dBGWGI5eZuqJsA?pwd=1234 提取码:1234) 我把还原的spine也分享了 不过我只还原了大立绘部分 因为对小人立绘不感兴趣

:slightly_smiling_face: 看来这个话题对我来说已经可以写个半个总结对cocos creator的印象…自带疼痛的压缩加密
其实对还原出来的live2d或spine资源,我现在不知道当个伸手党自己的心会怎样痛. (对的,我放弃了百度帐号是没法从百度网盘下载任何资料,以及IDM之类的很难装上…)
感谢看帖的各位在这个讨论踩过的坑坑洼洼到最后能还原资源过程中各种经验,失落与欢喜

接下来 我不知道要可以对此做什么,live2d部分我居然分类了2048*2048的webp贴图及38个moc3文件,json文件model3里面的动作和物理信息目前不知道怎么提出来…也没steam帐号买live2dexviewer…甚至我电脑cpu不支持live2d cubism… :upside_down_face:
有需要的我再列个大概的webp及moc3文件名单…

在那大立绘中,我想起还在玩zgirl3时,聊天频道有人喜欢更新时一个短发(有点圆头)、脚穿单滑轮,手貌似拉弦的角色立绘
而我对小人立绘感点兴趣是因为想看看现在的AI将平面图型转成三维模型有多大效果…现在只能说还不能进入工作流程,就不要为难AI对spine动画进行三维建模…

先这样吧

1 个赞

那怎样拆分那个从bin文件解压出的json格式来还原 模型名.model3.json、motions/act_xxx.motion3.json等等文件呢?
我已经将moc3模型及webp贴图分好类,就差json来配置给 Live2D Viewer Online 查看动作及物理效果…

1 个赞

用notepad++打开文件显示内容为Version的文件 使用json格式查看 可以得到里面是moc3相关的配置 包含对应moc3的名称 贴图名称 物理 以及动作 共有33个动作 第一个对应动作名称 第二是动作的数据 将其截取后就可以正常播放了 记得将斜杠替换掉 如果手动的话 估测所有模型总共大约1000个动作

看来我要分享如何分类从那些bin文件解压出来的json文件

原moc3文件名 _1(初始服装) _2(外出服装) _3(沙滩泳装) _4(学园制服) _5(婚纱) _6(睡衣/家居服) 非moc3相关的配置json文件搜索关键词
G1_(戴假猫耳)
G4_(金色卷短发)
G5_(短发,一圈光环绕头不是头顶光环) avrem
G9_(是黑发单马尾)
G15_(樱花发色)
G22_(已有示例) salia
G23_(水蓝色长发) belami
G24_(金长发) portia
G25_(短发半遮面) elma

hero_tachie118 hero_tachie129 hero_tachie135 hero_tachie307 这四个live2d卡面慢慢试吧…

看来感觉我自己已经能讨论的讨论完了,剩下完整的逆向工程找其他资源、制作live2d,甚至是脚本自动化处理已经不是我能做到的事
自己连做个伸手党都用不了百度网盘 :expressionless:
*
如果这个话题对你还原live2d资源有帮助,可以的话来个创意工坊lpk或wpk文件,怕了百度网盘之类的 (幻想发白日梦中…)
xxxxxxxxxxx
*表格内容已修正 ,如果制作创意工坊lpk或wpk文件不妨考虑减少l2d动作及添加拖拽区域。2023-12-01T16:00:00Z