小黑盒

来源自小黑盒

04月10日 10:29

作者:容大

道高一尺魔高一丈 PUBG的外挂与反外挂之争

导语

          虽说针对外挂问题官方一直在进行针对性封禁,但外挂技术同样日新月异,可谓道高一尺魔高一丈。

  绝地求生自面世以来,作弊外挂如同挥之不去的梦魇,不停地折磨着蓝洞公司以及广大绿色玩家。作为一个入坑时间相对较长的绿色玩家,内心深处一直渴望有朝一日这游戏能没有外挂,所有对手都是萌新。而昨日在巴拉巴拉站上看到大佬硬核狗的视频后才明白,外挂不会消失,而萌新则是杀一个少一个。

  言归正传,本文将大佬视频内容转译成图文形式(经同意),从技术层面上向各位盒友演绎这些年来蓝洞与外挂作者之间的刀光剑影。

  至于最终谁胜谁负,你我心中恐怕早有答案……

  (认为蓝洞就是靠杀鸡取卵封号挣钱的盒友看到这可以点击左上角退出了,以免浪费宝贵的时间徒生戾气)

  正文:

  作为一个FPS游戏,外挂对于游戏体验的破坏是非常巨大的。具体例如锁头、透视、穿墙、无后坐力等等。

  那么为什么FPS游戏中外挂屡禁不止?是不是游戏公司不愿意去与作弊者斗争?

  很遗憾,事实是,如果抛开Anti-Debug(反调试)的能力和法律层面,单从逻辑上讲,FPS类型的游戏面对锁头自动瞄准类型的作弊形式是毫无办法的。

  这无关于游戏厂商或者是逆向者(外挂作者)哪一方的技术实力更强,这是由游戏玩法逻辑决定的。

  如果要解释清楚为什么从逻辑上FPS游戏无法防止外挂,那就要从多人FPS游戏的服务器和客户端通讯逻辑讲起。

  例如在绝地求生中,这样的场景每天不停地在发生:

  在游戏中,你发现了一个敌人,瞄准他,开火射击,然后敌人被击中。

  当你发现敌人之前,游戏服务器已经将你周围的敌人信息下发同步给你的客户端。此时此刻,你的游戏客户端内存中有着如下数据:你周围有几个敌人、每一个敌人的坐标是什么、敌人身上的信息包括皮肤持有武器等等。

  当你发现了他,拖动鼠标进行瞄准。这个时候客户端会向服务器上报你这个动作,即:鼠标移动起始点,到每一帧鼠标划过的位置。通常会拆分成1秒钟3~10个数据包,采集关键帧后发向服务器,服务器再将这些差值轨迹同步给周围的其他玩家,其他玩家的客户端根据这些关键帧信息自动补全中间的动作差值,然后进行人物动作的绘制。

  之后在你按下鼠标时,客户端会根据你当前持有的武器从内存或配置文件中抽取这把武器的后坐力属性,然后将后坐力属性参与到你开火时镜头晃动的偏移运算中,然后再把你每次开火时的镜头朝向位置和后坐力偏移一同发往服务器,服务器根据这些数据来进行击中判定。

  每把武器的配置文件就储存在这个位置。

  当然现在这些文件是加密存储的,在启动客户端后会对这些文件进行解密操作,这也是为什么大家经常能听到无后坐力这种说法。原因就是因为外挂修改了内存中枪械的后坐力,让参与运算的后坐力偏移为0,自然就是无后坐力了。

  当然,这是一种比较傻的办法,很容易被服务器检测到你发过来的开火坐标是一个点,没有任何的偏移变化。于是……你就被Ban掉了。

  所以外挂通常会进行一些微小的偏移调整,伪装正常的用户行为。由于厂商发现外挂伪装后坐力的做法,于是修改了后坐力的算法。

  后坐力分为X轴偏移以及Y轴偏移,为了保持正常用户的手感一致,厂商不会经常改动后坐力的Y轴偏移值,也就是枪口向上的偏移。但是为了防止外挂,后坐力会有小幅度的左右随机移动。

  游戏厂商在每一局游戏开始的时候会向客户端广播一次随机种子来决定本局游戏中每把枪将产生怎样的随机后坐力。当你的硬件鼠标产生的位置偏移和武器的随机偏移值最终对不上的时候,就有可能是外挂通过内存形式改变了你实际的瞄准位置,从而被判定为外挂。

  但是道高一尺魔高一丈,外挂作者们发现自己的外挂封号率变高了以后,也升级了自己改变瞄准镜头的方式——从写内存变成利用硬件驱动,模拟第二鼠标轨迹来保证上传的硬件数据和真实玩家一致,同时还能达到锁头的目的。

  我们经常看到一些作弊者在游戏中的镜头并没有瞄准头部,但是不管他对着什么方向开枪,结果却是枪枪爆头。这个就不是锁头了。

  现在FPS游戏中为了追求真实,会将子弹单独实例化:这其中包括下坠、子弹速度等等,以求达到更真实的效果。子弹飞行轨迹通常为了节省服务器资源,是由客户端的物理引擎进行模拟之后再上报轨迹的。

  那么如果外挂篡改了子弹的飞行轨迹,也就是说不管子弹怎么飞,最终一个坐标点定到目标头上,你就会看到刚才描述的这种效果。就好比所谓的穿墙挂、魔法子弹等,其实就是修改了子弹的轨迹,并没有在枪械瞄准上做手脚。

  综上所述,无论是锁头还是锁子弹,有的是作弊方法,不管是不是服务器判定击中都防不了外挂——根源在于瞄准这个动作是由客户端发出的。客户端在外挂的加持下,就是头铁地告诉服务器“我打的就是目标的头”.

  服务器又怎能分辨出我是真的职业选手还是挂C呢?

  现在绝地求生中还流行着一种外挂,叫做雷达挂。它并不对游戏本体的内存做任何形式的修改,而是通过分析客户端与服务器之间通讯的数据包,将周围的敌人、资源等显示在另外一个屏幕上,这另外一个屏幕甚至可以是手机或者IPAD。

  它的原理是在客户端和服务器中间加入一个代理人程序,通过转发客户端和服务器之间的通讯来获取信息,这个在行业内叫作“中间人攻击”。

  游戏的客户端和服务器之间是需要网络进行通讯的。在早年的绝地求生中,蓝洞还是很稚嫩的,游戏客户端和服务器之间的数据包并没有进行加密,使用的是明文通讯,很快就有“热心”的网友将通讯协议解析好并公布。当然,现在的蓝洞已经将通讯协议进行了加密。

  所谓的加密通讯协议就是相当于是这个数据包在发出去之前先加密再发给服务器,到了服务器之后先进行解密然后再进行相应的处理。反馈给客户端的数据包也是一样的,发之前服务器加密再往客户端发。

  每一个用户和服务器通讯等额加密密钥都有所不同,每个游戏的加密方式也有所不同。一般都是在每局游戏开始的时候,在客户端和服务器通讯的前几个数据包互换密钥,加密方式基本一律都采用类似Aes的可逆加密。

  但是仅仅加密的通讯协议就能阻挡外挂开发者的脚步吗?他们太天真了。

  外挂作者擅长的作者是反汇编领空,他们通过二进制逆向杀入反汇编领空,找到关键的加解密函数,分析加解密函数对数据所做的操作,然后将一样的逻辑放在前文提到的中间人雷达程序中。

  由于分析加解密所需要的逆向、注入等操作是在前置阶段完成的。在真正的游戏运行过程中,这种雷达程序工作是不需要修改内存的,所以这种雷达外挂更加隐蔽,丝毫不注入游戏本身,也不会读取游戏的内存,从数据层面看起来毫无问题。

  这下又轮到游戏厂商头疼了,因为中间人雷达程序看起来和常规的加速器别无两样。要知道我们使用的加速器也是利用数据包的转发来达到加速效果的。

  那如何区分加速器和雷达挂呢?游戏厂商在发现雷达挂也具备加解密功能之后,又祭出了一个杀手锏——暗桩。

  所谓“暗桩”就是由于服务器不定期的发送一个奇奇怪怪的数据包,这个数据包里面的内容和意义与当前游戏逻辑没有任何关系。数据包加解密方式也和之前常规的数据包加解密不一致,同时又在这个数据包中标识了客户端应该用哪一套密钥回复给服务器。

  由于正常的加速器是不会在中间进行加解密操作的,只是单纯的转发,而雷达挂是要在中间做骚操作的。

  当这个暗桩发下来的时候,雷达挂并不知道要如何解密,于是肯定就原封不动地发给客户端了。而客户端拿到这个包之后是知道这个包的真正含义的,于是给服务器又回了一个包,并告知服务器在第几个序列号后的数据包更新密钥。

  双方这一来一回就已经拿到了各自想要的信息,而雷达挂在中间只关心游戏数据的拆解,并不知道这个暗桩约定了什么。

  而蓝洞也很鸡贼,并不会当场BAN掉作弊者,而是瞧瞧地记录作弊者的ID,于是在一段时间之后——突然一大批挂C同时倒下了(即我们常说的追封)。

  外挂作者也只好硬着头皮开始排插暗桩,过几天一大批雷达挂又纷纷上线卷土重来。

  一切仿佛又回到了原点……

  如果说锁头外挂从逻辑上没有办法防范,那么透视外挂是否可以通过在游戏逻辑层面加以限制呢?

  答案是肯定的。所谓透视外挂就是原本你不应该看到的敌人却被外挂通过服务器传回来的数据显示到了你的屏幕上……

  不知大家有没有想过为什么例如DOTA2或者LOL这样的MOBA类游戏的透视外挂非常罕见呢?

  其实不难思考,因为服务器在广播你敌人信息的时候做了一个小处理,只有你视野内的敌人服务器才会对你的客户端进行广播,那些处于战争迷雾中的单位你本身就不需要看到,客户端也不需要渲染,自然就没有必要发给你了。这种算法被称之为“剔除算法Occlusion Culling”.

  由于MOBA类游戏的特性,尤其是可以忽略高度轴的存在,所以用一个2D几何平面求一个点是否在一个圆形范围内的公式就可以轻松解决这个剔除算法。

  常见的MOBA游戏一局最多10个人,每一帧服务器运行10次2D的剔除算法毫无压力。那么3D FPS游戏呢?

  3D世界中的剔除算法其实也并不难写:从玩家当前视野朝向发射一条射线,射线没有被阻挡的地方就是可同步区域,然后将当前视角看不到的物体和单位全部剔除,不广播给客户端。

  这其实是一个很成熟的算法,又称为视锥算法:就是你看得到的东西我才告诉你,看不见的我就从内存中剔除。

  这和MOBA类游戏的战争迷雾从思路上是一致的,通常用于客户端渲染帧数的优化。在客户端上每秒运行60次这样的算法其实是完全没有问题的,毕竟客户端通常只需要运算自己这个主角。

  那如果把这个算法放到服务器端,运算量会成长成什么样子?

  在一个一局有100个人的吃鸡游戏中,服务器要想达到这个效果,不仅仅是每帧为这100名玩家计算可视单位。最可怕的是,服务器还要实时掌握每一个人的镜头运行朝向,并且伴随着角色移动以及视角更改重新计算剔除算法。

  按照1秒钟运算60次的情况,如果一局游戏有100个人,那么单台服务器每秒钟需要运算的量就是60*100=6000次。同时服务器还要对每个客户端做每秒60次的同步信息——就是说服务器运算完之后还要发给客户端。

  这显然对网络带宽和服务器运算资源产生了极大的浪费,没有哪个厂家愿意用这套算法跑在服务器上去防止外挂,巨大的资源消耗以及可能造成的延迟卡顿使得这个方案的投入产出比太低。

  明白了这个道理以后,基本上所有的厂商会把反外挂的重心进行转移,从实时反外挂在时间轴上向后沉淀——也就是根据游戏后的数据LOG对当前这些游戏来进行复盘分析。

  说白了就是使用统计学的办法设定出各种阈值,比如单场杀人的平均数之类的来进行抽查:例如某一局游戏中发现某一个玩家杀人杀得特别多,日志分析工具就会被激活,然后着重看一下这名玩家在各个行为上有没有异常,进一步分析这名玩家在这个游戏中的平均移动速度、后坐力、鼠标轨迹等等,最终抓住开挂者。

  这样的做法可能对于需要CDK的游戏有点作用,增加了开挂成本。但是对于那些免费的吃鸡游戏,例如APEX或者COD16,开挂成本就相当低廉了。(各位保护好自己的STEAM账号)如果不对外挂加以治理,这些游戏的人气将会迅速走向衰败。

  有的朋友会说“为什么企鹅游戏的外挂比较少?”,其实前文已经提到了,除了Anti-Debug日志分析这种技术手段,还有一种强有力的武器——法律。

  企鹅爸爸抓外挂作者那是毫不手软。

  所以外挂作者们经过几年的洗礼之后,都有一个不成文的规定,就是企鹅的游戏尽量不碰。虽然说过企鹅Tencent Protect的方法在黑市上只需要6000块钱就能买到关键Call,但是你看市面上谁敢大张旗鼓地贩卖企鹅的外挂?所以说不是腾讯的反调试能力强,而是外挂作者们都特别遵从自己的内心……

  厂商和外挂作者的博弈从未停止……也许真的只有等到国服上线举起法律之盾这场战斗才会逐渐平息吧。