Godot 逆向工程实战:gdsdecomp 帮你把丢失的源码从游戏包里找回来
【免费下载链接】gdsdecompGodot reverse engineering tools项目地址: https://gitcode.com/GitHub_Trending/gd/gdsdecomp
深夜两点,你盯着硬盘上那个空荡荡的源代码目录,脑子里只剩下一个念头:幸好,发布版的game.pck还在。这是不少独立开发者真实经历过的噩梦——代码没推进仓库、硬盘突然损坏、目录被误删,唯一幸存的,只剩编译打包后的成品文件。如果你正在接触Godot 逆向工程,或者恰好在为"项目只剩一个 pck 该怎么办"发愁,那么这篇文章要介绍的开源项目——gdsdecomp(GDRE Tools),很可能就是你要找的答案:它能把已发布的 Godot 游戏包重新拆回可读的源码和资源,帮你把"丢了"的项目找回来。
它到底是什么:一个会"逆向做饭"的引擎模块
你可以把 Godot 导出游戏的过程想象成"把面粉、鸡蛋、奶油烤成一个成品蛋糕"。引擎把 GDScript 源码编译成.gdc字节码,把场景、纹理、音频等资源重新编码后打包进 PCK 文件,最后分发的就是一个烤好的成品。正常情况下,没人会把蛋糕还原成面粉,但当你丢失了原料,gdsdecomp 就是那个试图帮你"拆蛋糕、找配方"的工具。
具体来说,这个项目提供了四类核心能力:
- 完整项目恢复:从 APK、PCK 或嵌入 PCK 的 EXE 中加载全部资源,反编译所有 GDScript 脚本,重建
project.godot工程文件,把导入过的资源还原成原始导入格式,还能重建插件配置。 - PCK 解包与打包:既可以把 PCK/APK/EXE 里的文件逐个提取出来,也可以反过来把一个目录重新打成 PCK。
- GDScript 批量反编译:支持 Godot 2.x、3.x、4.x 全系列项目的脚本还原。
- 资源格式互转:在文本格式(
.tres/.tscn)与二进制格式之间批量转换。
它最初是作为 Godot 引擎的一个模块存在的:把项目代码放进引擎的modules目录重新编译,即可获得完整的 GUI 与命令行能力;官方也发布有独立可执行文件,Windows 用户甚至可以用一条scoop命令装好。无论你是只想打开界面点几下,还是想把它接进自动化脚本,都有对应的入口。
为什么能反编译:一份跨越十多年的字节码"族谱"
反编译听起来像魔法,背后的原理其实很朴素:GDScript 编译生成的字节码,会随引擎版本不断变化——新增一个关键字、改一个函数名,字节码格式就可能不同。要还原 2014 年的脚本,你需要知道 2014 年的字节码长什么样。
gdsdecomp 的做法,是把这份"版本演变史"完整记录了下来:
- 项目在
misc/bytecode_versions.json里维护了从最早的 1.0 分支到今天所有字节码修订的定义,包括每个修订对应哪些 token、新增或删除了哪些函数; bytecode/目录下,每个字节码修订都对应一个专属的解析器类(如GDScriptDecomp_ebc36a7),它们统一继承自同一个基类;BYTECODE_HISTORY.md以表格形式整理了每次变化的时间、提交和原因。
下表是这份族谱的极简缩影(数据来自项目内的版本历史文档):
| 时代 | 代表性字节码修订与变化 |
|---|---|
| 1.0 分支(2014 年) | 从0b806ee起步,e82dc40加入SETGET关键字,字节码版本号升至 3 |
| 2.x 分支 | 23441ec加入var2bytes/bytes2var,ed80f45加入ENUM,版本稳定在 10 |
| 3.x 分支 | f8a7c46加入MATCH,c24c739加入WILDCARD,字节码版本来到 12 附近 |
| 4.x 分支 | 最新定义ebc36a7对应 4.5.0-stable,字节码版本号已达 101 |
反编译时,工具先通过文件头魔数、脚本结构特征判断项目属于哪个时代,再沿着"父版本"链条逐级尝试,找到最合适的解析器。即便遇到小众或修改过的引擎版本,你也能用--load-custom-bytecode=<JSON_FILE>加载自定义定义,或者用--dump-bytecode-versions=<DIR>把全部定义导出为 JSON 自行研究。想确认当前支持哪些版本,运行--list-bytecode-versions即可。
动手实操:五分钟把 game.pck 恢复成可打开的工程
理论说完了,我们来走一遍完整的恢复流程。请准备一个 PCK、APK 或 EXE 格式的 Godot 游戏文件,跟着下面的步骤来。
第一步:准备好目标文件
把游戏文件放到顺手的位置。如果你用的是图形界面版本,直接把它拖进程序窗口即可;命令行的基础用法是:
gdre_tools --headless <主命令> [选项]第二步:先看看包里有什么
正式动手前,先确认文件能被正确识别:
gdre_tools --headless --list-files=game.pck这条命令会列出 PCK 内所有文件的路径,并立即退出。看到脚本、场景、纹理等条目正常列出,说明文件解析没有问题,可以放心往下走。
第三步:执行完整恢复
gdre_tools --headless --recover=game.pck --output=recovered_project--recover接受 PCK、APK、EXE 或者已经解包的项目目录;--output指定输出目录,缺省时会自动生成一个以原文件名加_extracted结尾的目录。恢复过程中,工具会提取所有资源、反编译全部.gdc脚本、重建工程文件,并把二进制资源转回文本格式。如果游戏使用了标准 Godot 加密,记得带上密钥参数:
gdre_tools --headless --recover=game.pck \ --key=000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F密钥是 64 字符的十六进制字符串。在 GUI 版本里,你可以在 "Set Encryption Key" 菜单里完成同样的设置。
第四步:读一读恢复日志
恢复结束后,输出目录里会生成gdre_export.log一类的报告文件,它是你判断恢复质量的第一手资料。报告会告诉你:反编译成功了多少个脚本、导入了多少资源、有没有文件转换失败,以及——这一点很关键——建议用哪个版本的 Godot 打开这个工程。
建议记下这个版本号,并用同版本的 Godot 编辑器打开恢复出的工程,兼容性通常最好。报告底部列出的未转换文件及原因也值得留意,它会诚实告诉你哪些资源超出了当前能力范围。
第五步:只恢复你需要的部分
完整恢复有时并不必要。比如你只想要脚本,可以加上--scripts-only;只想处理特定目录,用--include和--exclude配合通配符过滤:
# 只恢复脚本 gdre_tools --headless --recover=game.pck --scripts-only # 排除掉体积大的纹理和音频 gdre_tools --headless --recover=game.pck \ --exclude="res://assets/textures/*.png" \ --exclude="res://assets/audio/*.ogg"注意,这些通配符匹配的是 PCK 里真实存在的文件:res://*.gdc会匹配根目录下的全部.gdc,而*.gdc这种不带目录的写法会被当作递归模式,等价于res://**/*.gdc。
恢复不是全部:命令行里还藏着这些能力
如果只把 gdsdecomp 当成"一键恢复工具",你就错过了它的一半价值。它的命令行里还提供了一批可以组合使用的能力,这里挑几个常见的整理成表:
| 想做的事 | 使用的命令 | 需要配合的参数 |
|---|---|---|
单独反编译某个.gdc脚本 | --decompile=<文件> | 可多次使用,也支持通配符 |
| 把 GDScript 编译回字节码 | --compile=<文件> | --bytecode=<提交号或版本号> |
| 从目录创建新的 PCK | --pck-create=<目录> | --pck-version与--pck-engine-version |
| 给已有 PCK 打补丁 | --pck-patch=<游戏文件> | --patch-file=源文件=目标路径 |
| 二进制场景/资源转文本 | --bin-to-txt=<文件> | 可多次使用 |
| 文本场景/资源转二进制 | --txt-to-bin=<文件> | 可多次使用 |
| 用 CSV 批量补丁翻译文件 | --patch-translations=<CSV>=<源路径> | 可结合--pck-patch使用 |
举个例子,想把一个.tscn二进制场景转回人类可读的文本格式,方便用编辑器查看差异,只需要:
gdre_tools --headless --bin-to-txt=stage.tscn再比如,如果你希望给玩家分发一个修改过的脚本,又不想完整解包整个游戏,可以用--pck-patch把新脚本直接写进现有 PCK。它支持把产物重新嵌入 EXE(--embed参数),对分发场景相当实用。
三个常见误区,以及对应的正确做法
基于这个工具的实际使用反馈,有三类问题被问得最多,我把它们和正确的处理方式放在一起对照说明。
误区一:遇到解密失败,第一反应是写自定义解密器
实际大多数情况是密钥不对,而不是加密方案特殊。官方文档docs/custom_decryptors.md里明确提醒:标准 Godot 项目使用的是 AES-256-CFB 加密,只要拿到正确的 64 字符密钥就能解开。只有当确认密钥无误、且用 Ghidra 之类的工具验证过游戏确实没有采用标准加密方案时,才值得编写自定义解密器。如果你真的需要,脚本必须继承CustomDecryptor类并实现_parse_and_decrypt()方法,项目里附带的docs/gdre_standard_encryption.gd是一个很好的参考模板。
误区二:用任意版本的 Godot 打开恢复结果
恢复出的工程对引擎版本很敏感。恢复日志会明确给出检测到的引擎版本,建议安装同版本 Godot 再打开。版本跨度太大时,脚本语法或 API 差异可能导致工程无法直接运行。
误区三:指望所有资源都能原样还原
目前仍有两类资源转换尚未实现:2.x 时代的模型文件(dae、fbx、glb 等),以及 GDNative / GDExtension 脚本。遇到它们,日志里会如实标记为"尚未支持",不要为此反复重试。另外,反编译出的脚本保留的是逻辑结构,变量名可能经过编译期优化,复杂脚本往往需要人工整理,这是所有反编译工具的共性,不必苛求完美。
写在最后:把故事补完
回到开头那个深夜的场景:硬盘坏了、源码没了、只剩一个game.pck。有了 gdsdecomp,这个故事不必以"重写整个游戏"结尾——你可以先恢复出全部脚本和资源,评估损失,再决定是直接修复重建,还是把它当作重构的起点。它未必能还原每一行注释,但它能让你在最短时间内拿回项目的"骨架"。
如果你想现在就试试,可以这样开始:
- Windows 用户:
scoop bucket add games后执行scoop install gdsdecomp,即可从命令行使用gdre_tools; - 想用图形界面:从官方 release 页面下载对应平台的可执行文件,把 pck 拖进窗口即可;
- 想从源码编译:执行
git clone https://gitcode.com/GitHub_Trending/gd/gdsdecomp,把仓库放进 Godot 引擎的modules目录(命名为gdsdecomp),然后按引擎编译文档重建。编译需要 rustup 与 dotnet 10 SDK,模块在配置阶段会自动把 CLI 钩子补丁应用到引擎的main/main.cpp,重复运行scons不会产生副作用。
最后留一个小小的建议:动手恢复之前,先给原始 PCK 做一份备份,用--list-files确认文件无误后,再让工具放手干活。祝你的下一次逆向工程之旅顺利——也愿你永远不需要用到它。
【免费下载链接】gdsdecompGodot reverse engineering tools项目地址: https://gitcode.com/GitHub_Trending/gd/gdsdecomp
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考