1 先找到 一只怪物 血量的地址

然后F5,再打怪
image.png

2 分析出 怪物对象的地址

有两种可能
0050439D - 89 86 FC050000 - mov [esi+000005FC],eax <<
ESI=3CC0D1E0

0089DD0A - 89 83 F4050000 - mov [ebx+000005F4],eax <<
EBX=3CC0D1E8

3 找怪物对象的基址

所以再分别搜索 这两个地址
对于3CC0D1E0,没有基址
image.png
对于3CC0D1E8,有两个基址
image.png
所以,怪物对象: 3CC0D1E8,怪物血量:[3CC0D1E8]+5F4
怪物对象的基址:02E6CDA4 或 04280BBC

4 用OD附加游戏进程,在内存窗口中

dd 02E6CDA4 dd 04280BBC
image.png image.png

5 在血量上方一定偏移处两个基址都发现了怪物名称,说明两个都是怪物对象基址。
但是可能一个是 所有怪物对象基址 ,一个是 周围怪物对象基址 。 凭感觉右边紧凑排列着怪物对象的应该是 我们要找的周围怪物对象基址。
备注:可以通过dc [02E6CDA4+4*i] + 5F4一直自增i来验证,会发现里面还有其他对象

dc [02E6CDA4] + 5F4 dc [04280BBC] + 5F4
image.png image.png

6 不妨取怪物对象基址为04280BBC
找到怪物名称的偏移,为: [怪物对象基址] + 360。且怪物对象基址-4 就变成了另一个怪物对象了。
image.png image.png
猜测04280BA0就是怪物列表的基址
image.png

7 可以对怪物对象的基址下一个内存访问断点,怪物列表应该经常要访问这个怪物对象。
看它断下处的代码段附近有没有基址,有的话那个基址就是我们要找的怪物列表基址。
image.png

8 果不其然,代码段就断在了这里,所以, 周围怪物列表的基址: 04280BA0
[04280BA0+4i]+360 名称
[04280BA0+4
i]+5F4 血量
[04280BA0+4*i]+5F8 等级
image.png

9 记下特征码
008A25B1 . BC 7119018B mov esp,0x8B011971
008A25B6 ? 088B 91E40000 or byte ptr ds:[ebx+0xE491],cl
008A25BC ? 006A 01 add byte ptr ds:[edx+0x1],ch
008A25BF . 6A 0E push 0xE
008A25C1 ? 50 push eax
008A25C2 > FFD2 call edx
008A25C4 ? 8B0CB5 A00B28>mov ecx,dword ptr ds:[esi*4+0x4280BA0] ;周围怪物列表基址
008A25CB ? 8B01 mov eax,dword ptr ds:[ecx] ; Client.00AAF118
008A25CD ? 8B50 04 mov edx,dword ptr ds:[eax+0x4]
008A25D0 ? 6A 00 push 0x0
008A25D2 ? 6A 01 push 0x1
008A25D4 ? 6A 02 push 0x2
008A25D6 . FFD2 call edx

10 还可以改一个怪的名字和等级玩玩
image.png

11 在内存窗口里 查看 32位浮点,找一下怪物坐标,先找一个 巨斧山贼,然后查看 32位浮点
image.png
image.png
image.png
坐标X: [4280BA0+4i]+1060
坐标Y: [4280BA0+4
i]+1068

12 再找怪物的状态,为了方便,我们先给一个怪物改个名字
image.png

13 然后到它的起始 地址
image.png
用CE从这个地址开始搜,活着搜1,死了搜0
image.png
最后找到这个地址,974H-620H=354H。所以,+354H 是否死亡
image.png

14 结论
周围怪物列表基址:04280BA0
死亡状态:[04280BA0+4i]+354
名称:[04280BA0+4
i]+360
血量:[04280BA0+4i]+5F4
等级:[04280BA0+4
i]+5F8
坐标X:[4280BA0+4i]+1060
坐标Y:[4280BA0+4
i]+1068