分析对象:
D:\rxjh2025\client\YGOnline.exe(32 位 PE,14,752,768 字节,ImageBase0x400000,构建 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 组互证 |
形态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 挂活进程读一次值。本报告已把所有「静态可证」的部分做完。
来源:辅助自己的常量文件;这是你当前正在用的基址。
| 常量名 | 地址 | 节区 | 指令引用 | 立即数出现 | 判定 |
|---|---|---|---|---|---|
怪物基址值 |
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 字节小端序列在整个文件里出现几次(宽松口径,会含巧合);「指令引用」才是硬判据。两者接近说明巧合很少。
| 名称 | 命中点 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 引用,待复核 |
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,正是你旧代码里硬编码的那个函数。
| 类别 | 条目 | 原因 |
|---|---|---|
| 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附近)——该函数就是「取人物基址 / 取全局大列表」的原始取址代码,其反汇编原文见第八节。
26 项全部 0 引用,包括 #怪物基址 0x03173B70、#角色基址 0x03165088、#背包基址 0x031455E4、#队员基址 0x03148650、#游戏基址 0x03165090 等,以及 #发包call地址、#隐藏怪物/人物/建筑、#穿墙地址1/2 等代码地址。
结论:31007 那套基址对本客户端完全不可用(与 2026-09-16 的结论一致,本次是全表复核确认)。队员基址 依然是空白项,必须用指针扫描现找。
| 名称 | 地址 | 验证结果 |
|---|---|---|
| 助手窗口虚表 | 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 引用)。
原特征帧尾 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 替换,进游戏打怪确认「攻击列表被填充且数量正确」即为定论。
| 基址 | 当前值 | 邻近真有引用的地址(±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),是仓库/物品相关的高频全局变量,很可能就是仓库基址的正确值。
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] 两种形态 —— 也是本次发现扫描盲区的直接证据。
静态已能证明「代码在用这些地址」,但地址里存的指针是否正确只能活体读。要做的话需要:
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 · 全部结论可凭上述脚本在本地复跑复核