热血传奇(Mir2Client.exe,窗口类 TFrmMain,标题 legend of mir2)里说的“关键CALL”,指客户端内部触发具体功能函数地址:走路、跑步、普通攻击、释放技能、选怪、吃药、拾取、换装、喊话、寻路、发包。找CALL本质是在游戏进程领空内,从数据变化或网络发包反向回溯到功能函数,再算出“模块基址 + RVA偏移”,用远程线程/DLL注入调用。
一、先搞懂基址与偏移关系
每次启动客户端因ASLR或版本不同,函数内存地址会变,但“主模块基址 + 相对偏移RVA”不变。实战取地址:
uintptr_t base = (uintptr_t)GetModuleHandle(L"Mir2Client.exe");
void* pFunc = (void*)(base + 0x301620); // 例:RVA 0x301620
老版传奇主模块基址常固定在 0x400000,新版用 GetModuleHandle 取真实基址再相加。
二、必备工具链
x64dbg / OD(OllyDbg):下断、看调用栈、跟汇编
Cheat Engine(CE):扫血量、坐标、状态值、找基址
IDA Pro:静态反编译,看函数序言/结尾、调用约定
Wireshark + 条件断点:配合 send/WSASend 抓明文包
注入端:CreateRemoteThread + LoadLibrary 注入 DLL,或 WriteProcessMemory 调参
三、通用找CALL四条主线
1. 发包回溯法(最常用)
在 ws2_32.send / send / WSASend 下 bp 断点 → 回游戏做动作(砍怪、吃药、说话、点地图寻路)→ 断下后 Alt+K 看调用堆栈 → 从 send 向上 Ctrl+F9 / F8 逐层返回 → 第3~6层出现的 call 地址即功能CALL。传奇类动作链:鼠标点击 → 选怪CALL → 走路CALL → 攻击CALL → 组包 → send。
例:释放技能断点返回层:
mov edx, esi ; 怪物ID
mov ecx, esi ; 角色对象(thiscall)
mov r8w, bx ; 技能ID
mov r9b, dil ; 技能等级
call 0x7FF7F9B75260 ; 技能CALL
2. 数据写入断点法
CE搜角色坐标(X,Y)、血量、寻路状态(静止0/移动1/战斗2)→ 找到稳定地址 → x64dbg对该地址下硬件写入断点 → 触发移动/寻路 → 断点命中处向上回溯 → 定位走路CALL / 寻路CALL。寻路CALL参数常见:ecx=角色对象指针、edx/xmm=目标X/Y、标志位=寻路模式,调用约定 __thiscall。
3. 对象结构追踪法
选中怪物 → CE搜未知初始值 → 换怪搜变动值 → 锁定怪物对象基址 → 下访问断点 → 攻击时断下 → 回溯到攻击CALL。技能ID、目标ID、怪物坐标都从对象结构里取。
4. 字符串/消息窗口法
OD加载客户端进领空 → Ctrl+N 找 Send / WSASend / OnLButtonDown / DefMainWndProc → 从 CGameProcess::OnLButtonDown 开始跟鼠标点击逻辑,传奇源码里点击地面→计算坐标→寻路→组包全在这条链上。
四、热血传奇典型关键CALL清单(参数特征)
• 走路/跑步CALL:8方向,参数含目标X、Y、方向、跑步标志;走路与跑步是同一CALL不同参数。
• 普通攻击CALL:等同技能ID=0(F1),参数 怪物ID/对象、技能ID、等级。
- 释放技能CALL:技能ID(烈火0x..、冰咆哮..)、目标ID、ecx=角色对象。
• 选怪CALL:鼠标点击命中后先选怪再走路再攻击,第一层返回多为选怪CALL。
• 吃药CALL:药品背包索引、类型(红/蓝/太阳水)、数量;注意流程是“功能CALL→发包→服务器回包→扣血/加血”,直接追血量地址只能找到表现层,不是吃药CALL本身。
- 拾取CALL:地面物品对象指针/索引;回溯 send 包类型 0x0A 左右(捡物指令)。
• 换装CALL:背包物品基址 + 装备槽位;先找“物品复制到鼠标”CALL,再找真正穿戴CALL。
• 喊话CALL:频道号、字符串指针、长度;发包类型 0x1F。
- 寻路CALL:目标X/Y、寻路模式、角色对象ecx;状态位 1 时生效。
• 明文发包CALL:缓冲区指针、长度、加密标志;在 send 上方贴近末尾下断最稳,避开反调试检测。
五、调用约定与参数判定
- __cdecl:参数右→左压栈,调用者平栈(add esp, x)
• __stdcall:被调用者平栈(retn 0Ch)
• __thiscall:ecx=this(角色/对象指针),剩余右→左压栈
- __fastcall:ecx+edx 前俩参数,其余压栈
进 CALL 内部看 ret n / add esp,n 算参数个数,临时变量看 [ebp-xx],传入参数看 [esp+xx](注意 CALL 本身压返回地址占4字节)。
六、经典基址线索(老版1.76客户端参考)
主角色对象指针:[[0x59C7CC]+0x4C] = HP,+0x50 = MaxHP,+0x54 = MP,+0x58 = MaxMP,+0xD8 = X坐标,+0xDC = Y坐标;地图名指针:[0x59C7CC+0x10] → 字符串地址。
注意:不同补丁/周年版偏移会变,必须本机重扫,不能直接抄老教程地址。
七、定位完整步骤(以“走路CALL”为例)
1. CE 搜当前X坐标→微移→搜变动→锁定坐标地址 A
2. x64dbg 附加 Mir2Client.exe,对 A 下硬件写入断点
3. 游戏里点地面移动 → 断下 → 看调用栈返回到游戏领空函数 FuncA
4. FuncA 头部记下 RVA = FuncA - 模块基址
5. 分析 FuncA 参数:ecx(角色对象)、push 目标X、push 目标Y、push 方向
6. DLL注入测试:构造 ecx + 参数 → call(base+RVA) → 角色移动即命中
八、常见坑点
• 线程发包:不直接走 send,另起线程组包,需先追线程数据来源再回溯功能CALL。
- 包体加密:异或/RC4/查表,Wireshark抓到乱码,需在 send 前找加密函数模拟组包。
• 软件断点被检测:换硬件断点(DR0~DR3)、条件断点、隐藏调试器插件。
• 状态值误判:追血量找到的是表现函数不是吃药CALL,必须沿“功能→发包→回包→改值”正向链找。
- 偏移失效:客户端更新、补丁重打包、ASLR开启,必须重算 RVA。
九、调用验证最小代码框架
DWORD base = (DWORD)GetModuleHandle(L"Mir2Client.exe");
DWORD walkCall = base + 0xABCDEF; // RVA
__asm {
mov ecx, roleObj // 角色对象指针
push dir // 方向
push y // 目标Y
push x // 目标X
call walkCall
add esp, 0xC
}
角色移动即CALL正确;崩调用约定或ecx错位。
找全CALL后,走路+选怪+攻击+拾取+吃药+寻路组合,就是完整自动打怪闭环,剩下只是计时器与判断逻辑。
热血传奇客户端关键CALL定位实录:发包回溯基址偏移寻路攻击吃药全拆解
来源:
作者:
点击:

