前阵子接手了一个老项目维护,碰到个挺有意思的需求:客户手里只有一个 CPlus 时代遗留下来的 Cocos Creator 2.4 打包 APK,源工程早就不知道丢哪儿去了。要在这个 APK 上做功能迭代,第一关就是能不能把游戏资源完整捞出来,甚至反推出一个能继续开发的工程。
这件事对常年做 Cocos 的人来说其实不算陌生,但真正上手会发现坑比想象中多。网上聊逆向大多是针对 Cocos 2d-x-Lua 的老路子,到了 Creator 2.4 这套资源和脚本处理机制上,不少经验要推倒重来。我这次完整走了一遍从 APK 解包、资源提取、再到还原工程的流程,把踩过的坑和能直接落地的工具方法整理成文,给后面接这种活儿的兄弟做个参考。
1. 逆向前的全局认识
1.1 Cocos Creator 2.4 打包产物规律
想要顺利逆向,先得搞清楚 Cocos Creator 2.4 打出来的 APK 内部到底是什么结构。Creator 2.4 的构建产物和 3.x 完全不同,它的核心资源目录是assets,里面塞的基本是纹理、图集、音频、字体、预制体和场景文件。真机上这些资源大部分被打进了assets目录对应的子文件夹,不加密的情况下是直接可见的。脚本方面,Creator 2.4 的 JS 代码会被打包进src目录下的project.js或settings.js,如果开启了脚本加密,则可能是project.js的混淆或二进制变体。
有一种容易被忽略的情况是老项目从 2.0 升级到 2.4,或者用了旧版插件,资源命名和 UUID 映射会有历史遗留痕迹。比如assets下每级目录会带一个meta文件,记录 UUID 映射关系。这些文件在逆向时非常关键,直接决定你还原工程后资源能不能被正常引用。
1.2 一句话明确逆向边界
很多新手一上来就想把 APK 里的所有东西“完美还原”成一个能直接打开、F5 运行的 Creator 工程。说实话,这不现实。Cocos Creator 的资源依赖关系、场景节点树、组件绑定信息、JS 逻辑,还原的越完整,工程量越大。我这次的目标很明确:提取全部可读资源,把资源结构还原到可以新建工程并手动重建场景的程度。如果有原版settings.js和project.js可读,脚本逻辑也能基本还原。
这一点想明白,后续所有步骤就都有取舍依据了。别一上来就追求 100% 还原,做出了 80% 可用的工程已经很值钱。
1.3 需要提前准备的工具体系
标题里写了“附工具包”,这里把我在实操中确认有效的工具整理一遍。它们各有分工,缺一不可:
| 工具 | 用途 | 版本建议 |
|---|---|---|
| apktool | APK 解包、反编译资源 | 2.7.0 及以上 |
| jadx | 查看 Java/Kotlin 层逻辑 | 1.4.4 及以上 |
| 7-Zip | 快速查看 APK 压缩包内结构 | 无特别要求 |
| AssetStudio | 看 Cocos 序列化资源 | 使用 Cocos 分支版本 |
| Cocos Creator 2.4.x | 用于还原工程、重建场景 | 2.4.3 ~ 2.4.13 均可 |
| Node.js | 跑自定义脚本批量处理资源 | 14.0 以上 |
| VSCode | 阅读 JS 代码,批量正则替换 | 无特别要求 |
工具包这东西,重要的是能形成闭环。apktool 负责拆壳,AssetStudio 负责读取 Creator 的序列化格式,最后落地用 Creator 本身。全部装齐不会超过半小时。
2. 完整提取游戏资源的五个阶段
2.1 阶段一:拆包拿到原始资源
第一步,用 apktool 把 APK 拆开。命令很简单:
apktool d game.apk -o game_src也可以先用 7-Zip 直接把 APK 当压缩包打开,拷贝出assets目录,速度快很多。区别在于 apktool 会把 AndroidManifest.xml 变成可读格式,同时把res目录里的二进制 XML 转成明文。如果不关心 Androi 层代码,只是提取 Cocos 资源,7-Zip 就够了。
这里有个细节:Cocos Creator 2.4 打包后,资源可能在assets目录下按类型拆得很碎,也可能直接以 bundle 形式打包成一个大文件。正常的非分包模式,assets下会有main目录(对应构建时填的主包名),里面才是真正的游戏资源和src目录。如果开启了按需加载或远程资源,部分 bundle 会在运行时从服务器下载,APK 本地只会有一小部分。遇到这种情况,逆向能拿到的是基础包资源,动态下载的别指望从 APK 里复原。
2.2 阶段二:识别资源加密与编码方式
Cocos Creator 2.4 本身提供“加密脚本”和“加密资源”选项。资源加密常见的方式是 AES 加密,密钥写在原生层代码里。如果客户当初没加密,assets下的文件基本都是明文或只有简单头部标记。如果加密了,处理方式会麻烦很多,得去 Java/Kotlin 层或者 libcocos.so 里找密钥和算法逻辑。
实操里最省事的办法是先用 7-Zip 打开 APK,直接看assets下的文件头。一个正常的 PNG 文件,开头应该是89 50 4E 47,一个正常的 json 文件开头是7B。如果看到的是完全不可读的二进制,或者开头几个字节被替换成固定魔数,说明资源做了加密处理。
如果只是简单魔数混淆,比如在文件头加了 4 个字节的固定前缀,写一个 Node.js 脚本批量去掉前缀就行。如果整体加密,就要去 jadx 里搜 AES 相关的工具类,典型的特征代码是Cipher.getInstance("AES")配合SecretKeySpec。这一步没有捷径,需要一定的原生逆向功底。
2.3 阶段三:分类提取可读资源
拿到明文资源后,我习惯按类型分目录整理,方便后续还原工程。一般会分成这几个目录:
| 资源类型 | 文件特征 | 提取方式 |
|---|---|---|
| 纹理 | .png, .jpg, .webp | 直接拷贝 |
| 图集 | .plist + 同名.png | plist 保留,图片保留 |
| 音频 | .mp3, .ogg, .wav | 直接拷贝 |
| 字体 | .fnt + .png, .ttf | 拷贝 fnt 和对应纹理 |
| 配置文件 | .json, .xml, .plist | 直接拷贝,注意编码 |
| 预制体/场景 | .fire, .prefab | 拷贝后用 AssetStudio 读取 |
这一步有个容易踩的坑:Cocos Creator 2.4 的图集在构建后,往往不会保留xxx.plist这种 Atlas 文件,而是直接生成一张大图和一份对应的序列化信息,存在.json或二进制.bin里。发现图集没法直接用,别急着骂资源缺失,先去assets/main下找带.bin后缀或者*.json的图集元数据。
2.4 阶段四:处理图集与纹理的特殊问题
Creator 2.4 构建出来的纹理,绝大多数是 PNG,也有部分被压缩成 WebP。WebP 文件在 Windows 上预览不方便,建议批量转成 PNG。用 Python 的 Pillow 库或者直接用在线工具都行,但资源多的时候必须写脚本。
这里分享一个检测纹理是否完好的小技巧:用 Python 读 PNG 头,检验宽高和通道数,再看文件尾部IEND块是否存在。如果 APK 解包时遇到过文件损坏,这个方法能快速定位无效资源,避免后续工程导入时一堆报错。
2.5 阶段五:提取脚本与配置信息
Creator 2.4 的 JS 脚本一般集中在assets/main/src目录下的project.js,也可能拆成main.js、settings.js等。如果未开启加密,直接打开就能读,代码可读性取决于开发者当初有没有混淆。多数老项目不会主动混淆,所以代码还原度很高。
配置方面,settings.js里记录了启动场景、资源版本、模块设置等关键信息,对整个工程还原非常重要。拿到settings.js后,建议第一时间解析其中的moduleId映射和rawAssets列表,这能帮你还原出 Creator 工程里的资源挂载关系。
另外说一下常见情况:项目如果用了第三方 SDK 或者热更新框架,比如自己封装的下载模块,src下可能还有其他 JS 文件,注意一并提取。
3. Cocos Creator 2.4 工程还原的核心实操
3.1 选择还原工程的基础版本
还原工程不等于把资源拖进新建工程就完事,第一步要选对 Creator 版本。2.4 系列内部差异主要体现在构建插件和部分引擎 API 上,建议优先使用原项目一样的版本。怎么判断原项目用的 2.4 的哪个小版本?看settings.js里的引擎版本字段,或者看project.js头部注释里的构建记录。
如果客户不清楚,稳妥的做法是用 2.4.13 新建一个空工程作为还原容器。2.4.13 是 2.4 系列的最终版,对旧版本构建出的资源整体兼容性最好,特别是资源和脚本导入时的兼容处理更完善。
3.2 还原资源目录结构
用 2.4.13 新建工程后,把提取出来的assets目录内容按原结构拷进工程assets目录。这里最花时间的不是拷贝,而是让资源依赖关系恢复正确:
先还原所有meta 文件。如果 APK 的
assets下每个文件旁边有同名.meta,直接一并拷贝。它记录了资源的 UUID,是资源之间互相引用的关键。但注意,Creator 2.4 打包后的 APK 里不一定会带 meta 文件。如果没有 meta,只能让 Cocos 重新生成,然后所有引用该资源的旧 UUID 全部失效,这就是“资源导入成功,但场景里全丢引用”的根源。其次处理场景和预制体。如果提取到
.fire或.prefab文件,可以直接放入assets对应路径。Creator 打开时会重新序列化,一般可以恢复大部分节点结构。如果原文件是二进制.bin,需要先用 AssetStudio 看一下能否导出为可读格式。最后处理脚本文件。把从
project.js中拆解出的原 JS 文件按原路径还原。还原脚本时建议一个文件一个文件地手动建,而不是直接丢一个合并的大 JS。因为 Creator 对组件脚本的文件名和类名有强关联,直接丢合并文件进去无法创建组件。
这个阶段最需要的是耐心。我一般会按“先从 UI 资源目录开始,再场景,再代码”的顺序,每还原一批就打开编辑器看一次资源是否正常显示。
3.3 还原场景与预制体
场景还原是整个流程里最依赖人工的地方。即使.fire文件是完好的,Creator 内部序列化格式在 2.4.x 各个小版本之间也可能有细微差异。如果直接用 2.4.13 打开低版本 2.4.x 的场景文件,通常能正常导入,但偶尔会出现节点丢失或组件报错。
如果场景文件是二进制.bin,最实用的方式是写脚本解析。Cocos Creator 2.4 的.fire和.prefab在构建后会变成序列化后的二进制数据,文件头一般是03000000结尾的数组。这种格式可以用 AssetStudio 打开,尝试导出为 JSON 或反序列化为文本,但导出的质量受资源原始状态影响很大。
我的经验是:场景和预制体的还原不需要追求一步到位,先保证纹理、图集、字体、音频能够被正确引用,然后在新工程里手动重建场景关键层级和 UI,也能达到可用状态。特别是 2D 游戏,UI 节点布局信息丢失后,手动重建有时比折腾二进制反序列化更快。
3.4 还原脚本逻辑与组件绑定
脚本还原和场景还原是相辅相成的。如果.fire里引用了某个自定义脚本组件,但工程里没有这个脚本,导入时组件会变成红色报错。这个现象的底层逻辑是 UUID 失效。
实操方法:
- 提取到
project.js后,先全文搜索cc.Class或者 ES6 的class定义,列出所有组件类名。 - 新建对应脚本文件,脚本类名和文件名保持严格一致。
- 打开场景或预制体,把之前的红色丢组件重新绑上对应脚本,手动补引用。
这里有个心得:如果原项目代码有混淆,比如变量名变成a、b、c,组件绑定关系很难自动恢复。但 Cocos 2.4 的自定义组件类名通常保留在project.js的属性名描述里,即使逻辑代码被压缩混淆,文件路径和类名依然可读,所以工程还原基本可行。
3.5 构建测试与迭代
还原工程最终以“能打开编辑器不出错”和“能成功构建出可运行 APK”为准。构建前需要检查:
| 检查项 | 具体验证方式 |
|---|---|
| 资源无红叉报错 | 打开编辑器资源管理器全选查看 |
| 场景无缺失组件 | 逐个打开场景看 console 面板报错 |
| 构建输出无报错 | 构建面板预构建一次 |
| 运行无致命 JS 异常 | 浏览器预览模式先跑一遍 |
构建到 Android 的流程和普通项目一样,但要注意包名若沿用原包名,签名证书需要从原 APK 里反编译提取或者让客户提供。签名证书缺失的话,只能重新生成,升级安装会被系统拒绝,只能卸了重装,这也是需要提前告知客户的点。
4. 常见问题与排查技巧实录
4.1 常见报错速查表
逆向过程中遇到的各种报错,我整理成一个速查表,基本覆盖了大部分常见情况:
| 现象 | 原因 | 解决方案 |
|---|---|---|
| 资源导入后全部红叉 | 缺少 meta 文件,UUID 丢失 | 检查脚本引用路径,逐个恢复 |
| 场景打开后节点全空 | 场景文件加密或构建处理过 | 用 AssetStudio 找序列化资源 |
| 图集碎片显示不全 | 图集源文件被裁剪或拼接处理 | 检查对应的 plist 或二进制信息 |
| 音频无法播放 | 加密或格式被改 | 查看头文件,确认格式,去掉自定义前缀 |
JS 报module is not defined | 从 project.js 分离脚本时模块名没对上 | 根据 settings.js 的 moduleId 重建模块映射 |
| 构建时提示资源 GUID 冲突 | 新旧工程 meta 文件混用 | 删除冲突资源的 meta 让 Creator 重新生成 |
有一个容易被忽略的坑出现在资源路径大小写上。APK 里资源路径有些是全小写,有些保留了原始大小写。Windows 开发机上文件系统不区分大小写,但 Android 系统区分。如果还原工程时把目录名改了大小写,构建出的 APK 很可能在读取远程资源或动态加载时找不到文件。
4.2 动态加载资源引发的“缺失”
Cocos Creator 2.4 项目经常会用resources.load动态加载assets/resources目录下的资源。构建时,这些资源会被放在 Assets 包的 resources 子目录中,加载时路径是相对resources的。
但如果原项目用cc.assetManager.loadBundle下载远程 bundle,本地 APK 里根本不会存在这些资源,来源是 CDN 或服务器。逆向工程能不能完整还原,很大程度取决于远程资源有没有同步导出。如果客户手里有完整的远程资源包,把 bundle 直接放进还原工程的assets下即可。
实测中我发现,很多刚上手的朋友把“本地 APK 里找不到资源”当成“资源丢失”,其实只是没有从服务器拉取动态资源。这件事在项目立项和需求阶段就要跟客户沟通清楚,省得到后面白忙活。
4.3 从原生层拿到资源解密密钥
如果碰上资源加密,常用的排查路径是这样:
- 用 jadx 打开 APK,在 Java 层搜索
AES、decrypt、Cipher等关键词。 - 如果 Java 层没有,去
lib/arm64-v8a下找libcocos.so,用 IDA 或 Ghidra 打开字符串搜索加密相关方法名。 - 找到密钥后,在本地写个脚本批量解密。
Cocos Creator 2.4 的官方文档里提到过一种简单的 XXTEA 加密,用于脚本保护。但真正用到的项目不多。更多是开发者自己集成第三方加固或自研加密模块。如果遇到整个 APK 都加了壳,那就得先脱壳,再走上面的流程,工作量会明显变大。
4.4 写脚本一键批量重命名与去头
资源多了以后,手动处理不现实。我写了一个简单的 Node.js 脚本,去掉自定义前缀并重命名,效果稳定:
const fs = require('fs'); const path = require('path'); function processDir(dir) { fs.readdirSync(dir).forEach(file => { const fullPath = path.join(dir, file); const stat = fs.statSync(fullPath); if (stat.isDirectory()) { processDir(fullPath); } else { const buf = fs.readFileSync(fullPath); // 检查文件头是否为自定义魔数,假定前4字节为 0x41 0x42 0x43 0x44 if (buf.length > 4 && buf[0] === 0x41 && buf[1] === 0x42 && buf[2] === 0x43 && buf[3] === 0x44) { fs.writeFileSync(fullPath, buf.subarray(4)); console.log('Fixed:', fullPath); } } }); } processDir('./extracted');这种脚本的核心价值在于批量、快速、可重复执行。逆向过程中资源文件数量动辄上千,手动去头只会让人崩溃。
5. 工具链选型与高级技巧
5.1 不同工具的适用场景对比
工欲善其事,必先利其器。整理一份工具适用场景对比:
| 工作内容 | 首选工具 | 备选方案 | 注意事项 |
|---|---|---|---|
| APK 拆包 | apktool | 7-Zip | apktool 解包更完整 |
| 查看 Java 层 | jadx-gui | jadx 命令行 | 搜索字符串时用 GUI 更方便 |
| 查看 .so 层 | Ghidra | IDA | 免费工具足够用 |
| Cocos 资源查看 | AssetStudio | CocosStudio 旧版 | 注意下载 Cocos 分支版 |
| JS 代码分析 | VSCode + Prettier | Sublime Text | 格式化后再读 |
| 批量处理资源 | Node.js | Python | 看个人熟悉程度 |
| 生成还原工程 | Cocos Creator 2.4.13 | 对应版本 Creator | 小版本越一致越好 |
AssetStudio 这个工具很容易被忽略。它原本是为 Unity 资源准备的,但社区有 Cocos 分支,支持读取 Creator 2.x 的序列化文件。实测它对.fire、.prefab、.anim等文件有不错的解析能力,能把二进制内容转成可视化节点列表,对还原场景帮助很大。
5.2 用 Test 工程验证资源完整性
还原工程做到一半,建议先新建一个临时场景,把提取到的关键资源(图集、预制体、字体)逐个拖进去,跑一遍预览模式,验证资源是否真正可复用。这个过程能快速发现资源缺失或格式异常,避免把问题遗留到最后构建阶段。
Test 工程是临时性质的,验证完后可以直接删除。养成这个习惯,逆向效率能提升一倍。有一次我就是忽略了 Test 场景,直接在新工程里大量导入资源,结果构建时才发现音频格式在一半文件里损坏,排查花了一整天才定位到问题。
5.3 UUID 处理的正确姿势
还原工程时,meta 文件非常重要。如果从 APK 里找到了.meta,意味着 UUID 能保持原样,场景和预制体里的资源引用也能自动链接上。这时候直接把资源和 .meta 一起拷进工程即可。
如果 meta 文件缺失,我只做一件事:把资源放进去后使用 Creator 的“重新导入资源”功能批量重新生成 meta,然后接受场景里的引用丢失现实。最忌讳的是自己编造 UUID 或者从旧工程里复制不匹配的 .meta,到头来问题更多。
5.4 自定义加密规则还原套路
部分老项目会自己写构建插件,把资源文件整个改造成非标准格式,比如所有文件前面统一加随机噪音字节。这种加密没有通用工具,只能逐一分析。
我的分析套路:
- 先看正常参考文件(同一目录下未被加密的文本 json)的文件头字节。
- 对比被加密文件的头部差异,找出变换规律。
- 写脚本批量还原。
这种自定义规则的逆向,难度不在技术,而在细心和对文件格式的敏感度。建议保留一份解密前后的文件对比记录,便于后续复查。
6. 逆向还原后的合规边界与安全提示
6.1 技术和法律的界限
必须明确一点,提取 APK 资源并还原工程这件事,具备一定技术门槛,同时也涉及版权和法律边界。我自己做这类工作,前提一定是拿到了原始项目拥有者的授权,或者是为了做自有产品的数据恢复和安全评估。
如果你是接到外包单子,务必在合同里写清楚:涉及逆向的资源归属、最终交付物的使用范围、不得侵犯第三方知识产权等条款。客户手上有原项目的版权,或者能提供源码丢失的证明,才算一个合规的项目背景。否则贸然对来历不明的 APK 做逆向并二次分发,极易惹上官司。
6.2 资源敏感内容的处理
逆向出的资源里,常常包含客户的敏感数据:后台地址、API Key、数据库连接串、第三方 SDK 的 App Secret,甚至内网地址。这些信息一旦泄露,危害很大。在交付还原工程前,建议执行一次敏感信息扫描:
- 全局搜索
http://、https://、aliyun、amazonaws等地址后缀。 - 搜索
appid、secret、token、apiKey等关键词。 - 检查
AndroidManifest.xml里声明的权限,确认是否有过度授权。
发现敏感信息后,要求客户确认这些值和测试环境是否有关。输出任何技术文章或示例时,一律使用脱敏后的假地址。
6.3 逆向工程与道德操守
技术是一把双刃剑。写这篇文章不是鼓励大家去破解别人的游戏,而是分享一套做合法授权项目时的标准和流程。我自己在每一次实操前,都会先做一遍“动机检查”:这个项目是否有合法授权,用途是否正当,成果是否会被用于盗版或侵权行为。
如果你遇到有人拿着不明来历 APK 要求“破解”“去掉广告”“拿到别人美术资源”,直接拒绝。这类单子的技术含量普遍不高,但法律风险极高,没必要为一个项目赌上职业生涯。
7. 这套方法后续还能用在哪
7.1 从逆向到代码学习
其实还原工程这件事,除了应急恢复,对学习 Cocos Creator 也有很大帮助。有些老项目代码组织非常优秀,通过逆向你能看到别人是怎么设计 UI 层级、怎么组织事件系统、怎么管理资源加载的。我在还原一个 2.4 项目时,从它的代码里学到了一种挺妙的“对象池 + 事件分发”组合模式,后来直接用到我自己的新项目里。
而且逆向出来的资源和工程,可以作为项目的“二次开发基座”。很多客户做海外市场本地化,原包丢了,逆向恢复出工程后就能快速做多语言替换、UI 调整、支付渠道切换。省去重新开发的成本,相当划算。
7.2 从 APK 恢复到后续其他平台
这套流程不仅适用 APK,Cocos Creator 2.4 打出来的微信小游戏、抖音小游戏、原生发布包,资源提取逻辑几乎一样。小游戏包内的资源甚至更直白,因为平台限制必须暴露若干 web 端口资源,很多开发者甚至没有开启任何加密处理。
以后我可能针对 Windows/Mac 原生打包的场景另写一篇,思路和 APK 大体一致,但有些原生层的钩子逻辑会少很多,过程会更清爽。
7.3 自动化脚本和持续集成的延伸
如果逆向项目不只做一次,而是定期从线上包恢复代码和资源,那整套操作可以脚本化。从解包、去头、重命名到拷贝进工程,都能用 Node.js 或 Python 跑通。设计好脚本参数,配合 CI 平台,就能做到一键产出“最新还原工程”。
考虑到 Cocos 构建机制在不同版本下的差异,脚本最好做成插件形式,按项目类型定制规则。这套自动化体系搭好后,后续新项目接入只是改配置的事。
写在最后的体会
逆向一个 Cocos Creator 2.4 的 APK,说难不难,说简单也不简单。难在资源和代码的组织方式千变万化,简单在于只要懂得 Creator 的打包规律、手头有正确的工具链、再有点耐心,恢复到可用的工程大概率是能做到的。
我个人在整个过程里感触最深的一点是:chất lượng của meta 文件和资源命名规范,直接决定逆向还原的难度。那些开发时认真维护资源命名、保留版权信息的项目,逆向起来顺畅得多。所以我现在写新代码时,也特别注重脚本模块划分、资源路径可读性这些“第一天看着麻烦、后来救人一命”的习惯。
如果你手头也遇到类似的 Cocos Creator 2.4 逆向恢复需求,照着这套流程先走一遍,大概率能省下不少试错时间。有新的坑和玩法,也欢迎一起交流补充。