首页
论坛
课程
招聘
[原创]实现游戏角色的穿墙
2020-6-10 23:59 4062

[原创]实现游戏角色的穿墙

2020-6-10 23:59
4062

游戏环境:
热血江湖
WIN 7专业版 x64

 

效果图

 

原理:
游戏内,角色之所以不能穿过建筑物模型,是因为在游戏代码内,存在对障碍物的检测,如角色行进到某一处,向前的坐标可能是标识为障碍物,当角色被触发前进的操作,会先执行对前方障碍物的判断的函数,当前方是障碍物时,角色不执行前行的操作,而对玩家而言,就是操作角色在障碍物前卡住不前。所以对穿墙的实现,可以将游戏内对障碍物的判断nop 掉或者让它总是返回无障碍状态。

 

思路:
1、角色可以移动时,会对目的地坐标进行改写和访问
2、角色可以移动时,会对当前坐标进行改写和访问

 

相关基址:
角色基址:Client.exe+3E80BA0
目的地X 坐标:[[Client.exe+3E80BA0]+2420]
当前X坐标:(float)[[Client.exe+80BFFC] + 30]
在这里插入图片描述
·注:以上地址仅作为测试使用,临时分析得出

 

开始分析:
1、充目的地坐标入手,对该地址进行访问查看
在这里插入图片描述
整理得出:

代码段1:
0049BC3B - 56 - push esi
0049BC3C - 8B 75 10  - mov esi,[ebp+10]
0049BC3F - B9 07000000 - mov ecx,00000007 <<
0049BC44 - F3 A5 - repe movsd 
0049BC46 - 5E - pop esi

代码段2:
005D8C3B - 8B F3  - mov esi,ebx
005D8C3D - E9 5E010000 - jmp Client.exe+1D8DA0
005D8C42 - D9 06  - fld dword ptr [esi] <<
005D8C44 - 8B 4E 0C  - mov ecx,[esi+0C]
005D8C47 - 8B 56 10  - mov edx,[esi+10]

代码段3:
00456DB4 - D9 41 F8  - fld dword ptr [ecx-08]
00456DB7 - 83 C1 1C - add ecx,1C
00456DBA - D9 18  - fstp dword ptr [eax] <<
00456DBC - 83 C0 1C - add eax,1C
00456DBF - D9 41 E0  - fld dword ptr [ecx-20]

代码段4:
0049A7BB - 56 - push esi
0049A7BC - 8B 75 10  - mov esi,[ebp+10]
0049A7BF - B9 07000000 - mov ecx,00000007 <<
0049A7C4 - F3 A5 - repe movsd 
0049A7C6 - 5E - pop esi

代码段5:
0054507A - 8D 14 C5 00000000  - lea edx,[eax*8+00000000]
00545081 - 2B D0  - sub edx,eax
00545083 - D9 04 91   - fld dword ptr [ecx+edx*4] <<
00545086 - D8 A5 94FEFFFF  - fsub dword ptr [ebp-0000016C]
0054508C - D9 9D A8FEFFFF  - fstp dword ptr [ebp-00000158]

代码段6:
005454EF - 2B C8  - sub ecx,eax
005454F1 - 8D 04 8A   - lea eax,[edx+ecx*4]
005454F4 - 8B 08  - mov ecx,[eax] <<
005454F6 - 89 8D 64FEFFFF  - mov [ebp-0000019C],ecx
005454FC - 8B 50 04  - mov edx,[eax+04]

代码段7:
00530B19 - C2 0C00 - ret 000C
00530B1C - 8B 86 20240000  - mov eax,[esi+00002420]
00530B22 - 8B 08  - mov ecx,[eax] <<
00530B24 - 8B 7D 08  - mov edi,[ebp+08]
00530B27 - 89 0F  - mov [edi],ecx

在角色移动这个过程中,之前也大致猜测,流程可能是先进行障碍物的判断,在对角色进行操作,这个流程,处理操作可能有:
执行对障碍物判断的CALL----> 根据结果计算路径----> 将坐标传到FPU(坐标一般为浮点型数据) ----> 将坐标结构地址传递到寄存器(或栈) ----> 操作角色移动并同步服务器数据

 

所以一般这个过程靠前或许距离目标比较接近,在上面的访问代码中,正好有一段代码是对FPU 传递浮点数据005D8C42 - D9 06 - fld dword ptr [esi] <<所以,尝试在此处作为入口点

 

打开xdbg 32,并且附加游戏:
在这里插入图片描述
在这里,可能存在一段代码,是对角色前方障碍物的判断,既然有判断,那么应该会有一段判断的指令,如cmp、test 等,判断之前,可能是执行了判断前方是否有障碍物的CALL,所以可能存在如下形式代码:

call 某一处地址
cmp eax, X
jmp 某一处地址

注:这里可以使用x32 dbg 的流程图查看,比较直观的看到在哪些位置存在判断和跳转
在这里插入图片描述
向下查看代码,发现一处代码类似上面的结构
在这里插入图片描述

$+96     005D8CD8                   | E8 83F3FFFF           | call <client.sub_5D8060>                          | 存在一个CALL 判断,可能是判断前方障碍物
$+9B     005D8CDD                   | 83F8 02               | cmp eax,2                                         | 判断eax 是否为2
$+9E     005D8CE0                   | 0F84 2B020000         | je client.5D8F11                                  | eax == 2 跳
$+A4     005D8CE6                   | 8B8D 4CFFFFFF         | mov ecx,dword ptr ss:[ebp-B4]                     |
$+AA     005D8CEC                   | 2B8D 48FFFFFF         | sub ecx,dword ptr ss:[ebp-B8]                     |
$+B0     005D8CF2                   | 8BBD 78FFFFFF         | mov edi,dword ptr ss:[ebp-88]                     |
$+B6     005D8CF8                   | B8 93244992           | mov eax,92492493                                  |

在此处进行条件断点(eax != 1) 发现没断下来,估计这里可能只返回1,数值2应该是一个错误数值,在这里进行校正,进入到CALL 内部观察

 

同样,找一下有没有上面结构的代码段:

005D80DB                            | 8945 9C               | mov dword ptr ss:[ebp-64],eax                     |
005D80DE                            | E8 3DDDFFFF           | call <client.sub_5D5E20>                          | 在这里执行了一个CALL, 判断返回值是否为0
005D80E3                            | 8BF0                  | mov esi,eax                                       |
005D80E5                            | 85F6                  | test esi,esi                                      |
005D80E7                            | 0F84 DD000000         | je client.5D81CA                                  |
005D80ED                            | D945 08               | fld st(0),dword ptr ss:[ebp+8]                    |
005D80F0                            | 8B7E 14               | mov edi,dword ptr ds:[esi+14]                     |
005D80F3                            | D95D 88               | fstp dword ptr ss:[ebp-78],st(0)                  |
005D80F6                            | D945 10               | fld st(0),dword ptr ss:[ebp+10]                   |
005D80F9                            | D95D 8C               | fstp dword ptr ss:[ebp-74],st(0)                  |

而此处的CALL <client.sub_5D5E20> 对其进行下段
发现当角色前方存在障碍物时,返回值eax != 0,当前方没有障碍物时,返回的值是0,角色前移

 

所以,找一个CALL 是对障碍物的判断的可能性比较大,进入到<client.sub_5D5E20> 内部,尝试修改返回值:
在这里插入图片描述
或者也可以做以下修改:
在这里插入图片描述
这里推荐使用第一种方式修改,因为该函数在很多地方都进行了调用,修改返回值是比较高效率的改法

 

但修改后,并不能实现穿墙,但是可以实现坐标在障碍物上点击(之前点击是没有光标的)
修改后,出现光标:
在这里插入图片描述

 

虽然没有实现穿墙,但是找到了障碍物判断的函数,总结:
没实现穿墙的原因大概率是因为除了障碍物的判断函数以外,还有类似功能的代码,对游戏角色行进的位置进行校正。

 

并且也发现,当游戏角色可以移动时,当前坐标才会发生改变,当遇到障碍物时,这些代码是不会被调用的,所以从这个思路进行切入,查看改变了当前坐标的代码:
在这里插入图片描述

代码段1:
0043B09C - D9 50 38  - fst dword ptr [eax+38]
0043B09F - D9 50 34  - fst dword ptr [eax+34]
0043B0A2 - D9 50 30  - fst dword ptr [eax+30] <<
0043B0A5 - D9 50 2C  - fst dword ptr [eax+2C]
0043B0A8 - D9 50 24  - fst dword ptr [eax+24]


代码段2:
0043B304 - 8B 45 90  - mov eax,[ebp-70]
0043B307 - B9 10000000 - mov ecx,00000010
0043B30C - 8D B5 30FFFFFF  - lea esi,[ebp-000000D0] <<
0043B312 - F3 A5 - repe movsd 
0043B314 - 8B BD 70FFFFFF  - mov edi,[ebp-00000090]


代码段3:
005486B0 - D9 9F A41C0000  - fstp dword ptr [edi+00001CA4]
005486B6 - 8B BF 24340000  - mov edi,[edi+00003424]
005486BC - 81 C7 50020000 - add edi,00000250 <<
005486C2 - F3 A5 - repe movsd 
005486C4 - D9 85 30FEFFFF  - fld dword ptr [ebp-000001D0]

代码段4:
0053C0DF - 8B 83 24340000  - mov eax,[ebx+00003424]
0053C0E5 - D9 06  - fld dword ptr [esi]
0053C0E7 - D9 98 80020000  - fstp dword ptr [eax+00000280] <<
0053C0ED - 8B 8B 24340000  - mov ecx,[ebx+00003424]
0053C0F3 - D9 83 681C0000  - fld dword ptr [ebx+00001C68]

上面是对当前坐标进行访问的代码段,其中代码段1和代码段2是在角色移动开始和结束进行修改,代码段3是在角色移动过程中修改当前坐标,而代码段4是在角色移动结束后调用,所以,可以使用前面3个作为分析的切入点:
经过分析,发现代码段1和代码段2在下段点后都会一秒断下,说明在其他地方也在调用,这里我没继续分析下去,而是使用代码段3作为入口点:
在这里插入图片描述
同样,此处代码是在游戏角色前方没有障碍物时才会被执行到,所以可以猜测在这段代码前面的部分或者上层应该存在上述代码结构,对障碍进行判断,当没障碍时执行到该部分。使用流程图查看代码执行流程:
在这里插入图片描述

$-68     0054864E                   | E8 2DB70A00           | call <client.sub_5F3D80>                          |可能是判断障碍物
$-63     00548653                   | 8BF0                  | mov esi,eax                                       |
$-61     00548655                   | 8B47 14               | mov eax,dword ptr ds:[edi+14]                     |
$-5E     00548658                   | 50                    | push eax                                          |
$-5D     00548659                   | E8 026CECFF           | call <client.sub_40F260>                          |
$-58     0054865E                   | 33D2                  | xor edx,edx                                       | edx = 0
$-56     00548660                   | 83C4 04               | add esp,4                                         |
$-53     00548663                   | 3BC2                  | cmp eax,edx                                       |
$-51     00548665                   | 0F84 18160000         | je client.549C83                                  |
$-4B     0054866B                   | 3BF2                  | cmp esi,edx                                       | esi != 0
$-49     0054866D                   | 74 7A                 | je client.5486E9                                  |
$-47     0054866F                   | 83FE 03               | cmp esi,3                                         | esi != 3
$-44     00548672                   | 74 75                 | je client.5486E9                                  |
$-42     00548674                   | 83FE 02               | cmp esi,2                                         | esi != 2
$-3F     00548677                   | 75 0E                 | jne client.548687                                 |
$-3D     00548679                   | 8997 E4260000         | mov dword ptr ds:[edi+26E4],edx                   |
$-37     0054867F                   | 8D42 01               | lea eax,dword ptr ds:[edx+1]                      |
$-34     00548682                   | E9 A51B0000           | jmp client.54A22C                                 |
$-2F     00548687                   | D985 30FEFFFF         | fld st(0),dword ptr ss:[ebp-1D0]                  |

在此处断点,发现在前进时CALL client.sub_5F3D80 返回值总是为1,猜测可能是1标识可以前行,0、2、3标识不能前行或错误数值,所以进入call 内部,修改返回值,让call 始终返回1

005F456D                            | 5F                    | pop edi                                           |
005F456E                            | 5E                    | pop esi                                           |
005F456F                            | 5B                    | pop ebx                                           |
005F4570                            | 8B4D F0               | mov ecx,dword ptr ss:[ebp-10]                     |
005F4573                            | 33CD                  | xor ecx,ebp                                       |
005F4575                            | B8 01000000           | mov eax,1                                         | 修改eax = 1
005F457A                            | 8BE5                  | mov esp,ebp                                       |
005F457C                            | 5D                    | pop ebp                                           |
005F457D                            | C2 1C00               | ret 1C                                            |
005F4580 <client.sub_5F4580>        | 55                    | push ebp                                          |
005F4581                            | 8BEC                  | mov ebp,esp                                       |
005F4583                            | 6A FF                 | push FFFFFFFF                                     |

再次点击角色,发现实现穿墙:附上截图:卡在墙内的我
在这里插入图片描述

 

参考:郁金香老师教程
http://www.yjxsoft.com/forum.php?mod=viewthread&tid=3552&highlight=%E7%A9%BF%E5%A2%99


[公告] 2021 KCTF 春季赛 防守方征题火热进行中!

收藏
点赞1
打赏
分享
最新回复 (14)
雪    币: 20
活跃值: 活跃值 (12)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
明天去要饭 活跃值 2020-6-11 01:03
2
0
总结的很好,看了郁金香老师的教程 没看下去  一直在看他排错误代码了
雪    币: 1729
活跃值: 活跃值 (1731)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
tutuj 活跃值 2020-6-11 08:12
3
0
谢谢点评
雪    币: 5519
活跃值: 活跃值 (584)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
gamehack 活跃值 2020-6-11 10:45
4
0
感谢分享,这游戏真是好多年了,现在玩的人还多吗?
雪    币: 1729
活跃值: 活跃值 (1731)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
tutuj 活跃值 2020-6-11 11:36
5
0
现在都是僵尸号了吧
雪    币: 215
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
mb_fkpcckya 活跃值 2020-6-11 15:39
6
0
老哥留个联系方式啊 想写个登录器,卡住了,可否交流一下
雪    币: 256
活跃值: 活跃值 (171)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ZwCopyAll 活跃值 2020-6-11 16:04
7
0
感谢分享
雪    币: 4704
活跃值: 活跃值 (568)
能力值: ( LV3,RANK:25 )
在线值:
发帖
回帖
粉丝
alphc 活跃值 2020-6-13 16:22
8
0
很详细,爱了爱了
雪    币: 878
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
abin27 活跃值 2021-3-1 09:36
9
0
很棒,学习学习
雪    币: 1703
活跃值: 活跃值 (298)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
木志本柯 活跃值 2021-3-1 10:02
10
0
我凑不错的思路。。。。。。。。。
雪    币: 37
活跃值: 活跃值 (17)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mozzom 活跃值 2021-3-1 11:50
11
0
谢谢分享,很棒!
雪    币: 107
活跃值: 活跃值 (375)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ffashi 活跃值 2021-3-2 22:28
12
0
其实很简单的,不着太费事了,正常情况下,找到人物基址+偏移N 写0,穿一切,包括地面。
雪    币: 107
活跃值: 活跃值 (375)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ffashi 活跃值 2021-3-2 22:30
13
0
有一次手痒,突发超级异想。这个异想不敢说,反正结果是成立的。角色无敌。
雪    币: 9963
活跃值: 活跃值 (2147)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
ninebell 活跃值 2021-3-2 23:31
14
0
目标看得透,特征取得准;秃子狠瞎子愣,直接爆头。
雪    币: 107
活跃值: 活跃值 (375)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
ffashi 活跃值 2021-3-2 23:35
15
0
一种错位,导致角色无敌。
游客
登录 | 注册 方可回帖
返回