我一直在使用Unity创建一个完全脱机的2D游戏(这是问题所在),游戏过程需要您在特定级别输入某些字符串,并且Unity编译为DLL,可以很容易地对其进行逆向工程,因此有没有一种方法可以保护这些字符串(游戏处于离线状态,所以我无法从其他来源获取)?
游戏非常依赖这些字符串,是的,我知道混淆,但是我想要更强大的东西。而且我知道,简单的方法就是从数据源在线进行所有操作,但是我想知道是否有可能。
strings
程序指向它即可。
我一直在使用Unity创建一个完全脱机的2D游戏(这是问题所在),游戏过程需要您在特定级别输入某些字符串,并且Unity编译为DLL,可以很容易地对其进行逆向工程,因此有没有一种方法可以保护这些字符串(游戏处于离线状态,所以我无法从其他来源获取)?
游戏非常依赖这些字符串,是的,我知道混淆,但是我想要更强大的东西。而且我知道,简单的方法就是从数据源在线进行所有操作,但是我想知道是否有可能。
strings
程序指向它即可。
Answers:
不要存储这些字符串,请存储它们的(加密)哈希。
(加密的)哈希函数(例如加密)是一种将字符串转换为“乱码”(称为哈希)的方法,但是与加密不同,您无法从此哈希中获取原始字符串(除非您可以对其进行暴力破解或哈希功能已损坏)。大多数(如果不是全部)哈希函数采用任意长度的字符串,并返回恒定长度的字符串(取决于函数)。
您如何检查用户输入的字符串正确?由于您无法从哈希中获取有效的字符串,因此您唯一可以做的就是对用户的猜测进行哈希处理并将其与正确的哈希进行比较。
警告(由Eric Lippert撰写):请勿将内置函数GetHashCode
用作此类函数-不同的.NET版本和平台之间其结果可能会有所不同,从而使您的代码只能在特定的.NET框架版本和平台上工作。
您试图做的事既徒劳又毫无意义。
这是徒劳的,因为无法正确隐藏用户计算机上的信息。任何专心致志的人都会找到它。您可以加大难度,但永远无法避免。如果对它进行加密,则需要将加密密钥和算法存储在某个位置。无论您添加了多少个加密层,为了运行游戏,始终都需要对最外层进行解密。
这也毫无意义,因为我们生活在互联网时代。当您的游戏在远程流行时,这些密码将被发布到整个网络上。
您所能做的就是相信玩家不要通过查找游戏本来不会告诉他们的信息来破坏他们自己的游戏体验。无论如何,绝大多数玩家都不会开始对游戏进行逆向工程。如果少数具备必要技能的人这样做,那是他们自己的错。
如果确实需要这样的东西,则可以考虑在运行时从数字输入值构建字符串,而不是进行哈希处理。
优点是,如@Philipp所指出的那样,如果可以期望将代码隐藏在Internet上,则尝试将代码隐藏在可执行文件中是毫无意义的。不管是否经过哈希处理,在互联网上找到并输入到游戏中的相同单词都将给出相同的哈希值,并且将以任何一种方式起作用。
除了...,除非别人的代码对您不起作用。您可以轻松地做到这一点-不是100%防篡改,但对于普通用户而言相当难以解决。像“在线精灵名称生成器”一样简单的事情就可以做到(可以任意简单,实际上不需要太多markov文本生成引擎,从随机列表中提取4-5个音节就足够了)。
只需生成一个特定于用户或计算机的编号,它甚至不必是完全唯一的或非常防篡改的。大多数人可能会有所不同,并且不太可能定期更改的内容,例如计算机的网络名称,MAC地址或系统磁盘驱动器的GUID,无论如何(GPU序列号可能非常差因为用户可能会升级GPU)。加上解锁代码所指的数字代码,并将其输入到单词生成器中。但是准备好在玩家使用两台计算机或更换其网卡时回答支持问题(这很常见,但并非不可能)。最好只生成一次随机ID,然后将其与游戏设置一起存储,这是一个不错的计划。这样,如果发生任何更改,至少它不会破坏同一台计算机上的现有安装。
或者,您可能只使用游戏的序列号,该序列号是唯一的,并且在用户更换硬件时可以使用(具有讽刺意味的是,但是,这可能会促进盗版,因为共享的解锁代码适用于盗版序列而不适用于合法客户!)。
注意,防止用户作弊不一定是一件好事。在离线(即非竞争性游戏)中,如果用户从某个地方而不是从游戏中作弊并获取代码,通常是没有问题的。他只是在欺骗自己。谁在乎。
另一方面,如果他们真的想作弊,那就别忙了,这是彻底烦死付费客户的绝好机会。
所以...在采取这种方式之前,请先仔细考虑一下您是否真的想要那个,以及想要什么。非常有可能,拥有人类可读的字符串(或用xor使其琐碎地变成“不可读的”)就足够好了,实际上是可取的。
hash(serial + 1)
,您计算得出与第一个代码相对应的数字。然后将其输入到单词生成器中,该单词生成器从输入的每4位16个列表中提取一个音节。随您去,为每个用户提供单独的“单词”。
hash(serial+1)
在下载后进行计算,那么阻止用户进行什么计算hash(serial+1)
呢?一旦下载了程序,用户就可以访问程序执行的所有操作。
hash(serial + 1)
。所以呢?这不是问题。看,如果有人花一到两个小时(对于没有软件开发人员背景的典型“用户”来说可能花费6到8个小时)只是为了欺骗自己,那...让他吧。事实是,这只适用于一个人,但不适用于每个人,而且它没有竞争力……所以,没问题。
如果您不需要显示字符串,那么散列方法可能是解决之道。另一方面,如果确实需要将它们显示给用户,则可以通过其他方法避免它们直接显示在DLL中。
除了加密或混淆字符串以外,解决此问题的一种方法是将它们分解。也许只有一个按字母顺序排序的字典,其中包含游戏中所有字符串中的所有可能单词。然后在某个地方放置一个数组,使您可以通过索引单词数组将单词拼凑成所需的字符串。这样,您就不会在游戏中的任何地方拥有完整的字符串。不需要主密钥来解密字符串。举例来说,如果每个使用字符串的函数只有一个局部于该函数的索引数组,那么表明其顺序的数据就可以遍及整个源。我不确定这在您的特定情况下有多实用,但这是做到这一点的一种方法。
您甚至可能会有由几个单词组成的字符串,但是它们最终以不同的顺序排列。例如,您可能需要以下两个字符串:
您的词组列表将同时包含“一只熊”和“我的房子”,但是您可能会在它们之间插入大量其他词组,因此弄清楚哪一个与实际弄清楚一样困难游戏中的难题(或其他)。例如,动作短语可以是“经过”,“被烧毁”,“被推到”,“保护我免受”,“与我隔离”,“神奇地产生”等。
您可以通过使索引基于玩家已收集或完成的操作来将其纳入您的游戏。因此,游戏内任何地方都没有索引的主列表。它们将由玩游戏的玩家生成。
strings
可执行文件。