常用游戏反外挂技术总结
外挂是游戏行业毒瘤般的存在,利用游戏漏洞,破坏游戏平衡,损害了其他玩家和游戏开发商的利益。如何有效进行游戏反外挂(作弊)一直都是游戏运营过程中需要面对的重要问题,下文将对日常游戏开发过程中针对反外挂做一个大概性总结。
# 1. 外挂的分类
外挂根据性质和功能大概可以分为两大类:
- 辅助类外挂
- 破解类外挂
# 1.1 辅助类外挂
辅助类外挂需要依赖游戏客户端,不能独自生效,常见的辅助类外挂如下:
脚本自动模拟点击:这类外挂对游戏破坏相对较小,但是也最常见,常见外挂工具:按键精灵、金手指
修改客户端的内存信息:这类外挂通过分析游戏所使用的内存,找到内存中的变量去分析猜测变量是代表的什么含义。由于客户端本身保存着很多游戏信息,比如技能cd、移动速度等。由于游戏技能的管理和发起是由客户端控制的,若外挂能去把技能cd改为了0,客户端就可以无限放此技能。常见外挂工具:葫芦侠、八门神器
加速齿轮:加速齿轮可以加速某一个进程的时间流逝速度,通过加速齿轮,可以让游戏客户端进程的时间加速N倍。真实时间可能只过了1s,而客户端进程的时间已经过了Ns。通过加速齿轮,可以让人物移动速度加快、技能cd加速等。常见外挂工具:加速齿轮
重发、篡改同步信息:此类外挂可以截获客户端发送给服务器的消息,然后进行篡改或者重发。比如可以截获一个释放技能消息,然后再无限重发给服务器,服务器若没有验证,就会无限执行技能。常见外挂工具:WPE三件套(eg+wpe+ccp)
# 1.2 破解类外挂
破解类外挂一般是外挂作者基于游戏协议的分析,自己开发的一个游戏客户端。通常情况下,这类客户端都可用来多开直接刷副本等功能,收益巨大,工作室对这类外挂的需求较大。
# 2. 常用反外挂手段
# 2.1 客户端安全加固
安全加固的目的是降低移动应用普遍存在的被破解、篡改、劫持、盗版、数据窃取、钓鱼欺诈等各类安全风险,一般我们会选用第三方服务器作为供应商,比如:网易云盾 (opens new window)
# 2.2 服务器校验
# 2.2.1 非法输入
常见的非法输入场景有:
- 参数非法:例如购买道具时传入负数,将本应该扣除的游戏币变成了增加游戏币。一般情况下,当涉及通过客户端传入参数来进行加减扣除操作时,都需要进行参数范围等合法性校验,不要信任客户端输入;
- CD冷却无效:在一些帧同步操作中,客户端通过某些手段可以绕过CD时间,比如连续触发某NB技能,这个时候需要在服务器校验前后两次操作的CD时间是否合法;
# 2.2.2 透视挂
透视挂主要是破解通信协议,获取到非关联信息。比如棋牌游戏中,服务端向客户端广播所有手牌的信息,如果协议被破解,那么外挂玩家就可以看到对手的手牌。这些服务器漏洞,都让外挂有机可乘,服务端应最大限度地控制信息发送范围,同时也能降低服务器网络IO负载。
# 2.2.3 防变速器
变速器是最常见的外挂之一,它可以改变客户端的运行速度,从而获取速度上优势。例如,客户端真实运行了1分钟,Time.time的值理应是60(秒),但由于加速器把游戏速度调高了1倍,现在Time.time的值变成了120,程序从每0.2秒发送一次协议变成每0.1秒发送一次。对于变速器我们可以引入“限流器“之类的概念,如果前后相同msg的发送间隙小于合理范围就判定为作弊。
实际在大部分服务端的设计中,客户端要定时向服务端发送心跳包,以便服务端检测客户端是否掉线,利用心跳包来判断玩家是否作弊是一种常见的做法,由于加速器改变的是全局时间,因此其也会改变心跳包的发送频率,从而露出马脚。
# 2.2.4 防封包
外挂通常会利用WPE(Winsock Packet Editor,网络数据包编辑器)等封包工具,这类工具可以截取和修改网络数据包,进而向服务端发送任意数据。
一般这种情况,我们会对通信协议的消息体进行加密,同时也会在通信协议中取一个段内容用来判断数据包的合法性,比如下面协议的“密码段”。
# 2.2.5 帧同步投票
帧同步的操作是完全依赖客户端运算,很容易作弊。服务端可以通过投票机制找出作弊的玩家。服务端可以要求每个客户端每隔一定的帧数就发送一次状态协议,协议中包含客户端当前的帧数及状态码。如果没有作弊,那么在同一帧时,各客户端应处于同样的状态,状态码也应相同。服务端需要收集所有客户端的状态码,如果某个客户端的状态码不一样,则该客户端的玩家很有可能是在作弊(也有可能是游戏本身的Bug造成的)。
{frameid = 10, status_code = 14566455}
状态码是反映客户端当前状态的数值,例如角色的生命值、体力值、位置、攻击力,金币数、道具数等都是游戏的某一项状态值,组合这些状态值便能反映游戏的整体状态。
//状态码
void GetStatusCode() {
int code = 0;
//计算战场中所有角色(英雄)的血量
foreach(Hero hero in heros){
code = code + hero.hp;
}
//计算所有塔的血量
foreach(Tower tower in towers){
code = code + tower.hp;
}
return code;
}
2
3
4
5
6
7
8
9
10
11
12
13
# 2.3 总结
存在利益的地方就会有人钻漏洞,与外挂的战斗是一场持续的、此消彼长的斗争,技术人员能做的是尽可能提高玩家作弊的难度,但想彻底杜绝作弊任重而道远,除了产品本身提高作弊门槛外,法律对信息安全的保护和威慑才是至关重要的。