有时在反编译 Java 代码时,反编译器无法正确反编译它,最终会在输出中得到少量字节码。
反编译器的弱点是什么?有没有编译成难以反编译的字节码的 Java 源代码示例?
更新:
请注意,我知道利用此信息不是隐藏代码中秘密的安全方法,并且将来可以改进反编译器。
尽管如此,我仍然有兴趣找出今天的反编译器是什么样的代码。
有时在反编译 Java 代码时,反编译器无法正确反编译它,最终会在输出中得到少量字节码。
反编译器的弱点是什么?有没有编译成难以反编译的字节码的 Java 源代码示例?
更新:
请注意,我知道利用此信息不是隐藏代码中秘密的安全方法,并且将来可以改进反编译器。
尽管如此,我仍然有兴趣找出今天的反编译器是什么样的代码。
任何经过混淆器处理的 Java 字节码都会从反编译器得到“荒谬”的输出。此外,当您有其他语言(如 Scala)编译为 JVM 字节码时,没有规定字节码可以很容易地用 Java 表示,而且很可能不是。
随着时间的推移,反编译器必须跟上新的语言特性和它们产生的字节码,所以新语言特性不容易被你使用的工具逆转是合理的。
编辑:作为 .NET 中的示例,以下代码:
lock (this)
{
DoSomething();
}
编译为:
Monitor.Enter(this);
try
{
DoSomething();
}
catch
{
Monitor.Exit(this);
}
反编译器必须知道 C#(相对于任何其他 .NET 语言)具有专门用于这两个调用的特殊语法。否则你会得到意想不到的(冗长的)结果。
DB2 Connect 的 JDBC type-4 驱动程序是经典的。一切都称为一个或两个字母的名称,不相关的代码最终没有效果,等等。曾经尝试看一下调试一个特别烦人的问题,基本放弃了。我希望(但绝不相信)这是通过混淆器传递的,而不是实际上看起来像那样的代码。
另一个最喜欢的技巧(虽然我不记得产品)是重命名要从 set 构造的所有对象{'0','O','l','1'}
,这使得阅读变得非常困难。
假设您可以将源代码反编译回合理的样式(您不能总是这样做),那么难以“逆向工程”的是在不熟悉的问题域中运行的算法。如果您不了解快速傅里叶变换,那么您是否可以取回实现 FFT 蝴蝶的代码也没关系。(如果这句话你不熟悉,我编码一个我已经赢了。如果你熟悉,你是一个很好的工程师,可能对逆向工程代码没有任何兴趣)。[你与朝鲜人的里程可能会有所不同。]
Java 在字节码中保留了大量信息(例如许多名称)。所以反编译比较容易。难以反编译的字节码主要是由难以阅读的源代码生成的(所以这不是一个真正的选择)。如果您真的想混淆您的代码,请使用混淆器,它将所有方法和变量重命名为无法识别的内容。
异常通常很难反编译。然而,任何被混淆或用另一种语言编写的代码都很难反编译。
BTW:你为什么想知道这个?
Java Bytecode 不直接对应Java 构造,所以反编译意味着你知道某个Java 字节码序列对应Java 代码构造。
用于反编译 java 字节码的 Soot 框架有很多关于这方面的信息,但是他们的网页现在对我来说是关闭的。