题
背景
我已经有一段时间遇到玩家在我的 Android 游戏中作弊的问题了。对于严格的单人游戏来说,这不会是一个大问题,但由于我的游戏包含多人战斗和全球高分列表,因此会导致合法玩家因为作弊者而停止玩游戏。
他们如何作弊
作弊者使用名为 root 用户的应用程序 加梅吉赫. 。Gamecih 允许用户暂停应用程序、更改变量值,然后恢复应用程序。所以在我的例子中,他们只是暂停游戏,将“生命值”更改为 74 万亿,然后把多人游戏中的每个人都踢出去。这是一个 视频 展示 Gamecih 如何在《水果忍者》(不是我的游戏)中作弊。
考虑的方法
- 代码混淆。这是行不通的,因为混淆不会改变变量 价值观, ,只是变量 名字. 。这意味着作弊者仍然可以找到与其当前健康状况具有相同值的变量,然后更改该变量。
- 代码混淆 + getter 和 setter 值更改。这样一来,健康实际上并不能代表真正的健康价值。在 getter 方法中,我会执行类似 return health*10; 的操作;在设置器中我会做 health=input/10;这当然可能更复杂。
我想要的是
可以说我应该使用经过考虑的方法 2,但话又说回来,它并不能防止黑客攻击,只会让黑客攻击变得更加困难。理想情况下,我想检测人们何时使用 Gamecih 作弊,显示一个弹出窗口,显示“该死的,你这个讨厌的黑客”,然后关闭应用程序。我愿意 不是 想要一个依赖于服务器的解决方案,因为我希望我的玩家也能够在离线时玩游戏。如果可能的话,我还想避免代码混淆。
解决方案
您可以在x的变量中存储寿命,并且实际值将是它们的总和(始终动态计算)。随机选择哪一个更新。最重要的是,您可以添加一些一致性检查,骗子变得非常难以实现什么以及如何更改它。
一致性检查可能是一个简单的规则,即第一个,第2和第3变量越来越多的顺序,而第4则是最小的。用这个工具来弄清楚有人很好。
Yoy还可以在某些加密等中获得更多创意和混合(您提到的方式)之上。然后,除非有人有你的代码,否则它将成为不可能的。
编辑:添加100个随机变量,随机名称和数组中的位置,使其更轻松地更改),然后为寻找合适的骗子而良好的运气。每次他们都必须再次破解它,都会使其成为动态的。
其他提示
如果在不应该的情况下,您可以定期检查。
例如,您可以存储在单独的隐藏标志中,即运行状况值已更改。如果检查方法确实检测到值的变化,则不会设置标志,那么您可以告诉变更是非法的。
例如:
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 !
}
}
}
}
. try{
ApplicationInfo info = getPackageManager().
getApplicationInfo("com.cih.gamecih", 0 );
return true;
} catch( PackageManager.NameNotFoundException e ){
return false;
}
.
如果此函数返回true,甚至甚至不允许黑客进入多人游戏模式,并提示他卸载它。
从存储的值动态计算统计数据。
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);
.
但是,最安全的方式是通过服务器实现所有这些更改。 我有一个想法,因为我有时我自己使用gamecih。您可以有一个滚动的10条目交易日志,即在每个新事务上进行自检。
你会做什么(由于Gamecih只能一次处理一个变量)是有两个互相检查的两个变量。
- 原始(或11年前)值
- 变化值的数组1到10
- 求和值,否定。(这完全更改了您可以看到的十进制值,并且当最旧的日志条目汇入它时,它将与原始值不同。)
如果求和值的负面不匹配原始加上10个记录的事务,则返回错误。
你只需要改变统计模式的处理方式 - 如果甚至其中一个仍然尝试直接修改原始值,那么您的游戏将返回它被错误更改。
擅长作弊游戏的人也读过这些论坛,他们知道你所有的小秘密。
没有固定的方法来防止人们在欺骗一个存储在本地存储重要变量的游戏。游戏必须在服务器上保留这些变量。如果这些变量不保存在服务器上,则将始终有人能够破解您的游戏。
要防止内存作弊,您可以执行以下操作之一:
- 存储位数阵列中的最重要的值,而不是在 变量
- 存储作为字符串的值以及随时修改 它检查它是否与字符串匹配。
- 从Mochi(ActionScript 3)看看Mochidigits类,并提出Java端口。 https://代码.google.com / p / cunitescore / source / browse / trunk / AS3 / Unitescore / Mochi / Mochidigits.as?r= 92
您应该存储健康等的哈希(例如CRC32或MD5)。每次更新值时,请执行当前设置值的哈希检查。在这种情况下,骗子必须编写处理哈希的单独应用程序。可能的,但这将很快停止脚本和骗子骗子。
在 Pokemon 游戏中,他们使用了 DMA。当游戏暂停很短的时间时,您可以通过关闭计时器并触发所有值的更新来获得类似的效果。更新将为所有变量添加一些随机量(包括从中减去以获得单个值的变量)。您还可以尝试将值存储在一个大数组中并更改起始位置。而不是像这样的绝对指针 GameState[121]
, ,你会有类似的东西 GameState[121+StartingPosition]
只需将值增量器与位置随机发生器结合起来即可。在这两种情况下,模算术都是你的朋友。警惕数组溢出和差一错误。缓冲区溢出就不好了。;)
如果这是 Flash 或 Java 应用程序:遗憾的是,使用内存管理来快速重新映射 RAM 中值的位置并不像 Gameboy Advance 使用的本机二进制文件那样方便。以随机顺序将所有变量复制到第二组,然后删除并垃圾收集原始值可能会使您的游戏运行得非常慢。
你可以检查游戏发布的root访问权限吗?然后拒绝在扎根设备上打开应用程序或拒绝多人游戏模式?只有在初始化应用程序时提供一个小检查,只有当应用程序初始化应用程序时,可能会有应用程序请求超级用户,那么如果用户授予它尝试执行不允许的无害功能,则没有超级用户,然后代码检查所述功能是否成功,然后撤消更改弹出一个消息框,指示用户应该再次留下根模式。
可以在进入多人模式时应用此检查。
您还可以从服务器和单个播放器运行多人游戏模式,并让单个播放器十六进制自由编辑。