当我的应用程序被完全反编译时,RSA 没用吗?

信息安全 密码学 RSA
2021-09-09 21:21:26

我用 Unity Engine 编写了一个 Android 游戏。正如您在 Unity 中所知道的,脚本编译成一个名为“Assembly-CSharp.dll”的文件。我用 C# 编写了我的脚本。

将整个游戏编译成 .apk 后,我将其重命名为 .zip 并将 Assembly-CSharp.dll 拖入 ILSpy 之类的工具中,而整个程序已完全反编译,包含我的 RSA 公钥或 AES 密码等所有详细信息,IV ,盐...
我的应用程序的逻辑是客户端(Android)和服务器(Java)。

当玩家完成一个关卡时,通过这个 URL: http://www.example.com:8080/MyApp/SaveScores.do?hash=labla....labla,我们给他分数。真正的参数是用户名、分数、时间戳。我们的加密算法是 RSA 1024 位。

当作弊者/攻击者嗅探 HTTP 流量以使用重放攻击时,我们使用 RSA 和时间戳参数检查解密的哈希值,我们将他踢出去。

但是当他使用工具 (ILSpy) 完美地反编译代码时,他只需找到我的公钥并发现我使用该公钥加密了用户分数和时间戳。然后,他将编写一个 Unity 或 C# 程序,用新的时间戳简单地加密他操纵的消息,并且他将在我的服务器端应用程序中受到信任,因为任何事情都是真实的。

他将通过在不玩游戏的情况下向服务器发送 HTTP 请求来提高分数。他可以简单地作弊。

我能做什么?

  1. 我不能使用 SSL。
  2. 通过混淆,只会增加破解时间。
  3. 通过在运行时从服务器到客户端提供公钥,内存检查器或流量嗅探器可以简单地看到公钥。
2个回答

简短的回答是:是的,在这种情况下 RSA 没用。如果所有游戏逻辑都发生在客户端,则无法防止作弊。

如果您的游戏仅报告最终分数而没有其他任何内容,则加密无济于事。游戏必须知道如何提交分数,因此必须始终将完整信息存储在其中。您只能通过添加混淆和其他障碍来使作弊者更难。

我建议两件事:

  • 发送的不仅仅是最终分数。发送一些有关游戏进展情况的信息。(某个时间的分数是多少,当用户失去生命时,他做了什么决定......)然后在服务器上验证是否有可能以这样的游戏进度获得这样的分数。
  • 禁止任何提交无效结果或之前提交的结果的用户。确保你的游戏总是产生有效的结果,并且足够随机,不可能两次产生相同的结果。您甚至不必让作弊者知道他已被禁止,只需将他的分数从任何公开列表中隐藏即可。

如果您的客户端可以发送时间,则服务器可以向客户端颁发具有过期时间的公钥证书,而不是在您的应用程序中对公钥进行硬编码。