为什么混淆器会删除行号,我可以安全地保留它们吗?

逆向工程 混淆 爪哇
2021-07-03 08:20:14

应用安全工程师在这里。当我们编译我们的 Java 代码时,我们使用 KlassMaster 对其进行混淆并让它删除行号(参见KlassMaster 文档),因为“它使逆向工程变得更加困难”。

我想核实一下,这实际上增加了逆向工程的难度,足以保证在调试无用的堆栈跟踪时浪费的开发时间。

2个回答

剥离行号对逆向工程代码的难度影响最小。如果它给您带来问题,我建议您禁用它。

Col-E 的回答是一个红鲱鱼,因为逆向工程师很容易将合成行号插入字节码以消除堆栈跟踪的歧义(假设他们首先不只是重命名方法)。这些显然与原始源代码行号不匹配,但是如果您想要的只是一种消除堆栈跟踪歧义的方法,那么这很容易实现。

TamusJRoyce 的回答也是错误的。Javac 没有像 GCC 那样进行优化,这就是未混淆的 Java 可以如此干净地反编译的原因。我所知道的 Javac 在编译时所做的唯一值得注意的优化是内联和简化常量表达式。

KlassMaster 文档实际上很好地总结了原因。

由于该类com.mycompany.c通常会被混淆以包含许多带有名称a和 的重载方法,因此b诊断问题和重现错误对于您的开发人员来说将非常耗时,并且对于您的客户来说非常令人沮丧。

他们在此摘要下方提供了堆栈跟踪。我将重点关注这四行:

at com.mycompany.c.a(c.java)
at com.mycompany.c.a(c.java)
at com.mycompany.c.b(c.java)
at com.mycompany.c.a(c.java)

很明显,在这些堆栈跟踪元素中,类总是相同的c,但是方法呢?第 1、2 和 4 行给出了方法名称,a但问题是由于名称重载(多个具有相同名称但返回/参数类型不同的方法),您无法确定它们是否都指向相同的方法

这就是行号的用武之地。由于您是具有源代码访问权限的开发人员,因此您可以轻松跳转到堆栈跟踪提供的行号。攻击者没有源代码,但他们可以轻松地查看类的字节码以制作一个表,将不同的行号与其方法相关联(更具体地说,问题发生在方法字节码中的哪个位置)这将允许他们绕过名称重载的目的,因为他们可以在任何给定的堆栈跟踪元素中查找与行相关联的方法。

如果您要删除行号,那么攻击者将无法获取任何给定的堆栈跟踪元素并立即知道它链接到的方法。在这种情况下,攻击者的最佳选择是从堆栈跟踪中的已知位置开始,并手动跟踪字节码以确定堆栈跟踪中显示了哪些重载方法。


如果反编译是您最关心的问题,而不是上述情况,那么您应该保留调试信息。无论是否包含调试信息,Java 反编译器甚至可以在混淆的程序集上生成相当准确的代码。