Files
IC.Rebuild/diagnostics/2026-10-11-network-full-capture.md

4.7 KiB
Raw Permalink Blame History

0.1.8 完整游戏载荷采集

基线:国际服 2026.09.15.0000.0000,本机 ffxiv_dx11.exe;实现限定此完整版本。前期线索见 network-length-research.md。本次原生检查只读磁盘文件,不调用原生函数;现场验收尚未完成。

上行证据

上行签名唯一匹配 RVA 0x1D718C0,ABI 为 byte(connection, data, arg, byte flag)。data 是发送对象,Opcode 在 +0,消息长度为 +8 的 uint64,业务载荷在 +0x20。

  • 0x1D7198C:从 [rsi+8] 取长度,源指针 rsi+0x20,长度减 0x10,调用 0x1DA6CB0。
  • 0x1D71A84:另一分支执行相同的复制区间。
  • 0x1DA6CB0:按 r8 长度分派复制;0x1DA6DD0 的 16—32 字节分支从 rdx、rdx+r8-0x10 读取并写入 rcx、rcx+r8-0x10,确认其复制含义。
  • 0x1CFD1D0 的发送对象创建例:Opcode 在对象 +0,uint64 长度 0x18 在 +8,经 ZoneClient.SendPacket(0x1D03040)进入上述函数。复制的业务长度为 8。

采集发生在发送原函数之前,只表示进入发送路径,不代表发送成功或服务端接收。

下行证据与有效期

调用链:NetworkModule 0x1D02040 → ZoneClient.ReceivePacket 0x1D03020 → ZoneReceive 0x1D71440。后者 ABI 为 byte(connection, holder),返回值非零表示接收成功。

  • 0x1D71464—0x1D71468:将消息对象写入 holder+0x10。
  • 0x1D714D7—0x1D714E0:从 holder+0x10 取对象,再从对象+0x38 取 IPC 缓冲区。
  • 对象+0x30 为 uint64 消息长度。接收构造路径 0x1D68875—0x1D6889E 从外层消息长度减去 0x10,按此大小复制到对象+0x38,并将相同大小写入对象+0x30。它包含 0x10 字节 IPC 头。
  • 0x20EF800 读取缓冲区+2 的 Opcode,其各分支从缓冲区+0x10 取得业务载荷。
  • NetworkModule 0x1D021AD 从对象+0x20 取得目标标识;保留位范围按原函数标准化,不能把对象+0x24 的其他值擅自标为 Source。
  • 0x1D02203—0x1D02220 将 IPC 缓冲区交给 Application 接收回调;0x482440 转发到 PacketDispatcher 0x18D9500。
  • 0x1D02366—0x1D02370 在分派后释放消息,下一次接收前清空 holder+0x10。Hook 在接收原函数成功返回后立即复制,尚未返回给上述调用者,不保存原生指针供后台使用。

下行签名的栈保存偏移 0x18 必须保留。将其通配后同时匹配 0x1D20BF0(另一接收入口)和 0x1D71440。最终完整签名在当前文件仅匹配一次:

48 89 5C 24 18 57 48 83 EC 20 48 83 B9 88 00 00 00 00 48 8B FA 48 8B D9

下行不再挂接 PacketDispatcher,不重复记录同一包,也不从 IPC 指针之前猜读外层头部。

读取与失败行为

  • 使用 Dalamud.SafeMemory.ReadBytes(当前进程 ReadProcessMemory)复制;没有使用旧结构大小推断原始指针长度。
  • 先验证指针、头部读取和 uint64 长度,长度减 0x10 前检查下限及上限,单载荷最多 65536 字节。
  • 完整读取才标记 PayloadComplete=true;确实零字节的合法载荷可以完整,不等于失败。
  • 已有 Opcode 的异常长度、截断或复制失败保留仅元数据及 CaptureIssue;头部/对象失败不能可靠获得 Opcode,记录异常计数及最近原因,不伪造包。
  • 暂停或方向过滤可避免读取对象,Opcode 过滤在读取载荷之前执行。
  • 两个原函数都保持一次调用及原参数/返回值;发送在采集后调用,接收先调用再读取成功结果。采集托管异常不会替代游戏原函数结果。
  • 记录通过复制成为托管数组;缓冲区按 2048 条和 8 MiB 载荷双重限制,淘汰最旧记录。后台保存只使用这些副本。
  • 只覆盖当前版本 Zone 通道。聊天、登录和录像回放通道未挂接。上行 Source/Target、下行 Source 没有足够依据,保持 null。

结果与测试

Release 构建通过,0 警告、0 错误;57 项离线测试通过。新增模拟有界内存场景覆盖精确复制区间、对象引用链、目标标准化、恶意 uint64 长度、截断/部分读取、空载荷、64 KiB 上限、无效指针、过滤、错误原因导入导出和缓冲字节预算。

一次新增导出测试使用系统临时目录时受到沙箱文件移动限制;已改为与既有测试一致的测试输出目录,完整构建和测试重跑通过。此修正没有放宽插件文件路径或权限策略。

现场验证:重新加载 0.1.8,开启 36、37,方向全部、Opcode -1;正常移动、使用技能 20—30 秒。观察完整上下行计数是否增长、异常是否出现,再 /icr export capture-018.jsonl 并关闭 36。以导出样本核验真实载荷和已有解析,之后再扩展 37。

本版完成采集代码接入与离线边界验证,不把 36 标为游戏内已验证,也不据此宣称 37 的历史解析全部正确。