FPS全屏秒杀以及全屏飞刀漏洞的逆向分析
FPS全屏秒杀以及全屏飞刀漏洞的逆向分析
- PlaneJun ・2019-11-19 20:45
目录
一、引言
二、正文
1、全屏飞刀原理及实现
2、全屏秒杀原理及实现
三、总结
四、白嫖
分析对象:CS1.6 5Eplay 版本
编程工具:Visual Studio 2019
工具:CheatEngine 6.7
一、引言
不知道有多少人是经历过穿越X线的神仙时代。我只记得当时最疯狂的是一个房间充满着各种奇葩的科学家,例如飞天、遁地、隐身、加速、子弹穿墙,飞刀等等,但是,最有意思的还是Bug不掉血的卡箱和卡墙。这些东西虽说是游戏的漏洞造成的,但是当时那个时候玩起来依旧是很开心,毕竟当时的游戏环境还是很认可的,武器属性的平衡,玩家之间的默契度,战队里的开黑,都让我们对当时的一些保留着一无比忘怀的怀念。



二、正文:
煽情完了,咱们开始正题。今儿咱们来说说远古时期的大发明-全屏飞刀和全屏秒杀。这篇文章依旧使用被无数次仙人跳的游戏来操作,嗯,没错就是CS1.6。

在我们干事之前,稍微对游戏的一个动作进行思考,这里咱们先讲全屏飞刀,再讲全屏秒杀。
一、 全屏飞刀原理及实现

这里我总结了三种思路:1、通过游戏播放的音效来寻找。细心的同志可能会发现,挥刀的时候,打中和没打中是有两种音效播放的,所以我们只需要在游戏目录下找到这个音效的名字,然后去文件操作相关的api下断,看他什么时候去访问这个文件就行了,断下后直接返回应该就直接能找到关键代码处。2、只要是个有脑子的人,手里拿着枪的时候可以砰砰砰的射击,但是切刀之后就没法实现击中效果了。那么他肯定会有一个关键跳转来判断你当前武器是否是刀(有可能判断当前手持的模型ID),这个时候找到这个跳转,搞就完事。3、都知道鼠标控制开火,那么鼠标消息肯定会经过关键代码,这个时候直接鼠标消息下断后去分析就行了,但是相比前两种方法,要分析的代码量更多,头发多的人推荐尝试。
这里我用的是第二种方法,但是其他方法依旧希望大家去试试,毕竟技多不压身(其实就是懒得去弄)。

在正式去找的时候我们先来整理一下思路。首先我们要找的是全屏飞刀,那什么是全屏飞刀?顾名思义,就是当我们拿着刀的时候不用贴着敌人也能打中敌人。此时我们是不是很容易去联想到攻击call?因为你的刀能不能攻击到别人是取决于你的攻击call的代码流程,所以在内部代码中极有可能存在着某条跳转用来判断你这个攻击是否有效,如果有效,给你击中;如果无效,直接给你ret。下面是给出的伪代码:
1 | bool 开始攻击(xxxxxxxx) |
理论就说这么多,咱们直接找吧!

首先咱们要找到游戏对人物处理血量的关键代码处,然后下断返回,就能看到攻击call了。很简单,找到血量->访问血量->射他->出现代码->记录代码->甩进OD->开始分析,其中前5步我就不演示了,直接放甩进OD的部分。


给他下个F2断点,然后用刀划他**(记住,一定要用刀划,因为我们先在是要找基于刀的攻击代码)**。

这里我返回5层,因为我分析过,所以知道这5层内必有我们要找的东西,但是在实际分析其他游戏的时候,建议大家多返回。
在开始分析这些call之前,我先和大家说两点非常关键的问题。
1)、我们从哪一层开始分析?
从最外层。为什么呢?很简单,因为越内层的call往往是对攻击处理,而不是对开始攻击逻辑的处理。实在不理解的话,咱们想一下咱们在写某个动作代码的时候,是不是先判断逻辑操作,再去执行核心代码?
2)、代码的执行逻辑
这个稍微有点难解释,因为他和第一个问题有小牵扯。如果我们对人物血量处理下断后返回层数不够多会怎么样?答案是,我们只得到了他攻击call处理代码。意思就是说当前得到的所有call是处理已经成功击打后的代码,而不是处理开始攻击逻辑的代码,导致在最外层下断的时候会出现一个问题,单纯挥刀不会断下,开枪才会断下**(因为你怎么开枪都会击中)**。解决的办法就是在人物血量处理地方下断后疯狂返回上一层并且记录,然后挨个下断挥刀,能断下说明找到了,断不下就再找。
接下来依旧是我最喜欢的摊牌环节。

其实在这5层中,第5层就是处理开始攻击逻辑的call,其他的全是成功击打的call。因为只有在第5层call下断挥刀的时候才会断下,其他call下断挥刀不断。不信的同志可以去试试,接下来我们就来分析第5层call。
我们现在先下一个断。

然后我们对着墙或者人物划一刀**(可以击中的状态)**,发现断点断下了。

这个时候非常关键,我们F7进去后F8单步跟一下。 注意,记得标记跳转是否实现
在通过F8单步跟的时候,细心的人会发现一个东西。


他这里会播放wav,实际上他这里就是在判断你的刀是否击打到物体,击打到了就播放击打音效,反之播放未击打音效。其实hit是击打音效,slash是未击打音效,笔者也是在分析的过程中看到这个才萌发处第一种思路。而且在单步跟踪的时候发现他跳过了播放slash音效,而去播放了hit音效并且执行了我们记录的第4层call**(攻击处理)**,说明上面有相关跳转控制了击打判断。
现在我们返回第5层call,下断,对着空气挥刀看看。

同样F7进入后,F8单步跟,并且记录跳转是否实现。

这里观察到之前的实现的跳转现在没有实现了,说明这里可能是一个关键点
包括下面这张图的位置

最后会发现他去执行了这一串代码

这一串刚刚好是播放未击中音效的代码。再继续F8单步跟,发现他直接ret了,并没有去执行我们第4层的攻击代码。

经过以上分析,我们得出了两个关键点,那就是那两个jne跳转。在我们对墙壁或者人挥刀并且成功击打的时候该跳转是实现的,但是现在我们对着空气挥刀发现他跳转没有被实现,那么说明该跳转就是关键跳转,而且他们都是对同一个地址进行了读操作,所以游戏很有可能是对该地址的值进行一个校验,来判断是否能击打。

首先这个代码是一个很典型的浮点数比较代码,大概就是将0x19FEC660 和st(0)比较后把状态值传给ax,然后ah判断是否能击中物体。我们用CE看看这个地址的值。

发现是0,我们尝试改为1。回到游戏的时候,发现我们挥刀的时候竟然是击中的音效。此时全屏飞刀已经实现。

一、 全屏秒杀原理及实现
虽然我们实现了全屏飞刀,但是会发现,当我们向敌人挥刀的时候,发现敌人并没有掉血,这个时候就会有人认为我在坑大家了。

其实呢,咱们还得需要一个东西,那就是选择攻击对象。这里呢,不知道大家还记得我在文章开头写的那个伪代码吗?我们当前只是修改了第一个if,但是还有第二个if**(可能还有更多if)**没有修改。我们虽然让他成功全屏攻击了,但是他可能会判断,你这个人和敌人是否在可攻击距离内,如果不在的话直接给你攻击一个空对象,具体的逻辑代码大家可以去分析一下。
现在咱们来说说这个全屏秒杀,无论你拿着什么武器,你要射人,那你肯定要有一个攻击对象吧。于是咱们可以去跟一下,看看他的攻击对象的来源,然后用第三方手段去修改,这样我们想打谁就打谁了。攻击对象很好找,因为你攻击call的参数必定有攻击对象,然后就去追这个对象的来源。这里呢我就直接放追到的来源。

其实这里就是第4层call进来的内容,我在OD也注释了,他这里做了简单的判断,如果你的攻击对象为0那么就ret,否则就对攻击力进行一个赋值,然后进行攻击。在这里我们可以去观察我们全屏飞刀的时候,他的攻击对象一直为0,那就说明他没有选择一个攻击对象。我们换成枪,去打一下敌人,发现他的内容变了。我们直接锁定,然后换成刀去划,发现这个时候咱们的刀能打人了,而且对着哪里划都能打中,包括枪。咱们这时直接去修改攻击力,直接是一划既死。这个时候灵机一动。

是不是我们直接让程序不断的向这个地址写入对象,然后在修改攻击力就完事了?没错。就是这样。下面是效果展示
其实这里还有一个处理方法,在0x1A0665F8下一个写入断点,能来到这个地方

其实这里是对攻击对象和攻击力进行一个0的初始化。处理方法很简单,直接在头部ret,不让他初始0,然后再用程序去写入会更稳定些,因为游戏会调用这个call,进行清0。
好了,基本上这就是全屏秒杀的分析。
另外 攻击对象的值=对象]+0x7C]

三、总结:
其实这个全屏飞刀的实现的思路是来源于我在很久之前就实现的植物大战僵尸的折叠种植功能,当时找的方法和本篇文章实现飞刀基本类似,就是用通过这种特殊的判断去分析的,在种植call下断后去实现一次普通的种植,然后跟进去记录跳转;然后再去种植call下断,直接去实现一次重叠种植,断下后F7进去单步直接可以发现关键跳转,然后直接改成jmp(好像是jmp),直接就实现了折叠种植。昨天前段微风吹过脑壳,突发奇想来试试,果不其然,还真能实现!但是出现了无法攻击到对象的情况,然后偶然发现在飞刀的时候攻击call传进来的对象是0,于是就想到应该有一个地方有赋值对象的。然后努力了一波,就实现了全屏秒杀和全屏飞刀的效果。

虽说这个是对cs1.6的漏洞分析,但是其他游戏的实现原理我觉得是差不多的,就拿飞刀来说,游戏肯定是需要去判断你这个武器是不是刀,是刀给你ret;反之给你攻击。所以这个地方基本上可以成为一个突破点。至于全屏秒杀,只要找到攻击对象的赋值也就差不多了。