探讨刀塔传奇是怎么防止客户端作弊的

来源:互联网 发布:linux eagle 编辑:程序博客网 时间:2024/05/17 06:08

       如果你玩过刀塔传奇,你会发现它用的是短连接,每次需要连接服务器的时候才连接,处理完之后就直接断开连接了。所以你会发现,如果你先进入战斗,然后断开网络,那么你还是能继续战斗的。战斗结束后才会再一次连接服务器确认战斗结果。

      好了,那么客户端作弊怎么办呢?比如我直接改了数据告诉服务单我赢了,服务端怎么知道这个是假造的呢?

      首先,我们可以推断客户端源代码是无法反编译的。刀塔传奇是基于cocos2d-x的,不管是用lua还是c++,反编译得到的只能是汇编,我们可以认为这基本是无法获得源代码的。当然如果你觉得有汇编达人能够再一次反编译出来,那么我相信大部分游戏是无法依赖客户端的。这里我们基于最基本的假设就是这是非常困难的,而这个也是让客户端处理战斗过程的基本保障。

      既然无法知道源代码,那么客户端要怎么作弊呢?

     第一种是修改内存。比如把客户端运行的钱的内存地址找到,改成很大的一个数值,然后继续操作。当然我们相信钱这么重要的数值服务端肯定有存储的,这里只是举个例子,毕竟战斗结果或者战斗数值这种东西可能就放在客户端判断了。为了防止内存地址被找到,我们需要做的就是加密。没错,对这些重要的数值加密,当然运行的时候是会解密出来运行。不过这样的话即使修改了那些解密的数值也是没有意义的,因为实际的数值肯定不是这个,我们无法知道内存修改器修改的结果,也许是直接导致程序崩溃,当然这是他们自作自受。毫无疑问的是,这个加密是基于源代码无法被破解的基础上。后面的也都是一样的,我就不多赘述了。

    第二种是发包,因为网络包是可以被截获并且被解析的。当然你可以对网络包加密,不过解密网络包相比于解密源代码要容易的多。而且如果只是单纯的加密还是有问题的,因为对方可以重复发包,比如它打赢了一场战斗,然后不断发送战斗胜利的包。首先我们看下怎么处理网络发重复的包。比如打副本,他连续发了三个打副本胜利的包。这种情况其实还是好判断的,你只要保证发送信息中有一个时间戳,而且保证时间戳的有效期,那么你就可以丢掉超过比如3分钟的包。当然3分钟可能过长了,也许30秒就很长了。当然这样你还是无法保证它不会再很短的时间内发包,这个你除了时间戳只要还需要提供一个唯一的序列号。这个序列号可以是递增的,那么如果玩家发送重复的包,你就可以知道这个肯定是非法的而且丢掉。当然这个有个策略问题,因为基于网络的不稳定,你要考虑各种各样的情况。假设服务端保存的序列号是1,客户端也是1,那么假设网络良好,一切都很美好,客户端变成2,服务端也变成2.然后当玩家重复发包的时候,服务端其实已经变成3了,所以就可以排除这些包。那如果出现丢包的情况怎么办呢,首先假设客户端发送给服务端的包丢了,那么就是客户端的序列号大于服务端的序列号,当然你可以判断如果丢包就不增加序列。我们这里假设还是出现了这种情况,其实问题不大,因为大于的话我们认为这还是合理的。当然服务端马上就要把这个值变成和客户端一样。同理,假如服务端的值过大呢?客户端的包可能就都无效了。我们可能真的无法知道玩家是故意发包还是真的是网络丢包引起的。所以可能我们还是不使用序列号,而是使用时间戳作为标志。如果两次时间戳一样,那么是发包。如果时间戳早,那么也判断为发包,那么问题来了,时间戳晚,你怎么知道是正常包还是发包呢?这就要用到我们的新的验证措施:校验码。

     校验码的概念就是,比如你发了串数字,12345,然后你定义校验码的概念是求和,那么最终和是15,也许你可以把15放在最后,就是1234515.如果你只改了第一位,比如改成2234515,那么毫无疑问校验码是错误的。因为求和变成了16.当然我举得例子十分简单,一般真正的校验码会非常复杂。有了校验码,如果对方不知道我们的校验码生成规则,那么毫无疑问,他通过修改部分数据来得到结果是不可能成功通过验证了,而且我们还能够发现这样的人,打个日志。

     好了有了以上的措施,应该基本可以确保客户端的安全了。当然这些都是我的猜测,实际做法不一定是这样。

0 0
原创粉丝点击