33

想象一个带有滚动关卡的太空射击游戏。有哪些方法可以防止恶意玩家修改游戏以谋取利益?他可以做的很难限制服务器端的事情是自动瞄准,在可见区域外窥视,速度黑客和其他事情。

有什么方法可以防止这种情况?假设服务器是任何语言并且客户端通过 WebSocket 连接。

始终假设代码是 100% 可破解的。想办法防止客户完全重写(出于作弊的目的)作弊。这些可以是诸如编写安全游戏协议的方法、服务器端检测等。

4

9 回答 9

37

服务器为王。客户端是可破解的。

你想要做的是你的 websocket 的两件事。

向服务器发送游戏动作并从服务器接收游戏状态。

你渲染游戏状态。然后您将输入发送到服务器。

  • 自动瞄准 - 这个很难解决。你必须追求现实主义。如果用户在 10 毫秒内爆头 10 次,那么你就踢他。编写一个聪明的作弊检测算法。
  • 在可见区域外窥视 - 通过仅将可见区域发送给每个客户端来解决
  • 加速黑客攻击 - 通过正确处理输入来解决。您收到用户向前移动的事件,您可以控制他的移动速度。

你不能通过缩小代码来解决这些问题。客户端上的代码用于处理输入和显示输出。所有逻辑都必须在服务器上完成。

您只需要编写服务器端验证。唯一的问题是,由于复杂性,游戏输入比表单输入更难验证。这与您为确保表单安全所做的事情完全相同。

不过,您需要非常小心您的“输入有效”检测。您不想在游戏中踢/禁止高技能玩家。很难在机器人检测过于宽松和机器人检测过于严格之间取得平衡。整个机器人检测领域总体上非常困难。例如,Quake 有一个自动瞄准检测功能,可以在当天将技术娴熟的玩家踢回来。

至于阻止机器人直接连接到您的 websocket,请在您的多人游戏上设置单独的 HTTP 或 HTTPS 验证通道以增加安全性。使用多个 Http/https/ws 通道来验证客户端是“官方的”,充当某种形式的握手。这将使直接连接到 ws 变得更加困难。

例子:

想想一个简单的多人游戏。基于 2D 房间的赛车游戏。多达 n 个用户在平面 2D 平台游戏地图上竞相从 A 到 B。

假设为了争论,您有一个安全系统,其中通过 HTTPS 通道进行复杂的身份验证,因此用户无法直接访问您的 websocket 通道并被迫通过浏览器。您可能有一个处理身份验证的 chrome 扩展程序,并且您强制用户使用它。这减少了问题域。

您的服务器将发送客户端渲染屏幕所需的所有视觉数据。您无法掩盖这些数据。无论你尝试什么,一个愚蠢的黑客都可以拿走你的代码并在调试器中减慢它的速度,直到他只剩下一个围绕你的 websocket 的原始包装器。他让您运行整个身份验证,但您无法阻止他删除您编写的任何 JavaScript 以阻止他这样做。你所能做的就是限制足够熟练的黑客访问你的 websocket 的数量。

因此,黑客现在将您的 websocket 放在了 chrome 沙箱中。他看到了输入。当然,您的赛道是动态且独特地生成的。如果你有一定数量的它们,那么黑客可以预先设计出最佳的比赛路线。您发送的用于可视化此地图的数据可以更快地呈现,然后人类与您的游戏交互,并且可以计算赢得赛车游戏的最佳动作并将其发送到您的服务器。

如果您要尝试禁止对您的地图数据反应过快的玩家并称他们为机器人,那么黑客会对此进行调整并增加延迟。如果您尝试禁止玩得太完美的玩家,那么黑客会对此进行调整,并使用随机数玩得不够完美。如果您在地图中放置只有算法机器人陷入的陷阱,那么可以通过了解它们、通过反复试验或机器学习算法来避免它们。为了绝对安全,您无能为力。

您只有一个选项可以绝对避免黑客。那就是建立你自己的不能被黑客入侵的浏览器。将安全机制构建到浏览器中。不允许用户在运行时实时编辑 javascript。

于 2011-03-09T18:51:49.427 回答
3

在服务器端,有 2 个选项:

1) 完整的服务器端游戏

每个客户端都将它们的“动作”发送到服务器。服务器执行它们并将相关数据发回。例如,一艘船想要向北移动,服务器计算它的新位置并将其发送回来。服务器还发送可见船只列表(解决地图黑客)等。

2) 完整的客户端游戏

每个客户端仍将其操作发送到服务器。但是为了减少服务器上的工作量,服务器不会执行这些操作,而是将它们转发给所有其他客户端。然后客户端同时解决所有操作。因此,每个客户最终都应该得到一个相同的游戏。每个客户端都会定期将其绝对数据(船舶位置等)发送到服务器,服务器会检查所有客户端数据是否相同。否则,游戏不同步,肯定有人在黑。

第二种方法的缺点是一些黑客仍然未被发现:例如地图黑客。作弊者可以注入代码以便他看到所有内容,但仍然只将他通常应该能够看到的数据发送到服务器。

--

在客户端,有 1 个选项:一个 javascript 组件,它扫描游戏代码以查看是否有任何修改(例如修改代码以呈现不可见但向服务器发送不同验证数据的对象)。

显然,黑客可以很容易地禁用这个组件。要解决这个问题,您可以强制客户端定期从服务器重新加载组件(服务器可以检查用户是否定期请求脚本文件)。这引入了一个新问题:黑客只是通过 AJAX 定期请求组件,但阻止它运行。为避免这种情况:让组件重新下载自身,但对其自身进行稍微修改的版本。

例如:让组件位于 yoursite/cheatdetect.js?control=5。服务器将生成一个稍作修改的 cheatdetect.js,以便在下一次迭代中,必须下载 cheatdetect.js?control=22(例如)。如果控制机制足够复杂,黑客将无法预测下一次请求哪个控制号,必须执行cheatdetect.js才能继续游戏。

于 2011-03-09T20:08:49.103 回答
1

您无法真正阻止任何人修改您的 JS 或编写 GreaseMonkey 脚本。但是,您可以通过缩小您的脚本以及使您的代码尽可能神秘来使他们变得困难。甚至可能会加入一些虚假的方法或变量,这些方法或变量什么都不做,只是用来把攻击者赶走。但是如果有足够的时间,这些方法都不是万无一失的,因为一旦你的代码到达客户端,它就不再是你的了。

于 2011-03-09T18:31:53.600 回答
1

他们不必接触您的客户端代码——他们可以嗅探并实现您的 Websocket 协议并编写一个伪装成人类玩家的微型代理。

更新:这个问题有几个部分,我没有想到答案,但可以考虑这些问题来评估各种选项:

  1. 你愿意走多远来防止作弊?如果你只关心随便的作弊,有多少障碍足以阻止随便的作弊者呢?中级 Javascript 程序员?认真的专家?权衡这与作弊的好处,是否有任何真正有价值的东西,比如现金和奖品,或者只是名誉?
  2. 您如何高度确信人类正在为您的游戏提供输入?例如,有了一个足够好的计算机视觉库,我可以在一个单独的机器上对你的游戏进行建模,将输入输入假装成鼠标的计算机,但这具有较高的相对成本(不值得我花时间)。
  3. 您如何在您的协议中创建一个信任链,以便将 (2) 的知识传递给服务器,并且您的服务器相对确信您的客户端代码正在发送消息?

当然,您设置的许多障碍都可以避开,但玩家和您的成本是多少?见“消耗战”。

于 2011-03-09T18:36:23.680 回答
1

我什至可以想到实现这一点的唯一方法是修改您的 Javascript 以充当客户端,然后设计一个中央服务器机制来验证从该客户端发送的数据。这可能是一个很大的实施变化,并且很可能会使您的项目更加复杂。但是,如前所述,如果应用程序完全在客户端上运行,客户端几乎可以使用您的脚本为所欲为。保护它的唯一方法是使用受信任的机器来处理验证。

于 2011-03-09T18:43:34.450 回答
1

其他一些可以实现的方法:

  • 使脚本难以将目标元素与其他元素区分开来。尽可能避免使用可预测的类和 id 名称的 div。使用 JavaScript 而不是使用类来注入样式。像黑客一样思考,让自己很难受。
  • 使用脚本将触发的诱饵。例如,如果威胁向量是使用像素颜色的屏幕抓取算法,则在非目标元素中抛出一些常见的像素颜色。对这些非目标的命中对作弊者来说似乎无关紧要,但可以检测到。你不想让骗子知道你为什么知道。
  • 将动作之间的最短时间限制在略低于人类最佳水平的水平。最好的玩家会达到这个平台,谁在作弊并不重要,并且能够立即检测到任何比通过旁调用方法调用更快的脚本编写的人。
  • 随机数生成器通常是统一的。人性不是。随机数生成器的值可能在设定的限制范围内且分布均匀。自然分布是高斯曲线。如果您对分布进行采样并且它在 x 和 y 轴上看起来像一个方波,那么 100% 它是一个骗子。作弊者很难检测到算法的阈值,因为它是随机的导数,而不是随机分布本身。您还使用聚合数据而不是单个播放来检测它,因此在不了解您的检测算法的情况下对算法进行逆向工程将非常困难。
  • 尽可能利用熵。避免可预测的游戏玩法。想象一下在一组赛道上进行的赛车游戏。每场比赛的牵引力、马力和动力水平可能略有不同。剧本必须非常好才能击败它。在滚动游戏中,您可以更改人类本能但计算机难以处理的因素,例如风力、重力变化等。它还可以作为附带好处使其更有趣。
  • 服务器生成的令牌可用于验证使用的 UI 元素,而不是对代码本身的调用。可以在游戏结束时将事件与 UI 元素的散列代码进行比较,在一次调用中处理验证。令牌应该是一个带有服务器私钥和一些 UI 元素值的散列。
  • 用他们认为你用来检测作弊的数据来诱骗作弊者。例如对 DetectCheat 方法的调用以及对假后端的虚拟调用。这是老魔术师的伎俩。在这里挥手,同时用另一只手将卡片滑入牌库。让他们在一个没有出口的迷宫里连续几天浪费时间,很多头发都在拉扯。
于 2020-06-13T23:52:18.840 回答
0

尽可能混淆您的客户端公开代码。此外,使用一些魔法。

于 2011-06-22T07:50:09.280 回答
0

我会结合使用缩小和 AJAX。如果所有的功能和数据都没有加载到页面中,那就更难作弊了。

另一方面,对于像 Id Software 这样的公司来说,改装被证明是一种非常有利可图的工具。也许允许对系统进行修改可能会使整个社区的游戏更加愉快。

于 2011-03-09T18:37:24.453 回答
0

您可以在浏览器上编辑 javascript 并使其工作。有人建议打电话与服务器核对一下。因此,在调用服务器后,它将在服务器中进行验证。一旦验证,它将来到客户端并执行操作。但我认为即使这样也不是万无一失的。

例如,。对于基本登录操作:在 Angular 中调用服务器时,后端验证用户名和密码,如果验证,它将返回客户端并让用户使用 Angular 登录。

当我说使用 Angular 登录时,它会将内容存储在 cookie 中,例如用户对象和其他内容。但是用户仍然可以删除调用后端的 JS 代码,并返回 TRUE(在需要的地方)并将用户对象(虚拟)插入到 cookie 和其他对象(无论需要什么)并登录。这是一件非常困难的事情,但它是可行的。在许多情况下,即使编辑/破解代码需要数小时,这也是不可取的。

这在单页应用程序中是可能的,其中 JS 文件不会为每个页面重新加载。为了减少被黑客入侵的可能性,我们可以使用缩小代码。而且我想如果像这样的操作是在后端完成的(比如在 Django 中登录),它会更安全。

如果我错了,请纠正我。

于 2016-02-17T09:41:50.203 回答