浅谈手游如何防破解,并附上自己的防作弊框架
道高一尺魔高一丈,现在市场上的作弊辅助软件越来越厉害了,博主也遭遇过大量破解玩家的摧残,当时项目紧急下线,做了好久的防破解才再次上线。所以在这里和大家分享一下一般的作弊软件的工作原理以及如何有效的针对。
客户端作弊方法:
修改内存内容:这个是最常见的,以前的金手指也是这么操作的,一般就是多次改变某个数值,达到定位到该数值的内存地址,然后进行修改。
让某个数值不能改变:例如可以让玩家的血量锁死,无论怪物怎么攻击,玩家的血量永远大于0,永远打不死。
。。。
以上是针对客户端的,还有服务器端的作弊途径博主就不写了,毕竟博主只是客户端开发。
其实当你了解它们的作弊方法后,自然而然会有相应的对策,总的思路是两个,一个是防止玩家修改,第二个是让他们改,咱们只要能捕捉到修改,再进行封号踢下线操作即可。
1.针对修改内存内容: 咱们可以让某个值,让其界面显示和内存中不相等,这样玩家搜索界面显示的值,自然不能定位相应内存地址。
比方说,当前玩家血量是1000,但是实际上血量字段在内存中300,显示时加上了700而已,那样玩家再怎么搜索1000也搜不到。
2.再例如,针对数值锁死。可以再创建一个该字段的副本,初始和字段值一样,字段如何变化,改副本也如何变化,每次使用字段前和副本比较一下是否相等。如果改字段被锁死了,那么它和副本必定不相等。
3.要想比较好的防作弊,最好把比较的计算放在服务器,如果为了缓解服务器压力,可以前端计算一部分,然后和服务器进行一个验证对比。例如博主之前的项目战斗数值被破解了,于是前端按照各个属性值进行一个战力计算,然后和服务器计算的战力对比,相等或者相差不大即可视为安全。
下面摆上博主项目中使用的防作弊框架:(详细思路写在注释里)
module "SavetyModule"
SavetyModule = CC.Class:Subclass("SavetyModule")
SavetyData = CC.Class:Subclass("SavetyData")
function SavetyData:Create(tVal) --如果某个值不想让玩家作弊器搜索到,那么即可创建一个SavetyData
if tVal and tVal.bHide then --bHide为true时,作弊器就搜索不到这个字段
self.bHide = tVal.bHide
end
--思路就是每一个安全字段都会配有一个随机数值hideNum,tVal.value即为该字段的实际值,self.value即为实际值加上一个hideNum后
--在内存中常驻的值,例如:玩家血量显示为100,但其实内存中血量字段真实值为100+hideNum,玩家不知道hideNum是啥,所以搜索
--100的时候,并不会暴露该血量字段
--除此以外,该字段还有一个副本cValue,具体啥作用请往下看
if self.bHide then
self.hideNum = CC.Math:Random(1, 1000)
self.delNum = CC.Math:Random(1, 1000)
self.value = tVal.value + self.hideNum
self.cValue = self.value + self.delNum
else
self.value = tVal.value
self.cValue = self.value
end
end
--获得改安全字段的真实值,获得之前都会check一下,正常情况下,self.value 个 self.cValue会相差一个delNum。一旦self.value暴露被
--修改,前端既可捕捉到。
function SavetyData:Get( )
if self:Check() then
if self.bHide then
return self.value - self.hideNum
else
return self.value
end
else
CC.Error("SavetyData error")
end
end
function SavetyData:Check( )
if self.value == self.cValue - self.delNum then
return true
else
CC.Error("SavetyData error")
return false
end
end
function SavetyData:Set(iVal)
if self:Check() then
if self.hideNum then
self.value = iVal + self.hideNum
else
self.value = iVal
end
self.cValue = self.value + self.delNum
end
end
function SavetyData:DeltaChange(iVal)
if self:Check() then
self.value = self.value + iVal
self.cValue = self.value + self.delNum
end
end
-----------------------------------------------------------------------------
function SavetyModule:Create(tVal)
local sd = SavetyData:New()
sd:Create(tVal)
return sd
end
--如何使用
--self.act = CC.SavetyModule:Create({value = CC.tonumber(100)}) --创建一个savetyData作为攻击属性
--self.act :Get() --获得该属性的真实值
这个框架可以有效防止内存修改以及数值锁死。但是博主认为也不是百分百放破解,最好和服务器一起配合,做到最大程度安全。当然这个框架也有缺点,就是会有额外内存已经时间开销。但是鱼和熊掌不可兼得,咱们为了安全,总得牺牲其他一点,怎么取舍看你了。