首先,在处理混淆应用程序时永远不要使用javap,因为javap它不是为处理恶意字节码而设计的,并且很容易以多种方式受阻。幸运的是,Krakatau 反汇编器是专门为处理混淆字节码而设计的,几乎可以处理任何事情。(如果您发现任何在 JVM 上运行且无法反汇编的内容,请提交错误)。幸运的是,在这种情况下,它没有错误地反汇编。
除了字节码反汇编器和汇编器,Krakatau 还包含一个 Java 反编译器,专门用于反编译混淆的字节码。它不是特别用户友好,但它通常可以反编译其他反编译器无法处理的东西。在这种情况下,Krakatau 能够在进行一些小修复后无错误地反编译您的应用程序。
为了使用 Krakatau 反编译您的应用程序,我必须做两件事:
- 修正了一个Python 2的unicode处理错误(
'ascii' codec can't decode byte 0xe2 in position 0: ordinal not in range(128)通过改变你得到消息).decode()来.decode('utf8')。
- 提供带有
-path选项的 Spigot 库。我必须先稍微修改 Spigot jar,将 bukkit 部分移动到正确的路径(它期望类位于org/bukkit/craftbukkit/entity/CraftPlayer,但该类位于bukkit/craftbukkit/v1_15_R1/entity/CraftPlayer我下载的 Jar 中)。
无论如何,一旦完成,您提供的混淆jar就会反编译而不会出错。请注意,jar 使用了invokedynamic,它通常无法反编译,因为它是一个字节码功能,没有 Java 等效项。为了警告您这一点,Krakatau 在反编译源中输出注释,如下所示
label12: {
try {
if (!/*invokedynamic*/false) {
break label12;
}
if (b) {
break label12;
在这种情况下,您需要查阅反汇编的字节码以确切了解它在做什么
L14: iload 6
L16: ifne L8
L19: invokedynamic InvokeDynamic invokeStatic Method [c24] '\u200c\u2001\u2005\u2001' [u26] : '\ufb05\u58d7\ufb06\u0226\udb3d\u78ef\ufb09\u0226\ufb00\u58d5\udb3d\u221f\udb32' '()L\u2004\u2006\u2007\u2007;'
L24: invokedynamic [id154]
L29: invokedynamic InvokeDynamic invokeStatic Method [c24] '\u200c\u2001\u2005\u2001' [u26] : [nat157]
L34: invokedynamic InvokeDynamic invokeStatic Method [c24] '\u200c\u2001\u2005\u2001' [u26] : '\ufb05\u58d7\ufb06\u0226\udb3d\u78ef\ufb09\u0226\ufb00\u58d5\udb3d\u221f\udb32' '()L\u2004\u2006\u2007\u2007;'
L39: new '\u200b\u2007\u2006\u200d'
L42: dup
L43: aload 4
就混淆而言,我注意到的主要混淆是 a) 将所有内容重命名为 unicode,以及 b) 插入虚拟字段和一堆在这些字段上分支的假控制流。这是反编译输出中后者的示例:
boolean b = \u200e\u200a;
label0: {
if (b) {
break label0;
}
if (b) {
break label0;
}
\u2005\u200c\u2005\u2009 = new java.util.HashMap();
if (!b) {
}
}
请注意,Krakatau 反编译器进行了大量分析以简化控制流程,因此这是Krakatau 的简化通过后剩下的。难怪其他反编译器看到这样复杂的控制流程就会放弃。
还值得注意的是,这是一个相当弱的混淆。特别是,它创建了一个静态字段并在该值上进行了分支,但它实际上从未分配给该字段,因此可以将该字段替换为常量以简化字节码。这让我想起了一些我见过的被 ZKM 混淆的字节码,所以你的朋友可能正在使用 ZKM。
例如,在我修补 jar 以将静态字段替换为常量false并再次反编译之后,Krakatau 的常量传播能够完全简化假控制流。这是将字段替换为与上述相同功能的反编译版本false:
static {
\u2005\u200c\u2005\u2009 = new java.util.HashMap();
}