Files
IC.Rebuild/diagnostics/2026-10-12-protocol-stage2.md
T

7.1 KiB
Raw Permalink Blame History

2026-10-12 阶段 2(0.1.14)协议补全、事件包分层与动作回包关联审计报告

  • 审计日期:2026-10-12
  • 目标二进制:E:\SteamLibrary\steamapps\common\FINAL FANTASY XIV Online\game\ffxiv_dx11.exe
  • 客户端版本:2026.09.15.0000.0000
  • 二进制 SHA256:5BBC501DD5C7F22FD61A11D08C25356041D878DB7CD83203ADAE393E4DFACC44
  • 样本文件:capture-018.jsonl(SHA256 407B6933E0886AA567C7A585B2732BA8064DC5B731987EB3744F14F4296AF639,891 条完整记录)
  • 映射缓存:opcodes.json(SHA256 6B40585D43CC83C31EC16A8DD9CF2B3008D3084752472BD5E89B4D20C6C14F7E)
  • 离线回放报告:diagnostics/2026-10-12-capture-018-v0114.json

1. 上行构造与发送包装层核实

1.1 原生发送结构体与包装函数(为阶段 3 M4 预备证据)

  • ZoneClient.SendPacket:0x1D03040(内部转调 ZoneUp 0x1D718C0)。
  • NetworkModuleProxy 发送包装层:0x1CFD090、0x1CFD140(由 0x4810E0 调用)、0x1CFD170(由 0x481100 调用)、0x1CFD1A0(由 0x4810C0 调用)。
  • 原生发送结构体(rdx):+0x00 uint Opcode、+0x08 ulong TotalSizeWithHeader(等于 payloadLength + 0x10)、+0x20 byte[] Payload。

1.2 UP_ActionSend(913 / 0x391,载荷 32 字节)與 UP_ActionSendPos(891 / 0x37B,载荷 24 字节)

  • 构造调用链:0x8E21A3 → 0xB36F50(UP_ActionSend,总长 0x30 = 载荷 0x20);0x8E2255 → 0xB37050(UP_ActionSendPos,总长 0x28 = 载荷 0x18,旧版 UpPacketStructs.cs 记为 0x20 已过期)。
  • 共用头部(+0x00..+0x0B):
    • +0x00 uint ActionId
    • +0x04 byte CastBuff
    • +0x05 byte ActionKind
    • +0x06 ushort RequestId(样本 27 条递增为 179..205)
    • +0x08 ushort Facing
    • +0x0A ushort TargetFacing
  • UP_ActionSend 尾部:+0x10 ulong TargetId、+0x18 uint Arg(共 32B)。
  • UP_ActionSendPos 尾部:+0x0C float X、+0x10 float Y、+0x14 float Z(共 24B,校验有限浮点数)。

1.3 UP_ClientTrigger(391 / 0x187,载荷 32 字节)

  • 构造器:0xB352F0、0xB353B0、0xB35550(总长 0x30 = 载荷 0x20)。
  • 载荷布局:+0x00 uint CommandId、+0x04..+0x10 uint Arg0..Arg3、+0x18 ulong TargetId。

1.4 P2 变长事件包冲突解决(UP_EventFinish* 与 UP_EventAction*)

  • 旧版 UpPacketStructs.cs 将 UP_EventFinish 与 UP_EventAction 写成单一固定长度结构,与在线 opcodes.json 的变长后缀表冲突。
  • 原生反汇编确认客户端按 ArgCount(r9b)分成 8 档固定长度 Opcode 发送:
    • UP_EventFinish*(0xB32C5C..0xB33022):UP_EventFinish(982,cap=2,16B)、4(607,24B)、8(516,40B)、16(856,72B)、32(283,136B)、64(787,264B)、128(779,520B)、255(658,1032B,含 4B 对齐尾填充)。
    • UP_EventAction*(0xB33050..0xB333DA):UP_EventAction(140,cap=2,16B)、4(778,24B)、8(938,40B)、16(957,72B)、32(637,136B)、64(988,264B)、128(703,520B)、255(705,1032B)。
  • 共用 8 字节头部:+0x00 uint EventId、+0x04 ushort SceneId、+0x06 byte State、+0x07 byte ArgCount(校验 ArgCount <= capacity),+0x08 起为 uint Args[capacity]。

2. 下行 PacketDispatcher(0x18D9500,跳表 0x18DD980)核实

名称 Opcode 长度 跳表入口与消费函数 已核实字段与旧版差异
DOWN_ActorControl 607 (0x25F) 24B (0x18) 预处理 0x18DA1EC;跳表 0x18DAABB → 0x18DAB03 → 0xB3A350 +0x00 ushort Category,+0x04..+0x10 uint Arg0..Arg3。当 Category == 0x22 时,采集发生在 0x18DA1EC 减去会话值 esi 之前
DOWN_ActorControlSelf 516 (0x204) 40B (0x28) 跳表 0x18DAB9E → 0x18DABE6 → 0xB3A350 +0x00 ushort Category,+0x04..+0x20 uint Arg0..Arg7(旧版 32B 仅 6 个参数,现为 8 个 uint)
DOWN_ActorControlTarget 856 (0x358) 32B (0x20) 跳表 0x18DAB4D → 0x18DAB95 → 0xB3A350 +0x00 ushort Category,+0x04..+0x10 uint Arg0..Arg3,+0x18 ulong TargetId
DOWN_Effect 787 (0x313) 124B (0x7C) 预处理 0x18DA4CC;跳表 0x18DA9C6 → 0xB3A0F0 → 0x902C20 旧版 120B 已变为 124B。+0x08 uint RawActionId(采集时含会话偏移 esi),+0x0C uint Sequence,+0x10 float LockTime(有限数),+0x18 ushort RequestId,+0x1C ushort AnimationId,+0x1F byte ActionKind,+0x21 byte TargetCount(<=1),+0x70 ulong TargetId
DOWN_EffectResult 305 (0x131) 96B (0x60) 跳表 0x18DAF52 → 0xB38CA0 → 0x8A6BF0 +0x00 byte Count(<=1),+0x04 uint Sequence,+0x0C uint CurrentHp,+0x10 uint MaxHp,+0x14 ushort Mp,+0x16 byte TargetIndex,+0x17 byte ClassJob,+0x18 byte Shield,+0x19 byte StatusCount(<=4),+0x1C 起 4×16B 状态项(内部调用 StatusManager.SetStatus 0x8A6BF0)
DOWN_StatusEffectList 131 (0x83) 384B (0x180) 预处理 0x18D97FC;跳表 0x18DAE4B → 0xB385F0 → 0x8A78F0 +0x00 byte ClassJob,+0x01 byte Level,+0x04 uint CurrentHp,+0x08 uint MaxHp,+0x0C ushort Resource,+0x0E ushort MaxResource,+0x10 byte Shield,+0x14 起 30×12B 状态槽(采集时 +0x00 ushort RawStatusId 尚未减去 si,+0x04 float Timer 校验有限数)
DOWN_ActorDelete 974 (0x3CE) 8B (0x08) 跳表 0x18DA75C → 0xB37C00 +0x00 byte ObjectIndex
DOWN_ObjectSpawn 238 (0xEE) 64B (0x40) 跳表 0x18DAD80 → 0xB4ADA0 (0xB4B057) +0x00 byte ObjectIndex,+0x01 byte Kind,+0x04 uint BaseId,+0x08 uint EntityId,+0x1C float Scale,+0x34 float X, +0x38 float Y, +0x3C float Z(旧版坐标偏移 0x30 错误)
DOWN_NpcSpawn 524 (0x20C) 656B (0x290) 跳表 0x18DA6FA → 0xB37A10 → 0x8CF750(rsi = payload + 0x10) +0x40 uint BaseId,+0x54 uint OwnerId,+0x5C uint MaxHp,+0x60 uint CurrentHp(旧版 HP 颠倒且 OwnerId 偏移错),+0x7E byte ObjectIndex,+0x81 byte ObjectKind,+0x82 byte SubKind,+0x86 byte Level,+0x87 byte ClassJob,+0x200 float X, +0x204 float Y, +0x208 float Z

3. 动作发包与下行效果关联(PacketCorrelator.Actions)

  • 关联依据:UP_ActionSend(32B)与 UP_ActionSendPos(24B)在 +0x06 写入递增非零 ushort RequestId;服务端返回的本地动作确认 DOWN_Effect(124B)在 +0x18 回传同一 ushort RequestId(其他角色/NPC 的 DOWN_Effect 该字段为 0)。
  • 样本验证:capture-018.jsonl 中 27 条 UP_ActionSend(RequestId = 179..205)与 27 条 DOWN_Effect(RequestId = 179..205)100% 一一配对,往返耗时 68.5 ms .. 138.3 ms。

4. capture-018.jsonl 回放复核结果

  • Records = 891(上行 534,下行 357)
  • Complete = 891,Known = 891
  • Parsed = 891(由 0.1.13 的 679 提升至 891,覆盖率 100%)
  • SupportedButRejected = 0
  • PingPairs = 8,ActionPairs = 27