修复缺失的 AOB(进阶详解)

修复缺失的 AOB(进阶详解)

如果 UE4SS 因缺失 AOB(Array of Bytes,即字节数组签名)而无法正常启动,可以使用 Lua 提供自定义 AOB 和回调函数。不过,这需要一定的逆向工程知识和工具配置,初次接触时可能会觉得复杂。本指南在基础说明之上补充了细节、背景和技巧。

先决条件

  • 了解逆向工程基础概念: 大致了解签名(AOB)的含义、调试器的用法,以及如何在 x64dbg 中浏览内存。
  • 熟悉 UE4SS 的安装和目录: 确认应该在何处创建 UE4SS_Signatures 文件夹(应与 ue4ss.dll 同级,或位于游戏专属工作目录中)。
  • 准备并安装工具:
    • Epic Games Launcher 与 Unreal Engine: 用于建立引擎版本正确的“空白 Shipping 游戏”参考环境。
    • x64dbg: Windows 调试器(https://x64dbg.com/)。
    • (可选)Baymax Tools: 帮助轻松生成签名的插件。
    • (可选)Swiss Army Knife(Nukem9 开发): 便于提取通配符设置正确的签名。

什么时候需要这样做,为什么

有些游戏没有使用 Unreal Engine 的默认配置,而 UE4SS 开箱即用支持的只有默认配置。任何影响编译器生成代码的因素,包括开发者使用 Clang 而非 MSVC,都可能使内置 AOB 失效。UE4SS 依靠这些 AOB 查找正常工作所必需的函数和变量。

流程概览

  1. 确定缺失的签名: 查明 UE4SS 找不到哪些函数或变量,例如 GUObjectArray、GMalloc、FName。
  2. 建立参考环境: 使用与目标游戏相同的 Unreal Engine 版本创建空白游戏,以 Shipping 目标构建并保留调试文件(PDB),便于清楚地识别函数签名。
  3. 逆向并提取 AOB: 用 x64dbg(可配合插件)打开空白游戏,在内存中定位所需函数,复制能够构成可靠签名的独特字节。必须正确设置通配符,否则无法在目标游戏中匹配。
  4. 将签名用于实际游戏: 将 x64dbg 附加到目标游戏,查找匹配字节,确认提取的签名能够匹配要制作 Mod 的游戏代码。
  5. 创建 Lua 脚本: 在 UE4SS_Signatures 中编写 Lua 文件,通过 Register 告诉 UE4SS 搜索什么 AOB,通过 OnMatchFound 指定最终返回哪个地址。

查找 AOB:详细说明

[!CAUTION] 逆向这些签名并不简单。可能需要阅读本指南范围之外的逆向教程,或寻求社区支持。以下步骤只是起点,并非完整的逆向工程教程。

第 1 步:确定游戏的 Unreal Engine 版本

UE4SS 会尝试自动检测引擎版本。若需要核实,以下方法通常有效:

  • 右键点击游戏的 .exe 文件(通常在 Binaries 文件夹中)。
  • 选择“属性”(Properties)→“详细信息”(Details)。
  • 查找“文件版本”(File Version)或“产品版本”(Product Version),它们通常与 Unreal Engine 版本有关。

例如,如果显示 5.3.2.0,很可能对应 UE 5.3.2。少数情况下,版本可能为空,或显示的是游戏版本而非引擎版本。通常最后的补丁版本号并不关键,因此游戏使用 UE 5.3.2 时,空白游戏一般可以使用任何 5.3 版本。

第 2 步:安装匹配的 Unreal Engine 版本

  • 创建 Epic Games 账号并安装 Epic Games Launcher。
  • 在启动器中进入 Unreal Engine → Library 页签,安装与游戏匹配的引擎版本,例如 UE 5.3.2。

第 3 步:创建带 PDB 的空白 Shipping 游戏

  1. 启动已安装的 Unreal Engine 版本。
  2. 在新建项目窗口选择 Games → Blank 模板。
    • 取消勾选 Starter Content,因为不需要它,也可节省时间和空间。
    • 为项目命名并指定目录。
  3. 项目创建后,打开 Platforms → Packaging Settings,启用 Include Debug Files in Shipping Builds。
  4. 从 Platforms → Windows 选择 Shipping 配置(或与目标游戏构建类型相同的配置)。
  5. 选择 Package Project,再选择输出文件夹。
  6. 打包完成后,确认输出文件夹的 Binaries 目录同时包含 .exe 和 .pdb。.pdb 提供逆向分析所需的符号信息。

第 4 步:用 x64dbg 分析空白项目

  1. 从 https://x64dbg.com/ 安装 x64dbg。
  2. 从根目录运行刚打包好的空白项目 .exe。
  3. 打开 x64dbg。
    • 选择 File → Attach,选中空白项目的 .exe。
    • 确保附加的是打包后的 .exe;根据实际情况,可能位于 Binaries 或根目录。

第 5 步:确定要查找的函数

必须明确希望在目标游戏中匹配哪个函数或变量。例如,如果 UE4SS 在查找 GMalloc 时失败,需要先找到 FMemory::Free,再以它为参考定位 GMalloc。

可选步骤:

  • 将 Epic Games 账号与 GitHub 关联,以访问 Unreal Engine 源码。
    • Epic Games 网站 → Manage Account → Apps and Accounts → GitHub。
    • 通过邮件接受邀请。
  • 在 Unreal Engine 源码中查找所需函数。以 UE5.3.2 的 FMemory::Free 为例,可查看:

第 6 步:在 x64dbg 中定位函数

注意,x64dbg 存在一个问题:有时从 Symbols 页签跳转到代码或内存时无法正常工作。如果跳转后看到的内容不符合预期,可以重启 x64dbg 再试。也可以从 Symbols 页签复制地址,再在 CPU 页签的正确面板中手动跳转。

  1. 在 x64dbg 中切换到 Symbols 页签。
  2. 在左侧面板选中 .exe。
  3. 在右侧面板搜索函数名称,例如 FMemory::Free。
  4. 双击找到的函数,返回 CPU 视图,定位到内存中该函数的开头。

第 7 步:提取签名

确定函数开头后,需要复制一段独特的字节序列:

  1. 可以为 x64dbg 安装 Baymax Tools 或 Swiss Army Knife,以简化签名提取。
  2. 选中函数开头的一组指令。
    • 右键 → Copy → Selection (Bytes only),取得原始字节序列。
    • 使用 Baymax Tools 时:右键 → Baymax Tools → Copy Signature,直接取得签名模式。
  3. 保存字节或模式,供后续比对。可以写入文件以便随时查阅。

术语说明

  • 签名(Signature): 精心选择的字节序列,用于唯一识别某个函数或代码片段。
  • 字节块(Block of Bytes): 一段简单的原始数据,可能没有特定结构,也不天然具有唯一性。
  • RIP(指令指针): 保存下一条待执行指令地址的 CPU 寄存器。

第 8 步:在实际目标游戏中搜索

得到参考签名后,需要在目标游戏中找到它:

  1. 启动目标游戏 .exe。
  2. 与前面一样附加 x64dbg:File → Attach → 选择游戏 .exe。
  3. 在 x64dbg 中搜索从空白项目提取的签名。
    • 如果直接搜索失败,尝试搜索其中一部分字节。
    • 尝试 Baymax Tools 生成的模式。
    • 对比空白项目和实际游戏的指令,定位相似代码区域。

找到匹配项后,就确定了实际游戏中目标函数或变量对应的地址。如果无法找到,可能需要改进签名、选择函数的其他部分,或向社区求助(UE4SS Discord 或 GitHub Issues)。

第 9 步:在 UE4SS 中应用签名

得到可用 AOB 后:

  1. 如果工作目录中尚未存在 UE4SS_Signatures,创建该目录。
  2. 为缺失的 AOB 创建对应 .lua 文件,例如修复 GMalloc 时创建 GMalloc.lua。
  3. 在该文件中定义 Register 和 OnMatchFound。

Register 函数: 将 AOB 签名作为字符串返回,空格可选。例如:

function Register()
    return "48 8B D9 48 8B 0D ?? ?? ?? ?? 48 85 C9 75 0C E8 ?? ?? ?? ??"
end

OnMatchFound 函数: 接收匹配地址,并且必须返回目标函数或变量的准确内存地址。需要时使用 DerefToInt32 解析相对地址。

function OnMatchFound(MatchAddress)
    local MovInstr = MatchAddress + 0x03
    local Offset = DerefToInt32(MovInstr + 0x3)
    local RIP = MovInstr + 0x7
    local GMallocAddress = RIP + Offset
    return GMallocAddress
end

验证结果

  • 再次通过 UE4SS 运行游戏。如果成功,UE4SS 将使用自定义脚本找到此前缺失的地址。
  • 如果仍然失败且没有明显提示,请确认:
    • Lua 脚本位于正确目录。
    • AOB 正确且唯一。
    • OnMatchFound 返回正确的最终地址。

如果仍无法解决,可以在 UE4SS 社区渠道提供详细步骤、日志和代码片段。细节越充分,其他人越容易帮助你找到解决方案。

OnMatchFound 的返回内容与示例脚本

参阅基础指南。

技巧与故障排查

  • 耐心与反复尝试: 提取、改进 AOB 可能需要试错。签名不起作用时,可以尝试另一段字节,或检查函数的其他位置。
  • 局部签名: 找不到完整函数签名时,可以尝试其中具有唯一性的部分。
  • 社区帮助: 遇到困难时,在 UE4SS Discord 或 GitHub Issues 展示步骤、脚本和日志。
  • 仔细检查偏移: 差一字节或索引错误很常见,应反复核对计算。
  • 手动验证: 有时在 x64dbg 中重新运行空白项目,并与目标游戏内存比对,就能发现差异。

按照以上扩展步骤并使用所述工具,可以更全面地理解如何修复 UE4SS 缺失的 AOB。虽然过程仍然复杂,但本指南应能帮助理清流程,并提供逆向分析的实用思路。


原文:docs/guides/fixing-compatibility-problems-advanced.md · 固定提交 560411f18512 · 来源与 MIT 许可