阻止人们入侵 Flash 游戏的基于 PHP 的高分表的最佳方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/73947/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 21:23:02  来源:igfitidea点击:

What is the best way to stop people hacking the PHP-based highscore table of a Flash game

phpactionscript-3securityactionscriptactionscript-2

提问by Iain

I'm talking about an action game with no upper score limit and no way to verify the score on the server by replaying moves etc.

我说的是一个没有分数上限的动作游戏,也没有办法通过重播动作等来验证服务器上的分数。

What I really need is the strongest encryption possible in Flash/PHP, and a way to prevent people calling the PHP page other than through my Flash file. I have tried some simple methods in the past of making multiple calls for a single score and completing a checksum / fibonacci sequence etc, and also obfuscating the SWF with Amayeta SWF Encrypt, but they were all hacked eventually.

我真正需要的是 Flash/PHP 中可能的最强加密,以及一种防止人们通过我的 Flash 文件以外的方式调用 PHP 页面的方法。过去,我尝试过一些简单的方法,例如多次调用单个分数并完成校验和/斐波那契序列等,还使用 ​​Amayeta SWF 加密混淆 SWF,但最终它们都被黑客入侵。

Thanks to StackOverflow responses I have now found some more info from Adobe - http://www.adobe.com/devnet/flashplayer/articles/secure_swf_apps_12.htmland https://github.com/mikechambers/as3corelib- which I think I can use for the encryption. Not sure this will get me around CheatEngine though.

感谢 StackOverflow 的回应,我现在从 Adob​​e 找到了更多信息 - http://www.adobe.com/devnet/flashplayer/articles/secure_swf_apps_12.htmlhttps://github.com/mikechambers/as3corelib- 我想我可以用于加密。不确定这会让我绕过 CheatEngine。

I need to know the best solutions for both AS2 and AS3, if they are different.

我需要知道 AS2 和 AS3 的最佳解决方案,如果它们不同的话。

The main problems seem to be things like TamperData and LiveHTTP headers, but I understand there are more advanced hacking tools as well - like CheatEngine (thanks Mark Webster)

主要问题似乎是 TamperData 和 LiveHTTP 标头之类的东西,但我知道还有更高级的黑客工具——比如 CheatEngine(感谢 Mark Webster)

回答by tqbf

This is a classic problem with Internet games and contests. Your Flash code works with users to decide a score for a game. But users aren't trusted, and the Flash code runs on the user's computer. You're SOL. There is nothing you can do to prevent an attacker from forging high scores:

这是网络游戏和竞赛的经典问题。您的 Flash 代码与用户一起决定游戏的分数。但是用户不受信任,Flash 代码在用户的计算机上运行。你是索尔。您无法阻止攻击者伪造高分:

  • Flash is even easier to reverse engineer than you might think it is, since the bytecodes are well documented and describe a high-level language (Actionscript) --- when you publish a Flash game, you're publishing your source code, whether you know it or not.

  • Attackers control the runtime memory of the Flash interpreter, so that anyone who knows how to use a programmable debugger can alter any variable (including the current score) at any time, or alter the program itself.

  • Flash 比您想象的更容易进行逆向工程,因为字节码有详细的文档记录并描述了一种高级语言 (Actionscript) --- 当您发布 Flash 游戏时,您正在发布源代码,无论您是知道与否。

  • 攻击者控制 Flash 解释器的运行时内存,以便任何知道如何使用可编程调试器的人可以随时更改任何变量(包括当前分数),或更改程序本身。

The simplest possible attack against your system is to run the HTTP traffic for the game through a proxy, catch the high-score save, and replay it with a higher score.

针对您的系统的最简单可能的攻击是通过代理运行游戏的 HTTP 流量,捕获高分存档,并以更高的分数重播。

You can try to block this attack by binding each high score save to a single instance of the game, for instance by sending an encrypted token to the client at game startup, which might look like:

您可以尝试通过将每个高分存档绑定到游戏的单个实例来阻止这种攻击,例如通过在游戏启动时向客户端发送加密令牌,它可能如下所示:

hex-encoding( AES(secret-key-stored-only-on-server, timestamp, user-id, random-number))

(You could also use a session cookie to the same effect).

(您也可以使用会话 cookie 达到相同的效果)。

The game code echoes this token back to the server with the high-score save. But an attacker can still just launch the game again, get a token, and then immediately paste that token into a replayed high-score save.

游戏代码将这个令牌以高分保存回传给服务器。但是攻击者仍然可以再次启动游戏,获取令牌,然后立即将该令牌粘贴到重播的高分存档中。

So next you feed not only a token or session cookie, but also a high-score-encrypting session key. This will be a 128 bit AES key, itself encrypted with a key hardcoded into the Flash game:

所以接下来您不仅要提供令牌或会话 cookie,还要提供高分加密会话密钥。这将是一个 128 位 AES 密钥,它本身使用硬编码到 Flash 游戏中的密钥进行加密:

hex-encoding( AES(key-hardcoded-in-flash-game, random-128-bit-key))

Now before the game posts the high score, it decrypts the high-score-encrypting-session key, which it can do because you hardcoded the high-score-encrypting-session-key-decrypting-key into the Flash binary. You encrypt the high score with this decrypted key, along with the SHA1 hash of the high score:

现在,在游戏发布高分之前,它会解密高分加密会话密钥,它可以这样做,因为您将高分加密会话密钥解密密钥硬编码到 Flash 二进制文件中。您使用此解密密钥以及高分的 SHA1 哈希值对高分进行加密:

hex-encoding( AES(random-128-bit-key-from-above, high-score, SHA1(high-score)))

The PHP code on the server checks the token to make sure the request came from a valid game instance, then decrypts the encrypted high score, checking to make sure the high-score matches the SHA1 of the high-score (if you skip this step, decryption will simply produce random, likely very high, high scores).

服务器上的 PHP 代码检查令牌以确保请求来自有效的游戏实例,然后解密加密的高分,检查以确保高分与高分的 SHA1 匹配(如果您跳过此步骤,解密只会产生随机的,可能非常高的分数)。

So now the attacker decompiles your Flash code and quickly finds the AES code, which sticks out like a sore thumb, although even if it didn't it'd be tracked down in 15 minutes with a memory search and a tracer ("I know my score for this game is 666, so let's find 666 in memory, then catch any operation that touches that value --- oh look, the high score encryption code!"). With the session key, the attacker doesn't even have to run the Flash code; she grabs a game launch token and a session key and can send back an arbitrary high score.

所以现在攻击者反编译你的 Flash 代码并快速找到 AES 代码,它像拇指一样突出,尽管即使没有它也会在 15 分钟内通过内存搜索和跟踪器找到(“我知道我这个游戏的分数是 666,所以让我们在内存中找到 666,然后捕获任何触及该值的操作——哦,看,高分加密代码!”)。有了会话密钥,攻击者甚至不必运行 Flash 代码;她获取一个游戏启动令牌和一个会话密钥,并可以发回任意的高分。

You're now at the point where most developers just give up --- give or take a couple months of messing with attackers by:

您现在正处于大多数开发人员放弃的地步 --- 通过以下方式给或花费几个月的时间与攻击者打交道:

  • Scrambling the AES keys with XOR operations

  • Replacing key byte arrays with functions that calculate the key

  • Scattering fake key encryptions and high score postings throughout the binary.

  • 使用 XOR 操作加扰 AES 密钥

  • 用计算密钥的函数替换密钥字节数组

  • 在整个二进制文件中散布假密钥加密和高分发布。

This is all mostly a waste of time. It goes without saying, SSL isn't going to help you either; SSL can't protect you when one of the two SSL endpoints is evil.

这主要是浪费时间。不用说,SSL 也不会帮助您。当两个 SSL 端点之一是邪恶的时,SSL 无法保护您。

Here are some things that can actually reduce high score fraud:

以下是一些实际上可以减少高分欺诈的事情:

  • Require a login to play the game, have the login produce a session cookie, and don't allow multiple outstanding game launches on the same session, or multiple concurrent sessions for the same user.

  • Reject high scores from game sessions that last less than the shortest real games ever played (for a more sophisticated approach, try "quarantining" high scores for game sessions that last less than 2 standard deviations below the mean game duration). Make sure you're tracking game durations serverside.

  • Reject or quarantine high scores from logins that have only played the game once or twice, so that attackers have to produce a "paper trail" of reasonable looking game play for each login they create.

  • "Heartbeat" scores during game play, so that your server sees the score growth over the lifetime of one game play. Reject high scores that don't follow reasonable score curves (for instance, jumping from 0 to 999999).

  • "Snapshot" game state during game play (for instance, amount of ammunition, position in the level, etc), which you can later reconcile against recorded interim scores. You don't even have to have a way to detect anomalies in this data to start with; you just have to collect it, and then you can go back and analyze it if things look fishy.

  • Disable the account of any user who fails one of your security checks (for instance, by ever submitting an encrypted high score that fails validation).

  • 需要登录才能玩游戏,让登录生成会话 cookie,并且不允许在同一会话中启动多个未完成的游戏,或同一用户的多个并发会话。

  • 拒绝持续时间少于有史以来最短的真实游戏的游戏会话的高分(对于更复杂的方法,尝试“隔离”持续时间低于平均游戏持续时间少于 2 个标准差的游戏会话的高分)。确保您正在跟踪服务器端的游戏持续时间。

  • 拒绝或隔离只玩过一两次游戏的登录的高分,这样攻击者就必须为他们创建的每次登录生成看起来合理的游戏“纸上记录”。

  • “心跳”在游戏过程中得分,这样您的服务器就会看到一个游戏生命周期内的得分增长。拒绝不遵循合理分数曲线的高分(例如,从 0 跳到 999999)。

  • 游戏过程中的“快照”游戏状态(例如,弹药量、关卡中的位置等),您可以稍后与记录的临时分数进行核对。你甚至不需要有办法检测这些数据中的异常情况;你只需要收集它,然后如果事情看起来很可疑,你可以回去分析它。

  • 禁用任何未通过您的一项安全检查的用户的帐户(例如,提交未通过验证的加密高分)。

Remember though that you're only deterring high score fraud here. There's nothingyou can do to prevent if. If there's money on the line in your game, someone is going to defeat any system you come up with. The objective isn't to stopthis attack; it's to make the attack more expensive than just getting really good at the game and beating it.

请记住,您只是在此处阻止高分欺诈。有没有什么可以做,以防止误。如果您的游戏中有钱,那么有人会打败您想出的任何系统。目标不是阻止这次攻击;这是为了让进攻变得更加昂贵,而不仅仅是真正擅长比赛并击败它。

回答by Stephen Deken

You may be asking the wrong question. You seem focused on the methods people are using to game their way up the high score list, but blocking specific methods only goes so far. I have no experience with TamperData, so I can't speak to that.

你可能问错了问题。您似乎专注于人们用来在高分列表中排名靠前的方法,但阻止特定方法仅到此为止。我没有使用 TamperData 的经验,所以我无法谈论这个。

The question you should be asking is: "How can I verify that submitted scores are valid and authentic?" The specific way to do that is game-dependent. For very simple puzzle games, you might send over the score along with the specific starting state and the sequence of moves that resulted in the end state, and then re-run the game on the server side using the same moves. Confirm that the stated score is the same as the computed score and only accept the score if they match.

您应该问的问题是:“我如何验证提交的分数是否有效且真实?” 做到这一点的具体方法取决于游戏。对于非常简单的益智游戏,您可以发送分数以及特定的起始状态和导致结束状态的移动顺序,然后使用相同的移动在服务器端重新运行游戏。确认声明的分数与计算的分数相同,只有在匹配时才接受分数。

回答by stormlash

An easy way to do this would be to provide a cryptographic hash of your highscore value along with the score it self. For example, when posting the results via HTTP GET: http://example.com/highscores.php?score=500&checksum=0a16df3dc0301a36a34f9065c3ff8095

一个简单的方法是提供一个你的高分值的加密哈希值以及它自己的分数。例如,通过 HTTP GET 发布结果时:http: //example.com/highscores.php?score= 500&checksum= 0a16df3dc0301a36a34f9065c3ff8095

When calculating this checksum, a shared secret should be used; this secret should never be transmitted over the network, but should be hard coded within both the PHP backend and the flash frontend. The checksum above was created by prepending the string "secret" to the score "500", and running it through md5sum.

计算此校验和时,应使用共享密钥;这个秘密永远不应该通过网络传输,而应该在 PHP 后端和 Flash 前端中进行硬编码。上面的校验和是通过在分数“ 500”前面加上字符串“ secret”并通过 md5sum 运行它来创建的。

Although this system will prevent a user from posting arbitrary scores, it does not prevent a "replay attack", where a user reposts a previously calculated score and hash combination. In the example above, a score of 500 would always produce the same hash string. Some of this risk can be mitigated by incorporating more information (such as a username, timestamp, or IP address) in the string which is to be hashed. Although this will not prevent the replay of data, it will insure that a set of data is only valid for a single user at a single time.

尽管该系统会阻止用户发布任意分数,但它并不能阻止“重播攻击”,即用户重新发布先前计算的分数和哈希组合。在上面的示例中,500 的分数将始终产生相同的哈希字符串。通过在要散列的字符串中加入更多信息(例如用户名、时间戳或 IP 地址),可以减轻部分风险。虽然这不会阻止数据的重放,但它会确保一组数据一次仅对单个用户有效。

To prevent anyreplay attacks from occurring, some type of challenge-response system will have to be created, such as the following:

为了防止发生任何重放攻击,必须创建某种类型的质询-响应系统,例如:

  1. The flash game ("the client") performs an HTTP GET of http://example.com/highscores.phpwith no parameters. This page returns two values: a randomly generated saltvalue, and a cryptographic hash of that salt value combined with the shared secret. This salt value should be stored in a local database of pending queries, and should have a timestamp associated with it so that it can "expire" after perhaps one minute.
  2. The flash game combines the salt value with the shared secret and calculates a hash to verify that this matches the one provided by the server. This step is necessary to prevent tampering with salt values by users, as it verifies that the salt value was actually generated by the server.
  3. The flash game combines the salt value with the shared secret, high score value, and any other relevant information (nickname, ip, timestamp), and calculates a hash. It then sends this information back to the PHP backend via HTTP GET or POST, along with the salt value, high score, and other information.
  4. The server combines the information received in the same way as on the client, and calculates a hash to verify that this matches the one provided by the client. It then also verifies that the salt value is still valid as listed in the pending query list. If both these conditions are true, it writes the high score to the high score table and returns a signed "success" message to the client. It also removes the salt value from the pending query list.
  1. Flash 游戏(“客户端”)不带参数执行http://example.com/highscores.php的 HTTP GET 。此页面返回两个值:一个随机生成的值,以及该盐值与共享秘密相结合的加密哈希。此盐值应存储在待处理查询的本地数据库中,并且应具有与之关联的时间戳,以便它可以在一分钟后“过期”。
  2. Flash 游戏将盐值与共享秘密相结合,并计算哈希值以验证它是否与服务器提供的值匹配。这一步是必要的,以防止用户篡改盐值,因为它验证盐值实际上是由服务器生成的。
  3. Flash 游戏将盐值与共享秘密、高分值和任何其他相关信息(昵称、IP、时间戳)结合起来,并计算哈希值。然后它通过 HTTP GET 或 POST 将此信息连同盐值、高分和其他信息发送回 PHP 后端。
  4. 服务器以与客户端相同的方式组合接收到的信息,并计算散列以验证这与客户端提供的信息匹配。然后它还会验证盐值是否仍然有效,如挂起查询列表中列出的那样。如果这两个条件都为真,它会将高分写入高分表并向客户端返回一个签名的“成功”消息。它还从挂起的查询列表中删除盐值。

Please keep in mind that the security of any of the above techniques is compromised if the shared secret is ever accessible to the user

请记住,如果用户可以访问共享机密,则上述任何技术的安全性都会受到损害

As an alternative, some of this back-and-forth could be avoided by forcing the client to communicate with the server over HTTPS, and insuring that the client is preconfigured to trust only certificates signed by a specific certificate authority which you alone have access to.

作为替代方案,可以通过强制客户端通过 HTTPS 与服务器通信,并确保客户端预先配置为仅信任由您单独访问的特定证书颁发机构签署的证书,从而避免这种反复出现.

回答by DGM

I like what tpqf said, but rather than disabling an account when cheating is discovered, implement a honeypot so whenever they log in, they see their hacked scores and never suspect that they have been marked as a troll. Google for "phpBB MOD Troll" and you'll see an ingenious approach.

我喜欢 tpqf 所说的,但与其在发现作弊时禁用帐户,还不如实施一个蜜罐,这样每当他们登录时,他们就会看到他们被黑的分数,并且永远不会怀疑他们已被标记为巨魔。谷歌搜索“phpBB MOD Troll”,你会看到一种巧妙的方法。

回答by divillysausages

In the accepted answer tqbf mentions that you can just do a memory search for the score variable ("My score is 666 so I look for the number 666 in memory").

在接受的答案中,tqbf 提到您可以对分数变量进行内存搜索(“我的分数是 666,所以我在内存中查找数字 666”)。

There's a way around this. I have a class here: http://divillysausages.com/blog/safenumber_and_safeint

有办法解决这个问题。我在这里有一堂课:http: //divillysausages.com/blog/safenumber_and_safeint

Basically, you have an object to store your score. In the setter it multiplies the value that you pass it with a random number (+ and -), and in the getter you divide the saved value by the random multiplicator to get the original back. It's simple, but helps stop memory search.

基本上,你有一个对象来存储你的分数。在 setter 中,它将您传递给它的值与一个随机数(+ 和 -)相乘,在 getter 中,您将保存的值除以随机乘法器以获取原始值。这很简单,但有助于停止内存搜索。

Also, check out the video from some of the guys behind the PushButton engine who talk about some of the different ways you can combat hacking: http://zaa.tv/2010/12/the-art-of-hacking-flash-games/. They were the inspiration behind the class.

另外,看看 PushButton 引擎背后的一些人的视频,他们谈论了一些可以打击黑客的不同方式:http: //zaa.tv/2010/12/the-art-of-hacking-flash-游戏/。他们是这门课背后的灵感来源。

回答by Chris Panayotoff

I made kind of workaround... I had a gave where scores incremented ( you always get +1 score ). First, I started to count from random num (let's say 14 ) and when I display the scores, just showed the scores var minus 14. This was so if the crackers are looking for example for 20, they won't find it ( it will be 34 in the memory ). Second, since I know what the next point should be... I used adobe crypto library, to create the hash of what the next point should be. When I have to increment the scores, I check if the hash of the incremented scores is equal to the hash is should be. If the cracker have changed the points in the memory, the hashes are not equal. I perform some server-side verification and when I got different points from game and from the PHP, I know that cheating were involved. Here is snippet ot my code ( I'm using Adobe Crypto libraty MD5 class and random cryptography salt. callPhp() is my server side validation )

我做了一些解决方法......我有一个分数增加的地方(你总是得到+1分数)。首先,我开始从随机数(假设为 14 )开始计数,当我显示分数时,只显示分数 var 减去 14。因此,如果饼干正在寻找例如 20,他们将找不到它(它内存中将是 34)。其次,因为我知道下一个点应该是什么......我使用了adobe crypto library,来创建下一个点应该是什么的哈希. 当我必须增加分数时,我会检查增加的分数的哈希值是否等于应该是的哈希值。如果破解者改变了内存中的点数,则哈希值不相等。我执行了一些服务器端验证,当我从游戏和 PHP 中得到不同的分数时,我知道涉及作弊。这是我的代码片段(我使用的是 Adob​​e Crypto libraty MD5 类和随机加密盐。callPhp() 是我的服务器端验证)

private function addPoint(event:Event = null):void{
            trace("expectedHash: " + expectedHash + "  || new hash: " + MD5.hash( Number(SCORES + POINT).toString() + expectedHashSalt) );
            if(expectedHash == MD5.hash( Number(SCORES + POINT).toString() + expectedHashSalt)){
                SCORES +=POINT;
                callPhp();
                expectedHash = MD5.hash( Number(SCORES + POINT).toString() + expectedHashSalt);
            } else {
                //trace("cheat engine usage");
            }
        }

Using this technique + SWF obfustication, I was able to stop the crackers. Also, when I'm sending the scores to the server-side, I use my own small, encryption / decryption function. Something like this (server side code not included, but you can see the algorithm and write it in PHP) :

使用这种技术 + SWF 混淆,我能够阻止饼干。此外,当我将分数发送到服务器端时,我使用自己的小型加密/解密功能。像这样的东西(不包括服务器端代码,但你可以看到算法并用 PHP 编写):

package  {

    import bassta.utils.Hash;

    public class ScoresEncoder {

        private static var ranChars:Array;
        private static var charsTable:Hash;

        public function ScoresEncoder() {

        }

        public static function init():void{

            ranChars = String("qwertyuiopasdfghjklzxcvbnm").split("")

            charsTable = new Hash({
                "0": "x",
                "1": "f",
                "2": "q",
                "3": "z",
                "4": "a",
                "5": "o",
                "6": "n",
                "7": "p",
                "8": "w",
                "9": "y"

            });

        }

        public static function encodeScore(_s:Number):String{

            var _fin:String = "";

            var scores:String = addLeadingZeros(_s);
            for(var i:uint = 0; i< scores.length; i++){
                //trace( scores.charAt(i) + " - > " + charsTable[ scores.charAt(i) ] );
                _fin += charsTable[ scores.charAt(i) ];
            }

            return _fin;

        }

        public static function decodeScore(_s:String):String{

            var _fin:String = "";

            var decoded:String = _s;

            for(var i:uint = 0; i< decoded.length; i++){
                //trace( decoded.charAt(i) + " - > "  + charsTable.getKey( decoded.charAt(i) ) );
                _fin += charsTable.getKey( decoded.charAt(i) );
            }

            return _fin;

        }

        public static function encodeScoreRand(_s:Number):String{
            var _fin:String = "";

            _fin += generateRandomChars(10) + encodeScore(_s) + generateRandomChars(3)

            return _fin;
        }

        public static function decodeScoreRand(_s:String):Number{

            var decodedString:String = _s;
            var decoded:Number;

            decodedString = decodedString.substring(10,13);         
            decodedString = decodeScore(decodedString);

            decoded = Number(decodedString);

            return decoded;
        }

        public static function generateRandomChars(_length:Number):String{

            var newRandChars:String = "";

            for(var i:uint = 0; i< _length; i++){
                newRandChars+= ranChars[ Math.ceil( Math.random()*ranChars.length-1 )];
            }

            return newRandChars;
        }

        private static function addLeadingZeros(_s:Number):String{

            var _fin:String;

            if(_s < 10 ){
                 _fin = "00" + _s.toString();
            }

            if(_s >= 10 && _s < 99 ) {
                 _fin = "0" + _s.toString();
            }

            if(_s >= 100 ) {
                _fin = _s.toString();
            }           

            return _fin;
        }


    }//end
}

Then I send the variable among with other fake-vars and it just get's lost among the way... It is a lot of work for just small flash game, but where prizes are involved some people just get greedy. If you need any help, write me a PM.

然后我将变量与其他假变量一起发送,它只是在途中丢失了......对于小型 Flash 游戏来说这是很多工作,但是在涉及奖品的地方有些人会变得贪婪。如果您需要任何帮助,请给我留言。

Cheers, Ico

干杯,伊科

回答by zeller

You cannot trust any data the client returns. Validation needs to be performed on the server side. I'm not a game developer, but I do make business software. In both instances money can be involved and people will break client side obfuscation techniques.

您不能相信客户端返回的任何数据。验证需要在服务器端进行。我不是游戏开发者,但我确实制作商业软件。在这两种情况下,都可能涉及金钱,人们将打破客户端混淆技术。

Maybe send data back to server periodically and do some validation. Don't focus on client code, even if that is where your applicaiton lives.

也许定期将数据发送回服务器并进行一些验证。不要专注于客户端代码,即使那是您的应用程序所在的位置。

回答by Scott Reynen

In my experience, this is best approached as a social engineering problem rather than a programming problem. Rather than focusing on making it impossible to cheat, focus on making it boring by removing the incentives to cheat. For example, if the main incentive is publicly visible high scores, simply putting a delay on when high scores are shown can significantly reduce cheating by removing the positive feedback loop for cheaters.

根据我的经验,最好将其视为社会工程问题而不是编程问题。与其专注于让作弊变得不可能,不如专注于消除作弊的动机,让它变得无聊。例如,如果主要激励是公开可见的高分,那么通过消除对作弊者的积极反馈循环,简单地推迟显示高分的时间可以显着减少作弊。

回答by Oli

Encrypting using a known (private) reversible key would be the simplest method. I'm not all up on AS so I'm not sure what sorts of encryption providers there are.

使用已知(私有)可逆密钥加密将是最简单的方法。我并不完全喜欢 AS,所以我不确定有哪些类型的加密提供程序。

But you could include variables like game-length (encrypted, again) and a click count.

但是您可以包括诸如游戏长度(再次加密)和点击次数之类的变量。

All things like this canbe reverse engineered so consider throwing in a bunch of junk data to throw people off the scent.

像这样的所有事情都可以进行逆向工程,因此请考虑放入一堆垃圾数据以让人们远离气味。

Edit: It might be worth chucking in some PHP sessions too. Start the session when they click start game and (as the comment to this post says) log the time. When they submit the score you can check they've actually got an open game and they're not submitting a score too soon or too large.

编辑:在某些 PHP 会话中也可能值得一试。当他们点击开始游戏时开始会话并(如这篇文章的评论所说)记录时间。当他们提交分数时,您可以检查他们是否真的有一场公开比赛,并且他们提交的分数不会太快或太大。

It might be worth working out a scalar to see say what the maximum score is per second/minute of play.

可能值得计算出一个标量,看看每秒/每分钟的最高得分是多少。

Neither of these things are uncircumventable but it'll help to have some logic not in the Flash where people can see it.

这些事情都不是不可规避的,但是在人们可以看到的 Flash 中没有一些逻辑会有所帮助。

回答by Jan Krüger

Whenever your highscore system is based on the fact that the Flash application sends unencrpyted/unsigned highscore data via the network, that can be intercepted and manipulated/replayed. The answer follows from that: encrypt (decently!) or cryptographically sign highscore data. This, at least, makes it harder for people to crack your highscore system because they'll need to extract the secret key from your SWF file. Many people will probably give up right there. On the other hand, all it takes is a singly person to extract the key and post it somewhere.

当您的高分系统基于 Flash 应用程序通过网络发送未加密/未签名的高分数据这一事实时,这些数据可以被拦截和操纵/重放。答案如下:加密(体面!)或加密签名高分数据。这至少使人们更难破解您的高分系统,因为他们需要从您的 SWF 文件中提取密钥。许多人可能会立即放弃。另一方面,只需要一个人就可以提取密钥并将其张贴在某个地方。

Real solutions involve more communication between the Flash application and the highscore database so that the latter can verify that a given score is somewhat realistic. This is probably complicated depending on what kind of game you've got.

真正的解决方案涉及 Flash 应用程序和高分数据库之间的更多通信,以便后者可以验证给定的分数在某种程度上是真实的。这可能会很复杂,具体取决于您拥有的游戏类型。