Project1

标题: 【宝可梦语奏】关于成功制作外挂而被踢 [打印本页]

作者: MCCF    时间: 2020-1-16 12:18
标题: 【宝可梦语奏】关于成功制作外挂而被踢
本帖最后由 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万金币的图片放到粉丝群上,于是被群主(此游戏作者)踢了,终身不得加入。

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

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

[line]2[/line]

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

(顺便也想探讨一下,Ruby这种过于开放的语言(类中定义的方法及变量与对象中的实际数据完全不必要一致)是否会引发一些游戏数据安全上的问题?)
作者: Zeldashu    时间: 2020-1-16 13:05
一般情况下大部分制作人都是反感别人修改自己游戏的,毕竟是自己的劳动成果,至于这个反感程度也是每个人不同的。这其实和画师反感别人改自己的画差不多。

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

所以这算是一条潜规则吧:除非作者本人明确表示不在乎任何修改行为,否则修改游戏这种还是私底下默默讨论别让作者看到的好,毕竟这是最起码的尊重。
作者: 89444640    时间: 2020-1-16 13:15
个人修改只要能从中得到乐趣就可以了,但是一旦游戏只能改的才有乐趣,平衡性就成问题了。
主要是改了以后还把图发出来这个会让人烦,会让人觉得这是想表达什么意思。
如果原始工程平衡性有严重问题,可以考虑和作者商量共同进行难度修正。

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


作者: 流浪杰哥    时间: 2020-1-16 14:39
我是这么觉得的,改个钱或者经验道具什么的都无所谓,无伤大雅的,毕竟制作者不能要求玩家按照他的想法来玩游戏,玩家想怎么玩是玩家自己的事情,我从来不会因为别人改了钱或者道具什么的去踢人,这没有什么意义,也许游戏设计的数值不够平衡才导致有人修改,再或者往好的方面想一想,人家也许是因为没有时间玩而修改钱或者道具什么的来体验一下的,每个人的想法都不一样,也不好评断说对谁错,不过呢话虽是这么说,但还是要尊重一下制作者,改就改了你自己自娱自乐就好,但不要发出来。
作者: SixRC    时间: 2020-1-16 14:47
本帖最后由 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啊 不说脚本肯定编译过 内部字节码啥的也不知道 要是再改改数据存储逻辑 那安全性不就上来了吗
作者: Mono_kyrin    时间: 2020-1-16 16:07
本帖最后由 Mono_kyrin 于 2020-1-16 16:10 编辑

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

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

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

更何况,这个防策对于某通用存档修改器来说是无效的……
作者: orochi2k    时间: 2020-1-16 17:00
少年们,你们应当直面现实,RM的加密是幻觉。石器的一段代码可以瞬间将大部分的RM游戏变成石器的一个DLC
作者: guoxiaomi    时间: 2020-1-16 17:18
修改游戏并且公开发布方法我觉得永封不过分,毕竟作弊就是原罪。

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

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

本身做个游戏就已经很累了,要求作者放弃默认系统,花费更多的精力采用复杂的加密方案并不合适。
作者: MCCF    时间: 2020-1-16 18:53
瑟瑟发抖……

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

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

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


作者: MCCF    时间: 2020-1-16 19:06
本帖最后由 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,正好和游戏中看到的钱数一样(此处是已经修改的,具体实现时可用诸如正则的方式取得),岂不是就可以进行修改了?所以这里是比较缺乏安全性的。

[line]1[/line]

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

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 19:35
按我最近看到的例子就是,你帮他挖鼻孔,就算最后鼻子通了,被挖的时候也很难受,这样的感觉。
作者: 坏数据    时间: 2020-1-17 01:25
配图与楼主和楼主提及作者无关
只是一位好友的默认加密游戏被人修改后玩  来找我改进加密的方式





作者的内心是怎样的我想不需要解释了
反倒是很好奇楼主到底是出于一种怎样的心态?
文字中多次使用成功 神奇等字眼去描述自己写的脚本
又牵扯到自尊等 用阴阳怪气的语气去描述作者?
再在文末加上探讨漏洞一系列去转换话题 或许就觉得可以给自己justify?


如果你觉得我这篇回帖没有尊重你或者喷了你
做人吧 让别人尊重自己应该要学先会尊重别人

至于你所说的"漏洞" 难道不是RM本身的缺陷?
guoxiaomi 版主的回复也对此问题说明得够明白了
如果你真认为自己技术那么牛 这么一点逻辑简单的意识都没有吗?

作者: yang1zhi    时间: 2020-1-17 11:38
一般来说,作者都是讨厌别人修改他的东西的。
这个作者呢,一看你发图,就把你踢了呢,是比较急。
但是呢。群啊,贴吧啊,就是这样的地方吧,管理不开心了,就发动权限。
你要是提供技术支持,我相信他会喜欢你的。
作者: 灯笼菜刀王    时间: 2020-1-17 11:43
本帖最后由 灯笼菜刀王 于 2020-1-17 12:13 编辑

我觉得, 一个贼在光天化日之下公开某个保险柜的撬法, 尤其是在主人面前, 被打屎都算轻的吧?

既然人家加密了就表示不希望被破解, 那公开发布破解方法自然就被视为挑衅了

嘛,破解我也做过, 这种行为和贼一样, 哪怕你有正当的理由(劫富济贫 =.=?)也不能公开, 偷偷摸摸才是道
作者: 陈大帅帅帅哥    时间: 2020-2-1 16:24
小鬼毕竟是口袋改版圈的,不是RM圈,自然是不太希望有人在群里讨论太深入的问题,这可以理解。而且国外的RM口袋圈子面向的主要用户并非RMer而是正儿八经的宝可梦玩家,因此有不加密的习惯,作为一个RMer知道这个福利闷声发大财就好了,对于一般的宝可梦玩家来说这并不是什么漏洞(这应该是楼主和小鬼的主要矛盾点)。这就好比在元气骑士官方群里面分享破解版,作者不高兴是很自然的是,不必扯到什么尊严问题。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1