找魔域的寻路Call,核心思路是用CE定位寻路状态变化点,下断跟踪到调用源头,然后扒出参数格式和调用地址。下面这套方法在多个版本的魔域客户端上都验证过,照着走基本都能拿到可用的Call。
**第一步:用CE找寻路状态地址**
打开CE附加到魔域游戏进程,先搜索数值1,然后在游戏里让角色走路或者点击地面寻路,切回CE搜索0,反复切换搜索直到剩下两条绿色基址。这两条基址里有一条是控制寻路状态的开关,修改为0能直接让角色停止走路的就是正确地址。
**第二步:下硬件写入断点回溯代码**
找到正确的寻路状态地址后,用CE或者XDBG在这个地址上下硬件写入断点。下完断点后在游戏里点地面触发寻路,断点会命中,这时候记下命中位置的地址。然后向上翻看汇编代码,沿着调用链往上回溯,找到push坐标参数和call指令的位置。
**第三步:定位真正的寻路Call**
实际逆向过程中,寻路Call附近通常会看到类似这样的汇编结构:
```
02AE963A | B8 D01B4703 | mov eax, 0x3471BD0
00CE679A | 8B10 | mov edx, dword ptr ds:[eax]
00CE679C | 6A 01 | push 0x1
00CE679E | 6A 00 | push 0x0
00CE67A0 | 6A 01 | push 0x1
00CE67A2 | 57 | push edi ; NPC名称或目标标识
00CE67A3 | 53 | push ebx ; 目的Y坐标
00CE67A4 | 56 | push esi ; 目的X坐标
00CE67A5 | 8BC8 | mov ecx, eax
00CE67A7 | FF52 04 | call dword ptr ds:[edx+0x4]
```
从这个结构能看出来,寻路Call一共压入了六个参数:三个固定值(0x1、0x0、0x1)、一个目标标识(可能是NPC或空值)、目的Y坐标、目的X坐标。eax寄存器存放的是一个基址常量,edx从该地址取值后,最终调用的是[edx+0x4]指向的函数。
**第四步:提取Call地址和调用格式**
把上面的汇编翻译成可调用的格式:
```
push 0x1
push 0x0
push 0x1
push 0
push 目的Y坐标
push 目的X坐标
mov eax, 0x3471BD0
mov edx, [eax]
mov ecx, eax
call dword ptr [edx+0x4]
```
注意在汇编里push的顺序是从右往左压入的,所以调用的时候最后一个push才是第一个参数。X坐标和Y坐标的值可以直接填地图坐标数字,不需要换算成屏幕像素。
**第五步:辅助验证手段**
如果走路Call调用后内存报错或者人物不动,多半是堆栈不平衡,检查有没有少push参数或者调用约定不对。走路Call通常是有参Call,参数里至少包含目的地的X和Y坐标值。另外也可以用寻路状态偏移来辅助判断,人物基址加上偏移+14C的值,在寻路中为1,停止为0,用这个值校验寻路是否触发成功。
**第一步:用CE找寻路状态地址**
打开CE附加到魔域游戏进程,先搜索数值1,然后在游戏里让角色走路或者点击地面寻路,切回CE搜索0,反复切换搜索直到剩下两条绿色基址。这两条基址里有一条是控制寻路状态的开关,修改为0能直接让角色停止走路的就是正确地址。
**第二步:下硬件写入断点回溯代码**
找到正确的寻路状态地址后,用CE或者XDBG在这个地址上下硬件写入断点。下完断点后在游戏里点地面触发寻路,断点会命中,这时候记下命中位置的地址。然后向上翻看汇编代码,沿着调用链往上回溯,找到push坐标参数和call指令的位置。
**第三步:定位真正的寻路Call**
实际逆向过程中,寻路Call附近通常会看到类似这样的汇编结构:
```
02AE963A | B8 D01B4703 | mov eax, 0x3471BD0
00CE679A | 8B10 | mov edx, dword ptr ds:[eax]
00CE679C | 6A 01 | push 0x1
00CE679E | 6A 00 | push 0x0
00CE67A0 | 6A 01 | push 0x1
00CE67A2 | 57 | push edi ; NPC名称或目标标识
00CE67A3 | 53 | push ebx ; 目的Y坐标
00CE67A4 | 56 | push esi ; 目的X坐标
00CE67A5 | 8BC8 | mov ecx, eax
00CE67A7 | FF52 04 | call dword ptr ds:[edx+0x4]
```
从这个结构能看出来,寻路Call一共压入了六个参数:三个固定值(0x1、0x0、0x1)、一个目标标识(可能是NPC或空值)、目的Y坐标、目的X坐标。eax寄存器存放的是一个基址常量,edx从该地址取值后,最终调用的是[edx+0x4]指向的函数。
**第四步:提取Call地址和调用格式**
把上面的汇编翻译成可调用的格式:
```
push 0x1
push 0x0
push 0x1
push 0
push 目的Y坐标
push 目的X坐标
mov eax, 0x3471BD0
mov edx, [eax]
mov ecx, eax
call dword ptr [edx+0x4]
```
注意在汇编里push的顺序是从右往左压入的,所以调用的时候最后一个push才是第一个参数。X坐标和Y坐标的值可以直接填地图坐标数字,不需要换算成屏幕像素。
**第五步:辅助验证手段**
如果走路Call调用后内存报错或者人物不动,多半是堆栈不平衡,检查有没有少push参数或者调用约定不对。走路Call通常是有参Call,参数里至少包含目的地的X和Y坐标值。另外也可以用寻路状态偏移来辅助判断,人物基址加上偏移+14C的值,在寻路中为1,停止为0,用这个值校验寻路是否触发成功。

