bp WS2_32.send
0018F844 008182FB /CALL 到 send 来自 Game.008182F5
0018F848 00000898 |Socket = 898
0018F84C 7E8C0040 |Data = 7E8C0040
0018F850 00000042 |DataSize = 42 (66.)
0018F854 00000004 \Flags = MSG_DONTROUTE
消息队列:并不是windows里面的消息队列,而是游戏内部的消息队列,使用quene
先进去的消息就先执行
通过硬件写入断点,可以找到一个调用堆栈,如果在还没有移动的时候就已经断点了,
说明不是当前断点,一定要在进行移动之后断点下来的,才是真正执行的地方
小提示: 通过Ctrl+K 获取调用堆栈列表,可以复制到剪切板
地址 | 堆栈 | 函数过程 / 参数 | 调用来自 | 结构 |
---|---|---|---|---|
0018F66C | 00716477 | 包含Game.00819624 | Game.00716474 | |
0018F724 | 004569D7 | ? Game.007163A0 | Game.004569D2 | |
0018F814 | 00457EBB | Game.00456840 | Game.00457EB6 | |
0018F954 | 004598C9 | Game.00457D10 | Game.004598C4 | 0018F950 |
0018F960 | 0043BAD4 | 包含Game.004598C9 | Game.0043BAD1 | 0018F9AC |
可以从 ( 调用来自) 00716474->004569D2->00457EB6->004598C4->0043BAD1 一层一层的找
得到调用点 00457EB6
0018F814 00457EBB Game.00456840 Game.00457EB6 //顶层调用点
c++ 代码模拟
//定义目标点结构体
typedef tagPoint{
float x;
float y;
}POINT,LPPOINT;
// 游戏内部的用户对象
Player player;
POINT tagetPoint = {};
targetPoint.x = 155;
targetPoint.y = 253;
//执行移动
player.Move(targetPoint)
c++ 汇编为win32汇编后的代码:
sub esp,20H
mov eax,431b0000H ;155 的float的值
mov [esp],eax ; 不能直接给非通用寄存器赋值
mov eax,437d0000 ;253 float 的值
mov [esp+4],eax
mov ecx,[7EF30010] ;游戏内部的用户对象的内存地址,本章节不做用户基址的搜索
push esp ;结构体入栈
call 03105121 ;游戏内部通常使用_stdcall ,不用自己进行add esp,n 堆栈平衡
add esp,20H ; 这个是为了恢复自己申请的栈空间
//假设游戏玩家类有这些字段,n[0xm]表示我们不知道的内容
class Player{
char nothing[0x160];//占位0x160个字节,不知道前面放的是什么,只知道0x164是状态
int state; //占位4
char nothing[0x18];// 占位 0x18
bit isAlive ;第0x180位的状态
};
//流程图中的 `移动函数开始`
define MOVE_STATE 2
if(player.state == MOVE_STATE && player.isAlive){
... dosomething
player.Move(point);
}
cmp [ecx+164],3;汇编的数字都是16进制,164 表示 0x164(10进制356),而不是10进制的164
je 07aa0110 ;判断用户的状态是不是移动,是移动就跳转到结束
cmp [ecx+180],1;判断是否活着
je 07aa0110 ;死亡就结束
call move;判断执行完成之后,就执行移动
现在就是通过第4节的 顶层call 00457EB6
在这里向上回溯,知道找到条件判断,进入一小段函数体的判断
两个判断,如果都成功才会进入走路call
00457D3B 8A86 64010000 MOV AL,BYTE PTR DS:[ESI+164]
00457D41 84C0 TEST AL,AL
00457D43 53 PUSH EBX
00457D44 74 17 JE SHORT 00457D5D
00457D46 83BF D8010000 0>CMP DWORD PTR DS:[EDI+1D8],2
00457D4D 75 0E JNZ SHORT 00457D5D
00457D4F 8B87 E0010000 MOV EAX,DWORD PTR DS:[EDI+1E0]
00457D55 85C0 TEST EAX,EAX
00457D57 0F84 7C010000 JE 00457ED9
00457D5D 8DBE 4C010000 LEA EDI,DWORD PTR DS:[ESI+14C]
if(esi+0x164==1)//是否活着
{
if(edi+0x1d8!=0x2)//可能是 人物移动状态
{
//具体移动代码
}
}
调用堆栈
地址 | 堆栈 | 函数过程 / 参数 | 调用来自 | 结构 |
---|---|---|---|---|
0018F45C | 0045823F | ? Game.00457AA0 | Game.0045823A | 0018F458 |
0018F47C | 0045A1D1 | ? Game.004581E0 | Game.0045A1CC | 0018F478 |
0018F4F8 | 0045983C | 包含 Game.0045A1D1 | Game.00459839 | 0018F4F4 |
0018F50C | 00459971 | Game.00459800 | Game.0045996C | 0018F508 |
0018F524 | 00455D33 | 包含 Game.00459971 | Game.00455D30 | 0018F520 |
0018F5C4 | 0056E231 | 包含 Game.00455D33 | Game.0056E22E | 0018F5C0 |
0018F5E0 | 004649D9 | 包含 Game.0056E231 | Game.004649D6 | 0018F5DC |
0018F960 | 007ABB04 | 包含 Game.004649D9 | Game.007ABB01 | 0018F95C |
0018F9D4 | 007AF7BF | Game.007AB270 | Game.007AF7BA | 0018F9D0 |
Game.0045823A-> Game.0045A1CC->Game.00459839-> Game.0045996C -> Game.00455D30 -> Game.0056E22E -> Game.004649D6 ->Game.007ABB01 -> Game.007AF7BA
依次寻找,直到找到游戏引擎的循环体的前一步
地址 | 堆栈 | 函数过程 / 参数 | 调用来自 | 结构 |
---|---|---|---|---|
0018F5C4 | 0056E231 | 包含 Game.00455D33 | Game.0056E22E |
0056E200 55 PUSH EBP
0056E201 8BEC MOV EBP,ESP
0056E203 8B0D C08CB300 MOV ECX,DWORD PTR DS:[B38CC0]
0056E209 56 PUSH ESI
0056E20A 8B75 08 MOV ESI,DWORD PTR SS:[EBP+8]
0056E20D 56 PUSH ESI
0056E20E E8 BDB72300 CALL 007A99D0
0056E213 A1 D885B200 MOV EAX,DWORD PTR DS:[B285D8]
0056E218 8B48 5C MOV ECX,DWORD PTR DS:[EAX+5C]
0056E21B 8B46 04 MOV EAX,DWORD PTR DS:[ESI+4]
0056E21E 8B89 E4010000 MOV ECX,DWORD PTR DS:[ECX+1E4]
0056E224 8B11 MOV EDX,DWORD PTR DS:[ECX]
0056E226 6A 00 PUSH 0
0056E228 6A 01 PUSH 1
0056E22A 50 PUSH EAX
0056E22B 8B06 MOV EAX,DWORD PTR DS:[ESI]
0056E22D 50 PUSH EAX
0056E22E FF52 10 CALL DWORD PTR DS:[EDX+10]
0056E231 FF15 84699000 CALL DWORD PTR DS:[<&tEngine.TdGetTim>; tEngine.TdGetTimeTickCountSafe
0056E237 A3 389CB200 MOV DWORD PTR DS:[B29C38],EAX
0056E23C 5E POP ESI
0056E23D 5D POP EBP
0056E23E C2 0400 RETN 4
push 0
push 1
push 0x42bc0000
push 0x438a0000
mov ecx,[0B285D8]
mov ecx,[ecx+0x5c]
mov ecx,[ecx+0x1e4]
mov edx,[ecx]
mov edx,[edx+0x10]
call edx
经过测试,可以成功进行本图寻路
[[B285D8]+0x5C]+0x1E4
8B 11 6A 00 6A 01 50 8B 06 50
1.人物基址寻找(为了课程连贯性,人物基址查找和人物信息查找,单独做一节)
2.特征码寻找 ,(用来在游戏更新之后,我们可以根据特征码自动定位基址,而不是在重新找一遍)