.版本 2 .支持库 spec '══════════════════════════════════════════════════════════════ ' 开关内挂丸(引擎手法版 v7 2026-09-25) ' 2026-09-25 用 CE 桥活体实读 YGOnline.exe (PID 23140) 定案 '══════════════════════════════════════════════════════════════ ' ' 【活体实测数据】(本轮 CE 直读,不再是猜测) ' 池基址 63133528 (0x3C35758) —— 自洽校验 9/9 通过 ' 证明:池[读(控件+0x0C)] == 控件 ' ' 控件对象 首字段 [+0x00] = 虚表 0x10F1EE4(.rdata,确认是真控件) ' +0x00 虚表 ' +0x0C 自己的槽号 ' +0x364 控件ID ← 868 十进制!不是 860(之前代码的笔误) ' +0x368 名称字符串 ' ' ★ ID 表(槽号固定,跨进程一致) ' 槽4231 ID=49 「启动内挂丸」 ' 槽4232 ID=50 「停止内挂丸」 ' 槽4233 ID=51 「设定内挂丸」 ' 槽4234 ID=52 「关闭内挂丸」 ' 槽4270 ID=0 「设定内挂丸的攻击行动范围。」 ' ' 【点控件 = 引擎原生手法】 ' 静态反汇编 0x75A6F8(exe 原文),这就是游戏自己点控件的地方: ' push 0 / push 1 / push 0x3F4 ' mov ecx,[[[0x183C52C]+0x3EC]+0x39C] ' ecx = 当前目标控件 ' mov edx,[ecx] ' 虚表 ' mov eax,[edx+4] ' 虚表槽1 = 动作分派 ' call eax ' thiscall(0x3F4, 1, 0) ' ' 翻译成机器码(这版确定的调用序列): ' 6A 00 push 0 ' 68 push 控件ID ' 68 F4 03 00 00 push 0x3F4 ' 8B 4D FC mov ecx,[ebp-4] ' ecx = 控件对象本身 ' 8B 11 mov edx,[ecx] ' 虚表 ' FF 52 04 call [edx+4] ' 槽1 动作分派 ' ' 【本轮实测:槽1 = 0xCFB4B0】两个控件同一个虚表,槽位一致,可调用。 ' ' 【不再需要的东西】 ' ✗ 0x682880 命令执行器(cmd 49 的 handler 0x683834 会读空指针 → 必崩) ' ✗ [0x3C441BC] 体检门槛(与本链路无关) ' ✗ 助手窗口 +0x3938/+0x393C 那条按钮偏移表(那是旧的另一条路) '══════════════════════════════════════════════════════════════ ' ─────────────────────────────────────────────────────────── ' 核心:点一个池控件 '─────────────────────────────────────────────────────────── .子程序 内挂丸_点控件, 逻辑型, 公开 .参数 槽号, 整数型 ' 4231 启动 / 4232 停止 … .局部变量 控件, 整数型 ' ★ 必须排第一!ecx=[ebp-4] 取第一个局部变量 .局部变量 控件ID, 整数型 .局部变量 虚表, 整数型 .局部变量 槽1, 整数型 控件 = 内存_读整数型 (全局_进程句柄, 63133528 + 槽号 × 4) .如果真 (控件 ≤ 65536) 写日志 (“点控件失败【槽” + 到文本 (槽号) + “ 控件指针非法=” + 到文本 (控件) + “】” + #换行符) 返回 (假) .如果真结束 控件ID = 内存_读整数型 (全局_进程句柄, 控件 + 868) ' +0x364 虚表 = 内存_读整数型 (全局_进程句柄, 控件) 槽1 = 内存_读整数型 (全局_进程句柄, 虚表 + 4) 写日志 (“点控件【槽” + 到文本 (槽号) + “ 控件=” + 到文本 (控件) + “ ID=” + 到文本 (控件ID) + “ 虚表=” + 到文本 (虚表) + “ 槽1=” + 到文本 (槽1) + “】” + #换行符) .如果真 (槽1 ≤ 65536) 写日志 (“✗ 虚表槽1 非法,跳过调用” + #换行符) 返回 (假) .如果真结束 ' push 0 (68 imm32,ID 一律用 32 位写法,通用) 置入代码 ({ 106, 0 }) ' push 控件ID (68 imm32,小端:低字节在前) ' 低字节 = ID - ID÷256×256 ' 次字节 = ID÷256 - ID÷65536×256 ' 三字节 = ID÷65536 - ID÷16777216×256 ' 高字节 = ID÷16777216 置入代码 ({ 104, 控件ID - 控件ID ÷ 256 × 256, 控件ID ÷ 256 - 控件ID ÷ 65536 × 256, 控件ID ÷ 65536 - 控件ID ÷ 16777216 × 256, 控件ID ÷ 16777216 }) ' push 0x3F4 置入代码 ({ 104, 244, 3, 0, 0 }) ' mov ecx,[ebp-4] ecx = 控件对象 置入代码 ({ 139, 77, 252 }) ' mov edx,[ecx] 虚表 置入代码 ({ 139, 17 }) ' call [edx+4] 置入代码 ({ 255, 82, 4 }) 延迟 (取随机数 (300, 600)) 返回 (真) ' ─────────────────────────────────────────────────────────── ' 开关入口 '─────────────────────────────────────────────────────────── .子程序 开关内挂丸, 逻辑型, 公开, 31开 32关 .参数 状态, 整数型, , 31是开 32是关 .如果 (状态 = 31) 写日志 (“── 内挂丸【开】──” + #换行符) 返回 (内挂丸_点控件 (4231)) .否则 写日志 (“── 内挂丸【关】──” + #换行符) 返回 (内挂丸_点控件 (4232)) .如果结束 ' ─────────────────────────────────────────────────────────── ' 只读:把池里所有控件的名称 + ID 打出来(诊断用,绝不会崩游戏) ' 用法:内挂丸_列出 () '─────────────────────────────────────────────────────────── .子程序 内挂丸_列出 .局部变量 S, 整数型 .局部变量 控件, 整数型 .局部变量 控件ID, 整数型 .局部变量 名称, 文本型 写日志 (“── 列出池内控件(丸/内挂)──” + #换行符) S = 0 .判断循环首 (S < 14998) 控件 = 内存_读整数型 (全局_进程句柄, 63133528 + S × 4) .如果真 (控件 > 65536) 控件ID = 内存_读整数型 (全局_进程句柄, 控件 + 868) 名称 = 编码_BIG5到简体 (内存_读文本型 (全局_进程句柄, 控件 + 872, 0)) .如果真 (寻找文本 (名称, “丸”, 1, 假) > 0 或 寻找文本 (名称, “内挂”, 1, 假) > 0) 写日志 (“ 槽” + 到文本 (S) + “ ID=” + 到文本 (控件ID) + “ ” + 名称 + #换行符) .如果真结束 .如果真结束 S = S + 1 .判断循环尾 () 写日志 (“列出结束。” + #换行符)