004 两种方法找寻路call

关于寻路call

寻路call在大部分的游戏里都是存在的,游戏的策划为了用户体验,一般都会自带寻路的功能,可以一键自动让人物到目的地。

但是也有一些游戏不包含寻路call,那样的游戏就需要我们去找一些地图数据以及障碍的遍历判断等等,再自己用算法去实现。

这个寻路call不太适合用send断点回溯去找,因为在寻路的过程需要不断的向服务器发送数据包,是一个比较复杂的过程,里面可能有很多循环和逻辑算法。单纯通过一个简单的调用关系不一定能找到这个call。

通过参数找寻路call

CE搜索寻路目的地坐标

在找这个call之前我们先来思考一下这个call会有什么样的参数,参数可能会有很多个,但是有一个参数是必然存在的,就是寻路的目的地坐标。

在这里插入图片描述

这里有三个坐标分别是XYZ,选择任意一个即可。

在这里插入图片描述
先让人物进行寻路,寻路完成之后,当前的人物坐标就是目的地坐标。接着搜索人物当前的坐标。

在这里插入图片描述

坐标在内存中的形式都是用的浮点数,浮点数的值是经过四舍五入以后显示到游戏界面的,所以这里要搜索一个区间的值,而不是搜索精确值,区间尽量给大。

在这里插入图片描述

接着让人物进行寻路,寻一个远一点的位置,这个时候寻路目的地坐标发生改变,此时在CE里搜索变化的值。

在这里插入图片描述

然后在人物寻路的过程中目的地坐标是不变的,我们可以一直扫描未变动的值

在这里插入图片描述

等人物到达目的地以后,再用根据当前的人物坐标进行一个范围的浮点数值扫描。

在这里插入图片描述

一直重复这个过程筛选掉CE的结果,最后会剩下二十多个,这二十多个值都是一样的,都等于当前人物的坐标。那么说明这些值都是人物的目的地坐标。这种情况只能一个一个去测试。

通过参数定位寻路call

这里有两个基地址,有基地址的情况当然优先考虑选择用基地址。

打开OD,在这两个基地址下四字节的硬件写入断点。然后让人物寻路,此时OD断下

在这里插入图片描述

此时[edi+0x2C]是我们的目的地坐标,然后下面这个call将坐标作为参数传入下面的call,那么这个call有可能是寻路call,也有可能是在寻路call的内部对参数进行处理。

在这里插入图片描述

删除硬件断点,Ctrl+F9执行到返回,上面的这个call也可能是寻路call。

实际上这两个call都是寻路call,里层的寻路call有点类似于封包,需要对数据进行组包,所有的数据糅合在一起,分析起来不是那么方便。外层的寻路call参数多,比较清晰,分析起来方便。这里我们选择外层的寻路call进行分析。

寻路call参数分析

我们在外层的寻路call下断,让游戏断下。

在这里插入图片描述

esi这个地方是一个常量1,多测试几次会发现这个参数的含义是地图ID。

在这里插入图片描述

往上翻一下也可以找到这个地图ID的一个基址表达式

在这里插入图片描述

在这里插入图片描述

edx是一个地址,指向的地址内容是和当前的人物坐标是一致的,那么edx就是出发点的人物坐标,坐标在内存中的存储形式是XZY

在这里插入图片描述

D1F930这个地址有点眼熟,回到CE

在这里插入图片描述

这个地址正是我们用于找call的切入点,也就是目的地的坐标

在这里插入图片描述

最后一个参数ecx是一个当前模块的基址,没有什么特殊含义

寻路call代码测试

接下来用代码注入器测试一下我们找到的这个call是否有效

在这里插入图片描述

首先随便找一块地址按照XZY的方式填入出发点的人物坐标

在这里插入图片描述

然后在0D1F930填上人物的目的地坐标

在这里插入图片描述

在注入器填上相关的汇编代码,注入到游戏进程,效果如图:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ek4EuVau-1586586062769)(004 两种方法找寻路call.assets/自动寻路.gif)]

寻路状态找寻路call

搜索寻路标志位

当人物正在寻路的时候是处于跑动的状态,不寻路的时候人物处于站立不动的状态。在寻路call的内部一定会对这个状态进行改写。

利用这个特点我们可以利用状态值作为突破口,来定位到寻路call

在这里插入图片描述

首先在人物寻路的过程中搜索1

在这里插入图片描述

然后在人物寻路结束的时候搜索0

在这里插入图片描述
最后可以筛选出三个地址,我这里正确的地址是第二个,大家需要去挨个测试。

通过寻路标志位找寻路call

在这里插入图片描述

打开OD,在寻路标志位下硬件写入断点,等游戏断下

在这里插入图片描述

打开调用堆栈,找到最后一个call,显示调用

在这里插入图片描述

这个地方,就是我们之前找到的寻路call。

代码之前已经测试过了,这里就不再测试。另外这个call的参数有出发点的人物坐标,也就是说以当前人物坐标为切入点也是可以找到这个call 的,各位可以自行尝试,到此分析结束。

相关工具:

https://github.com/TonyChen56/GameReverseNote

  • 5
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
以下是五种不同的 MATLAB 代码实现: 方法一:循环遍历奇数序列中的每个数字,并判断是否包含数字3。 ```matlab num = 4727914947; odd_nums = 1:2:num; count = 0; for i = odd_nums if contains(num2str(i), '3') count = count + 1; end end disp(count); ``` 方法二:将奇数序列转化为字符串,然后使用正则表达式进行匹配。 ```matlab num = 4727914947; odd_nums = 1:2:num; str_odd_nums = join(string(odd_nums), ''); count = numel(regexp(str_odd_nums, '3')); disp(count); ``` 方法三:使用数组逻辑操作,将奇数序列中每个数字转化为字符串,然后统计包含数字3的字符串数量。 ```matlab num = 4727914947; odd_nums = 1:2:num; str_odd_nums = string(odd_nums); count = sum(str_odd_nums == '3', 'all'); disp(count); ``` 方法四:将奇数序列中每个数字转化为字符串,然后拼接成一个长字符串,最后统计其中数字3的数量。 ```matlab num = 4727914947; odd_nums = 1:2:num; str_odd_nums = string(odd_nums); long_str = join(str_odd_nums, ''); count = count(long_str, '3'); disp(count); ``` 方法五:使用 cellfun 函数,将奇数序列中每个数字转化为字符串,然后统计包含数字3的字符串数量。 ```matlab num = 4727914947; odd_nums = 1:2:num; str_odd_nums = cellfun(@num2str, num2cell(odd_nums), 'UniformOutput', false); count = sum(cellfun(@(x) contains(x, '3'), str_odd_nums)); disp(count); ``` 以上五种方法都可以求解出从1开始到4727914947的奇数序列中,数字3出现的次数。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

鬼手56

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值