Melaton's Blog

Protect Your Godot Game

Table of Contents

由于godot的开源,逆向变得易如反掌,本文会提供一些保护的方案

# 前言

阅读本文你需要一定的 Godot 开发基础

使用 Table Of Contents 快速跳转到你想看的内容

永远没有绝对安全的保护,唯一能做的只有增加逆向成本

# 基本知识

## 游戏根目录

Example.console.exe  -- Debug独有,启动游戏的同时会启动控制台
Example.exe          -- 类似于缩减版的godot游戏引擎,只有运行游戏的功能
Example.pck          -- 存储着你项目目录的所有文件

由此可见,Godot 的逆向十分简单,只要逆向 .pck 文件即可获得完整的项目,使用 gdsdecomp 可以还原出完整的项目

## C# 和 GDScript

GDScript 是 Godot 开发的编程语言

Godot 可以同时使用 C# 和 GDScript 编程,两者在使用时差别不大,性能差距可以忽略,GDScript 更全能一些,C# 目前还不支持 Android 平台

另外,GDScript 在运行时不会被编译,C# 会被编译。GDScript 在运行时会被 GDScript VM 调用并直接执行

# 基础防护

## PCK 密钥

这种是官方的加密方法,逆向相对简单,以下是操作方法

  1. 配置环境

    • 安装 Git

    • 安装 Python

    • 安装 Scons pip install scons

    • 安装 llvm-mingw ,下载 msvcrt-x86_64.zip,添加 bin 到环境变量

  2. 生成密钥

    1. 下载 openssl

    2. 使用 openssl rand -hex 32 生成密钥 如f91476533bd554c408e3d03ec634da97ee5e6ccae009dc8062dd39cbd23fa3fc

    3. 保存好这个密钥

  3. 获取源码

    1. git clone https://github.com/godotengine/godot.git

    2. 选择对应的版本 git checkout tags/4.2-stable

  4. 构建导出模板

    1. 在源码根目录打开cmd,输入set SCRIPT_AES256_ENCRYPTION_KEY=你的key

    2. 如果不需要 C# 功能:

      scons platform=windows target=template_release
      

      如果需要 C#:

      scons platform=windows target=template_release module_mono_enabled=yes
      

      在命令后添加 -j 即可多线程编译,如 -j32 就是32线程

    3. 等待构建结束,结束后在 /bin 会有以下两个文件

      godot.windows.template_release.x86_64.console.exe
      godot.windows.template_release.x86_64.exe
      

      如果需要debug模式,则需要另外构建target=template_debug

  5. 使用构建模板

    项目 - 导出 - 添加 - Windows Desktop

    选项 - 自定义模板 - 发布 定位到你的 godot.windows.template_release.x86_64.exe

    加密 - 加密导出的PCK - 加密密钥 填写前面生成的密钥

## 代码混淆

建议使用现成的插件 gdmaim

## 使用 C#

因为目前大部分工具没办法还原完整的 C# 代码,所以使用 C# 是相对安全的选项

# 进阶防护

## 自定义PCK加解密

core/io/file_access_encrypted.cpp 中,open_and_parse 负责pck的解密

FileAccessEncrypted::open_andparse(Ref<FileAccess> p_base, const Vector<uint8_t> &p_key, Mode p_mode, bool p_with_magic) {

其中 p_key 是32字节的密钥

你可以在这里对 p_key 进行处理,比如变换其中的字节、二次加密之类的,这样即使 gdke 能读取到密钥,也无法用 gdsdecomp 解包,因为游戏在使用密钥解密时有额外的处理

如果想要更强的保护,我建议在编译 Godot Engine 时就进行混淆,这样逆向时就没办法轻易定位到 open_andparse 这个函数,建议在每个版本发布时都重新进行一次 Godot Engine 混淆,可以保证跨版本时更难进行修改

## Strip 导出模板

源码里的gdscript::load_byte_code函数负责读取加密后的文件并解密,逆向者可以轻易定位到该函数并找到对应的解密key script_encryption_key。使用strip命令可以消去symbols,增加定位函数的逆向成本

## 删除错误日志输出

即使函数名被strip,字符串还是能被轻易定位,godot的错误日志函数_err_print_error可以泄露当前函数的具体名称,因此可以在构建阶段删除所有错误日志。或者采用更温和的方法,将字符串使用保护器动态加解密,这样既可以保留错误日志也能增加逆向成本

# 购买已有构建

你可以通过Telegram或邮件咨询我,购买我制作的Godot修改版,支持Godot全版本/全平台保护,可直接用于编译项目,无须对已有项目进行修改。支持定制额外功能如网络验证

目前已有功能:

  • 非Debug构建不再输出_err_print_error
  • 非Debug构建不再输出具体报错信息,出错的函数/文件/行数不会泄露
  • 非Debug构建自动将CoreGlobals::print_error_enabled设置为False
  • 非Debug构建将自动去除符号信息
  • 若开启pck加密,密钥将获得额外的保护
  • 脚本加密密钥更难以使用静态工具提取

# Credits

https://github.com/bruvzg/gdsdecomp

Compiling with PCK encryption key

Protecting Your Godot Project from Decompilation

Protecting Your Godot Project from Decompilation (Web archive)