# 热血江湖 基址全量复验报告 > **分析对象**:`D:\rxjh2025\client\YGOnline.exe`(32 位 PE,14,752,768 字节,ImageBase `0x400000`,构建 2026-09-14) > **验证方式**:纯静态(pefile 解析节区 + capstone 逐条反汇编 + 全代码段 disp32 引用索引),不依赖运行环境 > **验证范围**:历史上找过的**全部基址** —— ①辅助常量「XXX基址值」系列 ②「基址更新」子程序 34 条 FindData 特征 ③31007 参考模块 ④助手 UI 链路地址,共 **70 项** > **结论**:**A 组 8/11 有效、B 组 20/20 全部有效(含 8 条 call 类全通)、C 组 31007 全部失效、D 组助手链路全部有效**;另修正了 2 条旧特征、指认出 1 条攻击列表正确候选、定位 2 个 0 引用基址的活跃邻居。 --- ## 一、结论速览 | 组 | 项目 | 有效 | 待复核 | 说明 | |---|---|---|---|---| | **A** 活游戏「XXX基址值」 | 11 | **8** | 3 | 怪物/人物/坐标/背包/凝神珠/状态栏/地图/NPC 全部有效;仓库、商店 0 引用;封包Eax基址是代码地址 | | **B** 基址更新 34 条特征 | 34 | **20** | 1 | 20 条精确命中(含 8 条 call 类 **全部** rel32 解析成功);14 条未命中(含 9 条 64 位特征) | | **C** 31007 参考模块 | 26 | **0** | — | 全部 0 引用 → 该版本基址已完全失效(与旧结论一致) | | **D** 助手 UI 链路 | 12 | **12** | — | 虚表、函数入口、全局变量全部实打实验证通过 | **一句话**:你的辅助现在用的那 8 个「XXX基址值」**全都还是活的**;「基址更新」那套特征查找**20 条能命中且指向正确的全局变量**——这套运行时自适应机制是当前最可靠的找址方式。 --- ## 二、验证方法(含一处关键修正) 对每个基址做三重判据: | 判据 | 做什么 | 为什么可信 | |---|---|---| | **① 地址归属** | 该 VA 落在哪个节区(`.text` / `.rdata` / `.data`) | 判断「是全局变量 / 是代码 / 是越界死值」 | | **② 指令级引用计数** | 在 `.text` 内统计**有多少条指令以 disp32 绝对寻址访问它** | 引用 ≠ 0 即证明**当前程序真的在用它**;这是「死值」的决定性判据 | | **③ 交叉解析** | 特征命中点 + adj → 读出 4 字节 → 得到真正的全局变量地址 → 再回代判据② | 把「代码偏移」翻译成「真实数据地址」,与 A 组互证 | ### ★ 关键修正:disp32 有两种形态,上一版漏了 SIB 变址 ``` 形态1 [disp32] 例:8B 15 CC 28 BF 03 mov edx,[0x3BF28CC] 形态2 [索引*4 + disp32] 例:8B 14 8D 68 3E BE 03 mov edx,[ecx*4+0x3BE3E68] ↑ ModRM=0x14(mod=00,rm=100) 带 SIB=0x8D(base=101→disp32) ``` **只统计形态 1 会大面积误判**——例如「怪物基址值 0x03BE3E68」在形态 1 下是 **0 引用**(像死值),补上 SIB 形态后是 **1487 处引用**(明确有效)。本报告全部数据均为**补齐两种形态后**的结果。 ### 节区表(用于判据①) | 节区 | VA | VirtualSize | 文件原始大小 | 性质 | |---|---|---|---|---| | `.text` | `0x00401000` | `0xC6D5B1` | `0xC6D600` | 代码段 | | `.rdata` | `0x0106F000` | `0x170356` | `0x170400` | 只读数据 / **虚表** | | `.data` | `0x011E0000` | `0x4A377A8` | **`0x1F800`** | 全局变量区(原始大小极小 → **绝大多数全局变量在文件里无内容,运行时才赋值**) | | `.fptable` | `0x05C18000` | `0x80` | `0x200` | — | | `.rsrc` | `0x05C19000` | `0x14320` | `0x14400` | 资源 | > ⚠ 由此得出一条重要限制:**静态验证只能证明「代码在用这个地址」,不能证明「运行时该地址里存的指针指向的对象是对的」**。后者必须用 CE 挂活进程读一次值。本报告已把所有「静态可证」的部分做完。 --- ## 三、A 组|活游戏基址总表(「XXX基址值」系列) 来源:辅助自己的常量文件;这是你当前**正在用**的基址。 | 常量名 | 地址 | 节区 | 指令引用 | 立即数出现 | 判定 | |---|---|---|---|---|---| | `怪物基址值` | `0x03BE3E68` | .data | **1487** | 1971 | ✅ 有效 | | `人物基址值` | `0x03BF28CC` | .data | **2503** | 3000 | ✅ 有效 | | `坐标基址值` | `0x03BF28CC` | .data | **2503** | 3000 | ✅ 有效(与人物基址同址) | | `背包基址值` | `0x03B9DCE0` | .data | **3417** | 3495 | ✅ 有效 | | `凝神珠背包基址值` | `0x03B9DCEC` | .data | **78** | 79 | ✅ 有效 | | `状态栏基址值` | `0x03BA387C` | .data | **897** | 906 | ✅ 有效 | | `地图基址值` | `0x011E0084` | .data | **3** | 3 | ✅ 有效 | | `NPC基址值` | `0x0183C52C` | .data | **10268** | 10793 | ✅ 有效(全表引用最多,也是助手链路头) | | `仓库基址值` | `0x0182A2DC` | .data | 0 | 0 | ⚠ 0 引用,待复核(见第八节) | | `商店基址值` | `0x03BC33BC` | .data | 0 | 0 | ⚠ 0 引用,待复核(见第八节) | | `封包Eax基址` | `0x0076C2A1` | .text | — | — | 代码地址,`lea eax,[ebp-0x401c]`(发包用的取址点,非函数入口) | > 「立即数出现次数」= 该 4 字节小端序列在整个文件里出现几次(宽松口径,会含巧合);**「指令引用」才是硬判据**。两者接近说明巧合很少。 --- ## 四、B 组|「基址更新」34 条 FindData 特征 ### 4.1 data 类 12 条 —— 命中点 + adj = 取址点 → 读出真正的全局变量 | 名称 | 命中点 VA | +adj 取址点 | 读出的全局变量 | 引用数 | 判定 | |---|---|---|---|---|---| | 血量基址 | `0x009F529E` | `0x009F52B9` | `0x03970A70` | 8 | ✅ | | 周围数量基址 | `0x00DE098E` | `0x00DE09A2` | `0x03BF2900` | 8 | ✅ | | 周围列表基址 | `0x00DE098E` | `0x00DE09AC` | `0x05BFEE78` | **14** | ✅ | | **背包列表基址** | `0x00ADEAA7` | `0x00ADEACB` | **`0x03B9DCE0`** | **3417** | ✅ ★与「背包基址值」**完全同址** | | 状态列表基址 | `0x006B9772` | `0x006B97BD` | `0x03BA4C3C` | 53 | ✅ | | 技能栏基址 | `0x00B4736D` | `0x00B473A8` | `0x03BA4A08` | 403 | ✅ | | 选中对象基址 | `0x00D34F6E` | `0x00D34F23` | `0x0183C51C` | 1786 | ✅ | | **NPC对话基址** | `0x00668955` | `0x00668951` | **`0x0183C52C`** | **10268** | ✅ ★与「NPC基址值」**完全同址** | | NPC选项基址 | `0x00C79138` | `0x00C7914F` | `0x017EF378` | 1005 | ✅ | | 副本道具基址 | `0x00D539C8` | `0x00D539F5` | `0x0184437C` | 114 | ✅ | | **BUFF遍历基址** | `0x00CE3CDB` | `0x00CE3CD0` | **`0x03BA387C`** | **897** | ✅ ★与「状态栏基址值」**完全同址** | | 道具遍历基址 | `0x00768D22` | `0x00768D49` | `0x01801170` | 0 | ⚠ 读出是合法 .data 地址但 0 引用,待复核 | ### 4.2 call 类 8 条 —— +adj 落在 `E8` 后的 rel32,读出来是「相对偏移」 **这是本次最重要的机制澄清**:call 类基址的 `+adj` **不是**指向函数入口,而是**指向 `call` 指令的 rel32 操作数位置**。读出 4 字节得到 rel32,再 `+ 取址点 + 4` 才是目标函数。 ``` call 指令 = E8 [rel32] 取址点 = rel32 的第 1 字节 目标 = 取址点 + 4 + rel32 ``` | 名称 | 命中点 | +adj 取址点 | 读出的 rel32 | 算出目标函数 | 入口 | 判定 | |---|---|---|---|---|---|---| | 放置技能CALL基址 | `0x00D5343A` | `0x00D53490` | `0xFFFE19BC`(-0x1E644) | `0x00D34E50` | ★ | ✅ | | 使用快捷CALL基址 | `0x00B49A0E` | `0x00B49A1E` | `0x00003AFE` | `0x00B4D520` | ★ | ✅ | | NPC_CALL基址 | `0x00C7963F` | `0x00C79661` | `0x0000520B` | `0x00C7E870` | ★ | ✅ | | NPC选项CALL基址 | `0x00C79138` | `0x00C79154` | `0xFFAF2F28`(-0x50D0D8) | `0x0076C080` | ★ | ✅ | | **小助手CALL基址** | `0x00A3F676` | `0x00A3F6E7` | `0x00000015` | **`0x00A3F700`** | ★ | ✅ ★与旧辅助直调目标**完全一致** | | NPC功能CALL基址 | `0x00C81C1C` | `0x00C81C5F` | `0xFFFF76FD`(-0x8903) | `0x00C79360` | ★ | ✅ | | 副本道具CALL | `0x00D539C8` | `0x00D539FA` | `0xFFB52162`(-0x4ADE9E) | `0x008A5B60` | ★ | ✅ | | 背包使用CALL | `0x00D538C3` | `0x00D538BE` | `0x0000819E` | `0x00D5BA60` | ★ | ✅ | **8/8 全部通过**,且每一个目标函数都是 `push ebp; mov ebp,esp` 开头的标准函数入口。 > 顺带解答了旧疑问:「小助手CALL基址」读出的 `0x15` 曾被误判为「不是地址」——它是 rel32,`0xA3F6EB + 0x15 = 0xA3F700`,正是你旧代码里硬编码的那个函数。 ### 4.3 未命中的 14 条 | 类别 | 条目 | 原因 | |---|---|---| | 64 位特征(架构不符) | 对话选项call、小范围瞬移call、函数遍历、快速出售灰色物品call、购买物品call | 含 REX 前缀(`48`/`44`/`45`/`49`),32 位 exe 永远 0 命中 | | 32 位但整段不存在 | 对话call基址、输入文本call基址、出售物品call基址、自动堆叠call基址 | 该构建里代码逻辑已变;另有昇天列表、辅组列表两条历史缺失 | | 帧偏移漂移(可修) | `人物基址`、`全局大列表基址` | 见下 | **两条可修的已给出修正字节,本次已复验唯一命中:** | 名称 | 原特征 | 修正特征 | 复验结果 | |---|---|---|---| | 人物基址 | `8B 8D 30 B6 FF FF …` (0 命中) | `8B 8D 20 B6 FF FF 8B 51 0C 89 90 24 1D 00 00` | ✅ 唯一命中 `0x007DB9C7` → 读出 `0x03BF28CC`(=人物基址值,2503 引用) | | 全局大列表基址 | `6A 00 6A 00 68 50 04 00 00 8B 85 3C B6 FF FF …` (0 命中) | `… 8B 85 2C B6 FF FF 8B 88 24 1D 00 00` | ✅ 唯一命中 `0x007DB8A9` → 读出 **`0x03BE3E68`(=怪物基址值)** | > 两条修正特征命中点相距仅 `0xED`,在同一个函数内(`0x7DB860` 附近)——该函数就是「取人物基址 / 取全局大列表」的原始取址代码,其反汇编原文见第八节。 --- ## 五、C 组|31007 参考模块(全部失效) 26 项全部 **0 引用**,包括 `#怪物基址 0x03173B70`、`#角色基址 0x03165088`、`#背包基址 0x031455E4`、`#队员基址 0x03148650`、`#游戏基址 0x03165090` 等,以及 `#发包call地址`、`#隐藏怪物/人物/建筑`、`#穿墙地址1/2` 等代码地址。 **结论**:31007 那套基址对本客户端**完全不可用**(与 2026-09-16 的结论一致,本次是全表复核确认)。`队员基址` 依然是空白项,必须用指针扫描现找。 --- ## 六、D 组|助手 UI 链路(全部有效) | 名称 | 地址 | 验证结果 | |---|---|---| | 助手窗口虚表 | `0x010A20F8` | ✅ **真虚表**:前 12 项中 9 项指向 `.text`;槽0=`0xA2FBF0`、槽1=`0xA3F3D0`(与实机读到的值一致) | | 助手分派槽#1 | `0x00A3F3D0` | ✅ ★函数入口 `push ebp; mov ebp,esp; sub esp,0x20` | | InterInGameTotalShop 虚表 | `0x01079A6C` | ✅ **真虚表**:前 12 项中 11 项指向 `.text`;**槽0 = `0x68B2B0`** | | 总控槽0 | `0x0068B2B0` | ✅ ★函数入口 | | `0xA3F700` 选项实现 | `0x00A3F700` | ✅ ★函数入口(旧辅助直调目标) | | 选项跳转表 / 字节索引表 | `0x00A41588` / `0x00A41698` | ✅ 在 .text 内且被代码引用(跳转表 1 处直接引用) | | 选项公共尾部 | `0x00A41204` | ✅ `cmp [ebp+8],0x1c / cmp [ebp+8],0x27`(区间批处理入口) | | 助手构造 | `0x00A2DCC0` | ✅ ★函数入口 | | 助手窗口创建点 / 写 `[+0x414]` | `0x009E739E` / `0x009E73CE` | ✅ `call 0xa2dcc0` → `mov [ecx+0x414], edx`(助手窗口链头的来源) | | `NPC基址值`(链头) | `0x0183C52C` | ✅ 10268 处引用 | > **一处细节修正**:`0x68B2B0` 是 InterInGameTotalShop 虚表的**槽 0**,此前记录成「槽 #1」。助手窗口那边 `0xA3F3D0` 才是槽 #1——两者不是同一个窗口体系,不要混用。 --- ## 七、三条交叉互证(不同来源指向同一地址) | 全局变量 | 来自「XXX基址值」 | 来自「基址更新」特征 | 引用数 | |---|---|---|---| | `0x03B9DCE0` | `背包基址值` | `背包列表基址` → `0xADEACB` 读出 | 3417 | | `0x0183C52C` | `NPC基址值`(助手链头) | `NPC对话基址` → `0x668951` 读出 | 10268 | | `0x03BA387C` | `状态栏基址值` | `BUFF遍历基址` → `0xCE3CD0` 读出 | 897 | 两套完全独立的定位方式(写死常量 vs 字节特征)指向同一个全局变量地址 —— **这三条是本次验证中可信度最高的基址**。 另外 `人物基址值 0x03BF28CC` 与修正后的「人物基址」特征互证(2503 引用),`怪物基址值 0x03BE3E68` 与修正后的「全局大列表基址」特征互证(1487 引用)。 --- ## 八、待复核项与修正建议 ### 8.1 攻击列表基址 —— 11 个候选已逐个评估 原特征帧尾 `F6 FF FF` 在本构建不存在,需从候选中挑。按「`-0x34` 取址点读出的值是否落在 .data 且被引用」,只有两个像真的: | 候选 | 命中点 | `-0x34` 取址点 | 读出值 | 引用数 | 评价 | |---|---|---|---|---|---| | **候选3** `89 85 FC F5 FF FF …` | `0x006B91DD` | `0x006B91A9` | **`0x03BA4C40`** | **204** | ⭐ **最可能**:与「状态列表基址」读出的 `0x03BA4C3C` **相邻 4 字节**,同属一个状态/列表区块 | | 候选4 `89 85 5C FF FF FF …` | `0x00A3C185` | `0x00A3C151` | `0x03BE3E68` | 1487 | 读出的是怪物基址(实体数组),语义不符「攻击列表」 | | 其它 9 个 | — | — | 非地址 / `.text` / 越界 | 0 | ✗ | **建议**:用候选3 替换,进游戏打怪确认「攻击列表被填充且数量正确」即为定论。 ### 8.2 两个 0 引用基址的活跃邻居(用于校正) | 基址 | 当前值 | 邻近**真有引用**的地址(±0x2000 内) | |---|---|---| | `仓库基址值` | `0x0182A2DC` | `0x0182B5E8`(244)、`0x0182AEB0`(70)、`0x0182AEC4`(42)、`0x0182AEA8`(12)、`0x0182AEA0`(10) | | `商店基址值` | `0x03BC33BC` | `0x03BC21F8`(76)、`0x03BC30F0`(16)、`0x03BC311C`(10)、`0x03BC30F8`(8)、`0x03BC2F2C`(7) | | `道具遍历基址`(特征) | `0x01801170` | 待复核 | > 注意:`0x0182B5E8` 恰好出现在「NPC_CALL基址」的反汇编里(`add eax, 0x182b5e8`),是仓库/物品相关的高频全局变量,**很可能就是仓库基址的正确值**。 ### 8.3 取址函数原文(两条修正特征的来源) ```asm 007DB89F cmp dword ptr [edx*4 + 0x3be3e68], 0 ; ← 怪物基址值(SIB 变址访问) 007DB8BE mov edx, dword ptr [ecx*4 + 0x3be3e68] 007DB8D3 mov ecx, dword ptr [ecx*4 + 0x3be3e68] 007DB8DA mov eax, dword ptr [edx + 4] ; 虚表槽1 007DB8DD call eax ; 与助手点击同一套虚调用机制 007DB911 mov edx, dword ptr [0x3bf28cc] ; ← 人物基址值 007DB96C mov ecx, dword ptr [0x183c52c] ; ← NPC基址值 007DB98F mov eax, dword ptr [0x183c52c] 007DB994 mov ecx, dword ptr [eax + 0x4d0] ; NPC 对象 +0x4D0 007DB9C2 mov eax, dword ptr [0x3bf28cc] 007DB9D0 mov dword ptr [eax + 0x1d24], edx ; 人物基址+0x1D24(索引/槽位) ``` 这段代码同时使用 `[disp32]` 和 `[索引*4 + disp32]` 两种形态 —— 也是本次发现扫描盲区的直接证据。 ### 8.4 关于「活体验证」 静态已能证明「代码在用这些地址」,但**地址里存的指针是否正确**只能活体读。要做的话需要: 1. CE 挂 `YGOnline.exe`,Table → Show Cheat Table Lua Script → 载入 `ce_mcp_bridge.lua` → Execute(出现 MCP 标记) 2. 我逐条读 `[基址]` 的值并核对指向的对象(例如 `[[NPC基址值]+0x414]` 应等于助手窗口、`[背包基址值]` 应指向物品容器) --- ## 九、本次复验脚本清单 | 脚本 | 作用 | |---|---| | `verify_all2.py` | 70 项基址总表:节区归属 + 指令引用(含 SIB)+ 立即数出现 + 代码入口判定 | | `verify_feat_map.py` | 34 条特征 → 命中 → 取址点 → 全局变量地址 → 引用数(data 类)/ rel32 算目标(call 类) | | `verify_calls.py` | call 类落点反汇编 + 目标函数入口判定 + 助手链路函数体检 | | `verify_feats2.py` | 两条修正特征复验 + 攻击列表 11 候选评估 | | `verify_addr47.py` | `0x7DB860` 取址函数完整反汇编 + 两种 disp32 形态举证 | **基线数据(可直接复核)**:exe 大小 `14752768`、`.text` 覆盖 `0x401000–0x106E5B1`、`.data` 内被引用地址总数 `3264`。 --- *报告生成:2026-09-18 · 分析对象 D:\rxjh2025\client\YGOnline.exe · 全部结论可凭上述脚本在本地复跑复核*