来源:
D:\AI空间\rxjh\旧版本更新.代码\常量.e.txt(E2TXT 1.2 反编译产物)
对象:旧版本更新.e当前工程
目的:把工程里实际在用的常量基址逐条列出来,并与《基址全量复验报告》的静态结论对表
生成:2026-09-18
| 项 | 结果 |
|---|---|
| 常量总数 | 209 条(含精易模块/魔鬼作坊模块带进来的通用常量) |
| 其中地址类(≥ 0x1000) | 18 条 |
| 明确是游戏内存基址 | 9 条 |
| 与静态复验对表 | 9/9 全部吻合 ✅ |
| ★ 交叉互证 | 发包call地址值 / 发包Call_ECX值 = 静态从「NPC选项CALL基址」特征推出的同两个地址 |
| 关键澄清 | 封包Eax基址 不是基址,是代码地址(发包取址点) |
| ⚠ 发现 bug | 助手_发命令 的 .参数 控件地址 丢了 整数型 → ④ 点控件必然失败(详见第八节) |
| 额外收获 | 从内联偏移反推出一套完整的对象字段结构表(第五节) |
一句话:工程里写死的 9 个游戏基址全部经静态复验确认有效;两个发包常量与独立特征路线完全对得上;
另外揪出一处会让「点控件」失效的类型声明缺失。
| 常量名 | 十进制 | 十六进制 | 性质 | 工程内引用 |
|---|---|---|---|---|
坐标基址值 |
62859468 | 0x03BF28CC |
人物对象基址 | 5 |
人物基址值 |
62859468 | 0x03BF28CC |
同上(同址) | 6 |
怪物基址值 |
62799464 | 0x03BE3E68 |
实体数组基址 | 15 |
商店基址值 |
62665660 | 0x03BC33BC |
⚠ 静态 0 引用 | 3 |
状态栏基址值 |
62535804 | 0x03BA387C |
BUFF/状态列表(当列表基址用) | 2 |
凝神珠背包基址值 |
62512364 | 0x03B9DCEC |
凝神珠背包 | 3 |
背包基址值 |
62512352 | 0x03B9DCE0 |
物品容器 | 41 |
当前血量值 |
60230256 | 0x03970A70 |
血量全局变量 | 74 |
NPC基址值 |
25412908 | 0x0183C52C |
NPC 数组 + 助手链路头 | 9 |
仓库基址值 |
25338588 | 0x0182A2DC |
⚠ 静态 0 引用 | — |
发包Call_ECX值 |
25097080 | 0x017EF378 |
发包 ECX 全局变量 | 1 |
地图基址值 |
18743428 | 0x011E0084 |
当前地图 ID | 9 |
发包call地址值 |
7782528 | 0x0076C080 |
代码地址(发包 call 目标) | 1 |
x坐标偏移值 |
8068 | 0x1F84 |
对象字段偏移 | 4 |
y坐标偏移值 |
8076 | 0x1F8C |
对象字段偏移 | 3 |
另外 3 条是地图枚举(
虎峡谷 25100/南林 6001/冰宫 5001),不是地址。
当前血量="03970A70"(字符串形式)与当前血量值=60230256(数值形式)指向同一地址,是历史遗留的双写。
静态复验(verify_all2.py,含 SIB 变址修正后)给出的指令引用数 vs 本常量表:
| 常量名 | 地址 | 静态引用数 | 判定 | 对表 |
|---|---|---|---|---|
怪物基址值 |
0x03BE3E68 |
1487 | ✅ | 一致 |
人物基址值 / 坐标基址值 |
0x03BF28CC |
2503 | ✅ | 一致(同址) |
背包基址值 |
0x03B9DCE0 |
3417 | ✅ | 一致 |
凝神珠背包基址值 |
0x03B9DCEC |
78 | ✅ | 一致 |
状态栏基址值 |
0x03BA387C |
897 | ✅ | 一致 |
地图基址值 |
0x011E0084 |
3 | ✅(引用极少,需活体验证) | 一致 |
NPC基址值 |
0x0183C52C |
10268 | ✅ | 一致 |
仓库基址值 |
0x0182A2DC |
0 | ⚠ 待复核 | 一致(静态也是 0) |
商店基址值 |
0x03BC33BC |
0 | ⚠ 待复核 | 一致(静态也是 0) |
九条全部对上,没有一条工程常量与静态结论矛盾 —— 说明这套静态判据是可靠的。
发包call地址值 = 0x0076C080 —— 不是基址,是函数地址静态复验的 B 组特征里有一条 NPC选项CALL基址,走 call 类规则:
命中点 0x00C79138 → +adj 0x00C79154 → 读到 rel32 = 0xFFAF2F28 (-0x50D0D8)
目标 = 0x00C79154 + 4 + (-0x50D0D8) = 0x0076C080 ← 与常量表完全一致 ✅
发包Call_ECX值 = 0x017EF378 —— 同一个特征的另一半静态复验里同一条特征的 NPC选项基址:
命中点 0x00C79138 → +adj 0x00C7914F → 读出 0x017EF378 ← 与常量表完全一致 ✅
发包Call → 置入发包(窗口程序集_MainDialogWnd.form.e.txt:9769)机器码原文等价于:
push [ebp+8] ; 封包长度
push [ebp+12] ; 封包指针
mov ecx, [ebp+16] ; #发包Call_ECX值 的地址
mov ecx, [ecx] ; ecx = [0x017EF378]
cmp ecx, 0x10000
jg +4
leave ; ret 0x10 ; ecx 太小 → 不进游戏、直接返回
call [ebp+20] ; call [0x0076C080]
leave ; ret 0x10
这是本次最有价值的一条互证:一条静态特征路线(字节搜索 + rel32 解析)与工程里写死的两个常量,
独立地指向同两个地址。两条路都走通了 → 这两个发包入口可以放心用。
除常量外,代码里还有 35 个内联 十六到十("…") 字面量。整理出这套对象字段图:
对象+8)| 值 | 含义 | 出处 |
|---|---|---|
0x2E |
怪物 | if 读整数(对象+8) == 0x2E(8 处) |
0x31 |
人物 | if 读整数(对象+8) == 0x31 ' 31=人物 |
⚠ 注意:
0x31在对象类型里是「人物」,在助手控件 ID 里是「开始挂机」。两套体系,别混。
0x31)| 偏移 | 内容 |
|---|---|
+0x18 |
名字(文本,BIG5) |
+0xC |
对象ID |
0x2E)| 偏移 | 内容 | 备注 |
|---|---|---|
+0xC |
槽位 ID | |
+0x14 |
全服 ID(发包值) | |
+0x74 / +0x78 |
当前血 / 最大血 | 旧一套 |
+0x364 |
名字(文本,BIG5) | |
+0x5F4 / +0x5F8 / +0x5FC |
当前血 / 最大血 / 等级 | 新一套 |
+0x1F84 / +0x1F8C |
坐标 X / Y(小数) | 与 #x坐标偏移值 同 |
+0x2780 |
等级 | |
+0x12FC / +0x130C |
坐标 X / Y(= 0x107C+0x280 / 0x1084+0x288) |
另一条寻址路径 |
同一字段存在新旧两套偏移(
0x74/0x78vs0x5F4/0x5F8、0x2780vs0x5FC),
说明客户端版本升级时字段搬过家,工程里两套都留着。以0x5F4/0x5F8/0x5FC这套为准(代码里在用的是它)。
| 表达式 | 含义 | 出处 |
|---|---|---|
[#坐标基址值 + 0x1D24] |
选中目标 ID / 对话 ID(可读可写) | 读:判「金香玉选中成功」;写:返回(内存_写整数型(… + 0x1D24, 对话ID)) |
与静态反汇编互为印证:
0x7DB9D0 mov [eax+0x1d24], edx(eax = [0x3BF28CC],即人物基址值)。
| 偏移 | 含义 |
|---|---|
+0x414 |
助手窗口偏移([NPC基址值] 解引用后 +0x414) |
+0x36C0 ~ +0x3B00 |
控件指针槽扫描区间(步长 4,共 74 槽) |
+0x364 |
控件命令 ID |
+0x3938 |
开始挂机按钮槽 |
+0x393C |
停止挂机按钮槽 |
0x400000 / 0x1200000 |
虚表合法性校验区间(= .text 段) |
0x400000这个值就是ImageBase—— 工程靠「虚表指针必须落在.text内」来判定控件指针有效,思路正确。
| 排行 | 常量名 | 引用次数 | 说明 |
|---|---|---|---|
| 1 | 当前血量值 |
74 | 血检最频繁,改地址风险最高 |
| 2 | 背包物品位置值 |
51 | 偏移 |
| 3 | 背包物品名称值 |
42 | 偏移 |
| 4 | 背包基址值 |
41 | ★ 全工程最吃重的基址 |
| 5 | 背包物品数量值 |
28 | 偏移 |
| 6 | 背包物品编号值 |
27 | 偏移 |
| 7 | 物品分类值 |
26 | 偏移 |
| 8 | 石头大小值 / 石头属性值 |
20 / 17 | 偏移 |
| 9 | 怪物基址值 |
15 | ★ |
| 10 | 地图基址值 |
9 | ★ |
| 11 | NPC基址值 |
9 | ★ 助手链路头 |
| 12 | 人物基址值 |
6 | ★ |
| 13 | 坐标基址值 |
5 | ★ |
| 14 | 商店基址值 / 凝神珠背包基址值 / y坐标偏移值 |
3 / 3 / 3 | |
| 15 | 状态栏基址值 |
2 | 当列表基址用(幸运符 20 格 / 轻功 15 格) |
| 16 | 仓库基址值 / 发包Call_ECX值 / 发包call地址值 / 封包Eax基址 |
1 / 1 / 1 / 1 |
改基址时的风险顺序:
背包基址值(41) >怪物基址值(15) >地图基址值(9) =NPC基址值(9) >
人物基址值(6) >坐标基址值(5) >商店基址值(3) =凝神珠背包基址值(3) >状态栏基址值(2) >
仓库基址值(1)。
而仓库基址值/商店基址值各只有 1~3 处引用 —— 改错影响面很小,值得优先试换(见待复核项)。
工程常量只覆盖了「写死」的那 9 条。其余靠运行时字节特征查找,不在这张表里:
| 来源 | 数量 | 位置 |
|---|---|---|
| 「基址更新」FindData 特征 | 34 条 | ❗ 本 E2TXT 里没有这个子程序 |
| 31007 参考模块 | 26 项 | ❗ 未使用(且静态已证全失效,0 引用) |
E2TXT 里只在注释和 进程_特征码搜索 的调用点见到零散特征码:
| 行 | 特征码 | 用途 |
|---|---|---|
| 1866 | 83 BC 81 3C 05 00 00 00 74 59 8B 95 74 BE FF FF |
背包基址(已注释掉) |
| 8780 / 8813 | 8B 91 EC 03 00 00 8B 82 90 03 00 00 0F B6 88 C8 06 00 00 85 C9 |
NPC对话基址 |
| 8781 / 8814 | 8D 4C 02 FF 8B 55 FC 8B 82 B4 34 00 00 89 48 2C |
小助手call基址 |
所以:「基址更新」34 条特征来自
辅助配置汇总.csv,不来自这个 E2TXT 工程。
该工程目前是「常量写死 + 少量特征码」的混合模式。
E2TXT 是当前工程状态的 dump,里面能找到助手链路的完整实现:
| 子程序 | 行号 | 状态 |
|---|---|---|
小助手开 |
8775 | 旧版(直调 0xA3F700) |
小助手关 |
8809 | 旧版 |
遍历助手控件 |
8907 | ✅ |
小助手开_新路 |
8934 | ✅ 读 0x3938 槽 |
小助手关_新路 |
8970 | ✅ 读 0x393C 槽 |
助手_发命令 |
9006 | ✅ v3.2(1 参数 0 局部,机器码只读 [ebp+8]) |
小助手_点控件 |
9031 | ✅ v3.2 |
助手_取槽控件 |
9074 | ✅ v3.2(虚表区间校验 0x400000~0x1200000) |
助手_发命令 机器码与交付版逐字节一致:
96 pushad
106,0 push 0 lParam
139,69,8 mov eax,[ebp+8] 控件(唯一参数)
139,128,100,3,0,0 mov eax,[eax+0x364] 命令ID
80 push eax wParam=命令ID
104,244,3,0,0 push 0x3F4 msg
139,69,8 mov eax,[ebp+8]
139,72,4 mov ecx,[eax+4] 父窗口
139,17 mov edx,[ecx] 虚表
255,82,4 call [edx+4] → 0xA3F3D0
97 popad
交付版(助手验证_极简版_易语言.txt:168) |
工程实际(E2TXT :9007) |
|
|---|---|---|
| 参数声明 | .参数 控件地址, 整数型 |
.参数 控件地址 ← 类型丢了 |
全文件只有 5 个「无类型」参数,其中 4 个是你原有的辅助子程序(当前属性 / 格子号),
只有 控件地址 是本该有类型却丢了的那一个 —— 不是 E2TXT 的显示省略(对比 :9075 .参数 助手窗口, 整数型 是带类型的)。
为什么致命:易语言里省略类型的参数是通用型,调用时压栈的是「通用型数据块的指针」,不是整数本身。
于是机器码的 mov eax,[ebp+8] 拿到的是块地址,mov eax,[eax+0x364] 读到的是栈上的垃圾 →
算出的「命令 ID」「父窗口」全错 → mov edx,[ecx] / call [edx+4] 要么无效要么直接崩。
你原有的
当前属性/格子号之所以一直没出问题,是因为它们只在易语言代码里参与算术(基址 + 偏移),
通用型会被自动拆箱。但置入代码不拆箱 —— 这是两回事。
修法:把第 9007 行改成
.参数 控件地址, 整数型
两个字符的事。改完 ④ 小助手_点控件 才可能真的生效。
| # | 事项 | 依据 | 影响面 |
|---|---|---|---|
| 0 | ★ 助手_发命令 参数补回 整数型 |
类型丢失 → 通用型传参 → 机器码读 [ebp+8] 拿到的是块指针 |
④ 能否生效就卡在这 |
| 1 | 核对 仓库基址值 → 试 0x0182B5E8 |
现用值静态 0 引用;邻居 244 引用 | 1 处引用,改错代价极低 |
| 2 | 核对 商店基址值 → 试 0x03BC21F8 |
现用值静态 0 引用;邻居 76 引用 | 3 处引用 |
| 3 | 活体确认 地图基址值 |
静态仅 3 引用,全表最低 | 9 处引用 |
| 4 | 攻击列表基址改用候选3 0x03BA4C40 |
与状态列表 0x03BA4C3C 相邻 4 字节,204 引用 |
待接 |
| 5 | 统一坐标读取偏移 | 代码里 0x1F84 与 0x12FC 两套并存 |
建议只留 0x1F84 |
前两项只需 CE 读两次值即可定案(见《基址活体验证清单》第 3 组)。
配套:《基址全量复验报告》03_内存逆向与基址/19_基址全量复验报告.html · 《基址活体验证清单》D:\AI空间\rxjh\基址活体验证清单.md
清点脚本:scan_e2txt_consts.py · 原始输出:_consts_e2txt.txt