51

我想知道是否有人在他自己的商业产品上使用商业/免费的 java 混淆器。我只知道一个项目在发布的 ant 构建步骤中实际上有一个混淆步骤。

你混淆视听吗?如果是这样,你为什么要混淆?

这真的是一种保护代码的方法,还是只是对开发人员/经理来说更好的感觉?

编辑:好的,我要准确地说出我的观点:您是否为了保护您的 IP(您的算法,您在产品中投入的工作)而进行混淆处理?出于安全原因,我不会混淆,这感觉不对。所以我只是在谈论保护您的应用程序代码免受竞争对手的侵害。

@staffan有一个很好的观点:

远离链接代码流的原因是,其中一些更改使 JVM 无法有效地优化代码。实际上,它实际上会降低应用程序的性能。

4

7 回答 7

64

如果您进行了混淆,请远离通过更改代码流和/或添加异常块等来修改代码的混淆器,从而使其难以反汇编。为了使代码不可读,通常只需更改方法、字段和类的所有名称即可。

远离更改代码流的原因是,其中一些更改使 JVM 无法有效地优化代码。实际上,它实际上会降低应用程序的性能。

于 2008-08-15T10:57:31.463 回答
27

我认为混淆的旧(经典)方式正在逐渐失去其相关性。因为在大多数情况下,经典混淆器会破坏堆栈跟踪(它不利于支持您的客户)

现在的重点不是保护某些算法,而是保护敏感数据:API 登录名/密码/密钥,负责许可的代码(盗版仍然存在,尤其是西欧,俄罗斯,亚洲,恕我直言),广告帐户 ID 等.

有趣的事实:我们在字符串中拥有所有这些敏感数据。实际上,字符串约占我们应用程序逻辑的 50-80%。在我看来,混淆的未来是“字符串加密工具”。

但现在“字符串加密”功能仅在商业混淆器中可用,例如:AllatoriZelix KlassMasterSmokescreenStringer Java Obfuscation ToolkitDashO

注意,我是 Licel LLC 的首席执行官。Stringer Java 混淆器的开发者。

于 2012-04-13T08:00:02.973 回答
18

我使用 proguard 进行 JavaME 开发。它不仅非常擅长使 jar 文件更小(对于移动设备来说必不可少),而且它还可以作为一种更好的方式来编写特定于设备的代码,而无需使用对 IDE 不友好的预处理工具,例如天线。

例如

public void doSomething()
{
    /* Generated config class containing static finals: */
    if (Configuration.ISMOTOROLA)
    {
        System.out.println("This is a motorola phone");
    }
    else
    {
        System.out.println("This is not a motorola phone");
    }
}

这会被编译、混淆,并且类文件最终就像您编写的一样:

public void doSomething()
{
    System.out.println("This is a motorola phone");
}

因此,您可以使用代码变体来解决 JVM/库实现中的制造商错误,而无需增加最终的可执行类文件。

我相信一些商业混淆器在某些情况下也可以将类文件合并在一起。这很有用,因为您拥有的类越多,您在 zip (jar) 文件中的大小开销就越大。

于 2008-08-15T09:29:07.790 回答
14

今年我花了一些时间尝试各种 Java 混淆器,我发现其中一个比其他混淆器领先几英里:JBCO。不幸的是,它设置起来有点麻烦,并且没有 GUI,但就它产生的混淆程度而言,它是无与伦比的。你尝试给它一个简单的循环,如果你的反编译器在尝试加载它时没有崩溃,你会看到如下内容:

    if(i < ll1) goto _L6; else goto _L5
_L5:
    char ac[] = run(stop(lI1l));
    l7 = (long)ac.length << 32 & 0xffffffff00000000L ^ l7 & 0xffffffffL;
    if((int)((l7 & 0xffffffff00000000L) >> 32) != $5$)
    {
        l = (long)III << 50 & 0x4000000000000L ^ l & 0xfffbffffffffffffL;
    } else
    {
        for(l3 = (long)III & 0xffffffffL ^ l3 & 0xffffffff00000000L; (int)(l3 & 0xffffffffL) < ll1; l3 = (long)(S$$ + (int)(l3 & 0xffffffffL)) ^ l3 & 0xffffffff00000000L)
        {
            for(int j = III; j < ll1; j++)
            {
                l2 = (long)actionevent[j][(int)(l3 & 0xffffffffL)] & 65535L ^ l2 & 0xffffffffffff0000L;
                l6 = (long)(j << -351) & 0xffffffffL ^ l6 & 0xffffffff00000000L;
                l1 = (long)((int)(l6 & 0xffffffffL) + j) & 0xffffffffL ^ l1 & 0xffffffff00000000L;
                l = (long)((int)(l1 & 0xffffffffL) + (int)(l3 & 0xffffffffL)) << 16 & 0xffffffff0000L ^ l & 0xffff00000000ffffL;
                l = (long)ac[(int)((l & 0xffffffff0000L) >> 16)] & 65535L ^ l & 0xffffffffffff0000L;
                if((char)(int)(l2 & 65535L) != (char)(int)(l & 65535L))
                {
                    l = (long)III << 50 & 0x4000000000000L ^ l & 0xfffbffffffffffffL;
                }
            }

        }

    }

你不知道 Java 有 goto 的吗?好吧,JVM 支持它们 =)

于 2008-09-21T07:23:26.520 回答
14

我使用ProGuard并强烈推荐它。虽然混淆确实可以保护您的代码免受临时攻击者的攻击,但它的主要好处是最大程度地减少了删除未使用的类和方法并将所有标识符缩短为 1 或 2 个字符的影响。

于 2009-05-02T07:32:26.430 回答
11

我认为在大多数情况下,混淆是没有意义的:即使有完整的源代码,通常也很难弄清楚到底是什么意图(假设没有注释,也没有对局部变量有意义的名称——当重新- 从字节码生成源)。混淆只是装饰蛋糕。

我认为开发人员,尤其是他们的经理往往会过分夸大有人看到源代码的风险。虽然好的反编译器可以生成漂亮的源代码,但使用它并非易事,并且相关的成本(更不用说法律风险)高到足以使这种方法很少有用。我只反编译以调试闭源供应商产品的问题(数据库抽象层中的死锁,呃)。我认为字节码实际上被混淆了,但我们仍然发现了根本问题——这是一个实际的设计问题。

于 2009-05-16T06:39:12.183 回答
7

我想这真的取决于的 Java 代码的用途、它的分布方式以及你的客户是谁。我们不会混淆任何东西,因为我们从来没有找到一个特别好的东西,而且它往往比它的价值更麻烦。如果有人可以访问我们的 JAR 文件并且知道能够嗅探其中的内容,那么他​​们可以做的事情远比窃取我们的源代码更令人担忧。

于 2008-08-15T09:22:45.320 回答