← 返回总索引道具遍历基址 · 二进制验证报告 2026-09-16-13-19-49\道具遍历基址_验证报告.md
分类:内存逆向与基址定位来源会话:2026-09-16原件:2026-09-16-13-19-49\道具遍历基址_验证报告.md

道具遍历基址 —— 二进制验证报告

游戏客户端:D:\rxjh2025\client\YGOnline.exe(32 位,ImageBase = 0x400000)
验证方式:Python 解析 PE + capstone 反汇编 基址更新 子程序里 道具遍历基址 特征命中点及其调用函数。


一、结论(一句话)

道具遍历基址 是「地面/掉落物品」的世界对象容器(global container),不是背包物品、也不是副本道具。

也就是说:这个基址遍历的是躺在地上、可被拾取的世界物品(掉落物 / 场景道具),和「背包里的物品(背包基址值 0x03B9DCE0)」「副本里的道具(副本道具基址 0x9539F5)」是三套完全不同的数据


二、特征命中确认

基址更新 里特征:

8B 95 E0 7F FF FF 83 C2 01 89 95 E0 7F FF FF 81 BD E0 7F FF FF 00 19 00 00

三、反汇编证据(这是关键)

3.1 主循环(VA 0x768D22 附近)

0x768D16  mov dword ptr [ebp-0x8020], 0          ; i = 0
0x768D22  mov edx, [ebp-0x8020]                  ; —— 特征起点 ——
0x768D28  add edx, 1
0x768D2B  mov [ebp-0x8020], edx
0x768D31  cmp [ebp-0x8020], 0x1900               ; i < 6400 ?
0x768D3B  jge 0x76914c                          ; 退出

0x768D41  mov eax, [ebp-0x8020]                  ; i
0x768D47  push eax
0x768D48  mov ecx, 0x1801170                    ; —— 容器 this ——
0x768D4D  call 0x769ba0                         ; GetAt(i)
0x768D52  mov [ebp-0x8018], eax                 ; element = 指针

0x768D63  mov ecx, [ebp-0x8018]
0x768D69  cmp dword ptr [ecx+8], 0x3a98         ; element+8 < 15000 ?
0x768D72  cmp dword ptr [edx+8], 0              ; element+8 >= 0 ?
0x768D80  mov ecx, [eax+8]
0x768D89  cmp dword ptr [ecx*4 + 0x3be3e68], 0   ; ★ 怪物基址数组(0x03BE3E68)该索引处非 NULL?
0x768D9D  cmp dword ptr [edx+0x10], 0           ; element+0x10 必须 != 0(有效性)
0x768DA7  mov ecx, [eax]                         ; element+0
0x768DAF  cmp ecx, [0x1801104]                   ; ★ 与“当前目标实体”比较

要点:
- 循环上限 0x1900 = 6400
- element+8 被直接用作怪物基址数组 0x03BE3E68 的下标[ecx*4 + 0x3be3e68])—— 说明每件地上物品都绑定一个实体(怪/NPC)
- element+0 与全局 [0x1801104](当前选中/目标实体)比较;相等时走“邻近拾取”分支(计算坐标 = [0x1801108]+0xC8 附近)
- 还访问全局位域 [ecx + 0x17eb718] & 0x80ecx=element+0)—— 这是“对象是否存活/激活”的位表,证明 element+0 是对象 id

3.2 GetAt(i)(VA 0x769BA0)—— 确认是「指针数组」

0x769BA0  push ebp
0x769BA4  mov [ebp-4], ecx                       ; this = 0x1801170
0x769BA7  cmp [ebp+8], 0
0x769BAB  jge 0x769bba
0x769BAD  cmp [ebp+8], 0x1900                   ; 越界检查同样 6400
0x769BBA  mov eax, [ebp+8]                       ; i
0x769BBD  mov ecx, [ebp-4]                       ; this
0x769BC0  mov eax, [ecx + eax*4 + 4]            ; return *(this+4 + i*4)

→ 容器布局:this+0 = 未知(vtable/计数),this+4 = 指向 6400 个指针的数组
元素 stride = 4 字节(指针),不是扁平结构体数组;元素本身是堆上的结构(指针)。

3.3 元素结构字段(从循环读出,已观察到的部分)

偏移 含义 证据
+0x00 对象 id / 类型(取值 0x78/0x79/0x80/0x81/0x82…) 多处 cmp [ecx], 0x78…;与 [0x1801104] 比较
+0x08 怪物基址数组下标(指向 0x03BE3E68 实体) cmp [ecx*4 + 0x3be3e68], 0
+0x0C 处理/占用标志(0/1 来回置) mov [ecx+0xc], 1 / cmp [eax+0xc], 0
+0x10 有效性标志(必须 != 0) cmp [edx+0x10], 0

类型字段 +0 的 5 个取值(0x78/0x79/0x80/0x81/0x82)决定后续调用 0xddce90 时用参数 7 还是 3(不同拾取/交互动作 id),属对象子类型区分。


四、与另外两套「物品」数据的区分

基址 运行时值 是什么 数据结构
道具遍历基址 0x1801170(容器) 地上掉落物 / 场景物品(世界对象) 6400 槽指针数组,元素绑定怪物基址数组下标
背包列表基址 / 背包基址值 0x03B9DCE0 玩家背包物品(在身) 遍历背包 用的大结构(+0x64 名称/+0x54 编号/+0xD4C 数量…)
副本道具基址 0x9539F5 副本内道具 另一套(与 NPC/副本 CALL 同源 0x952DC8)

三套互不相干,偏移不能混用。


五、易语言读取配方(给你游戏内验证)

' 道具遍历基址 已确认 = 0x1801170(模块基址 0x400000 时)
' 直接读容器首指针,再按 6400 槽遍历
数组指针 = 内存_读整数型 (窗口句柄, 道具遍历基址 + 4)   ' *(this+4) -> 指针数组
.计次循环首 (6400, i)
    元素指针 = 内存_读整数型 (窗口句柄, 数组指针 + (i - 1) × 4)
    .如果 (元素指针 = 0)
        到循环尾 ()
    .如果结束
    类型ID   = 内存_读整数型 (窗口句柄, 元素指针 + 0)    ' +0
    实体下标 = 内存_读整数型 (窗口句柄, 元素指针 + 8)    ' +8 -> 怪物基址数组下标
    处理标志 = 内存_读整数型 (窗口句柄, 元素指针 + 0x0C) ' +0xC
    有效标志 = 内存_读整数型 (窗口句柄, 元素指针 + 0x10) ' +0x10
    写日志 (“槽” + 到文本 (i) + “ 类型=” + 到文本 (类型ID) + “ 实体下标=” + 到文本 (实体下标))
.计次循环尾

提醒:元素首指针(堆对象)后面字段可能还有名字/物品模板 id,但本循环没读到名字字符串——名字可能要走「物品模板表(按类型ID查)」。若你要读物品名字/编号,告诉我,我再去反查 0xddce90 调用链或模板表基址。


六、一句话总结

道具遍历基址 验证为 地面掉落物/场景物品的世界对象容器(0x1801170,6400 槽指针数组),每件物品用 +0x8 绑定到怪物基址数组 0x03BE3E68 的某个实体。它不是背包物品,也不是副本道具—— 你的 遍历背包 那套大结构(0x03B9DCE0)对此不适用。