如何防止在我们的(多人)游戏中作弊?
Posted
技术标签:
【中文标题】如何防止在我们的(多人)游戏中作弊?【英文标题】:How to prevent cheating in our (multiplayer) games? 【发布时间】:2010-10-31 22:09:13 【问题描述】:如果您正在编写游戏,您应该考虑作弊者以及如何防止他们作弊。
我不认为只有 mmo 多人游戏,还有单人游戏或“自制”p2p mp 游戏。
当游戏完全基于服务器-客户端架构时,我认为这项工作几乎完成了,但也有墙壁黑客或其他东西。
我制作了自己的 p2p 游戏,但后来出现了作弊者。他们只是使用作弊引擎并尝试过速度黑客和记忆黑客的脚本小子。
大多数 speedhacks 钩子 gettickcount。我通过以下简单的技巧整理出了快速黑客。我只是跟踪time()-GetTickCount()
的值,如果差异发生变化,那就是作弊。
可以通过将散列副本保存在某处并始终移动它并始终按随机值重新散列它来解决内存损坏问题。不匹配会导致崩溃。
要彻底解决作弊引擎,只需检查:
if (OpenFileMapping(FILE_MAP_READ,false,'CEHYPERSCANSETTINGS')!=0)
// Cheat Engine runs.
(朋友告诉我的,我还没测试过。)
这些伎俩把骗子最多的一网打尽。但当然还有更多的作弊技巧。 我打开了这个wiki,来讨论更多其他的作弊技巧和避免它们的方法。
【问题讨论】:
如果您的游戏使用存档游戏,您需要检查存档游戏编辑和损坏情况 【参考方案1】:我认为你不应该做任何事情来停止在单人游戏中作弊。您的用户购买了游戏,他们应该可以作弊,只要他们不与其他人对战。
这是我做过的一些事情。这些主要是针对锦标赛游戏中的反作弊系统进行的,其中金钱是有风险的,并且对用户系统的一定程度的入侵被认为是可以接受的。我会小心在休闲游戏上做这些事情,因为如果你的游戏不稳定,可能会导致他们的系统出现问题。
1) 在可能的情况下,“永远不要相信客户”是您要遵守的最安全原则。在服务器上执行所有操作,并且只向客户端提供尽可能多的知识,以在任何给定时间呈现他应该能够在屏幕上看到的内容。即,如果客户端不知道隐藏在墙后面的玩家的位置,那么墙破解不会对用户有任何好处。对于高速动作游戏,这可能非常困难——尤其是现在实时阴影等已成为常态,即使玩家的身体可见,用户也可能需要能够看到阴影——但它应该始终是在您的选项顶部。在点对点游戏中也很难做到,但有一些方法可以限制同伴之间的知识。只有当它变得性能过高或超出您的时间/金钱预算时,才应考虑以下项目。
2) 打开所有其他进程,并钩住它们的 WriteProcessMemory 函数,这样它们就无法写入游戏进程中的内存。正确完成这一步骤将阻止 90% 的所有作弊和作弊引擎。
3) 做同样的事情,挂钩各种鼠标和键盘模拟功能。这将阻止许多瞄准机器人和其他类型的自动化机器人。
4) 在您的游戏进程中连接到 VirtualProtectEx/VirtualAllocEx/etc 函数,并监控哪些模块正在更改保护级别或分配新的内存块。当您的游戏进行大量分配时,您必须巧妙地处理这一点,以防止它过于占用 CPU,但这是可以做到的。
5) 挂钩 LoadLibrary 函数并监视任何动态加载的 DLL,以防止 DLL 注入。
6) 在您的游戏连接上使用一些轻量级的多态编码。
7) 使用一些反调试技术来防止调试器附加到您的进程。谷歌反调试,你应该能找到很多东西。
8) 使用自定义的专有 PE 打包程序来防止对您的游戏进行有用的反汇编。
9) 连接到处理透明度和 Alpha 混合的 OpenGL 或 Direct3D 函数和方法。
10) 如果使用着色器,请检查着色器和着色器常量值。
11) 对玩家角色使用额外的遮挡剔除技术,以防止他们在视线被其他几何体阻挡时被渲染。它可能对你的表现也有帮助,也可能没有,但它可以防止许多墙黑客。
【讨论】:
P2P=点对点,即不是单人游戏。尽管我同意不要浪费时间保护单人游戏,只要作弊不会以任何方式干扰其他玩家(例如在线高分榜或类似)。 只是想补充一点,在多人游戏的情况下,可能需要提及标准的“从不信任客户”理念。所有这些方法虽然非常有用,但随着技术和游戏的进步,只要有足够的时间,它们都会改变;但是,只信任服务器永远不会过时。然而,问题是关于单人游戏,所以也许没有必要,但提及它永远不会有坏处。 @DarthFutuza - 同意。这是旧的,但我想我没有提到它,因为提问者似乎对单人游戏和 p2p 游戏最感兴趣,那里没有真正的权威服务器。但我将此添加到列表的顶部,因为这是您可以做的最好的事情。【参考方案2】:您可能会发现Cheat Proof Game Protocols 上的这篇论文很有趣。它们都是同一个想法的变体:使用散列作为承诺,然后在满足其他玩家行为的条件时揭示散列承诺的含义。它很复杂,并且会影响性能,但其中一些想法可能很有用,尤其是对点对点游戏。
【讨论】:
链接已失效; this question 在 gamedev stackexchange 上有一些很棒的(实时)链接 Archive.org 链接:web.archive.org/web/20091123061710/http://prisms.cs.umass.edu/…【参考方案3】:当游戏完全基于服务器-客户端架构时,我认为这项工作几乎完成了,但也有墙壁黑客或其他东西。
如果您无法将大部分逻辑转移到服务器端运行,那么至少在每个游戏阶段尽可能少地共享状态,换句话说:考虑每个玩家的活动游戏模式,并且只分享当时实际相关的信息。
这样不仅可以减少作弊的可能性,还可以减少你的协议造成的流量,即提高效率。
这是一种在游戏/模拟行业中早已为人所知并应用的技术,用于提高渲染大型 3D 场景时的效率。
在那里,“平截头体剔除”用于确定场景的哪些部分实际可见,以便仅渲染相关部分。
同样,相同的技术可用于限制多人游戏客户端仅接收某些实际相关的更新/信息,例如如果其他客户端实际上在“相关范围”内,则其他客户端可以检索相应的更新。
不过,请区分相关性和“可见性”:被门隔开的两个玩家实际上可能不会“看到”对方,但根据周围环境,可能会很好地听到对方的声音。因此,区分不同类型的“可见性”:传播可听状态并不一定意味着传播玩家在游戏坐标中的实际位置。反之亦然:仅仅因为你“看到”了一个玩家,你不一定有权听到客户的声音(例如,想象一下步枪上的瞄准镜)。
换句话说,尝试将你支持的更新包松散耦合,使它们之间不存在相互依赖,也可以独立传播/订阅。
只要应用适当的封装和数据隐藏机制,就可以在很大程度上控制作弊,这样多人游戏客户端通常不会共享全局状态,而是共享状态直接取决于玩家的活动上下文(位置、航向、方向、速度等)。
【讨论】:
当然,如果玩家的某个部分对另一个玩家可见的可能性很小,那么在某些情况下,必须将该玩家的位置发送给客户端,以便进行墙壁破解工作. 我想你忘了说这不是一件容易的事,而且对性能有一定的影响。此外,它在许多情况下根本不起作用。 “兴趣管理”是谷歌搜索的术语。以上是关于如何防止在我们的(多人)游戏中作弊?的主要内容,如果未能解决你的问题,请参考以下文章
《有趣的二进制:软件安全与逆向分析》读书笔记:在射击游戏中防止玩家作弊
《有趣的二进制:软件安全与逆向分析》读书笔记:在射击游戏中防止玩家作弊
《有趣的二进制:软件安全与逆向分析》读书笔记:在射击游戏中防止玩家作弊