【问题标题】:Obfuscate source code using ProGuard使用 ProGuard 混淆源代码
【发布时间】:2012-08-21 07:37:02
【问题描述】:

最近我遇到了一些问题,有人在使用一款名为 Gamecih 的 root 用户应用作弊。 Gamecih 让用户可以在运行时暂停游戏并更改变量。

如果我混淆了我的代码,虽然作弊者很难知道在运行时要更改哪些变量,但我也担心它可能会导致其他一些问题。

我使用 Java 的 Serializable 接口序列化游戏对象,然后将它们写入文件。现在假设我正在序列化“Player”类的一个对象。它被序列化并保存到文件中。然后用户使用 Proguard 实现下载更新。 Proguard 将重命名类和类成员名称。尝试读取已保存的 Player 对象时,这不会导致严重错误吗?

如果我还没有启动我的游戏,这不是问题。但是现在有些玩家在同一个保存的游戏(这是一个 RPG)上玩了几个月。如果他们下载了更新并不得不从头开始,他们会非常生气。

我知道我可以指示 Proguard 不要混淆某些类,但我真正需要混淆的是 Player 类。

澄清:假设我有以下简单的 unobfuscated 类:

public class Player {

    private int gold;
    private String name;
    //Lots more.

    public Player(String name)
    {
        this.name = name;
    }
    public int getGold() {
        return gold;
    }
    public void setGold(int gold) {
        this.gold = gold;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
}

一个播放器被创建、序列化并保存到一个文件中。在我实现混淆器之后,它可能看起来像这样:

public class Axynasf {

    private int akdmakn;
    private String anxcmjna;

    public Axynasf(String adna)
    {
        anxcmjna=adna;
    }
    public int getAkdmakn() {
        return akdmakn;
    }
    public void setAkdmakn(int akdmakn) {
        this.akdmakn = akdmakn;
    }
    public String getAnxcmjna() {
        return anxcmjna;
    }
    public void setAnxcmjna(String anxcmjna) {
        this.anxcmjna = anxcmjna;
    }
}

想象一下,我现在发布了一个更新,而一个拥有未混淆播放器版本的播放器下载了该更新。当尝试读取该对象时,会有不同的成员名称和不同的类名称。我很可能会得到 ClassCastException 或类似的东西。

【问题讨论】:

  • 离题,但为什么呢?如果有些玩家想玩作弊让他们玩,那并不影响你或其他人。
  • @SJuan76:因为我有全球高分榜和pvp战。
  • 关于游戏的更多细节会有所帮助。另外我不明白你在客户端做什么可能会导致问题?
  • @pst:引用我自己的话:“我知道我可以指示 Proguard 不要混淆某些类,但我真正需要混淆的是 Player 类。”。目标是防止作弊,为此,我需要混淆整个 Player 类(包含黄金、物品、健康等变量)。
  • 只是从我的脑海中(所以可能是一个坏主意),但你为什么不使用某种校验和或变量的散列,添加一个新的类属性到 Player 类?如果在游戏中玩家获得了一些金币,那么您更新金币和校验和值。如果作弊者只是修改金币而不修改校验和你就知道他在作弊。

标签: java android serialization obfuscation proguard


【解决方案1】:

在 Proguard 方面没有专家,但我认为您认为它会破坏序列化是正确的。

解决此问题的一种可能方法是在您当前的保存结构上实现一个层 - 您可以告诉 Proguard 您不想混淆哪些类。现在让播放器(和类似的对象)保持不变,不要混淆。一旦对象被反序列化,将其传递给游戏其余部分处理的新层(被混淆) - 如果您不保留非混淆对象,那么它将导致作弊者问题调整在玩游戏期间(尽管不是在加载时)。同时,您可以考虑将玩家的游戏文件移至另一个不依赖于序列化的保存选项,这可能会在未来使此类问题变得更容易。

【讨论】:

  • 这实际上应该很容易,因为您可以将播放器(保存在文件中)扩展为 obPlayer(精确副本但经过混淆) - 但是不会阻止播放器更改保存文件中的数据
【解决方案2】:

为了确保 ProGuard 中的兼容序列化:

在 Java 中将序列化的类升级为不同的类:

  • JDK 文档 > 序列化 > 对象输入类 > readResolve

  • JDK 文档 > 序列化 > 对象序列化示例 > 演化/替换

【讨论】:

  • 请注意,您应该在此处或此站点上发布有用的答案点,否则您的帖子可能会被删除为"Not an Answer"。如果您愿意,您仍然可以包含该链接,但仅作为“参考”。答案应该是独立的,不需要链接。
【解决方案3】:

我了解 ppl 可以使用您命名的应用更新 vars @ runtime。

如果您更改成员名称,这些值仍会给出提示。 如果你混淆了,类名会改变,但新的名字无论如何都会在论坛上结束。 所以这还不够

您可以在更新中做的是,在启动时,在旧对象中加载序列化数据,转移到“新”混淆类,使用自定义序列化(使用 deviceID 值或 gmail 地址进行 XOR 以使其不太明显)。

尝试将您的玩家数据也放入多个类中。

【讨论】:

    【解决方案4】:

    在你的情况下我会怎么做:

    1. 发布带有混淆和非混淆类的更新。当播放器被加载时,它将尝试使用这两个类。如果播放器加载了非obf。类然后将此类映射到您的混淆类。
    2. 当玩家被保存时,它将使用混淆类保存。
    3. 在适当的时间后发布仅包含混淆类的更新。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-31
      • 1970-01-01
      • 2013-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多