如何防止假高分出现在全球高分榜上?
假设您正在设计一款记录高分的 PC 游戏。 除了保留本地分数外,还设置了一个全球高分服务器,游戏可以通过互联网访问该服务器。 玩家应该能够在完成游戏后立即将他们的高分提交到全局高分列表,或者稍后从本地高分列表提交。 这一定是一个常见问题; 现代游戏机上的街机游戏通常具有这样的全球高分列表。
我的问题归结为:如何防止某人提交虚假高分?或者,换句话说,全球高分服务器如何确保提交的分数确实是由运行产生的游戏?
我越想越觉得这可能是一个无解的问题。
要验证消息是否源自某个特定源,您通常会做的事情是让源对消息进行数字签名。 在这种情况下,您当然可以这样做,但真正的问题是,播放器通过拥有该软件,也拥有该软件的私钥。 无论它多么令人困惑,它都可以被逆向工程,甚至只是从内存中提取出来。
另一种选择是将玩家游戏的重播发送到高分服务器,该服务器将快速运行重播并验证提交的分数是否与重播的结果匹配。 这并不能解决问题,但如果你还必须制作一个非常复杂的重播来“证明”它,那么肯定会让伪造高分变得更加困难。
这是一个有解决办法的问题,还是真的无解? 家庭游戏机开发人员是否使用了一些技术来防止此类漏洞,或者他们只是依靠控制台来防止未经授权的代码运行?
Suppose you are designing a PC game that keeps track of high scores. In addition to keeping local scores, a global high score server is set up that is accessed by the game over the internet. Players should be able to submit their high scores to the global high score list right after they have completed a game, or later, from their local high score list. This must be a common problem; arcade games on modern game consoles often feature a global high score list that works like this.
My question boils down to: how can you prevent someone from submitting bogus high scores? Or, stated another way, how can the global high score server be sure that a submitted score was really produced by a run through the game?
The more I thought about this, the more I think it may be an unsolvable problem.
What you'd commonly do to verify that a message originated from a certain source is have the source digitally sign the message. You could certainly do that in this case, but the real problem is that the player, by having the software, also has the software's private key. No matter how obfuscated it might be, it can be reverse engineered, or even just plucked from memory.
Another option would be to send along a replay of the player's game to the high score server, which would quickly run the replay and verify that the submitted score matches the outcome of the replay. This doesn't solve the problem, but it certainly makes it more difficult to forge a bogus high score if you also have to produce a very complex replay that "proves" it.
Is this a problem that has a solution, or is it really unsolvable? Are there techniques used by the home game console developers to prevent this sort of exploit, or do they simply rely on the console preventing unauthorized code from running?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
对于由客户端生成分数的PC游戏来说,这不是一个可解决的问题,因为客户端本质上是不可信的。
您唯一可以尝试做的就是让某人更难提交虚假分数。
一些想法:
保护内存中的分数。
您可以使用 CryptProtectMemory 等 API 将分数隐藏在内存中 -简单的内存写入是行不通的。 但是,通过附加的调试器或通过将代码注入到您的进程中,他们仍然可以修改分数。 您可以研究各种尝试击败调试器的方案。
保护通往服务器的途中的分数。
您可以按照您的建议对发送到服务的数据进行加密,但由于不受信任的一方可以控制密钥,因此这只是混淆,并不能提供可靠的保护。
验证服务中的分数。
除了非常简单的检查之外,我不愿意这样做。 这里的错误将导致您拒绝有效分数。 无法区分作弊者和强者。
此时,您确实必须问问自己,工程方面的努力是否真的值得。 如果有人发布无效分数怎么办? 你实际上失去了什么? 我会尽最大努力用简单的脚本来防范孩子。 也就是说,不要让你的分数提交是公正的:
我只是在内存中使用简单的保护来防止偶然的窥探,在线上进行一些简单的混淆(使用服务器cookie对分数进行哈希处理)并完成。
For a PC game where the score is generated by the client, this is not a solvable problem since the client is inherently untrustworthy.
The only thing you can try to do is make it harder for someone to submit a fake score.
Some thoughts:
Protect the in-memory score.
You can use API's like CryptProtectMemory to hide the score in memory - a simple memory write will not work. However, with an attached debugger or via injecting code into your process, they could still modify the score. You can look into various schemes for trying to defeat debuggers.
Protect the score en-route to the server.
You can encrypt the data being sent to the service, as you suggest, but since the untrusted party has control over the key, this is merely obfuscation and offers no solid protection.
Validate the score at the service.
I'd be loathe to do this, beyond very simple checks. A bug here will result in you rejecting valid scores. It'll be impossible to distinguish between cheaters and strong players.
At this point, you really have to ask your self if the engineering effort is really worth it. What if someone posts an invalid score? What do you actually lose? I would do the bare minimum to protect against a kid with a simple script. I.e., don't have your score submission be just:
I would just use simple protection in memory against casual snoops, some simple obfuscation on the wire (hash the score with a server cookie) and be done.
据我所知,这是无法解决的。
我见过很多人试图混淆加密密钥。 我见过一些人还进行了其他健全性检查,例如经过的时间或剩余的敌人。 我从未见过发送重播的人,尽管当然这是可能的。
在一个未命名的网站中,他们设置了一个很容易被发现的假发送高分例程。 如果犯罪者使用它,他们的 IP 地址将被自动禁止用于未来的更新。
To my knowledge, this is unsolvable.
I have seen many people try to obfuscate the encryption key. I have seen a few people include other sanity checks like time elapsed, or enemies remaining. I have never seen one that sends a replay, though of course it is possible.
In a website that will remain unamed, they setup a fake send high score routine that is easily found. If a perpetrator uses it, their IP address will be automatically banned from future updates.
“另一种选择是发送玩家游戏的重播......这并不能解决问题,”
真的吗? 为什么不?
“你还必须制作一个非常复杂的重播来“证明”[分数]。”
您是否建议有人可以伪造重播? 在不实际玩游戏的情况下推理出超高分解决方案? 伪造时间戳和一切? 拉一个唐纳德·克劳赫斯特?
为什么不直接玩游戏而不是尝试伪造玩游戏的日志呢?
或者...如果很容易伪造游戏历史从而获得超高分,那么游戏可能设计不当。 如果游戏很“困难”,则该人必须做出所有正确的选择。 如果游戏很简单,那么分数就不能反映玩家的选择,并且是可以伪造的。
这样想吧。 选择任何游戏或运动。 有人说,比如说,瑞士在游艇比赛中击败了新西兰。 你会通过寻找有关场地、船只、团队和个人比赛的具体细节来挑战他们,以说服自己这是真的。 当然,他们可以伪造它,但如果他们有一套丰富的比赛细节,那么……这怎么不是“证据”呢?
"Another option would be to send along a replay of the player's game ... This doesn't solve the problem, "
Really? Why not?
"you also have to produce a very complex replay that "proves" [the score]."
Are you suggesting someone could fake the replay? Reason out a super-high-score solution without actually playing the game? Fake the timestamps and everything? Pull a Donald Crowhurst?
Why not just play the game rather than attempt to fake a log of playing the game?
Or... if it's that easy to fake a history of game play that leads to a super high score, perhaps the game is misdesigned. If the game is "hard", the person must make all the right choices. If the game is easy, then the score doesn't reflect the player's choices and is fakable.
Think of it this way. Pick any game or sport. Someone says that -- say -- Switzerland beat New Zealand in a yacht race. You would challenge them by seeking substantiating details on the venue, the boats, the teams and the individual races to convince yourself it was true. Certainly, they could fake it, but if they've got a rich set of details covering the race, then... how's that not "proof"?
忘记密码问题; 如果你的代码可以在本地机器上被黑客攻击,你如何防止有人人为地设置一个疯狂的高分,然后使用现有的可信机制传输它?
在您能够建立对代码本身的信任之前,通信的加密机制不会成为真正的问题。
Forget the cryptogaphic issue; if your code can be hacked on the local machine, how do you keep someone from setting a crazy high score artificially and then transmitting it using the existing trusted mechanism?
Until you can establish trust in the code itself, a crypto mechanism for the communications isn't going to be the real problem.
将(软件+随机盐)的哈希值与分数一起发送。 与服务器检查此哈希值。 如果匹配(意味着软件未更改),则接受它。 否则,分数来自游戏的“修改”版本。 拒绝它。 每次生成散列时,随机盐都应该改变(当前系统时间或类似时间)
检查 Quake III Arena 源代码。 他们的版本非常简单。 不幸的是,我现在不记得链接了。
Send the hash of the (software + a random salt) along with the score. Check this hash with the server. If it matches (meaning that the software is unaltered) accept it. Otherwise, the score comes from a "modded" version of the game. Reject it. The random salt should change every time the hash is generated (current sys time or something like that)
Check Quake III Arena source code. Their version was quite fool proof. Unfortunately, I don't remember the link now.