KamiKitsune420/bgt-decomp-tools
GitHub: KamiKitsune420/bgt-decomp-tools
一套用于从 BGT 引擎构建的音频游戏中恢复 AngelScript 伪源码、声音资源并支持重新打包的逆向工程工具包。
Stars: 1 | Forks: 0
# BGT 反编译工具包
从使用 **BGT**
(BlastBay Gaming Toolkit),即 2010 年的音频游戏引擎构建的游戏中恢复源代码级结构和资源。
给它一个游戏可执行文件,它就会以可读的伪源码形式返回该游戏的代码、
其中包含的每一个字符串,以及它的声音。
```
pip install -e .
bgt unpack game.exe -o work/
bgt lift work/game_bytecode.bin game.exe -o game.as
```
```
void ::main()
{
v1 = string("Psycho Strike");
ret = show_game_window(&v1);
v1 = string("sounds.dat");
ret = v1.open(retreave);
ret = reset_game();
ret = prepare_audio();
v2 = performance_debug;
if (v2) {
ret = start_profiling();
v1 = string("strikelog_errors.log");
ret = set_error_output(&v1);
}
...
```
## 安装
需要 Python 3.8+ 和 `pycryptodome`。
```
pip install -e .
```
这会为你提供一个 `bgt` 命令。你也可以不安装,直接在
`tools/` 目录中运行所有内容(`python tools/bgt_unpack.py ...`)。
## 你可能想要的五个功能
### 1. 从游戏中提取代码
```
bgt unpack game.exe -o work/
```
生成 `work/game_bytecode.bin` —— 即解密并
解压后的游戏编译脚本。
### 2. 阅读代码
```
bgt lift work/game_bytecode.bin game.exe -o game.as
```
伪源码:真实的函数名、类名、字符串字面量、`if`/`while`,
以及解析出的调用目标。这是大多数情况下你想要的。
如果你想要原始指令列表,请使用:
```
bgt disasm work/game_bytecode.bin game.exe -o game.asm
```
仅查看单个函数:
```
bgt lift work/game_bytecode.bin game.exe -f main
```
### 3. 查看声音包内部
```
bgt pack list sounds.dat
```
```
sounds.dat: v1, 975 entries, 974 encrypted, 1 distinct key
```
如果显示 **1 distinct key**,说明一个密码就能打开整个声音包。如果显示成千上万个,说明游戏为每个文件使用了独立的密钥,这时你需要的是推导逻辑,而不是密码。
### 4. 提取声音
你需要密钥。如果游戏的密码是其脚本中的纯字符串:
```
bgt crack sounds.dat --dict work/game_bytecode.bin --workers 0
```
然后执行:
```
bgt pack extract sounds.dat -o sounds/ --key
```
如果 `crack` 什么也没找到,说明密码是经过计算而不是直接存储的——这很
常见。请阅读构建该密码的函数。`set_sound_decryption_key` 是
引擎的一部分,它没有自身的函数体,因此请查找**调用**它的代码:
```
bgt lift work/game_bytecode.bin game.exe --calls set_sound_decryption_key
```
```
void ::prepare_audio()
{
ret = get_SCRIPT_COMPILED();
if (ret) {
v2 = string("ZGtz9mdqa2F3ZWx0dXdGSkRLTFNKVklDMTA4MzIx...");
ret = get(&v2); // <- this transforms it
ret = set_sound_decryption_key(v3, &v2);
v2 = string("sounds.dat");
ret = set_sound_storage(v3);
}
}
```
这就是种子以及将其转换为密钥的函数。`--calls` 也可以在
`bgt disasm` 中使用,当你拥有的名称属于
引擎而不是脚本时,这是通用的入口。
### 5. 修改内容并重新构建游戏
```
bgt asm work/game_bytecode.bin game.exe \
--replace sounds.dat=my_sounds.dat -o work/modified.bin
bgt repack game.exe work/modified.bin -o patched.exe
```
替换的内容长度可以不同。这两个步骤都会进行自我验证,
如果有任何异常都会拒绝写入。
## 所有命令
| 命令 | 功能描述 |
|---|---|
| `bgt unpack game.exe -o work/` | 从可执行文件中恢复脚本 |
| `bgt info game.exe` | 仅显示头部信息:overlay、密钥、大小 |
| `bgt lift module.bin game.exe` | 输出伪源码 |
| `... -f NAME` / `--calls NAME` | 输出单个函数,或调用该函数的内容 |
| `bgt disasm module.bin game.exe` | 带有注释的指令列表 |
| `bgt asm module.bin game.exe` | 重写模块,编辑其字面量 |
| `bgt repack game.exe module.bin -o out.exe` | 将模块放回可执行文件中 |
| `bgt pack list \| extract sounds.dat` | 检查或提取资源包 |
| `bgt crack sounds.dat --dict module.bin` | 在脚本中搜索资源包密码 |
| `bgt opcodes game.exe` | 转储引擎的操作码表 |
| `bgt validate a.exe b.exe` | 对多个游戏运行整个流水线 |
| `bgt ghidra status \| install \| decompile` | 设置并驱动 Ghidra |
运行 `bgt --help` 查看可用选项。
## 你能得到什么,以及得不到什么
**你能得到**每一个函数、类、属性和枚举的**名称**,每一个字符串
字面量,完整的调用图,以及以 `if` / `while` / `break` 形式呈现的控制流。
**你得不到**局部变量名、参数名、行号或
注释。BGT 在编译时会将它们剥离,并且它们确实已经消失了——局部变量
会显示为 `v3`,参数显示为 `a0`。因此你可以忠实地重建游戏;但无法
完全恢复其原始文本。
## 它适用于我的游戏吗?
运行:
```
bgt validate mygame.exe
```
每个阶段都会输出 `ok` 或 `FAIL`。开发此工具所针对的三款游戏都能通过
所有阶段:
| | Psycho Strike | Paladin of the Sky | Manamon 2 |
|---|---|---|---|
| 类 | 68 | 47 | 1,604 |
| 函数 | 1,102 | 926 | 9,924 |
| 已命名操作数 | 100% | 100% | 100% |
| 逐字节重建 | yes | yes | yes |
BGT 游戏共享同一个引擎,因此如果某个游戏失败,更有可能是遇到了此工具尚未见过的 BGT *版本*,而不是引擎被修改过。`bgt validate` 会显示是哪个阶段停止了运行。
## 如果出现问题
**"no xproc10 trailer"** —— 不是 BGT 可执行文件,或者是打包方式不同的
BGT 版本。
**`bgt lift` 提示 "no function bodies were recovered"** —— 模块解析成功,但其函数记录未能解析。它会告诉你具体的方言以及停止的位置。
**`bgt crack` 什么也没找到** —— 这只能排除它尝试过的候选词,并且
它会打印出尝试的数量。密码很可能是计算得出的;请参阅上面的第 4 步。
**Ghidra 命令失败** —— 运行 `bgt ghidra status`。Ghidra 需要 JDK 21 或更高版本,而你 PATH 中的 `java` 往往是为其他用途保留的旧版本。
## 文件
```
tools/ the toolkit
tests/ python -m pytest tests/ -q (124 tests, no game files needed)
docs/ ghidra_workflow.md — how to read the engine's own loader
CLAUDE.md the format itself, in detail, and why each part is believed
```
`CLAUDE.md` 是参考文档:加密链的工作原理、字节码
格式的布局、哪些部分是从二进制文件中读取的,哪些是推断出来的,以及
还有哪些问题尚未解决。在扩展任何功能之前,请先阅读此文档。
## 许可证
[PolyForm Noncommercial License 1.0.0](LICENSE.md) — 版权所有 KamiKitsune420
(Adel Spence)。
简而言之:**使用它、修改它、分享它、为它做贡献** —— 仅限任何
非商业目的,包括个人使用、业余项目、研究和
教育。你必须在传递给他人的任何副本中保留许可证和
版权声明,因此你不能将其冒充为自己的作品。你**不得出售**它或
将其用于商业用途。
这是一个源码可见的许可证,而不是 OSI 批准的开源许可证;非商业
限制是其原因所在。
## 免责声明
**本软件按“原样”提供,不提供任何形式的保证。作者不对
使用本软件产生的任何后果负责** —— 包括文件损坏、游戏安装
损坏,或你对所恢复内容进行操作而产生的任何法律后果。请参阅
[No Liability](LICENSE.md#no-liability)。
本工具旨在用于互操作性、保存和研究你拥有的游戏。它不附带
任何游戏文件或密钥 —— 它所做的一切都是基于你已经拥有的可执行文件
推导出来的。提取或重新分发特定游戏的代码或
资源在你所在地区是否合法,由你自己决定,本
工具不承担相关责任。
标签:Python, URL提取, 云资产清单, 反编译, 密码学, 手动系统调用, 无后门, 游戏引擎, 资源提取, 逆向工具, 逆向工程