在游戏研发中如何有效防止外挂程序

由于HTTP协议是明文传输,很容易通过抓取HTTP包获取游戏内交互的逻辑和数据,请问如何能有效地防止外挂程序?

总的说来,道高一尺魔高一丈,外挂不可能100%被杜绝,只能通过不同的手段来防止大部分的外挂,具体可以从以下几个方面考虑:
1. 协议层加密
以flash客户端为例,在与后端做数据通信时,可采用amf协议,它虽然也是基于http协议,但是对传输的内容做了加密。当然,amf协议是透明的,所以该方法只能干掉一部分只知道用httpwatch/firebug等查看明文http包传输工具的小白。
如果需要继续增加门槛,可以自定义加密协议。但由于客户端需要知道解密方式,所以客户端本身也需要做好加密。关于flash本身格式的加密解密是另一个比较大的话题,在此就不展开赘述了。
2. checksum校验
客户端发送数据时增加一段checksum校验码,服务器端根据相应的算法进行校验,如果校验不通过则返回错误。与(1)一样,只要破解了客户端就可以知道checksum的校验算法。因此一方面需要注意客户端的安全,另一方面checksum生成算法需要不定期更换。
3. 通过任务策划来防治
外挂主要是代替人工来做些重复性的工作,这样玩家可以不操作电脑也能在游戏中获得收益。外挂的出现一般都是和利益有关,最好的治理方式是引导而不是打压,因此我们可以在产品设计方面做些降低外挂的工作:
1)降低长时间重复性任务所获得收益,或者同一种获得收益的任务随时间的增加收益减少。
2)游戏本身提供一些类似外挂的功能:比如自动打怪等辅助工具。
4. 定期检查数据
通过排行榜等数据统计,可以通过发现一些异常的数据来检测是否有外挂存在
5. 深入玩家内部,了解外挂行情
这个是客服们的工作,与技术关系不大,但有时能起到意想不到的作用。

 

防治外挂,首先要了解外挂,知道它有哪些主要功能,具体是怎样运作的,然后针对外挂的一般特性做抓捕脚本,我自己的经验大致总结有以下几点:

  1. 稳定周期性:外挂另外一个特点是周期性比较强,一般的设定是每隔XX秒执行XX操作,如果外挂是规律性的周期的话,有一个很容易抓捕的办法,就是每次同样的请求时都在session中记录下当前时间与上一次请求时间,两者的差值如果在多次请求中保持不变,基本上就能判定是外挂了,但是外挂现在很智能,周期是浮动的,比如周期设定为1分钟,浮动值设置为5秒钟,那么两次请求周期就是55秒-65秒,浮动值也可以手动设定,这样的话,这种方法就失效了。这种方法适用于基础级的外挂。
  2. 请求次数多:外挂为了定期监测一些数据变动,会频繁的发送一些请求,所以在请求数量上要比正常玩家的操作多很多倍,服务器端可以设置计数器,记录每个玩家每小时的请求次数,每小时筛选出来一批大于平均请求数N倍的玩家(N可以按实际需要设置),这些玩家记录为“疑似外挂”的情况。这也适用于单个某个请求的统计,比如getUserInfo这类查询类的请求。
  3. 设置外挂钓钩:外挂主要的特性是“自动化”,也就是按照预先指定的模拟指令来模仿客户端的操作。我们可以让游戏真实的客户端在每天的某几个时段在外挂常用功能的请求中加入特殊参数,服务器端通过判断是否有此参数或参数的值是否正确来判定此请求是否外挂发出,据此记录该玩家为“疑似外挂”。这种方法的特点是:钓钩参数(我起名叫“钓饵”)时有时无,外挂作者不容易捕捉到此钓饵数据,不容易被破解,但由于客户端和服务器端的时间会有不同步的情况,所以有一定误抓的可能性。
  4. 外挂的处理:处理外挂一定不能一发现就踢掉或提示验证码等等,这会让外挂捕捉到你的处理方式,应该是以记录+打分的方式,记录每一次“疑似外挂”的行为,每种行为按照疑似程度设置不同的分值,然后按照总的分值制定一个分值标竿,大于这个分值的,按运营手段处理,封禁也好、不定期弹出验证码也好。总的原则就是“非即时性”,让外挂作者不易察觉到你的抓捕机制,从而增加外挂升级更新难度。

其他针对游戏设计以及游戏生态的外挂功能也有相应的抓捕方式,不过还是那句话“道高一尺魔高一丈”,外挂做的越来越像客户端,原生的客户端一升级版本也有可能被误抓为外挂,所以我认为,抓外挂的手段中,辨别请求来源是很难的,这是游戏中外挂不好处理的主要原因。

看了前面几个兄弟的回答,从技术角度上已经很完备。
简单从产品和运营层面上说说我的经验,希望给大家点启发。第一次回答问题,有不当的地方,请大家尽情喷。

在之前的工作中,认识不少做外挂的朋友,也得知某些游戏外挂一年的销售额可以达到1200万人民币。
巨大商业利益的背后,是外挂团队极强的技术能力,对于网络协议加密,通过研读汇编语言去进行破解,是很常见的形态。从某种意义上说,与外挂的斗争,仅仅依靠技术手段,是无法取胜的。所以在各位所说的技术方案的基础上,应该制定一些策略。

外挂作为依附于游戏产品的衍生品,目前都有及其明确的商业目的,主要盈利模型:
1,通过收取玩家的月卡费用进行收费;
2,通过出售给金币工作室进行收费。
而我们的游戏设计首先能够设法杜绝工作室打金币的行为,使得第二个用途失效。这个做法是策划和运维的范畴,不同游戏类型有不同的做法,在此不做详细说明。

与外挂斗争,首先要确认几个关键的前提:
1,外挂的收入严重依赖一个前提,就是外挂的长期适用性,若经常不能使用,则无法保有付费用户。
2,外挂的利润率与外挂本身的更新难度、维护难度以及开发成本有直接的反比关系,因此当开发我们的外挂成本更高时,他们会倾向于去找一个难度更低的产品。
3,外挂团队一般小而精干,换言之,个人水平高,但人数有限;
4,外挂通常会降低用户的使用门槛并且尽量的做自动化。
5,外挂可能会利用游戏漏洞。

所以斗争的有效办法有以下几类:

1,疲惫法。不断地用小版本更新,来更改通讯加密的密钥,使得外挂制作者需要不断的破解,而相应外挂也会随着其破解能力的不同产生长短不一的失效期;
2,内挂法:游戏设计中涵盖外挂的大部分能力,适用于强PK MMO游戏;
3,考试法:对于长期进行枯燥循环的玩家,强制要求输入验证码,这种方式相对设计难度低,对于小外挂团队有效(大的外挂团队会开发识别算法甚至使用客服人肉回答);
4,隐形惩罚法:对于判断出是工作室使用的外挂,采取强制降低掉率的方式,使其很难盈利;
5,举报法:鼓励玩家举报外挂玩家,判断后加以惩罚。

当然,最好的办法是产品设计之初就考虑到外挂问题,使其不可能发生,这就是个很大的话题了,可以专门写本书,不详细说了:)

楼上的都说的很好,@胡春晖的checksum校验可以校验自身程序防篡改、@丛杰的基于行为的识别方法、@陈彦旭的二进制类似AMF协议的自定义协议方法。反外挂是我在公司的一项主要工作,一直没时间总结。来晚了,请不啬赐教。

外挂按实现技术分为“模拟类外挂”、“内部CALL调用外挂”、“脱机外挂”。

模拟类外挂”是外挂的鼻祖,靠发送或伪造按键消息到游戏客户端,模拟人的手工操作。实现技术分为Ring3层(应用层)、Ring0层(内核层)两种。

Ring3层通过Windows应用层API(SendMessage、PostMessage、keybd_event、mouse_event、SendInput,keybd_event和mouse_event会调用SendInput)向客户端消息队列发送键盘鼠标消息实现的。

Ring0层通过调用内核未导出函数 KeyboardClassServiceCallback、MouseClassServiceCallback实现的,其实这两个函数是Windows端口驱动在获得键盘鼠标硬件输入后往上传递给类驱动的两个回调函数(何为端口和类驱动需要补驱动和内核知识了:))。也就是正常情况下操作系统也是这样实现的。广州开发的“梦幻昆仑”游戏的一款很火的外挂“易坤辅助”就是这样实现的,从何而知?逆向工程又派上用场了。

防御的方法使用HOOK(替换原始函数),当外挂调用应用层API时,判断SendMessage、PostMessage、SendInput的目的地是否为我们的游戏客户端、发送源是哪个进程,若是系统或常用软件进程则放过,不是则阻止(做得好的话还需要判断一下发送的是否为按键消息)。

当外挂调用两个内核未导出函数时,在我们的HOOK函数中判断是哪个函数调用的,貌似这点不用汇编较难实现,汇编[ebp+4]即为调用者代码的下一句地址,再跟实际操作系统调用的函数地址对比,若一样则放过,不是则认为是外挂在模拟。这个方法也是我反“梦幻昆仑”的“易坤辅助”所用的方法,而现用的HProtect未做到这点。显然不能说我技术比他牛,HProtect做的工作n*n多。但“梦幻昆仑”一直被这样打着辅助旗号的伪善工具吸吮着。

内部CALL调用外挂”是稍后出来的技术,通过逆向工程反汇编、反编译分析游戏内部函数调用逻辑。比如:XXX游戏使用attack()函数对怪物进行攻击,外挂编写者分析出这个攻击函数后,就用这个函数作为外挂的打怪功能。由于需要精通汇编和逆向分析技术,所以较模拟类外挂实现起来较难,此类外挂也较少。

防御的方法要使用加密壳对客户端程序进行保护,或程序中运用反调试、暗桩(与丛杰的“非即时性”报告检测差外挂原则类似)。这样就可以一定程度上的抵御外挂作者对程序逻辑的分析,但会脱加密壳、反反调试的人大有人在(中国从来不缺少人才)。不过使用“虚拟机壳”+代码乱序+多态变形+深层次的反调试(可以利用自己挖掘的漏洞)可以吓到90%的外挂编写者,外挂编写者不是畏惧技术难度搞不定,卓越的程序员从来不觉得哪项技术难,而是花时间与游戏保护(反外挂程序)周旋的成本比外挂带来的价值大。

脱机外挂”是难度最大的一种外挂,外挂开发者需要完全分析出游戏客户端与服务器的通信逻辑,达到不使用官方游戏客户端,自己通过发送接收数据与服务端交互。但把通信数据加密和签名认证过程,足以让脱机外挂开发者雪上加霜。加密算法选用成熟的对称加密算法:3DES、AES、TEA等,密钥协商使用非对称加密算法或Diffie-Hellman。因为对称加密算法较快,加密大量通信数据需用此;非对称加密比对称的慢几十倍,传送个小数据量的对称加密用到得密钥合适。其实更简单的方法是配置上李老师做得加密框架。

有人可能会问到,用非对称加密算法传送对称加密用的密钥,不也需要客户端配置好公钥、服务端配置好私钥吗,这样通过逆向技术也动态跟踪内存,不就可以拿到对称加密用到的密钥了吗? 答案是使用前面提到的加密壳对客户端游戏加密,这样增加分析难度,甚至完全放弃。当然后续是要自己开发加密壳的,这样用起来也相对放心。

我们公司大都游戏是Flash的网页游戏,使用AMF协议通信,外挂都是“脱机外挂”。显然我们是没做加密工作的,要想杜绝大部分外挂,通信数据加密、Flash客户端用软件混淆是必须的。

以上谈了谈3类外挂的开发技术以及防御策略,然而不仅仅局限与这3种。楼上的基于数据挖掘的行为分析、关键数据效验自身发送

checksum、定期发送暗桩数据、类AMF的二进制协议自实现一定会作为后期的反外挂技术的重点。

另外,除了技术手段,需要结合游戏前期的设计、深入玩家(外挂作者)内部以及运用法律抄外挂编写者和运营工作室的老巢等对外挂实施全面打击。

说点自己的看法,大家表喷哈。
基于php实现的后端,flash客户端的二进制请求包通过C++连接层转发到后端的php进行处理;对于这类型的游戏,因为客户端代码会很容易被还原,无论怎么加密都没用,只能尽量加一些阻碍,让我们的防御措施不那么容易被看到。
个人觉得比较好的方式是通过代码混淆的方式,增加代码被破解后的可读性来增加阻碍,有两种方式:
1.编译前混淆,这种方式混淆效果较好,但是对于一些协议方面的编解码写法有限制,比如像我们有通过xml格式可以直接转成一个as3对象的写法,就不大好用这种方式。
2.编译后混淆,对已生成的执行文件进行加密和混淆,这种方式就比较方便,对于任何代码实现方式都没有限制。

目前市面上很多游戏都没有做这个方面的事情,所以都很容易拿到完整的可读性较强的源代码,修改编译错误后还可以在本地IDE上编译出来可运行的客户端;但是对于混淆后的游戏,要想完全拿到可读性较强源代码还是要花些时间的。

通常的防外挂的手段是协议加密、数据包校验和运营手段,但在实际项目实施过程中协议加密很容易增加服务器负载,数据校验和也很容易被模拟,根据之前做外挂的经历很多挂都使脚本录制包,这种校验和也很难防,基于HTTP的游戏如果浏览器端是FLASH实现,不防试试自己实现一个二进制的协议,服务端通过PHP端解析,二进制协议有一个比较好得特点是分析协议比较复杂,内容需要破解协议,相对破解明文协议二进制要复杂的多,而且基于二进制的协议加密简单,同时协议本身可以增加防外挂的协议帧,只需对防外挂的协议帧加密就可以了。

 

 

你可能感兴趣的:(在游戏研发中如何有效防止外挂程序)