某刀从首测开始已经经历了6年的时间,因为画风唯美,玩法多样,如今依然热度不减当年,这也导致了外挂工作室的层出不穷。虽然游戏进行了反复的修改,已经基本杜绝了BUG的出现,而且各类检测也限制了大部分工作室外挂的功能,但是依然有一些暴利功能可以通过内存的角度来实现。
狩猎是游戏中的一个非常重要的日常玩法,结合了RPG和FPS游戏的多种元素。由于狩猎过程中可以掉落装备强化中必不可少的材料,导致大量的外挂工作室盯上了这里。多方竞争导致最初封包自瞄秒怪已经无法满足其牟利需要,于是很多外挂开始从收包入手,来提高代码效率,达到抢怪的效果。
由于从收到服务器的协议封包到本地的数据结构遍历这个过程中,会经历很多的代码,其中还包括很多反调试所必须的VMP,代码混淆,以及线程循环。所以在怪物刷新时,直接收包读取怪物信息,和遍历本地结构里的信息要经过短暂的时间间隔,大概几十毫秒甚至上百毫秒。这个时间从玩家的角度来看,是无法分辨出来的,但是从软件的代码角度来讲是可以做很多事情的。这就导致现在不用收包是无法抢到被狩猎动物的。下面,我们就对这款游戏的64位收包函数进行分析,并找到怪物刷新的封包。
首先我们用64位的xllydbg对游戏进行加载,并跳转到recv函数头部(如图)
下F2断点观察recv的参数情况(如图)
游戏断下之后,我们发现RCX,RDX都是比较正常的情况,分别是socket和buf,但是R8的值只有5,也就是说收包的len非常小,这显然是不正常的,说明这有可能是一个干扰包,或者是一个心跳包。于是我们从新下断,并点击F9,发现R8在执行几次后变成了0x101052,这比较像正常收包的情况。(如图)
在这种情况下执行到返回,我们发现返回的位置和之前返回的位置是不同的(如图)
接下来就需要我们找到分解的收包,在函数上下F2断点,并点击F8单步执行(如图)
此时经过了收包函数,说明已经收到包,我们在游戏断下的情况下在包内下硬件访问断点(为了避免断在包头的位置,我们尽量在稍微靠下一些的位置下断),游戏断下(如图)
执行到返回后我们来到一个memmove函数处(如图)
在这里下断,并喊话,我们发现这里已经是明文收包的位置(如图)
我们喊话的内容是11111111,在包里会得到很多“31”的ascii编码字节集,我们还可以确定包长为0x63,单步执行后RDX向RCX里面拷贝了收包内容(如图)
在确定了明文收包的位置以后,我们就可以分析刷怪包了,由于怪物的刷新时间是我们无法准确掌握的,所以最好的方式是通过HOOK收包来进行分析。另外一种办法就是通过观察,得出怪物大概的刷新时间,然后提前下好断点,并不断的点击F9来获取刷怪包。
首先我们在不杀死怪物的情况下下F2断点,并不断点击F9来观察收包长度的变化,发现这里的包长大部分为0x36和0x19,并没有特别大的包出现(如图)
然后我们杀死一些怪物,并在怪物快要刷新的时候下F2断点,在点击F9执行的时候发现出现了一些包长为0x239的封包(如图)
接下来我们对这些封包进行观察,发现在+40的后面会出现一些UTF-8编码的字符串,经过转码后可以得到刷新怪物的名字(如图)
这样就可以确定封包为刷怪包了,接下来只要通过HOOK收包,对包头和内部的属性进行关联,就可以得到怪物的ID,坐标,等其他信息了。
通过这种方式获取到的怪物信息,要比在内部获取到的信息快了很多,这个差异淘汰了很多狩猎工作室,但同样也对游戏的平衡性产生了更大的影响,玩家在看不到怪物的情况下,怪物就已经被打死了。可以从CRC检测HOOK,以及加入时间戳,对怪物的刷新时间和死亡时间进行判断,来检测是否是玩家进行的操作。
玩游戏,学逆向,做安全,欢迎感兴趣的小伙伴关注我们。