java-deobfuscator / deobfuscator

The real deal
https://javadeobfuscator.com
Apache License 2.0
1.56k stars 290 forks source link

Update CafeDude for additional ASM crash patching #877

Closed Col-E closed 2 years ago

Col-E commented 2 years ago

Resolves #876

Can add ASM patching as a flag in your config:

patchAsm: true
magakis commented 2 years ago

This patch seems to fix the issue! I did encounter though the same error after using a transformer, during writing.

Transformer: com.javadeobfuscator.deobfuscator.transformers.zelix.StringEncryptionTransformer

Could this be related?

[main] INFO com.javadeobfuscator.deobfuscator.Deobfuscator - Loading classpath
[main] INFO com.javadeobfuscator.deobfuscator.Deobfuscator - Loading input
[main] INFO com.javadeobfuscator.deobfuscator.Deobfuscator - Computing callers
[main] INFO com.javadeobfuscator.deobfuscator.Deobfuscator - Transforming
[main] INFO com.javadeobfuscator.deobfuscator.Deobfuscator - Running com.javadeobfuscator.deobfuscator.transformers.zelix.StringEncryptionTransformer
[Zelix] [StringEncryptionTransformer] Starting
[Zelix] [StringEncryptionTransformer] Decrypted strings from 465 encrypted classes
[Zelix] [StringEncryptionTransformer] Decrypted 6092 strings
[Zelix] [StringEncryptionTransformer] Done
[main] INFO com.javadeobfuscator.deobfuscator.Deobfuscator - Writing

Deobfuscation failed. Please open a ticket on GitHub and provide the following error:
java.lang.ArrayIndexOutOfBoundsException: Index 1 out of bounds for length 1
        at org.objectweb.asm.AnnotationWriter.computeParameterAnnotationsSize(AnnotationWriter.java:498)
        at org.objectweb.asm.MethodWriter.computeMethodInfoSize(MethodWriter.java:2143)
        at org.objectweb.asm.ClassWriter.toByteArray(ClassWriter.java:489)
        at com.javadeobfuscator.deobfuscator.Deobfuscator.toByteArray(Deobfuscator.java:657)
        at com.javadeobfuscator.deobfuscator.Deobfuscator.lambda$start$9(Deobfuscator.java:461)
        at java.base/java.util.HashMap$Values.forEach(HashMap.java:1065)
        at com.javadeobfuscator.deobfuscator.Deobfuscator.start(Deobfuscator.java:459)
        at com.javadeobfuscator.deobfuscator.DeobfuscatorMain.run(DeobfuscatorMain.java:106)
        at com.javadeobfuscator.deobfuscator.DeobfuscatorMain.run(DeobfuscatorMain.java:99)
        at com.javadeobfuscator.deobfuscator.DeobfuscatorMain.main(DeobfuscatorMain.java:36)
Col-E commented 2 years ago

I was able to run the transformer on the small zip attached in #876 - Does the new error you're describing here happen on the same file, or something else? I'm pretty sure this case should be covered but if a new sample is breaking it I'd like to have it to test against.

magakis commented 2 years ago

This is the jar I'm experimenting with and the one having the issue: testsubject.zip

I don't know which specific part is breaking so here is the whole jar. I'm only using one transformer: StringEncryptionTransformer

Col-E commented 2 years ago

It looks like CAFED00D is able to patch it just fine but somehow the transformer re-introduces code that cannot be successfully written back. With no transformer applied I can read and write back 3A.

See comment below, figured out what was happening.

Col-E commented 2 years ago

loadInput in Deobfuscator only uses Cafedude when the reading fails but doesn't check for the writing. Making it always use cafedude resolves the problem. I'll update the PR in a sec.

Col-E commented 2 years ago

Your sample no longer crashes on write 👍

image

magakis commented 2 years ago

I can also confirm that the error doesn't come up anymore. Thanks for taking the time to fix this!

Something else I've noticed, When trying to excecute the deobfuscated version of the jar, I get the following exception:

Exception: ``` Exception in thread "main" java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file com/google/gson/Gson$2 at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012) at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150) at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:862) at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:760) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:681) at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:639) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520) ```

During deobfuscation I see this line: [main] INFO me.coley.cafedude.transform.IllegalStrippingTransformer - Attribute 'Code' on CODE-ATTRIBUTE will be removed since a sub-attribute is not legal!

Is that 'Code' Attribute wrongly getting stripped out by the IllegalStrippingTransformer?

This is the class file that contains the 'Code' attribute: gsonCodeAttribute.zip

Col-E commented 2 years ago

I'll take a look at that later today. Probably passed a wrong parameter on my end if thats happening.

Col-E commented 2 years ago

I added some additional logging and realized two things:

  1. That logging message is not formatted right, so its deceiving
  2. Its removing the code attribute because I made a mistake in a regex

Another quick fix, will bump to 1.9.1

magakis commented 2 years ago

With the latest commit e82b3c5 I got a NullPointerException from the zelix.StringEncryptionTransformer:

I narrowed it down to this class: nullpointer.zip

Stack: ``` java.lang.NullPointerException: Cannot invoke "String.equals(Object)" because "a.owner" is null at com.javadeobfuscator.deobfuscator.transformers.zelix.StringEncryptionTransformer.lambda$transform$25(StringEncryptionTransformer.java:140) at java.base/java.util.HashMap$Values.forEach(HashMap.java:1065) at com.javadeobfuscator.deobfuscator.transformers.zelix.StringEncryptionTransformer.transform(StringEncryptionTransformer.java:114) at com.javadeobfuscator.deobfuscator.Deobfuscator.runFromConfig(Deobfuscator.java:472) at com.javadeobfuscator.deobfuscator.Deobfuscator.start(Deobfuscator.java:429) at com.javadeobfuscator.deobfuscator.DeobfuscatorMain.run(DeobfuscatorMain.java:106) at com.javadeobfuscator.deobfuscator.DeobfuscatorMain.run(DeobfuscatorMain.java:99) at com.javadeobfuscator.deobfuscator.DeobfuscatorMain.main(DeobfuscatorMain.java:36) ```

It is thrown at this point.

Could this be related to the fix?

Col-E commented 2 years ago

Ah, unearthed a bug in where I missed a case where: inner_name_index can be 0

Normally 0 is reserved so it thought it was bad and removed it. 1.9.2 bump incoming...

magakis commented 2 years ago

Using the latest commit, after trying to launch the deobfuscated jar I get thrown this exception:

Exception in thread "main" java.lang.annotation.IncompleteAnnotationException: picocli.CommandLine$Command missing element modelTransformer
    at java.base/sun.reflect.annotation.AnnotationInvocationHandler.invoke(AnnotationInvocationHandler.java:86)
    at jdk.proxy2/jdk.proxy2.$Proxy4.modelTransformer(Unknown Source)
    at picocli.CommandLine$Model$CommandSpec.updateCommandAttributes(CommandLine.java)
    at picocli.CommandLine$Model$CommandReflection.extractCommandSpec(CommandLine.java)
    at picocli.CommandLine$Model$CommandSpec.forAnnotatedObject(CommandLine.java)
    at picocli.CommandLine.<init>(CommandLine.java)

The class that seem to contain the incomplete annotation is this one: IncompleteAnnotationException.zip

The only transformer used was the zelix.StringEncryptionTransformer

Col-E commented 2 years ago

Ah, I was assuming the class_info_index pointed to a CP_CLASS based on its name, but it instead points to a CP_UTF8. So that was making the illegal-patcher angry.

Will update PR once jitpack publishes the artifact.

magakis commented 2 years ago

Using the latest commit, after trying to run the deobfuscated jar I get a java.lang.VerifyError on this file VerifyError.zip

The only transformer used was the zelix.StringEncryptionTransformer

Stack: ``` Exception in thread "AWT-EventQueue-0" java.lang.VerifyError: Bad return type Exception Details: Location: net/miginfocom/swing/MigLayout.getPackable(Ljava/awt/Component;)Ljava/awt/Container; @38: areturn Reason: Type 'java/awt/Component' (current frame, stack[0]) is not assignable to 'java/awt/Container' (from method signature) Current Frame: bci: @38 flags: { } locals: { 'net/miginfocom/swing/MigLayout', 'java/awt/Component', 'javax/swing/JPopupMenu', 'java/awt/Component' } stack: { 'java/awt/Component' } Bytecode: 0000000: 1301 fb2b b802 1dc0 01fb 4d2c c600 252c 0000010: 4e2d c600 1d2d b600 9db6 0220 1302 22b6 0000020: 0225 9900 052d b02d b601 704e a7ff e52c 0000030: b013 01a5 2bb8 021d c000 bab0 Stackmap Table: append_frame(@17,Object[#507],Object[#180]) same_frame(@39) same_frame(@47) chop_frame(@49,1) ```

I might be wrong but it looks like there is an issue with casting?

Col-E commented 2 years ago

net/miginfocom/swing/MigLayout.getPackable(Ljava/awt/Component;)Ljava/awt/Container; @38: areturn

In the zip you sent there is no getPackable defined in either class 🤔

Its referenced in the constant pool, but there's no defined method by that name.

magakis commented 2 years ago

Hmm.. I sent only the class file that seemed relevant but I probably messed up. In this zip I have included the relevant classes (class and inner classes) along with a .java file that was produced using the cfr decompiler. MigLayout.zip

Col-E commented 2 years ago

Oh the verify error is totally unrelated. I can push that to this branch as well.

Janmm14 commented 2 years ago

I'd vote for patchAsm to be true by default

Col-E commented 2 years ago

None of the other options were, so I thought it'd be odd to do so. The message you get when things fail is also quite clear:

[main] ERROR com.javadeobfuscator.deobfuscator.Deobfuscator - Could not parse sample9.class (Try adding "patchAsm: true" to the config?)
java.lang.ArrayIndexOutOfBoundsException: 10106
        at org.objectweb.asm.ClassReader.readUnsignedShort(ClassReader.java:3573)
        at org.objectweb.asm.ClassReader.readStringish(ClassReader.java:3703)
        at org.objectweb.asm.ClassReader.readClass(ClassReader.java:3718)
Janmm14 commented 2 years ago

As nothing happens in this repo, I updated my repo with this PR and my PR 888 and some general cleanup: https://github.com/Janmm14/deobfuscator