.版本 2 '══════════════════════════════════════════════════════════════════ ' 「按钮点击call」原稿审查 + 修正版 2026-09-25 ' 活体数据源:CE 桥 PID 23140,脚本 D:\ce_mcp\_live7.py / _live8.py '══════════════════════════════════════════════════════════════════ ' ──────────────────────────────────────────────────────────────── ' 原稿的 7 处错误 ' ──────────────────────────────────────────────────────────────── ' ① 数据源 0x3BC13E8(62657576)实测全 0 —— 这条路走不通 ' 活体扫 [0..43] 与 [-4..43] 共 48 项,非零项 = 0 个。 ' 该数组跟控件池 0x3C35758 是两套东西,当前游戏状态下取不到 ' 任何控件对象,esi 恒为 0,后面 mov ecx,[esi+0x4] 读 0。 ' ' ② 栈不平衡 ' push 了 3 次(0 / 控件ID / 0x3F4),call 之后直接 popad/retn, ' 没有 add esp,0xC。返回后栈错位,调用方一轮崩一次。 ' ' ③ 缺 0x 前缀 ' Asm ("mov esi," + 十到十六(参数)) 生成的是 `mov esi,3BC13E8`, ' 汇编器会当成十进制或未知符号,必须写 `mov esi,0x3BC13E8`。 ' ' ④ 变量名 `参数` 与 .参数 声明同名,易语言解析存疑,改名。 ' ' ⑤ 参数 `偏移` 声明了却没用(地址写死 62657576),要么传进去要么删。 ' ' ⑥ AsmBegin/Asm/AsmCode/AsmCall 与 DLL 注释(AsmEnd)混用; ' 本地汇编用 汇编_开始/汇编_结束 + 汇编_调用,别用 AsmCall (句柄)。 ' ' ⑦ `mov ecx,dword ptr ds:[esi+0x4]` 之后 ecx 仍留在调用点 —— 这条 ' 其实是对的,而且恰好纠正了 v7 写错的地方(见下)。 ' ' ──────────────────────────────────────────────────────────────── ' ★ 活体实证:ecx 到底该传谁(_live8.py) ' ──────────────────────────────────────────────────────────────── ' 槽4231 控件 obj = 0x4E0608F0 虚表 0x10F1EE4 槽1 = 0xCFB4B0 ' 槽4232 控件 obj = 0x4E066C80 虚表 0x10F1EE4 槽1 = 0xCFB4B0 ' ' [控件 + 0x04] = 0x1E448080 ← 池里的「槽 4229」那个对象 ' 它的 +0x0C = 4229(自证槽号),虚表 0x10E3050,槽1 = 0xA82550 ' 反查池:0x1E448080 确实存在 → 槽 4229 ' ' ★ 两个虚表槽1 不是同一个函数: ' 父窗口虚表槽1 = 0xA82550 (ecx = [控件+4] 时走这个) ' 控件虚表 槽1 = 0xCFB4B0 (ecx = 控件本身 时走这个) ' 游戏原文 00A7D386 传的是 ecx=[esi+4],所以 ' → ecx 必须传「读(控件 + 4)」,不是控件对象本身。 ' → 之前 v7 那版 `mov ecx,[ebp-4]`(取控件本身)在这里是错的, ' 会调用 0xCFB4B0 而不是 0xA82550。 ' ' 对照游戏原文(00A7D386): ' mov ecx,[esi+4] ecx = 父窗口 ' mov eax,[ecx] eax = 父窗口虚表 ' push 0 ' push [esi+0x364] 控件ID ' push 0x3F4 ' call [eax+4] thiscall 槽1 '══════════════════════════════════════════════════════════════════ ' 修正版:走控件池 0x3C35758(自洽校验 9/9 已过)+ 照抄游戏原文的 ecx '══════════════════════════════════════════════════════════════════ .子程序 内挂丸_点控件, 逻辑型, 公开 .参数 槽号, 整数型 .局部变量 父窗口, 整数型 ' ★★ 必须第一个!ecx=[ebp-4] 取它 .局部变量 控件, 整数型 .局部变量 控件ID, 整数型 控件 = 内存_读整数型 (全局_进程句柄, 63133528 + 槽号 × 4) .如果真 (控件 ≤ 65536) 写日志 (“点控件失败【槽” + 到文本 (槽号) + “ 控件指针非法=” + 到文本 (控件) + “】” + #换行符) 返回 (假) .如果真结束 ' ★ ecx 传 [控件+4](父窗口),这是游戏原文 00A7D386 的写法 父窗口 = 内存_读整数型 (全局_进程句柄, 控件 + 4) .如果真 (父窗口 ≤ 65536 或 父窗口 = -1) 写日志 (“点控件失败【父窗口=[控件+4] 非法】控件=” + 到文本 (控件) + “ 父窗口=” + 到文本 (父窗口) + #换行符) 返回 (假) .如果真结束 控件ID = 内存_读整数型 (全局_进程句柄, 控件 + 868) ' +0x364 ★ 868 不是 860 写日志 (“点控件【槽” + 到文本 (槽号) + “ 控件=” + 到文本 (控件) + “ ID=” + 到文本 (控件ID) + “ 父窗口=” + 到文本 (父窗口) + “ 父虚表槽1=” + 十到十六 (内存_读整数型 (全局_进程句柄, 内存_读整数型 (全局_进程句柄, 父窗口) + 4)) + “】” + #换行符) ' push 0 6A 00 置入代码 ({ 106, 0 }) ' push 控件ID(imm32 小端) 置入代码 ({ 104, 控件ID - 控件ID ÷ 256 × 256, 控件ID ÷ 256 - 控件ID ÷ 65536 × 256, 控件ID ÷ 65536 - 控件ID ÷ 16777216 × 256, 控件ID ÷ 16777216 }) ' push 0x3F4 68 F4 03 00 00 置入代码 ({ 104, 244, 3, 0, 0 }) ' mov ecx,[ebp-4] ecx = 父窗口 置入代码 ({ 139, 77, 252 }) ' mov edx,[ecx] 父窗口虚表 置入代码 ({ 139, 17 }) ' call [edx+4] 置入代码 ({ 255, 82, 4 }) ' 被调是 stdcall 且自己清栈,故此处不 add esp;若调用后栈乱,解开下面这行 ' 置入代码 ({ 129, 196, 12, 0, 0 }) ' 81 C4 0C 00 00 add esp,0xC 延迟 (取随机数 (300, 600)) 返回 (真) .子程序 开关内挂丸, 逻辑型, 公开, 31开 32关 .参数 状态, 整数型 .如果 (状态 = 31) 返回 (内挂丸_点控件 (4231)) ' 启动内挂丸 ID=49 .否则 返回 (内挂丸_点控件 (4232)) ' 停止内挂丸 ID=50 .如果结束