设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 3420|回复: 20
打印 上一主题 下一主题

[交流讨论] 防止内存修改

[复制链接]

Lv3.寻梦者

梦石
0
星屑
2150
在线时间
1010 小时
注册时间
2015-10-17
帖子
1283
跳转到指定楼层
1
发表于 2017-5-31 18:53:15 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
有人建议搞个防内存修改的东西,防止有些人修改游戏,要是知道方法的告诉下,谢谢

Lv5.捕梦者 (管理员)

老黄鸡

梦石
0
星屑
39602
在线时间
7482 小时
注册时间
2009-7-6
帖子
13482

开拓者贵宾

2
发表于 2017-5-31 20:38:15 | 只看该作者
建议先去学习如何修改,这样你就知道设计程序的时候如何保存变量才不容易被找到。

点评

fjm
恩,感觉要学一下  发表于 2017-5-31 22:11
RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
3559
在线时间
2337 小时
注册时间
2015-8-25
帖子
960

开拓者

3
发表于 2017-5-31 21:59:29 | 只看该作者
自己写一套数值换算的方法,这是出自某个小黄油的做法。大概可以防御到数值检索和直接改存档两种修改手段。

一般玩家直接改存档应该是主流吧,其实仅是改用变量存几个关键的属性,已经可以防御到相当一部分傻瓜修改。

会拆工程的人就别防了。

点评

fjm
自己写,暂时有点困难了,主要是防傻瓜式修改就可以了  发表于 2017-5-31 22:12
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

梦石
1
星屑
23963
在线时间
3338 小时
注册时间
2011-7-8
帖子
3925

开拓者

4
发表于 2017-6-1 00:28:16 | 只看该作者
本帖最后由 guoxiaomi 于 2017-6-1 22:40 编辑

对于防止修改存档,可以手动对一些数据进行验证。比如要检查玩家是否修改了物品等,就验证 $game_party 这个量,或者细致一点,验证 $game_party.items,不过默认 @items 是不可访问的,要稍微修改一下脚本。

这样做:

1. 准备一个并没有什么用的密钥字符串(盐),比如说 r = '1234567890'

2. 存档前,把校验码写入变量 10
  1. v = $game_variables[10]
  2. r = '1234567890'
  3. v = Zlib::crc32(r + $game_party.items.inspect)
复制代码

3. 读档后,进行验证。
  1. r = '1234567890'
  2. v = Zlib::crc32(r + $game_party.items.inspect)
  3. if v != $game_variables[10]
  4.   p "存档验证失败,即将退出游戏!"
  5.   exit
  6. end
复制代码


多个数据各自调用自己的 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 代码复制
  1. class Game_Party
  2.   alias _check_item_initialize initialize
  3.   def initialize
  4.     _check_item_initialize
  5.     @salt = rand.inspect
  6.     @item_hash = item_hash
  7.   end
  8.  
  9.   alias _check_item_gain_item gain_item
  10.   def gain_item(*args)
  11.     cheat = check_item
  12.     _check_item_gain_item(*args)
  13.     @item_hash = item_hash if !cheat
  14.   end
  15.  
  16.   def item_hash   
  17.     sprintf("%08x%08x", (@salt + @items.inspect).hash, (@items.inspect + 'rpg.blue').hash)
  18.   end
  19.   private :item_hash
  20.  
  21.   def check_item
  22.     # 无作弊返回 false,否则返回 true
  23.     @item_hash != item_hash
  24.   end
  25.  
  26. end

(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 重新赋值。

我的想法就是这样了……

点评

fjm
非常感谢,我去试下  发表于 2017-6-1 08:40
熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (管理员)

老黄鸡

梦石
0
星屑
39602
在线时间
7482 小时
注册时间
2009-7-6
帖子
13482

开拓者贵宾

5
发表于 2017-6-1 01:07:22 | 只看该作者
其实有一个简单的方法,你的重要变量,写成一个类,每次赋值,都新建一个类,类格式如下。
  1. class Var
  2. attr_accessor:value
  3. end
复制代码

这样每次赋值后实际值在内存里的地址都会变化,别说防新手,只要不深入研究基本就无法修改(超多级指针

点评

fjm
像我这种脚本菜鸟,实在不能明白你说的,要不我把游戏发给你,帮忙看下怎么做  发表于 2017-6-1 08:43
千千万个object...  发表于 2017-6-1 04:33
醋瞎  发表于 2017-6-1 01:12
RGDirect - DirectX驱动的RGSS,点我了解.
RM全系列成套系统定制请联系QQ1213237796
不接受对其他插件维护的委托
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
2150
在线时间
1010 小时
注册时间
2015-10-17
帖子
1283
6
 楼主| 发表于 2017-6-1 22:20:18 | 只看该作者
guoxiaomi 发表于 2017-6-1 00:28
对于防止修改存档,可以手动对一些数据进行验证。比如要检查玩家是否修改了物品等,就验证 $game_party 这 ...

多谢,试了下会报错

QQ截图7899.jpg (10.66 KB, 下载次数: 4)

QQ截图7899.jpg

点评

嗯……既然这个思路是可行的,照着这个脚本接着写钱就行了……  发表于 2017-6-2 15:17
fjm
物品是可以,不过改钱还是可以改  发表于 2017-6-2 13:31
修改了物品之后,调用 $game_party.check_item 会不会返回true?  发表于 2017-6-2 12:59
fjm
多谢,试了下,用GM9还是能改游戏数据  发表于 2017-6-2 09:08
嗯你再看看吧?  发表于 2017-6-1 22:40
回复 支持 反对

使用道具 举报

Lv1.梦旅人

梦石
0
星屑
55
在线时间
407 小时
注册时间
2011-4-10
帖子
359
7
发表于 2017-6-3 20:11:23 | 只看该作者
如果不能保证游戏不被解包,弄这些还是做无用功而已。

点评

在我看来就是把难度提升到跟解包游戏一个水平……  发表于 2017-6-3 23:19
求教不是无用功的  发表于 2017-6-3 21:06
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-4-19 23:09

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表