击败作弊者的内存编辑器的策略-桌面游戏[关闭]


35

我假设我们正在谈论台式机游戏-玩家下载并在其本地计算机上运行的游戏。许多内存编辑器可让您检测和冻结值,例如播放器的运行状况。

您如何通过内存修改防止作弊?哪些策略可以有效地对抗这种作弊行为?

作为参考,我知道玩家可以:-通过值或范围搜索某些内容-搜索更改了值的某些内容-设置内存值-冻结内存值

我正在寻找一些好的。我使用的两个平庸的是:

  • 将数值显示为百分比而不是数字(例如46/50 =健康度为92%)
  • 一个低级类,将值保存在数组中,并在每次更改时移动它们。(例如,我没有一个int,而是一个由int组成的数组的类,并且每当值更改时,我都会使用其他随机选择的数组项来保存该值)

该游戏为离线,免费和单人游戏。

编辑:为了后代,我解决了这个问题(用C#语言),并将解决方案发布在这里,在我的博客上。

Answers:


21

(对于整数值)另一种可能性是使第二个成员变量保持现有变量的按位补码。

因此,想象你得到了health,你也会得到的healthComplement。您的实现可能如下所示:

// setter sets value and complement
void setHealth(int value){
    health = value;
    healthComplement = ~value;
}

// getter checks if value was changed outside of the setter
int getHealth(){
    if(value != ~healthComplement){
        // launch some cheat-counter-measure, like crashing the game?
        exit;
    }
    return health;
}

想要作弊的人必须正确设置health和healthComplement,否则游戏将崩溃。

我认为尝试阻止这种事情有点没有意义。人们已经成功地为更复杂的内容创建了骇客/作弊工具,只是不必要地混淆了您的代码或使您的游戏性能更差。


12

这是很久以前有人在某个板上要求时提出的一种方案。使用百分比或双倍变量并不能真正起作用,因为您可以搜索“任意”值并将其冻结。

相反,制作一个数据类型的怪物。

基本上,将重要的值存储为以下结构:

  • 32位指针
  • 为了快速阅读,也让该结构也将当前值也包含为一个普通的int

为了进行操作,请从分别分配的位(可以是true / false整数)中收集当前值,更改该值,然后将它们存储回去。

这是令人讨厌的位:每次您操纵值时,请释放并再次分配位。分配应该以随机顺序进行,因此数据会在内存中跳来跳去,并且不容易被冻结。

其他保护措施是存储值的校验和(以及“ plain” int),并在操作调用期间也将它们进行比较。如果发现不匹配,请执行一些细微的操作,例如,移除解锁游戏所需的随机钥匙。

编辑:为进一步移动内存,请确保在释放旧位之前分配新的“位”。

编辑:对于多人游戏,还可以序列化数据结构,对其进行压缩并通过网络发送。不是网络的最有效使用,但是绝对很难通过数据包嗅探来找出。


9

如何存储健康状况,并在每次存储时生成一个随机值作为补充。这至少会破坏简单的机制,即在内存中搜索增加/减少的值以找到运行状况。

class Player
{
  int m_Health;
  int m_RandomHealth;
  Random m_Rnd = new Random();

  public int Health {
    get
    {
      return m_Health ^ m_RandomHealth;
    }

    set
    {
      m_RandomHealth = m_Rnd.Next();
      m_Health = value ^ m_RandomHealth;
    }
  }
}

此外,即使健康状况没有变化,您可能仍想在每一帧重置该值。这样可以防止人们在健康状况发生变化时搜索更改的地址,而在健康状况保持不变的情况下保持不变。

奖励:每次更改时创建一个新对象,以便更改内存地址,并设置运行状况以每次读取时更改内存中的随机数,异或值和地址:

class Player
{
  int [] m_HealthArray; // [0] is random int, [1] is xored health
  Random m_Rnd = new Random();

  public Player() {
    this.Health = 100;
  }

  public int Health {
    get
    {
      int health = m_HealthArray[0] ^ m_HealthArray[1];
      Health = health; // reset to move in memory and change xor value
      return health;
    }

    set
    {
      m_HealthArray = new int[2];
      m_HealthArray[0] = m_Rnd.Next();
      m_HealthArray[1] = m_HealthArray[0] ^ value;
    }
  }
}

8

尽管我第一条评论是质疑降低部分观众的体验而没有明显收获的观点,但从技术角度来看,我仍然认为这是一个有趣的问题。

我只是有一个想法:作弊者所做的就是找到改变并冻结它们的价值。然后仅在死亡或改变玩家健康的事件之间进行搜索。而且,作弊者可以通过过滤掉他“不死”时发生的变化来完善搜索范围。

如果“健康”计数器一直在变化,该怎么办?如果性能影响太大,则使其成为指针并每隔一帧或每N帧重新分配一次。或将其与更改每个帧的随机值进行XOR(在使用新的随机值进行加密之前,再次对相同的值进行XOR进行解密)。

如果您还有其他游戏内数据也在更改整个时间(包括玩家角色的x和y位置或时间计数器),则可能很难找出所有更改的数据中的哪一个是健康状况。冻结整个游戏状态对作弊者是不行的。

对于进一步的误导,您实际上可以将运行状况存储在一个普通的只写变量(表示为蜜罐)中。

编辑

尽管如此,作弊者仍可能试图找出在整个时间中一直在变化的变量中哪些是通过反复试验而冻结的变量。一种可能的解决方案是将变量耦合在一起。

一个例子:

而不是存储健康状况(h)和位置(x),而是将它们存储在两个变量a和b中,以后可以从中获取值:

a = x+h; b = x-h
x = (a+b)/2; h = (a-b)/2

这样,如果作弊者只冻结其中一个,然后移动角色,则位置会受到影响,并且取决于冻结的角色,h变为负数(立即死亡)。您可以在上述公式与以下公式之间切换:

a = x-h; b = x+h
x = (a+b)/2; h = (b-a)/2

在连续的帧中,您可以保证在任一变量被冻结后最多2帧内,运行状况将在x改变时变为0。请记住,您仅存储a和b。如上所述,将其与连续的XOR相结合。结果是收集了一组变量,这些变量将每个帧更改为看似随机的值,冻结任何单个帧或其中的一个子集只会在游戏中产生不希望的副作用,即时死亡就是其中之一。


7

我认为可能可行的一种选择(我对这些作弊工具不太熟悉):不要隐藏它。执行您的操作并期待某些结果。操作后(可能是下一帧),请检查并确保结果与预期的一样。如果减去健康状况然后进行验证,只是发现健康状况从未改变,您可以确定(如果您没有一些晦涩的错误)它已被锁定。

如果您发现作弊,那么您现在可以自由地更改游戏规则,以达到最大程度的满足。如果您打算忽略作弊并使游戏继续运行,请在内存中的其他位置重新分配运行状况并更改指针,以便使用新值而忽略旧值。无限重复广告。


6

从理论上讲,任何单纯的混淆尝试都注定会失败,但实际上,您只需要付出足够的努力就可以打破挑战,而这比在游戏中成功要有趣。我不知道您的游戏是什么,因此我不会冒建议数据混淆方法的风险,甚至我认为它们毫无意义的风险也较小。

话虽如此,但您可能不会对此感到满意,我相信您正在寻找的是Memory Trusting,这是Trusted Computing概念。


3

一些流氓对象(DoomRL,Brogue)使用的一种非常有效的技术是掩盖实际变量。这意味着不是将健康显示为“ 2/10”,而是将其显示为“ 20%”。

请记住,大多数内存编辑器在特定值搜索/过滤方面都能很好地工作。如果您不知道特定的值,您仍然可以对其进行跟踪(例如,在玩家健康状况下降之后搜索更改/减小的值),尽管这样做的时间要长得多。

我还建议进行反作弊的反冲。例如,如果您的游戏中玩家受到非正向伤害并且其健康没有下降,那么您可以轻松而准确地进行检查并知道玩家作弊。做一些有趣的事情,例如在他周围产生一些超级敌人:)


2

编写在应用程序上调用ReadProcessMemory / WriteProcessMemory时挂接SSDT并记录/阻止的ring 0驱动程序。最好只记录日志,以便您可以随着时间的推移慢慢改变他们的游戏行为,而不仅仅是崩溃。


听起来您在谈论低级实施细节(Windows API?),我在询问一般的高级策略。
ashes999

2

为什么要阻止玩家作弊(在一个单人游戏中作弊就等于)?在多人游戏环境中,服务器的任务是检测不自然的变化并加以应对(通常是通过忽略输入或完全阻止罪魁祸首从服务器中逃脱),但是在单人游戏环境中,除了作弊者自己做了一个伤害。

IOW,除非您要创建多人游戏,否则这是浪费金钱,并且如果您正在考虑加固错误的地方。


2

研究已知的作弊工具-并经常检查是否检测到任何最常见的作弊工具(检查进程名称?)

如果检测到任何内容,请让玩家作弊(如果处于离线状态,这是无害的),但是请确保没有分数/成就会发布到任何在线排行榜/成就系统中-只是使其无声地失败了吗?

不会阻止更多坚定的黑客,但会减少更多随便作弊的行为搞乱您的排行榜的机会。

(尽管如此,可能会烦恼那些出于合法目的而打开和最小化开发工具并正在休息一段时间的开发人员,但是...)


7
我是Steam发行平台的忠实拥and,并在几年前玩了很多《军团要塞II》。一天晚上,我在长时间的编码会议上休息了一下,在玩的同时打开了Visual Studio和调试器。我发现自己因“作弊”而被TF2禁止。没有上诉,没有取消禁令的框架。一种“违法行为”,对于该帐户是永久性的。我仍然不知道为什么-相信我,我很生气-除了我深深地埋在FAQ中,玩游戏时打开“内存编辑器”构成了作弊行为而且是禁止的。哇。

1

我认为最简单的解决方案是实施作弊选项。在作弊选项中禁用评分。

另一个好主意,我不知道您将如何实现。是在存在冻结的内存变量或类似内容时关闭游戏:)

祝你好运(Y)


3
实施作弊是一个不错的选择。关闭游戏,没有那么多...(想象一下,如果您错了,并关闭了合法玩家。)
ashes999 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.