# 基址活体验证清单(CE 挂游戏逐条读值) > **用途**:静态复验只能证明「代码在用这个地址」,**不能证明「运行时地址里存的指针指向的对象是对的」**。 > 本清单用于 CE 挂上 `YGOnline.exe` 后逐条读值,把静态结论落到活体上。 > **前置**:① 游戏已启动并**进入游戏内**(标题界面不行,助手窗口要已创建)② CE 已附加 `YGOnline.exe` ③ MCP 桥接 Lua 已 Execute --- ## 为什么必须做这一步 `.data` 节区 VA 范围 `0x011E0000`,VirtualSize `0x4A377A8`,但**文件原始大小只有 `0x1F800`** —— 也就是说 99.6% 的全局变量在 exe 文件里**没有初值**,全部是运行时才写入的。静态扫描只能看到「代码碰过这个地址」, 看不到「这个地址此刻存的是什么」。所以: | 静态能证 | 只有活体能证 | |---|---| | 有指令在引用这个地址 | 地址里的指针是不是有效堆指针 | | 地址落在 `.data` 而不是 `.text` | 指针指向的对象结构是否对得上 | | 引用数(1487 / 2503 / 10268 …) | 对象里的字段值是否合理(血量、坐标、数量) | --- ## 第 1 组|助手 UI 链路(最高价值 —— 直接验证点击机制) 这是唯一能**同时**验证「基址 + 结构 + 虚调用机制」的一组。 | # | 读法 | 期望结果 | 含义 | |---|---|---|---| | 1.1 | `[0x0183C52C]` | 非 0 指针 | NPC 对象数组基址(也是助手链路头) | | 1.2 | `[[0x0183C52C]+0x414]` | **非 0 指针** | ★助手窗口对象地址(写值点在 `0x9E73CE`) | | 1.3 | `[[[0x0183C52C]+0x414]]` | **`0x010A20F8`** | ★助手窗口虚表 —— 与实机日志一致即为定论 | | 1.4 | `[[[[0x0183C52C]+0x414]]+4]` | **`0x00A3F3D0`** | ★分派槽 #1 函数地址 | | 1.5 | `[[[0x0183C52C]+0x414]+0x36C8]` | 某控件指针 | 控件表第 1 项(实机日志偏移 36C8) | **历史实机日志对照**(用来比对 1.2 的值): ``` 链路【助手窗口=1172743136 开始按钮=1258421128 父窗口=1172743136】 链路【助手窗口=1177242112 按钮=588239448 父窗口=1177242112 虚表=010A20F8 槽1=A3F3D0】 ``` → 1.2 的值应该落在 `0x45E60000` / `0x462A0000` 这类堆区段附近,且 **1.3 = `0x010A20F8`、1.4 = `0x00A3F3D0` 完全吻合**。 若不吻合 → 说明该局助手窗口是新对象(属正常,虚表/槽值仍应相同)。 --- ## 第 2 组|A 组 8 个「XXX基址值」解引用 辅助当前正在用的基址。全部读 `[地址]`,看是否为有效指针(非 0、落在堆区 `0x00xxxxxx`~`0x7Fxxxxxx`)。 | 常量名 | 地址 | 静态引用数 | 期望 | |---|---|---|---| | `怪物基址值` | `0x03BE3E68` | 1487 | 非 0 指针(实体数组) | | `人物基址值` | `0x03BF28CC` | 2503 | 非 0 指针(当前玩家对象) | | `坐标基址值` | `0x03BF28CC` | 2503 | 与人物基址**同址**(应读出同值) | | `背包基址值` | `0x03B9DCE0` | 3417 | 非 0 指针(物品容器) | | `凝神珠背包基址值` | `0x03B9DCEC` | 78 | 非 0 指针 | | `状态栏基址值` | `0x03BA387C` | 897 | 非 0 指针(BUFF 列表) | | `地图基址值` | `0x011E0084` | 3 | 非 0(引用少,重点看是否合理) | | `NPC基址值` | `0x0183C52C` | 10268 | 非 0 指针 | > **重点看 `地图基址值`**:静态引用只有 3 处,是全表最低。活体若无值或指向垃圾,说明该基址实际已失效。 --- ## 第 3 组|两个 0 引用基址的活体仲裁 静态显示这两个基址**没有任何指令引用**。用活体读值对照「活跃邻居」,一次定生死。 | 候选 | 地址 | 静态引用 | 读 `[地址]` 看是否有效指针 | |---|---|---|---| | 仓库基址值(现用) | `0x0182A2DC` | **0** | ? | | 仓库邻居 A ⭐ | `0x0182B5E8` | **244** | ? ← 疑为正确值 | | 仓库邻居 B | `0x0182AEB0` | 70 | ? | | 商店基址值(现用) | `0x03BC33BC` | **0** | ? | | 商店邻居 A ⭐ | `0x03BC21F8` | **76** | ? ← 疑为正确值 | | 道具遍历基址(特征读出) | `0x01801170` | **0** | ? | **判定逻辑**:被引用的邻居如果读出**有效堆指针**、而现用值读出 0 或垃圾 → 现用值是错的,直接换邻居。 若两者都有值,则要看它们指向的对象结构(进游戏打开仓库/商店各读一次对比)。 > 旁证:`0x0182B5E8` 恰好出现在「NPC_CALL基址」的反汇编里(`add eax, 0x182b5e8`), > 是仓库/物品相关的高频全局变量。 --- ## 第 4 组|三条交叉互证 + 攻击列表候选 「写死常量」与「字节特征」两套独立方式指向同一地址 —— 活体再确认一次对象语义。 | 全局变量 | 来源①「XXX基址值」 | 来源②「基址更新」特征 | 活体看什么 | |---|---|---|---| | `0x03B9DCE0` | 背包基址值 | 背包列表基址(`0xADEACB` 读出) | 指向物品容器;打开背包数量变化 | | `0x0183C52C` | NPC基址值 | NPC对话基址(`0x668951` 读出) | 指向 NPC 数组;对话时填充 | | `0x03BA387C` | 状态栏基址值 | BUFF遍历基址(`0xCE3CD0` 读出) | 指向 BUFF 列表;加 BUFF 数量变化 | **攻击列表基址待定项**(原特征在本构建不存在,需活体挑): | 候选 | 地址 | 静态引用 | 活体判据 | |---|---|---|---| | **候选3** ⭐ | `0x03BA4C40` | 204 | 打怪时该值应被填充且数量与攻击列表一致 | | 对照:状态列表基址 | `0x03BA4C3C` | 53 | 与候选3 **相邻 4 字节**,同属一个列表区块 | | 候选4 | `0x03BE3E68` | 1487 | 静态就判定是怪物基址,语义不符 | --- ## 第 5 组|B 组 data 类全局变量(11 条)全量读值 | 名称 | 全局变量地址 | 静态引用 | 读 `[地址]` | |---|---|---|---| | 血量基址 | `0x03970A70` | 8 | ? | | 周围数量基址 | `0x03BF2900` | 8 | ? | | 周围列表基址 | `0x05BFEE78` | 14 | ? | | 背包列表基址 | `0x03B9DCE0` | 3417 | ? | | 状态列表基址 | `0x03BA4C3C` | 53 | ? | | 技能栏基址 | `0x03BA4A08` | 403 | ? | | 选中对象基址 | `0x0183C51C` | 1786 | ? | | NPC对话基址 | `0x0183C52C` | 10268 | ? | | NPC选项基址 | `0x017EF378` | 1005 | ? | | 副本道具基址 | `0x0184437C` | 114 | ? | | BUFF遍历基址 | `0x03BA387C` | 897 | ? | | 道具遍历基址 | `0x01801170` | 0 | ⚠ 见第 3 组 | --- ## 第 6 组|模块基址确认 ``` ce_enum_modules → 找 YGOnline.exe,确认基址 = 0x00400000(无重定位,与静态分析一致) ``` 若基址不是 `0x400000`,则本清单所有绝对地址都要**整体平移**(`新值 = 原值 + 实际基址 - 0x400000`)。 --- ## 第 7 组|工程在用、但前六组没覆盖的地址(补漏) 对表 `旧版本更新.代码`(E2TXT)时发现工程实际引用了这 4 个,前六组都没列 —— 现在补上。 | # | 地址 | 工程里的名字 | 类型 | 读法 / 期望 | |---|---|---|---|---| | 7.1 | `0x0076C080` | `#发包call地址值` | **代码地址** | 反汇编确认是 `push ebp; mov ebp,esp` 开头的函数入口(= 静态从 `NPC选项CALL基址` 特征推出的目标) | | 7.2 | `0x0076C2A1` | `#封包Eax基址` | **代码地址** | 反汇编确认是 `lea eax,[ebp-0x401c]`(发包取址点),**不是基址** | | 7.3 | `0x01844380` | 内联 `十六到十("01844380")` | 全局变量 | 读 `[地址]` → 「是否进入角色选择界面」标志位(0/1) | | 7.4 | `0x01200000` | 内联 `十六到十("1200000")` | 边界常量 | 虚表合法性校验**上界**(`0x400000 ~ 0x1200000` = `.text` 段),无需读值 | **旁证(相邻关系)**:`0x01844380` 与「副本道具基址 `0x0184437C`」**只差 4 字节**,是同一区块的兄弟字段。 若 7.3 读到异常值,可顺手试 `0x0184437C`;反之亦然。 ### 7.1 / 7.2 的验证方式(不是读值,是看指令) ``` 0x0076C080 应形如 55 8B EC … (push ebp; mov ebp,esp …) 0x0076C2A1 应形如 8D 85 E4 BF FF FF (lea eax,[ebp-0x401c]) ``` > 另:`#角色金钱基址值` / `#角色金钱值` 只在注释行出现且常量表未定义,**不用验证**。 --- ## 执行顺序建议 1. **第 6 组**(先确认基址,否则后面的地址全错) 2. **第 1 组**(助手链路 —— 一次就能验证「基址 → 结构 → 虚表 → 函数」整条链,最有价值) 3. **第 2 组**(8 个现用基址,确认还能用) 4. **第 3 组**(两个 0 引用基址的仲裁,直接出可用/不可用结论) 5. **第 4 组**(交叉互证 + 攻击列表挑候选) 6. **第 5 组**(收尾全量) --- ## 已知桥接问题 - `ce_attach_process` **按 PID 附加失败**:`attempt to call a nil value (global 'getProcessNameFromID')` → 桥接 Lua 脚本缺这个全局函数。**按进程名附加正常**(`ce_attach_process("YGOnline.exe")`)。 需要按 PID 附加时先走名字。 --- *配套报告:《基址全量复验报告》 `03_内存逆向与基址/19_基址全量复验报告.html`* *生成:2026-09-18 · 分析对象 `D:\rxjh2025\client\YGOnline.exe`*