TRANSFORMERS: 锻造之战是一款3D格斗游戏,你将操控《变形金刚》宇宙中那些最具魅力的战士。没错,你听到的正是这些大名鼎鼎的角色——擎天柱、威震天、大黄蜂、救护车、声波和搅拌机。是的,你没看错。来自任何《变形金刚》系列的
本软件包包含一个可正常工作的 Transformers: Forged to Fight 离线启动版本,以及用于实现这一目标的所有工具、补丁和逆向工程笔记。它的设计目的是交给那些有时间和精力去迈出下一步(即从头重建游戏服务器端内容)的人。这里的所有内容都有文档记录,这样你就不必像我一样从零开始。
在动手之前,请先通读本文件。特别是“陷阱”部分,它将为你节省数天时间。
游戏完全离线启动,并进入其真正的交互式主屏幕,无需任何实时服务器。在主屏幕上,菜单导航不会崩溃:基地、机器人阵容(账户中拥有一个已拥有的机器人)、战斗模式选择、水晶屏幕以及常见的弹出窗口和提示。完整的登录流程已完成,每个在线子系统都已连接,首次体验和教程关卡已通过。脚本化的开场战斗(擎天柱 vs 红蜘蛛)甚至能走到开始加载战斗的阶段,并且3D角色模型能够渲染和动画化。
这是最困难的部分,而且已经解决了。客户端本身已离线复活。
实际游戏玩法无法运行。剧情模式不显示任何任务,战斗无法完全加载。这不是一个 bug,也不是补丁能修复的。
Forged to Fight 是全面服务器权威的。手机上的应用程序本质上只是一个带控制器的屏幕。游戏中几乎没有任何东西存在于应用程序中。每个任务、每场战斗、每个敌人阵容、整个阵容的属性和能力、经济以及所有平衡性都存在于 Kabam 的服务器上,并在每次会话中流式传输到设备。当服务器在 2020 年初关闭时,那个内容数据库也随之消失,并且从未发布或在我能触及的任何地方公开存档。
因此,情况被清晰地一分为二。美术和音频幸存了下来,因为它们随应用程序一起打包(见 re_notes/ASSET_INVENTORY.txt)。每个角色都是一个完整的 Unity 资源包,包含模型、纹理、骨架、动画剪辑、动画控制器、特效和音频。环境、建筑、UI、头像、过场动画和对话也都存在。没有幸存下来的是告诉游戏使用哪些资源、如何将它们组装成战斗或任务、以及每个机器人的具体数值的数据。所有零件都存在,但没有任何东西知道如何将它们组合起来。重建这一切就是剩下的全部工作。
这里有四个活动部分。它们共同让未经修改的游戏以为它正在与 Kabam 通信。
原生二进制补丁。游戏是 Unity IL2CPP,因此逻辑存在于编译后的 ARM 库 libil2cpp.so 中,而不是可编辑的脚本文件中。patches/patch_il2cpp.py 重写了该库中的六个函数以绕过已关闭的服务器检查:它击败了两条证书锁定路径,以便我们自己的 TLS 证书被接受;强制运行管理器注册块,即使实时配置为空;允许使用我们的本地设备会话登录成功;并抑制了否则会弹出“登录失败”对话框的子系统致命错误。它还会重新注入一个依赖项条目(请参阅陷阱部分),以便运行时挂钩实际上能够加载。输出为 libil2cpp.patched.so。
一个伪造的 Sparx 服务器。server/fakeserver.py 代替 Kabam 的后端。它在 TLS 443 和普通 HTTP 80 端口上监听,并回答游戏的 API 调用。预设响应位于 server/responses/ 中,每个端点一个文件,按方法和路径命名,例如 GET__account_data.json。少数端点在代码中动态回答,而不是从文件中读取,因为游戏期望它们回显请求中的值(教程端点和英雄详细信息端点)。响应结构为 {"error":null,"result": ...}。请注意,在 Sparx 错误负载中,该字段拼写为 err,而不是 error。这个细节很重要,而且很容易被忽略。
一个原生运行时挂钩。tools/nativehook/ 构建 libdothook.so,这是一个小型库,在游戏启动时加载,记录游戏读取的每个数据键,以及一些有针对性的行为调整。这是使其他一切成为可能的反馈循环:它准确地告诉你游戏在请求什么,这样你就可以合成一个响应并进行验证。这是一个纯字节覆盖内联挂钩,在执行前安装,因为用于此的正常工具(Frida)在模拟器的 ARM 转换层下会崩溃。
设备连接。模拟器必须将 Kabam 的域名发送到 PC,并信任伪造的证书。tools/provision_ldplayer.sh 一键完成此操作:它推送修补后的库和挂钩,通过 hosts 文件将 Kabam 主机名重定向到 PC 的 LAN 地址,将伪造的 CA 挂载到系统信任存储,并放宽 SELinux。每次模拟器重启后运行它,因为这些挂载在重启后不会保留。
运行时的数据流是:游戏向 Kabam 域名发起 HTTPS 调用,hosts 文件将其发送到 PC,伪造的服务器用 server/responses/ 中的响应回答,修补后的库接受证书和答案,挂钩记录读取的内容。这就是此版本中每个屏幕被唤醒的循环。
README.md 本文件
TECHNICAL_NOTES.md 更深入的技术参考:补丁、恢复的数据结构、发现
patches/
patch_il2cpp.py 六个原生补丁加上依赖项重新注入
disasm_fn.py 辅助工具:在偏移量处反汇编函数
find_callers.py 辅助工具:查找函数的调用者
find_str_ref.py 辅助工具:查找字符串的引用
server/
fakeserver.py 伪造的 Sparx 服务器
gen_certs.sh 重新生成 TLS 证书和 CA(运行此脚本,见下文)
setup_device.sh 设备端网络和信任设置参考
iterate.sh 快速重启和捕获循环
responses/ 每个游戏调用的端点一个 JSON 文件
tools/
provision_ldplayer.sh 将模拟器一键重新配置为工作状态
setup_arm64.sh 工具链设置笔记
decompile_targets.py 在选定偏移量处驱动 Ghidra 无头反编译器
find_xrefs.py 在二进制文件中进行交叉引用搜索
apply_labels.py 应用 IL2CPP 符号标签
light_analyze.py 轻量级静态分析辅助工具
frida_attach.py Frida 辅助工具(保留供参考,请参见 libnb 说明)
frida_run.py
hook_dot.js
nativehook/
hook.c libdothook.so 的源代码,即运行时挂钩
libdothook.so 预构建的挂钩,arm64
deploy.sh 构建和部署挂钩
relaunch_and_capture.sh 重新启动游戏并捕获日志
hook/dothook.c 较早的挂钩变体,保留供参考
re_notes/
dump.cs 完整的 IL2CPP 转储:游戏中每个类、方法和字段
decomp_out.c 关键函数的反编译体
decompile_targets.txt 值得反编译的偏移量
ASSET_INVENTORY.txt 已随应用程序打包的美术和音频列表
re_notes/dump.cs 是剩余工作中最有价值的文件。它是游戏的完整类型模型:每个类、每个方法,以及至关重要的客户端从服务器读取的每个数据字段。它是你整个后端 API 的地图。当你需要知道响应应该是什么结构时,答案就在那里。
这些是故意省略的,因为它们很大、或受版权保护、或保密,或者你应该自己生成。
com.kabam.bigrobot,版本 9.2.0)。大约 800 MB。请自己寻找副本。包名和版本在 TECHNICAL_NOTES.md 中。libil2cpp.so 和游戏资源。两者都直接来自 APK。解压 APK,库位于 lib/arm64-v8a/ 下,资源位于 assets/ 下。server/gen_certs.sh 生成你自己的匹配对,然后将设备信任存储指向新的 CA。libil2cpp.so 运行 patches/patch_il2cpp.py。re_notes/dump.cs。你需要在支持 ARM 转换的模拟器(使用了 LDPlayer 9,需 root 和可写系统)上安装 APK,PC 上安装 Python,以及上述章节中的项目。
bash server/gen_certs.sh。python patches/patch_il2cpp.py path/to/original/libil2cpp.so --apply。tools/nativehook/deploy.sh。python server/fakeserver.py。它需要能在端口 443 和 80 上被模拟器访问。bash tools/provision_ldplayer.sh <your-PC-LAN-IP>。每次模拟器重启后重新运行此命令。如果登录时卡住,首先检查陷阱部分的第一项。
以下这些让我花费了数小时。它们被记录下来,以免你重蹈覆辙。
libdothook.so。确切的字节和偏移量记录在修补脚本和 TECHNICAL_NOTES.md 中。provision_ldplayer.sh,否则什么都无法连接。err,而不是 error。使用错误的字段会导致客户端静默忽略或错误处理响应。这是真正的工作,而且规模巨大。以下是其大致情况以及从哪里开始。
目标是手动重新创建曾经流式传输到客户端的服务器端内容:任务和关卡、地图及其敌人阵容、包含每个机器人属性和能力的完整阵容、战斗公式和经济。这些现在都不存在了,所以所有这些都必须以客户端期望的确切结构从头编写。
有效的方法是本项目所围绕的循环。运行带有挂钩的游戏。挂钩记录客户端读取的每个键。当客户端请求你未提供的内容时,你就能准确地看到它想要什么。然后你以正确的结构合成一个响应,将其放入 server/responses/ 或添加到 fakeserver.py 的动态处理程序中,重新启动,并验证客户端接受它并继续前进。重复。当前版本中的每个屏幕都是通过这种方式唤醒的。re_notes/dump.cs 甚至在你运行之前就告诉你每个结构的形状,因为它列出了客户端读取的每个字段。
一个合理的攻击顺序:
decompile_targets.py)并读出确切的字段。ASSET_INVENTORY.txt 中列出的资源包中,因此你只需编写数值和能力定义,而不是资源。TECHNICAL_NOTES.md 中的键。现实地看待规模。即使对于粉丝在关闭前保存了实时服务器数据的游戏,搭建一个私人服务器也是一个长期项目。这里没有保存的数据可供开始,因此每个数值和每种能力都必须进行研究或重新发明,然后针对客户端进行验证。如果目标是真正的游戏,这需要多人多年的努力。话虽如此,路径已不再是谜。启动问题已解决,反馈循环已存在,类型模型已转储,资源完好无损。剩下的只是大量的、细致的数据重建工作,而不是对未知的进一步逆向工程。
从 TECHNICAL_NOTES.md 开始。它是更深入的技术参考,包含确切的补丁、恢复的数据结构和具体的发现,比本 README 更详细。然后运行循环。
祝你好运。现在它是一台真正的机器了。只需要重建其内容。