Godot逆向工程实战:一个命令把PCK打包的游戏恢复成完整项目源码

发布时间:2026/8/18 13:21:15
Godot逆向工程实战:一个命令把PCK打包的游戏恢复成完整项目源码 Godot逆向工程实战一个命令把PCK打包的游戏恢复成完整项目源码【免费下载链接】gdsdecompGodot reverse engineering tools项目地址: https://gitcode.com/GitHub_Trending/gd/gdsdecomp如果你手里有一个 Godot 打包出来的.pck或.apk文件却没有对应源码——可能是备份丢失、接手别人发布的游戏做安全审计也可能是想从老项目里抢救一段丢失的代码——恭喜你这正是GDRE ToolsGodot逆向工程领域流传最广的开源工具最擅长的战场。它能把你手上这堆编译后的二进制碎片重新拼回一份可以在编辑器中打开的工程。先说结论工具本身的使用门槛很低但想用好它你需要先理解它解决的是三个不同的问题。这篇文章会从问题出发带你一步步走完侦察 → 恢复 → 排错 → 自定义解密的完整路径。先搞清楚一件事你丢的是哪一层源码很多新手一上来就问怎么反编译但 Godot 的编译产物其实分三层GDRE Tools 也是按三层来设计的层打包前的形态打包后的形态对应 GDRE 的能力GDScript 脚本.gd源码文本.gdc字节码token 流批量反编译decompiler场景/资源.tscn/.tres文本.scn/.res二进制文本↔二进制双向转换项目整体project.godot 目录结构PCK 归档可能嵌入 EXE/APK完整项目恢复recovery为什么这样设计因为如果你只是提取文件拿到手的.gdc依旧是一堆不可读的字节只有先把字节码反编译回 GDScript、再把二进制资源转回文本格式、最后重建project.godot才能得到一个真正能打开的工程。完整项目恢复的核心逻辑都实现在导出器目录和字节码目录里不过你作为使用者不需要碰源码——一条命令就够了。第一次上手用一条恢复命令跑通全流程拿到工具GUI 版本或gdre_tools命令行版本均可之后最快的验证方式是直接把.pck/.exe/.apk文件拖拽到程序窗口上。如果你和我一样更习惯命令行用--recover子命令做完整恢复# 完整恢复从 PCK/EXE/APK 里重建整个可编辑项目 gdre_tools --headless \ --recovermy_game.pck \ # 目标包文件 --outputrecovered_project \ # 输出目录默认是 名字_extracted --key000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F \ # 加密包密钥64位十六进制 --ignore-checksum-errors # 跳过 MD5 校验失败的文件防止个别坏文件中断全程恢复过程会弹出一个配置窗口下图默认选中 Full Recovery 完整恢复模式如果你只想拿文件不想反编译可以切到 Extract only。恢复完成后工具会生成一份报告内容类似反编译脚本 9 个、失败 0 个、导入资源 7 个、成功转换 4 个、未转换 3 个……未转换的文件并不是失败了而是某些资源类型的转换支持尚未实现后面会细说。这里有个坑恢复完成后请用报告里检测到的 Godot 版本来打开项目。因为字节码和资源格式跟引擎版本强绑定用错版本会刷出一堆莫名其妙的报错。日志文件gdre_export.log会写明检测到的版本号。想少恢复一点先侦察再定向提取--recover是全量恢复但如果我只是想快速看看包里有什么或者只想拿脚本做安全分析全量恢复就太重了。正确的做法是先侦察再定向。# 第一步列出包里所有文件先摸清家底可以重复指定多个包 gdre_tools --headless --list-filesmy_game.pck # 第二步A只要脚本一键提取并反编译全部 .gdc gdre_tools --headless --recovermy_game.pck --scripts-only --outputscripts_analysis # 第二步B按 glob 模式定向恢复比如只要脚本和场景排除美术资源 gdre_tools --headless --recovermy_game.pck \ --includeres://**/*.gdc \ --includeres://scenes/**/*.tscn \ --excluderes://assets/textures/** \ --outputpartial_recovery用--include/--exclude时有三个容易踩的细节都是从源码注释和 README 里确认过的glob 要锚定在res://或user://下。res://*.gdc只匹配项目根目录不会匹配子目录。带通配符但没写目录的 glob 会被当成递归处理*.gdc等价于res://**/*.gdc。include/exclude 只匹配包里实际存在的文件。比如包里只有main.gdc没有main.gd那么--includeres://main.gd不会恢复任何东西得写res://main.gdc才会把反编译后的.gd恢复出来。顺带一提GUI 模式下这个侦察过程很直观打开包后左侧是res://文件树点击任意.gdc右侧立刻显示反编译预览版本信息、加密密钥输入框一目了然。为什么 4.5 和 3.1 的 .gdc 不是同一种字节码你可能想问为什么反编译还要特意检测版本因为GDScript 字节码从来没有稳定过。Godot 每加一个语法yield、match、onready……token 表就会变每改一次函数签名字节码格式也跟着变。GDRE Tools 的做法是把 Godot 每个版本的字节码提交记录整理成一张表见仓库根目录的 BYTECODE_HISTORY.md比如 2014 年的 1.0 分支只有 3 个字节码版本3.0 分支在MATCHtoken 加入后跳到版本 124.x 系列则从TK_EMPTY一路演进到 4.5 的 bytecode 101。每个版本对应bytecode/目录下一个bytecode_commit哈希.cpp解析器。更巧妙的是回退机制misc/bytecode_versions.json里每个版本都记录了parent字段当精确匹配失败时工具会尝试用父版本解析器去解析。所以遇到冷门自定义引擎版本时通常也只是反编译效果略差而不是直接崩溃。什么时候需要手动干预当工具检测错误、或者你想强制用某个版本解析时# 强制用 4.3.0 的字节码定义解析也可以用 commit 哈希如 f3f05dc gdre_tools --headless --recovergame.pck \ --force-bytecode-version4.3.0 # 或者加载自定义 JSON 字节码定义高级玩法适合自定义引擎版 gdre_tools --headless --recovergame.pck --load-custom-bytecodemy_bytecode.json遇到加密包从 --key 到自定义解密器很多商业游戏打包时开了script_encryption_key直接恢复会得到一堆密文。标准做法是先提取密钥# 密钥必须是 64 位十六进制字符串即 32 字节对应 AES-256 gdre_tools --headless --recoverencrypted_game.pck \ --key00112233445566778899AABBCCDDEEFF00112233445566778899AABBCCDDEEFF标准方案只有三种AES-256-CFB、Camellia-256-CFB、Aria-256-CFB实现都在 crypto/ 目录。如果你用正确密钥仍然解密失败别急着怀疑工具——大多数解密问题的根源是没有拿到正确的密钥。有些游戏会对加载后的密钥再做一次置换或异或从内存提取器拿到的原始密钥根本不对。官方文档docs/custom_decryptors.md里明确写了先用 Ghidra 之类的工具确认它确实不是标准加密方案再考虑写自定义解密器而且项目不会帮你恢复加密密钥。自定义解密器的写法其实很规整继承CustomDecryptor类实现_parse_and_decrypt()。标准加密方案的参考实现就在 docs/gdre_standard_encryption.gd结构通常是魔数(可选)→MD5→长度→IV→密文class_name MyDecryptor extends CustomDecryptor # 必须实现读文件头 → 解密 → 校验 → 返回 {error, length, data} func _parse_and_decrypt(file: FileAccess, key: PackedByteArray, non_pack_file: bool) - Dictionary: var result : {error: OK, length: 0, data: PackedByteArray()} # 非 PCK 内的独立加密文件开头通常有 GDEC 魔数0x43454447 if non_pack_file: if file.get_32() ! 0x43454447: result[error] ERR_INVALID_PARAMETER return result # 依次读取 MD5(16字节) / 长度(8字节) / IV(16字节) var md5 : file.get_buffer(16) var length : file.get_64() var iv : file.get_buffer(16) # 密文按 16 字节对齐先读足对齐后的长度再解密 var ds : length if ds % 16 ! 0: ds 16 - (ds % 16) var cipher : file.get_buffer(ds) # 用 GDRE 提供的 AESContextGDRE 走 CFB 解密 var ctx : AESContextGDRE.new() ctx.start(AESContextGDRE.MODE_CFB_DECRYPT, key, iv) var plain : ctx.update(cipher) ctx.finish() plain.resize(length) # 校验 MD5防止密钥或对齐搞错这是最常见的报错来源 var h : HashingContext.new() h.start(HashingContext.HASH_MD5) h.update(plain) if h.finish().hex_encode() ! md5.hex_encode(): result[error] ERR_FILE_CORRUPT return result result[length] length result[data] plain return result # 在恢复时加载--custom-decryption-scriptmy_decryptor.gd有两个实用细节_is_file_nonpck_encrypted()用于标记PCK 之外还单独加密了某些文件的游戏_get_required_key_size_in_bytes()默认返回 32即 AES-256。法律提醒如果打算分发解密脚本千万别把密钥写进脚本里这在部分地区可能违反数字版权相关法规文档原文也特别强调了这一点。资源转换与补丁别忽略恢复的另一半脚本恢复只是项目恢复的一部分场景和资源文件同样需要从二进制转回文本# 二进制资源 → 文本.scn → .tscn, .res → .tres gdre_tools --headless --bin-to-txtgame.scn --bin-to-txtgame.res # 反向文本 → 二进制做资源优化或重新打包时用 gdre_tools --headless --txt-to-bingame.tscn # 逆操作从目录重新打一个 PCK需要指定格式版本和引擎版本 gdre_tools --headless --pck-createmy_project_dir \ --pck-version2 --pck-engine-version4.3.0 --outputrepacked.pck另外两个高频命令--pck-patch可以在不整体重打包的情况下向已有 PCK 注入文件比如修 bug 后只替换某个.gd--compile/--decompile则支持单文件批处理配合 glob 使用--compile需要搭配--bytecode版本或commit指定目标版本。认清边界以下类型目前不支持转换README 的 Limitations 一节原话2.x 时代的模型文件.dae/.fbx/.glb以及 GDNative/GDExtension 脚本——这俩不是 GDRE 不想做而是本质上不属于可逆的字节码范畴。一张表收藏踩坑清单症状常见原因解决反编译出来逻辑错乱字节码版本检测错误--force-bytecode-version手动指定恢复报 MD5/校验错误个别文件损坏--ignore-checksum-errors跳过解密失败密钥不是游戏实际使用的值用 Ghidra 分析确认是否走了自定义加密打开项目一堆脚本报错用错了 Godot 编辑器版本按恢复日志检测到的版本打开某些文件未转换资源类型支持未实现如 2.x 模型用原始游戏二进制作为导出模板从使用者到贡献者你也能加一个字节码版本想从用工具进阶到改工具项目本身就是 Godot 引擎的一个模块源码目录划分非常清晰bytecode/放各版本解析器、exporters/放各类资源导出器、crypto/放加解密实现、compat/放格式兼容层。编译流程也不复杂git clone https://gitcode.com/GitHub_Trending/gd/gdsdecomp # 把 gdsdecomp 放进 Godot 源码的 modules/ 目录 # 然后按官方文档重新编译 Godot 引擎即可需要 rustup 和 dotnet 10 SDK社区为 Godot 新版本贡献支持的路径通常是分析新版字节码变化 → 在bytecode/下新增bytecode_commit.cpp→ 更新misc/bytecode_versions.json的版本定义含parent回退关系→ 用tests/下的测试套件验证。这套流程在 README 的编译章节有详细说明--dump-bytecode-versionsDIR命令还能把所有版本定义导出成 JSON 供你研究。最后说两句回头看GDRE Tools 真正厉害的地方不是某个单点功能而是把提取 → 反编译 → 转格式 → 重建工程这条链路做成了三个独立且可组合的能力层。无论是只想--list-files侦察一下、用--scripts-only快速做脚本审计还是连自定义加密都不在话下你总能找到刚好够用的那一档。下次再遇到打不开的 Godot 游戏包先别急着放弃——一条--recover命令可能就是找回全部源码的开始。【免费下载链接】gdsdecompGodot reverse engineering tools项目地址: https://gitcode.com/GitHub_Trending/gd/gdsdecomp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考