Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Roadmap #3

Closed
11 tasks done
andreblanke opened this issue Jun 24, 2022 · 2 comments
Closed
11 tasks done

Roadmap #3

andreblanke opened this issue Jun 24, 2022 · 2 comments
Assignees

Comments

@andreblanke
Copy link
Owner

andreblanke commented Jun 24, 2022

  • Add command line options to include or exclude certain packages
    • Obfuscation of library bytecode is unnecessary if the library is itself open source
  • Correct MethodType for emulations of invokevirtual, invokeinterface, and invokespecial on the native side
    • The implicit this is added as part of the transformation to invokedynamic but must be dropped again on the
      native side if we are dealing with any of the three instruction types
    • MethodType.dropParameterTypes(1, 0) should be usable to achieve this
  • No longer ignore invokespecial when obfuscating
    • The instruction is also used to invoke private members and is not limited to the invocation of constructors
  • Obfuscate field accesses by generating synthetic getters and setters which are also obfuscated
    • Run field obfuscation before adding a bootstrap method for both InputType.CLASS and InputType.JAR
    • No longer assume that all non-virtual fields belong to the current class: add another parameter to pass instance if field belongs to a different class
    • Change FieldAccessorIdentifier.getName to compute return value only once; otherwise native code and bytecode will have a method name mismatch due to the randomness
      • Improve FieldAccessorIdentifier overall. The current implementation is confusing
    • Exclude putfield/putstatic field instruction obfuscation of final fields within <init>/static final fields within <clinit>
  • Figure out why a duplicate <clinit> is generated when obfuscating InDyObfuscator.class
  • Check if Files.copy(arguments.getInput(), arguments.getOutput(), StandardCopyOptions.REPLACE_EXISTING) can be used as-is without additional checks (what if input and output are the same files?)
@andreblanke andreblanke pinned this issue Jun 24, 2022
@andreblanke
Copy link
Owner Author

Using MethodType.dropParameterTypes(1, 0) from the native implementation works. The obfuscator is now able to obfuscate itself as long as obfuscation is limited to the dev.blanke.indyobfuscator package. The obfuscated version correctly displays the usage information and available command line options, then terminates.

Obfuscation of shaded libraries should work in theory. In practice, attempting to obfuscate the entire shaded obfuscator artifact causes (*env)->FindClass(env, ownerName) to return NULL for e.g. org.objectweb.asm.Type but works correctly for e.g. dev.blanke.indyobfuscator.InDyObfuscator, which would suggest that it's a class loading issue. That can't be, however, as both classes are located inside the same jar file (due to the artifact being shaded) and should thus be loaded by the same ClassLoader.

The NULL return value is even more confusing if one attempts to debug the issue using FindClass.java and FindClass.cpp: when org.objectweb.asm.Type is obfuscated, FindClass.java (which utilitizes a URLClassLoader and ClassLoader.loadClass to load classes) successfully loads the class, suggesting that the bytecode is correct (?), as otherwise a VerifyError should be thrown. A compiled version of FindClass.cpp which starts a Java VM from native code, however, is unable to retrieve an instance of the class.

@andreblanke
Copy link
Owner Author

andreblanke commented Jun 25, 2022

The NULL return value is even more confusing if one attempts to debug the issue using FindClass.java and FindClass.cpp: when org.objectweb.asm.Type is obfuscated, FindClass.java (which utilitizes a URLClassLoader and ClassLoader.loadClass to load classes) successfully loads the class, suggesting that the bytecode is correct (?), as otherwise a VerifyError should be thrown. A compiled version of FindClass.cpp which starts a Java VM from native code, however, is unable to retrieve an instance of the class.

A VerifyError can be produced even if org.objectweb.asm.Type is not actually obfuscated but only has its class file major version incremented:

$ debug/a.out org/objectweb/asm/Type
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 191
Exception Details:
  Location:
    org/objectweb/asm/Type.getTypeInternal(Ljava/lang/String;II)Lorg/objectweb/asm/Type; @7: lookupswitch
  Reason:
    Expected stackmap frame at this location.
  Bytecode:
    0000000: 2a1b ba01 8a00 00ab 0000 00b8 0000 000c
    0000010: 0000 0028 0000 00ab 0000 0042 0000 0075
    0000020: 0000 0043 0000 0071 0000 0044 0000 0089
    0000030: 0000 0046 0000 0081 0000 0049 0000 007d
    0000040: 0000 004a 0000 0085 0000 004c 0000 009a
    0000050: 0000 0053 0000 0079 0000 0056 0000 0069
    0000060: 0000 005a 0000 006d 0000 005b 0000 008d
    0000070: b200 62b0 b200 67b0 b200 71b0 b200 6cb0
    0000080: b200 76b0 b200 5db0 b200 80b0 b200 85b0
    0000090: b200 7bb0 bb00 0259 1009 2a1b 1cb7 00ad
    00000a0: b0bb 0002 5910 0a2a 1b04 601c 0464 b700
    00000b0: adb0 bb00 0259 100b 2a1b 1cb7 00ad b0bb
    00000c0: 00e7 59bb 00e9 59b7 00ea 12ec ba01 b000
    00000d0: 002a ba01 b000 00ba 01b4 0000 b700 f6bf
    00000e0:                                        

(nil)

The issue occurrs due to missing stack map frames which explains why it is not reproducable for e.g. dev.blanke.indyobfuscator.InDyObfuscator, as our own classes have been compiled targeting a newer Java version and the produced bytecode already includes stack map frames (which don't need to be changed). This means the issue is basically a duplicate of #1.

Why java.lang.ClassLoader.loadClass did not throw a VerifyError is an open question, as that would have lead to less confusion.

@andreblanke andreblanke self-assigned this Oct 7, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant