混淆应用程序是否存在任何潜在问题?

时间:2010-01-18 21:08:56

标签: java spring obfuscation

我正在构建一个spring mvc web应用程序。 我打算使用hibernate。

我对混淆等没有多少经验。

混淆应用程序有哪些潜在的缺点?

我了解调试应用时可能存在问题,并且恢复丢失的源代码也是一个问题。

实际运行应用程序是否存在任何已知问题?可以引入错误吗?

由于这是我正在寻找一般指导的领域,请随时打开我应该注意的任何问题。

5 个答案:

答案 0 :(得分:7)

肯定存在一些潜在的性能/维护问题,但是一个好的混淆器可以让你至少绕过其中一些。需要注意的事项:

  • 一个显而易见的问题:如果您的代码通过反射调用方法或动态加载类,那么如果类/方法名称被混淆,则可能会失败;一个好的混淆器会让你选择不混淆的类/方法名来解决这个问题;
  • 如果并非所有应用程序都是同时编译,则会出现类似问题;
  • 如果它直接处理字节码级别,则混淆器可以创建原则上Java编译器无法创建的代码(例如,它可以插入任意GOTO指令,而从Java中,这些只能作为循环的一部分创建) - 这可能是理论上的一点,但如果我正在编写JVM,我会优化Java编译器可以创建的字节码序列的性能,而不是那些它不能创建的字节码...
  • 如果混淆器显着改变方法中的字节码数量,或者以某种方式改变给定方法/代码段是否达到某些JVM优化的阈值(例如“内联方法”),则混淆器可能会对性能进行其他细微更改少于X个字节码“)。

但正如你所看到的,有些影响是有点微妙和theoretical--所以在一定程度上,你需要做的是浸泡试验后,混淆你的应用是什么,就像你与其他任何重大变化。< / p>

您也应该注意不要的假设的那个模糊隐藏代码/算法(如果这是你的意图),只要你想它中场休息使用反编译器来看看在尽可能多产生的混淆类的内容。

答案 1 :(得分:6)

惊讶没有人提到速度 - 一般来说,更混淆=运行速度慢的代码


[编辑] 我不敢相信这有-2。这是一个正确的答案。

缩短标识符并删除未使用的方法会减小文件大小,但会对运行速度产生影响(除了加载时间之外的几纳秒)。同时,该程序的大多数混淆来自添加代码:

  • 将1方法分解为5;交错方法;合并类 [聚合转换]
  • 将1个算术表达式拆分为10个;混淆控制流 [计算转换]
  • 添加无效的代码块 [opaque predicates]

是所有常见的混淆技术,会导致程序运行速度变慢。

答案 2 :(得分:4)

您可能需要查看此处的一些注释,以确定混淆是否有意义: https://stackoverflow.com/questions/1988451/net-obfuscation

您可能想表达您想要混淆的原因。 IMO最好的理由主要是拥有一个较小的应用程序,因为你可以摆脱项目中没有使用的类,同时进行混淆。

我从未见过错误,只要您不使用反射,假设您可以找到某些内容,例如私有方法将更改其名称。

答案 3 :(得分:1)

最大的问题在于,混淆程序通常可以保证不改变目标程序的行为。在某些情况下,证明这很难做到 - 例如,想象一个程序通过字符串数组的反射来检查某些私有字段的值。混淆器可能无法告知该字符串也需要相应更新,结果将是在运行时弹出的意外访问错误。

更糟糕的是,程序的行为可能不明显地发生了变化 - 然后你可能根本不知道存在任何问题,直到你的客户首先发现并且感到不安为止。

一般来说,专业级混淆产品的复杂性足以捕捉到某些问题并阻止它们,但最终覆盖所有基础可能具有挑战性。最好的防御措施是针对混淆的结果运行单元测试,并确保所有预期的行为继续保持正确。

答案 4 :(得分:0)

您可能想要查看的1个免费的Babel。它被设计用于命令行(像许多其他混淆器一样),有Reflector addin that将为您提供UI。

谈到混淆时,你真的需要分析你的目标是什么。在您的情况下 - 如果您有一个Web应用程序(mvc),您是否计划将其作为可下载的固定应用程序出售? (如果没有,并且您将源保留在Web服务器上,那么您不需要它。)

您可能会查看组件并仅选择某些部分来混淆...而不是整个事情。一般情况下,当您尝试在开发混淆后添加混淆时,ASP.Net应用程序会非常容易,因为使用了所有反射。

上面提到的几乎所有内容都是正确的......这一切都取决于你打开多少功能以使代码难以反转:

  • 成员(字段/方法/事件/属性)的重命名是最常见的(有不同的风格:从GetId()到a()一直到不可读字符和删除命名空间的方法的简单重命名。顺便说一句:这是反射通常会破裂的地方。由于使用的字符串较小,您的汇编文件可能会变小。
  • 字符串加密:这使得反转代码中使用的静态字符串变得更加困难。 BTW:这与重命名配对使你很难调试你的重命名问题......所以你可以在你工作之后打开它。在IL
  • 中使用它之前,还必须添加代码来解密字符串
  • 代码重整......这就是BlueRaja所指的内容。它使你的代码看起来像spagetti代码 - 让人更难弄明白。 CLR不喜欢这样......它不能简单地优化事物,并且由于额外的分支和由于IL重写用于此选项而没有内联的东西,最终代码最可能会更慢地进程。顺便说一句:这个选项确实提高了扭转源代码所需的标准,但可能会带来性能损失。
  • 删除未使用的代码。一些混淆器为您​​提供修剪它找不到的任何代码的选项。如果你有很多死代码,这可能会使你的组件变得更小......但它只是一个免费的混淆器收益。

我的建议是只使用它,如果你知道为什么要使用它并考虑到那个目的而设计......在你完成代码之后不要尝试添加它(我已经完成了它并且它是不好玩)