本帖最后由 guoxiaomi 于 2017-6-1 22:40 编辑 对于防止修改存档,可以手动对一些数据进行验证。比如要检查玩家是否修改了物品等,就验证 $game_party 这个量,或者细致一点,验证 $game_party.items,不过默认 @items 是不可访问的,要稍微修改一下脚本。 这样做: 1. 准备一个并没有什么用的密钥字符串(盐),比如说 r = '1234567890' 2. 存档前,把校验码写入变量 10
3. 读档后,进行验证。
多个数据各自调用自己的 Object#inspect 方法,然后把字符串拼接到一起验证也是可以的。crc32 只是很简单的验证手段,不过足以应付大多数不懂程序的人了,如果觉得不放心可以用 SHA-1 等更优秀的哈希算法进行验证。但是计算速度就不保证了= = 其实直接调用 Object#hash 方法也能得到对应的验证,而且在我的电脑上它的速度比生成字符串再做 crc32 快了大概3000倍,我把这个也写进去供参考~ 但是直接调用 $game_party.hash 是不推荐的,如果实在要考虑性能,那最好带上盐多做几层,就像注释里面的一样。 原因是 crc32 算法是个公开的算法,而且所有语言、版本都得到一致的结果,而 Object#hash 可能不同的 ruby 版本得到不一致的结果。 刚刚不放心测试了一下,果然是有问题的,只有String (字符串) 的 hash 值是固定不变的,其他的对象的 hash 值每次游戏会发生变化。而且每次 inspect 方法得到的数据也不完全一样,所以注释的部分还是别用了(我已经删除)。Hash,Array,String,Fixnum 和 True/False/Nil 的 inspect 方法会返回相同的字符串,但是其他的 class XXX 的实例就不保证了,所我也把原来 $game_party.inspect 改为了 其 @items 对象的 inspect 方法。 如果要防止修改内存,也可以考虑用校验的方式,比如 @items 的每一次修改都是在 Game_Party#gain_item 方法里,在这个方法的结尾计算@items 的 hash 的值保存在一个全局变量里,然后在你需要的时候检验 hash 值和对应的对象转化的字符串是否相符合。 还是拿 @items 举例~ RUBY 代码复制
(RMXP)这段代码插入main前,可以在每次调用 gain_item 方法后判断是否为作弊,如果没有作弊则重置 hash。如果有作弊,@item_hash 的值不会更新,从而保证 check_item 一直返回 false,除非 @items 回归到作弊前的情况,或者玩家同时修改了正确的 @item_hash。 为了避免玩家猜出来正确的 @item_hash,盐字符串 @salt 的生成是随机的~所以每一个新的游戏或者存档,都有不同的 @salt,从而也不能通过其他人的存档得到对应的 @item_hash。从而获取盐字符串的方法只能穷举或者解包游戏~相比下来,解包说不定更快捷,那样就没有办法了。建议修改一下 item_hash 的具体计算方法,弄复杂一点点,比如像上面这样返回一个表示64位整数的字符串。 然后在你需要检查 items 作弊情况的时候判断 $game_party.check_item 即可。比如每次存、读档,进入菜单页面时。 如果游戏里存在不使用 gain_item 修改 @items 的情形,会被判定为作弊(当然)。如果无法避免这种情况,在每次修改了 $game_party.items 的后面都对 @item_hash 重新赋值。 我的想法就是这样了…… |
自己写一套数值换算的方法,这是出自某个小黄油的做法。大概可以防御到数值检索和直接改存档两种修改手段。 一般玩家直接改存档应该是主流吧,其实仅是改用变量存几个关键的属性,已经可以防御到相当一部分傻瓜修改。 会拆工程的人就别防了。 |
站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作
GMT+8, 2025-7-18 13:54
Powered by Discuz! X3.1
© 2001-2013 Comsenz Inc.