13

背景

玩家在我的安卓游戏中作弊已经有很长一段时间了。对于一个严格的单人游戏来说,这不是什么大问题,但由于我的游戏包含多人战斗和全球高分榜,这导致合法玩家因为作弊者而停止玩游戏。

他们如何作弊

作弊者使用名为Gamecih的 root 用户应用程序。Gamecih 允许用户暂停应用程序,更改变量值,然后恢复应用程序。所以在我的情况下,他们只是暂停游戏,将“健康”更改为 74 万亿,然后在多人游戏中将每个人都踢出去。这是一段视频,展示了如何使用 Gamecih 在 Fruit Ninja(不是我的游戏)中作弊。

考虑的方法

  1. 代码混淆。这是行不通的,因为混淆不会改变变量,只会改变变量。这意味着作弊者仍然可以找到与其当前健康值相同的变量,然后更改该变量。
  2. 代码混淆 + getter & setter 值改变。这样,健康实际上不会代表真正的健康价值。在 getter 方法中,我会做类似 return health*10; 在二传手我会做 health=input/10; 这当然可能更复杂。

我想要的是

可以说,我应该使用考虑的方法 nr 2,但话又说回来,它并不能防止黑客攻击,它只会让它变得更难。理想情况下,我想检测人们何时使用 Gamecih 作弊,显示一个弹出窗口说“该死的你,你这个讨厌的黑客”,然后关闭应用程序。我想要依赖服务器的解决方案,因为我希望我的玩家也能够离线玩游戏。如果可能的话,我还想避免代码混淆。

4

10 回答 10

9

您可以将生命存储在 X 个变量中,实际值将是它们的总和(始终动态计算)。您随机选择要更新的内容。最重要的是,您可以添加一些一致性检查,作弊者很难意识到什么以及如何更改它。

一致性检查可以是一个简单的规则,例如,第 1、第 2 和第 3 个变量按增长顺序排列,第 4 个变量最小。使用此工具需要花费一些时间才能解决这个问题。

Yoy 还可以获得更多创意,并在此之上混合一些加密等(您提到的方式)。然后,除非有人拥有您的代码,否则它变得几乎是不可能的。

编辑:添加 100 个随机变量,这些变量随随机名称(或数组中的位置,以使其更容易)一直变化,然后祝寻找正确的作弊者好运。并使其全部动态化,因此每次他们都必须再次破解它。

于 2012-10-01T09:42:28.373 回答
7

您可以定期检查您的值是否在不应该发生的情况下发生了变化。

例如,您可以将健康值已更改的事实存储在单独的隐藏标志中。如果您的检查方法确实检测到值的更改,并且未设置标志,那么您可以判断该更改是非法的。

例如 :

void incrementHealth(int amount) {
    health = health + amout;
    hiddenCheck.hasChanged = true;
    }

并在必须定期调用的单独方法中:

void checkHealth() {
    if (hiddenCheck.hasChanged) {
        // change is valid
        hiddenCheck.hasChanged = false;
        hiddenCheck.lastKnownValue = health;
        } else {
            if (hiddenCheck.lastKnownValue != health) {
                // An illegal change has occured ! Punish the hacker !
                }
            }
        }
   }
于 2012-10-01T09:58:11.923 回答
6
try{
    ApplicationInfo info = getPackageManager().
            getApplicationInfo("com.cih.gamecih", 0 );
    return true;
} catch( PackageManager.NameNotFoundException e ){
    return false;
}

如果这个函数返回true,千万不要让黑客进入多人模式,并提示他卸载它。

于 2012-10-01T13:02:12.610 回答
2

擅长作弊游戏的人也看过这些论坛,他们知道你所有的小秘密。

没有可靠的方法来防止人们欺骗在本地存储重要变量的游戏。游戏必须将这些变量保存在服务器上。如果这些变量没有保存在服务器上,总会有人破解你的游戏。

于 2015-02-10T03:13:36.977 回答
1

根据存储的值动态计算您的统计数据。

private double getSaltedSqrt(int i){
    return Math.sqrt(i)+1337;
}

private int getTrueValue(double i){
    return (i-1337)*(i-1337);
}

这样,任何大脑正常的人都无法从 RAM 中找到您的值。拥有 100 生命值的人的生命值将是 1347.0

如果有人对该玩家造成 10 点伤害,您只需调用:

currentHealth = getSaltedSqrt(getTrueValue(currentHealth)-damage);

但是,最安全的方法是通过服务器实现所有这些更改。

于 2012-10-01T09:55:28.177 回答
1

我对此有一个想法,因为我自己有时会使用 GameCIH。你可以有一个滚动的 10 条目事务日志,它可以对每个新事务进行自我检查。

你要做的(因为 GameCIH 一次只能处理一个变量)是有两个变量相互检查。

  • 原始(或 11 年前)值
  • 变化值 1 到 10 的数组
  • 求和值,取反。(这完全改变了您可以看到的十进制值,并且当最旧的日志条目被滚动到其中时,它的变化将与原始值不同。)

如果求和值的负数与原始值加上 10 个记录的事务不匹配,则返回错误。

您只需要更改您的 stat mod 的处理方式 - 如果其中一个仍然尝试直接修改原始值,您的游戏将返回它被错误地更改。

于 2013-06-07T13:58:57.547 回答
0

为防止内存作弊,您可以执行以下操作之一:

于 2013-03-12T14:41:58.170 回答
0

您应该存储健康状况的哈希值(例如 crc32 或 md5)等。每次更新值时,对当前设置的值进行哈希检查。在这种情况下,作弊者必须编写一个单独的应用程序来处理哈希。可能,但这将很快阻止脚本小子作弊者。

于 2013-12-23T00:06:13.223 回答
0

在 Pokemon 游戏中,他们使用了 DMA。您可以通过在游戏暂停很短的时间时让计时器关闭并触发所有值的更新来获得类似的效果。更新将为所有变量添加一些随机数量(包括您从中减去以获得单个值的变量)。您还可以尝试将值存储在一个大数组中并更改起始位置。而不是像这样的绝对指针GameState[121],你会有类似的东西GameState[121+StartingPosition],只需将值增量器与位置随机器组合起来。在这两种情况下,模算术都是您的朋友。小心溢出数组和一个错误。缓冲区溢出是不好的。;)

如果这是一个 Flash 或 Java 应用程序:可悲的是,使用内存管理快速重新映射值在 RAM 中的位置并不像 Gameboy Advance 使用的本机二进制文件那样方便。以随机顺序将所有变量复制到第二组,然后删除和垃圾收集原始值可能会使您的游戏运行缓慢。

于 2014-01-14T07:56:19.263 回答
0

你能在游戏启动时检查root访问权限吗?然后拒绝在有根设备上打开应用程序或拒绝多人模式?仅在应用程序初始化时在打开的加载屏幕上提供一个小检查,可能有应用程序请求超级用户然后如果用户授予它尝试执行没有超级用户不允许的无害功能然后代码检查所述功能是否成功然后撤消更改和弹出一个消息框,指示用户应该离开 root 模式重试。

或者,可以在进入多人模式时应用此检查。

你也可以从服务器运行多人模式,从设备运行单人游戏,让单人游戏自由编辑。

于 2014-02-24T12:16:16.593 回答