How to decompile obfuscated java programs avoiding

2019-03-31 11:21发布

I want to decompile a java program and recompile the derived (obfuscated) source. I unpacked the .jar archive and got a directory structure like that:

com/
com/foo/A/
com/foo/A/A.class
com/foo/A/B.Class
com/foo/B/A.class
...
com/foo/A.class
com/foo/B.class
org/foo/Bar.class
...

The problem is that there are name collisions between packages and classes, which makes it impossible to recompile the decompiled class files. A decompiled class will look like this:

package org.foo;
import com.foo.A; // <-- name collision error

class Bar {
    ...
}

Is there any way to resolve those naming issues, without renaming the class files?

EDIT: This is not a decompiler problem, but the question how it is possible to have a working .jar file with classes that violate naming conventions.

EDIT2: Okay, i guess on bytecode level such naming is possible, so with a smarter decompiler (who automatically renames the classes and fixes their references) this problem could be solved.

3条回答
在下西门庆
2楼-- · 2019-03-31 11:48

You can not import packages in Java, so why should this be a name collision? Which error message do you get from the compiler?

If there would be a name collision in the obfuscated code, the code would not run. So the decompiled code should be collision free.

查看更多
狗以群分
3楼-- · 2019-03-31 11:55

Java's import mechanism provides a shorthand for naming things, but you obviously cannot use it when there are collisions. You can always use the fully qualified name in your code, e.g.

package org.foo;  

class Bar { 
    private com.foo.Bar aDifferentBar;
    ...
}

EDIT:

I suppose there could be class files that comply with the JVM spec but which cannot be produced by a Java program that complies with the JLS spec. If so then you'll definitely need a smarter decompiler.

查看更多
放荡不羁爱自由
4楼-- · 2019-03-31 12:02

Do you really need to unpack the entire jar and recompile everything? Instead of recompiling the entire decompiled source by itself, use the original jar as the classpath, and extract and recompile only those classes that you need to modify. Then, when you need to package up your recompiled code, just copy the original jar and use jar -uf to replace the modified class files in place:

jar -uf ./lib/copy_of_original_jar_file.jar -C ./bin com/foo/A.class com/foo/B.class [...]

...and ./lib/copy_of_original_jar_file.jar becomes your new library.

One thing is for sure, and that is that the original jar must work properly with a Java classloader in order for the program to run. It should work just as well for compiling your one-off .class files.

You should experience much fewer naming collision issues by using the original jar because you keep the same classpath scanning order that the running application would use. Not only that, but Java decompilers aren't perfect. By eliminating the majority of the decompiled code from recompilation, you avoid the majority of issues that decompilers have with things like exception handler overlaps, special characters in obfuscated symbols, variable scoping issues, etc.

查看更多
登录 后发表回答