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

Project1

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

[随意闲聊] 【宝可梦语奏】关于成功制作外挂而被踢

[复制链接]

Lv4.逐梦者

梦石
2
星屑
6682
在线时间
501 小时
注册时间
2018-3-23
帖子
533

R考场第七期银奖

跳转到指定楼层
1
发表于 2020-1-16 12:18:07 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

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

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

x
本帖最后由 MCCF 于 2020-1-16 12:28 编辑

众所周知,宝可梦语奏是用RMXP制作的一代神奇作品。

然而我貌似在通普市时金币不足,以至于无法购买足够的超级球以供收服。

于是就有了此神奇的东西:

RUBY 代码复制
  1. #encoding:utf-8
  2. #==============================================================================
  3. # 金币修改器 - Pokemon Universe
  4. #    by MCCF
  5. #------------------------------------------------------------------------------
  6. # [说明]
  7. #    - Pokemon Universe(精灵宝可梦:宇宙)的金币修改器
  8. #------------------------------------------------------------------------------
  9. # [使用方法]
  10. #    - 复制到Main之前
  11. #    - 将存档(Game.rxdata)移动到游戏根目录,运行游戏,修改完成后自动关闭。
  12. #------------------------------------------------------------------------------
  13. # [注意]
  14. #    - 一般适用于懂得脚本的人。
  15. #    - 有可能有BUG,欢迎反馈。
  16. #------------------------------------------------------------------------------
  17. #  通用配置模块  
  18. #==============================================================================
  19. module Pokemon_Universe_Money
  20.  
  21.   #要修改的金币值
  22.   MONEY_VALUE = 20000000
  23.  
  24.   # 是否启用修改器
  25.   CHANGE_MONEY = true
  26.  
  27.   #存档文件名
  28.   FILENAME = "Game.rxdata"
  29.  
  30. end
  31. #------------------------------------------------------------------------------
  32. #  配置模块结束  
  33. #==============================================================================
  34. class PokeBattle_Trainer
  35.   attr_accessor :money
  36. end
  37.  
  38. class PokeBattle_Pokemon
  39.  
  40. end
  41.  
  42. class PBMove
  43.  
  44. end
  45.  
  46. class PokemonSystem
  47.  
  48. end
  49.  
  50. class PokemonMapFactory
  51.  
  52. end
  53.  
  54. class PokemonGlobalMetadata
  55.  
  56. end
  57.  
  58. class BugContestState
  59.  
  60. end
  61.  
  62. class PurifyChamber
  63.  
  64. end
  65.  
  66. class PurifyChamberSet
  67.  
  68. end
  69.  
  70. class SafariState
  71.  
  72. end
  73.  
  74. class PCItemStorage
  75.  
  76. end
  77.  
  78. class PokemonMapMetadata
  79.  
  80. end
  81.  
  82. class PokemonBag
  83.  
  84. end
  85.  
  86. class PokemonStorage
  87.  
  88. end
  89.  
  90. class PokemonBox
  91.  
  92. end
  93.  
  94. #==============================================================================
  95. # ■ Scene_Load
  96. #------------------------------------------------------------------------------
  97. #  处理读档画面的类。
  98. #==============================================================================
  99.  
  100. class Scene_Load < Scene_File
  101.   #--------------------------------------------------------------------------
  102.   # ● 读取存档数据
  103.   #     file : 读取用文件对像 (已经打开)
  104.   #--------------------------------------------------------------------------
  105.   def read_save_data(file)
  106.  
  107. end
  108. end
  109.  
  110. #==============================================================================
  111. # ■ Scene_Title
  112. #------------------------------------------------------------------------------
  113. #  处理标题画面的类。
  114. #==============================================================================
  115.  
  116. class Scene_Title
  117.   #--------------------------------------------------------------------------
  118.   # ● 主处理
  119.   #--------------------------------------------------------------------------
  120.   alias money_main main
  121.   def main
  122.     change_money if Pokemon_Universe_Money::CHANGE_MONEY
  123.     money_main
  124.   end
  125.   #--------------------------------------------------------------------------
  126.   # ● 处理金币修改
  127.   #--------------------------------------------------------------------------
  128.   def change_money
  129.     i = 0
  130.     n = 0
  131.     s = []
  132.     fr=File.open(Pokemon_Universe_Money::FILENAME, "rb")
  133.  
  134.     s[0]=Marshal.load(fr)
  135.     s[0].money = Pokemon_Universe_Money::MONEY_VALUE
  136.     begin
  137.       while n+=1
  138.         s[n]=Marshal.load(fr)
  139.       end
  140.     rescue
  141.  
  142.     end
  143.  
  144.     fw=File.open(Pokemon_Universe_Money::FILENAME, "wb")
  145.     while i<n
  146.       Marshal.dump(s[i],fw)
  147.       i+=1
  148.     end
  149.  
  150.     exit
  151.   end
  152. end
  153.  
  154.  
  155. #==============================================================================
  156. # ■ Scene_File
  157. #------------------------------------------------------------------------------
  158. #  存档画面及读档画面的超级类。
  159. #==============================================================================
  160.  
  161. class Scene_File
  162.   #--------------------------------------------------------------------------
  163.   # ● 生成文件名
  164.   #     file_index : 文件名的索引 (0~3)
  165.   #--------------------------------------------------------------------------
  166.   def make_filename(file_index)
  167.     return "Game.rxdata"
  168.   end
  169. end


把存档文档放在该工程目录下,运行工程自动退出。

然后我把一张2000万金币的图片放到粉丝群上,于是被群主(此游戏作者)踢了,终身不得加入。

此程序甚至还可以输出存档的全部内容

但是我并没有将代码放上去……嗯(仅仅是想提醒群主注意这个漏洞)




半年之后无意间发现了这个工程,于是将其发布到此,后来根据朋友的说法,那位群主大概是由于自尊的问题将自己的账号而采取如此措施。现在不清楚后来发生的情况,但是在想这种心理是否是每个游戏制作者,必然的或者说至少是普遍的一种情况。

(顺便也想探讨一下,Ruby这种过于开放的语言(类中定义的方法及变量与对象中的实际数据完全不必要一致)是否会引发一些游戏数据安全上的问题?)
祝好。

Lv5.捕梦者

梦石
0
星屑
21990
在线时间
1057 小时
注册时间
2019-3-5
帖子
1424
2
发表于 2020-1-16 13:05:50 | 只看该作者
一般情况下大部分制作人都是反感别人修改自己游戏的,毕竟是自己的劳动成果,至于这个反感程度也是每个人不同的。这其实和画师反感别人改自己的画差不多。

要想理解这个感受可能也比较困难,除非自己就是从事相关行业的。从外人的角度来看确实是比较奇怪的心思(似乎有点过于敏感)。

所以这算是一条潜规则吧:除非作者本人明确表示不在乎任何修改行为,否则修改游戏这种还是私底下默默讨论别让作者看到的好,毕竟这是最起码的尊重。

评分

参与人数 1+1 收起 理由
坏数据 + 1 起码的尊重+1

查看全部评分

回复 支持 反对

使用道具 举报

Lv5.捕梦者

梦石
0
星屑
35186
在线时间
4169 小时
注册时间
2007-12-15
帖子
10067
3
发表于 2020-1-16 13:15:24 | 只看该作者
个人修改只要能从中得到乐趣就可以了,但是一旦游戏只能改的才有乐趣,平衡性就成问题了。
主要是改了以后还把图发出来这个会让人烦,会让人觉得这是想表达什么意思。
如果原始工程平衡性有严重问题,可以考虑和作者商量共同进行难度修正。

然后改图的话,往好了改比我画的好而且没瞒着原作者,自然没问题,照着图画个新的并且没隐瞒原作者,也是无碍,18X和而已修改,个人不能忍受。

回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
8624
在线时间
1465 小时
注册时间
2012-6-6
帖子
349
4
发表于 2020-1-16 14:39:01 | 只看该作者
我是这么觉得的,改个钱或者经验道具什么的都无所谓,无伤大雅的,毕竟制作者不能要求玩家按照他的想法来玩游戏,玩家想怎么玩是玩家自己的事情,我从来不会因为别人改了钱或者道具什么的去踢人,这没有什么意义,也许游戏设计的数值不够平衡才导致有人修改,再或者往好的方面想一想,人家也许是因为没有时间玩而修改钱或者道具什么的来体验一下的,每个人的想法都不一样,也不好评断说对谁错,不过呢话虽是这么说,但还是要尊重一下制作者,改就改了你自己自娱自乐就好,但不要发出来。
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
13562
在线时间
2753 小时
注册时间
2014-10-4
帖子
756

R考场第七期纪念奖

5
发表于 2020-1-16 14:47:00 | 只看该作者
本帖最后由 SixRC 于 2020-1-16 17:52 编辑

游戏数据安全和用什么语言没太大关系吧  主要看游戏内部侦测逻辑?
我反而觉得脚本语言相对不好改
游戏如果用c/c++写 那么数值可能都是定址的 比方 [[[base + A] + B] + C] 是血量
偶尔还可以直接改运行逻辑 比方扣血改成加 因为每个过程都有个函数 可以直接改汇编 不影响其他部分 (当然大部分不行 不知道 我感觉??)
但如果是 ruby 那得理解他内部储存逻辑才能写修改器吧( 我不知道 没试过 也许暴力索引也行)
要改存档那也得知道存储逻辑吧  改RM简单是因为套路大概一致

另一个角度 用CE修改的话 一般游戏直接找数值就行 rm 你得 2x+1

刚刚想到了 CreateRemoteThread+执行RGSSEval 写了个小玩具

文件撤掉了就这样去吃饭了
逻辑是这样的
创建进程(当前目录下game.exe) 取进程权限句柄
读取输入 如果 #L 读取多行直到 #L
远程申请内存 复制代码 远程创建线程 执行 RGSSEval (用了RGSS103J的地址 懒)

当然要修改数值得知道要改的东西叫什么..

但对于别的匿名脚本语言 改个p啊 不说脚本肯定编译过 内部字节码啥的也不知道 要是再改改数据存储逻辑 那安全性不就上来了吗

点评

因为marshal dump就是明文,本来就没有加密的说法。我记得有个脚本会根据报错内容自动创建模块和类  发表于 2020-1-16 21:39
幽默的地方是,即使完全不知道存档了哪些对象,通过报错内容就能知晓;然后就能明文输出对象内部的变量名及其值……  发表于 2020-1-16 18:55
emmm……给破解者增加麻烦也是一种保护方式  发表于 2020-1-16 18:07
真正的保护代码 感觉只能编译成字节码 或者干脆机器码 其余都必然会出现明文 也就能提取出来吧  发表于 2020-1-16 17:50
保护大概是不可能的吧 我感觉 因为总是可以从内存读啊 要执行就要明文 只要一瞬间也足够解包了 我已经放弃了  发表于 2020-1-16 17:49
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
3670
在线时间
357 小时
注册时间
2018-9-4
帖子
272
6
发表于 2020-1-16 16:07:11 | 只看该作者
本帖最后由 Mono_kyrin 于 2020-1-16 16:10 编辑

默认第一个被Marshal.load递归读取的是$game_party?

那我文件开头写串乱码不就完了
RUBY 代码复制
  1. file.write(0xDEADCAFE)

虽然大概也只能防复制粘贴党

更何况,这个防策对于某通用存档修改器来说是无效的……
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
1
星屑
10049
在线时间
4430 小时
注册时间
2005-10-22
帖子
6953

开拓者贵宾

7
发表于 2020-1-16 17:00:33 | 只看该作者
少年们,你们应当直面现实,RM的加密是幻觉。石器的一段代码可以瞬间将大部分的RM游戏变成石器的一个DLC
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

梦石
1
星屑
23994
在线时间
3339 小时
注册时间
2011-7-8
帖子
3926

开拓者

8
发表于 2020-1-16 17:18:17 | 只看该作者
修改游戏并且公开发布方法我觉得永封不过分,毕竟作弊就是原罪。

自己定义一个存档格式并不难,但是因为RM的脚本很难加密,碰到想破解的人无论怎么做都是没用的。

RM这一天生的缺陷使得这游戏的加密变成了“防君子不防小人”。

本身做个游戏就已经很累了,要求作者放弃默认系统,花费更多的精力采用复杂的加密方案并不合适。

点评

不是加密很难,是导出很简单……  发表于 2020-1-17 06:23
倒也不是批评作者,毕竟拆包这事情很多人都干过,只能说不拆包努力打游戏的都是真君子  发表于 2020-1-17 03:04
好一个防君子不防小人  发表于 2020-1-17 01:24

评分

参与人数 2+2 收起 理由
坏数据 + 1 我很赞同 精品文章 认可答案
SixRC + 1

查看全部评分

熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *
回复 支持 1 反对 0

使用道具 举报

Lv4.逐梦者

梦石
2
星屑
6682
在线时间
501 小时
注册时间
2018-3-23
帖子
533

R考场第七期银奖

9
 楼主| 发表于 2020-1-16 18:53:10 | 只看该作者
瑟瑟发抖……

声明一下,本人并没有公开脚本内容。仅是放了图片。
后来考虑了一下,当时这种行为确实欠考虑,但并不是故意贬低

大致上的过程是(已被踢无法截图):

1. 在做的时候在群中发布一张内部对象数据的图片(XP的p指令输出的键值对,很长一条),并且提出”此处可能存在漏洞“。
2. 完成后发出成果(上面所述),清楚的记得一位管理员说”小鬼看见会不开心的“,于是明确表明”希望修复这一问题“。
3. 过了一会儿去看,果然被群主踢出。

祝好。
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
2
星屑
6682
在线时间
501 小时
注册时间
2018-3-23
帖子
533

R考场第七期银奖

10
 楼主| 发表于 2020-1-16 19:06:21 | 只看该作者
本帖最后由 MCCF 于 2020-1-16 19:49 编辑

再就第二个问题谈一谈。
看样子大部分意见是“修改必须知道改的东西叫什么”

然而RM足够开放:

RUBY 代码复制
  1. class PokeBattle_Trainer
  2.   attr_accessor :money
  3. end
  4.  
  5. class PokeBattle_Pokemon
  6.  
  7. end
  8.  
  9. class PBMove
  10.  
  11. end
  12.  
  13. class PokemonSystem
  14.  
  15. end
  16.  
  17. class PokemonMapFactory
  18.  
  19. end
  20.  
  21. class PokemonGlobalMetadata
  22.  
  23. end
  24.  
  25. class BugContestState
  26.  
  27. end
  28.  
  29. class PurifyChamber
  30.  
  31. end
  32.  
  33. class PurifyChamberSet
  34.  
  35. end
  36.  
  37. class SafariState
  38.  
  39. end
  40.  
  41. class PCItemStorage
  42.  
  43. end
  44.  
  45. class PokemonMapMetadata
  46.  
  47. end
  48.  
  49. class PokemonBag
  50.  
  51. end
  52.  
  53. class PokemonStorage
  54.  
  55. end
  56.  
  57. class PokemonBox
  58.  
  59. end


即使类都定义成这样,内部的所有数据还是可以输出:



这是使用代码:
RUBY 代码复制
  1. fr=File.open(Pokemon_Universe_Money::FILENAME, "rb")
  2. s=Marshal.load(fr)
  3. p s
实现的。

发现其中有个变量叫@money,正好和游戏中看到的钱数一样(此处是已经修改的,具体实现时可用诸如正则的方式取得),岂不是就可以进行修改了?所以这里是比较缺乏安全性的。




尤其是,即使完全不知道存档的内部结构,完全不知道上面所列出的五花八门的类名,也可以通过报错得到:

RUBY 代码复制
  1. def change_money
  2.   n = 0
  3.   fr=File.open(Pokemon_Universe_Money::FILENAME, "rb")
  4.   while n+=1
  5.     p Marshal.load(fr)
  6.   end
  7.   exit
  8. end


注意,这段代码没有使用异常处理,因此可以预料,在完全未定义任何类的情况下会报错:



是否注意到,此处已经提示出应有的类名,于是直接在前面打上:

RUBY 代码复制
  1. class PokeBattle_Trainer
  2.  
  3. end


然后又会提示出下一个,这样逐步类推,直到最后正常结束,也就取得了存档的所有信息。那么就是彻底的用RGSS自己破解RGSS。

点评

我开始没有看明白你的实现过程 现在我懂了..也明白你的意思了 所以我的意见是上面这些 嗯  发表于 2020-1-16 21:09
rgss的存档设计完全依赖Marshal可能就是懒 但ruby这么设计是为了给开发者最大的自由 我的观点还是引发安全问题的一直都不是语言而是具体实现  发表于 2020-1-16 21:07
我那句话只是针对我的那个例子而已啊//这里我觉得锅应该甩给rgss而不是ruby 如果不用Marshal只按序保存数据且加密不保存变量名就没这个问题了  发表于 2020-1-16 21:04
祝好。
回复 支持 反对

使用道具 举报

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

本版积分规则

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

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

GMT+8, 2024-11-16 06:27

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

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