热血江湖助手 · 分析资料站← 报告总目录助手主页
分区:13_内挂配置逆向源文件:控件状态读写_使用说明.md篇幅:6.6 KB收录:2026-10-19 17:10

内挂丸控件状态读写(按控件ID)

全部数据来自实机 CE 直读(YGOnline.exe,PID 38424,2026-10-18 23:30~23:40)。
工具:tools/rxjh_ctrl.lua(Cheat Engine Lua 库,415 行)

一句话结论

控件对象在控件池里能按内容地址直接定位,勾选状态是对象内一个 byte,读写都成立:

0x03C35758 + 控件池索引 × 4   →  控件对象指针
控件对象 + 0x360 (byte)       →  勾选状态 0/1      ← 可读可写,实测持久不被覆盖
控件对象 + 0x364 (dword)      →  控件ID
控件对象 + 0x368 (内联字节串) →  控件名称(BIG5,不是指针)

定位链路(四步,全部实测)

① 控件池基址  0x03C35758        ← 等于源码常量 #怪物基址值 = 63133528
② 池里找 ID=49 的对象 → 读它的 +0x004 得父窗口
③ 窗口对象   + 0x3000..0x3B00(步长 4)→ 逐个控件指针
④ 校验:控件+0x364 在 1..0x4000,虚表在已知 4 类内

本次实测值:

项值
控件池基址0x03C35758
内挂窗口对象0x4C102178(虚表 0x010E3050)
窗口内控件99 个(88 控件 + 5 容器 + 5 子窗 + 1 分隔)
⚠ 上一版报告里写的 0x4C0655F8 是换算错误 —— 那个地址全 0。
正确的窗口是 0x4C102178,+0x3938 正好是「啟動內掛丸」(ID49) 的指针。

窗口怎么认:控件池里 475 个不同的父对象,光看「含 ID 49」会误判 6 个。必须三条同时成立:


控件对象字段表

偏移类型含义实测样本(ID49)
+0x000dword虚表0x010F1EE4
+0x004ptr父窗口0x4C102178
+0x008dword常量0x22(34)
+0x00Cdword池索引4231
+0x04Cdword组编号0x1086
+0x360byte勾选 0/10
+0x364dword控件ID49
+0x368bytes内联 BIG5 名称B1 D2 B0 CA A4 BA B1 BE A4 59(啟動內掛丸)

四种虚表 = 四种控件类:

虚表数量类型+0x360 语义
0x010F1EE488按钮 / 勾选框 / 静态文本勾选位,安全可写
0x010FB2E05容器 / 页签不是勾选(读到 156、0x19B0xxxx 这类垃圾值),禁止写
0x010FAE945子窗口(编辑框等)同上,禁止写
0x010F1F5C1分隔条无效
这是踩过的坑:容器类 +0x360 位置存的是别的东西,当成勾选写会破坏对象。工具里已按虚表白名单拦截。

用法

脚本放在 D:/rxjh_out/rxjh_ctrl.lua。CE 里 Ctrl+Alt+L 打开 Lua 引擎:

dofile('D:/rxjh_out/rxjh_ctrl.lua')

读

ctrl.table()            -- 99 个控件全表(偏移/ID/类型/池索引/勾选/名称)
ctrl.checked()          -- 只列当前勾着的
ctrl.get(49)            -- 单个:返回 table(obj/idx/check/group/woff/name)
ctrl.format(ctrl.get(49))   -- 格式化成一行
ctrl.readRange(11, 35)  -- 读 ID11..45 的 35 个勾选位,输出 "0000???..."(? = 该ID不存在)

写

ctrl.set(49, 1)         -- 勾上,返回 true/false, 说明
ctrl.set(49, 0)         -- 取消
ctrl.setRange(11, {1,0,1,0,1})   -- 从 ID11 起批量按位图写
ctrl.verify(11, "00000000000000000000000000000000000")  -- 对照校验

监视

ctrl.watch(49, 2000)    -- 每 2 秒打印一次,值变了才输出
ctrl.stopWatch()        -- 结束

调试

ctrl.find(49)           -- 内挂窗口内(默认)
ctrl.findAny(49)        -- 全池,会捞到别家窗口同号控件(只读用,别拿来写)
ctrl.findWindow()       -- 返回窗口地址 + 控件数

实测验证记录

测试结果
窗口定位0x4C102178,99 个控件,耗时 0.19s
get(49)ID=49 控件 chk=0 idx=4231 grp=0x1086 woff=0x3938 啟動內掛丸
set(40,1) → 读回 → set(40,0)全部成功,0 -> 1 -> 0,进程无异常
写入持久性写 1 后连续观察 4.8 秒,值稳定为 1,游戏没有覆盖回去
容器类拒绝set(1,1) → `falseID=1 属于 容器 类,+0x360 不是勾选位,已拒绝`
越界拒绝set(9999,1) → `false找不到控件 ID=9999`(只在窗口内找)
非法值拒绝set(49,2) → `false只接受 0 或 1`

当前勾选状态(23:38 快照):7 个

ID=88   chk=1  woff=0x33F8  啟動戀人之魂。
ID=89   chk=1  woff=0x3400  啟動刺客之魂。
ID=90   chk=1  woff=0x33FC  啟動商人之魂。
ID=91   chk=1  woff=0x3404  設定要撿取的道具種類。
ID=113  chk=1  woff=0x3408  設定赤蛇鬥關的使用間隔時
ID=155  chk=1  woff=0x399C  發動東嶺之魂。
ID=156  chk=1  woff=0x39A0  指定要使用的美高異常狀態

两个必须知道的限制

1. ID 11~45 里只有 26 个真实存在

readRange(11, 35) 输出:

位置:  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 ...
值:    0  0  0  0  ?  ?  ?  0  0  0  0  ?  ?  ?  ?  ?  ?  0 ...
ID:   11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 ...

缺的是 ID 15/16/17 和 22/23/24/25/26/27(共 9 个)。<br>所以 不能 简单把 .aut 里那 35 位开关位图按 位 i ↔ ID(11+i) 直接对上去,中间有空洞。要建立映射只能靠对照实验。

2. 「改控件勾选」和「改内挂配置」目前是两件事

要确认第 2 点,最省事的办法:ctrl.set(某个功能ID, 1),然后看游戏里对应的功能有没有真的开起来 / 面板上勾有没有亮。一次就能定性。


附:控件清单

分析报告汇总/05_助手UI控件逆向/控件清单_20261018.tsv(99 行,Tab 分隔)

列含义
woff窗口偏移(重启不变,可当锚点)
id控件ID(发命令用)
type控件/容器/子窗/分隔
idx池索引(会漂移,不可写死)
chk+0x360 当前值
group组编号
name控件名称(BIG5 解出)
本页由 Markdown 报告自动转排;如需原始 md,可在原会话工作区取用。