The Bytecode Club
Log inJoin the club
Programming

CFR Java Decompiler

Started by Konloch · Nov 2, 2014

8 replies650,448 views
Nov 3, 2014#2

does this deobfuscate too?

Nov 4, 2014#3

does this deobfuscate too?

I'm not sure, I know FernFlower has the -ren option.

Nov 5, 2014#4

does this deobfuscate too?

Depends what you mean - it has multiple normalisation passes to deal with lots of interesting potential obfuscations, it doesn't trust most of the metadata attributes (signature table, variable name table etc.).  The normalisation passes quite often have a very good effect against obfuscated code, though there's always the classic illegal java rewrites (like replacing a loop with a self-vectoring exception table).

It will however currently not rewrite method names if they've been obfuscated into non-java compatible identifiers - this is because at that point, there's a danger that reflection based invokation will change semantics.

Lee.

(BTW - I wrote it 😉 )

Nov 5, 2014#5

classic illegal java rewrites (like replacing a loop with a self-vectoring exception table).

what u mean

Nov 6, 2014#6

Bibl wrote:

lab27 wrote:

classic illegal java rewrites (like replacing a loop with a self-vectoring exception table).

what u mean

what u mean

Nov 6, 2014#7

soulija boy wrote:

Bibl wrote:

lab27 wrote:

classic illegal java rewrites (like replacing a loop with a self-vectoring exception table).

what u mean

what u mean

This.

Take a loop, remove the back jump, replace it with a catch handler at the top.  That one's fairly easy to handle.  Then, wrap the body of the loop in a boolean so it only gets executed every other time via a forward jumping exception handler.

Here's an example:

  public static void main(java.lang.String[]);
    Code:
       0: new           #16                 // class java/lang/Exception
       3: dup           
       4: invokespecial #14                 // Method java/lang/Exception."<init>":()V
       7: astore        4
       9: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
      12: astore_1      
      13: ldc           #11                 // int 10
      15: istore_2      
      16: iconst_0      
      17: istore_3      
      18: aconst_null   
      19: pop           
      20: iload_3       
      21: ifne          27
      24: aload         4
      26: athrow        
      27: aload_1       
      28: iload_2       
      29: dup_x1        
      30: invokevirtual #24                 // Method java/io/PrintStream.print:(I)V
      33: ifne          37
      36: return        
      37: aconst_null   
      38: pop           
      39: iconst_1      
      40: iload_3       
      41: dup           
      42: ifne          51
      45: iinc_w        2, -1
      51: isub          
      52: istore_3      
      53: aload         4
      55: athrow        
    Exception table:
       from    to  target type
          26    27    38   Class java/lang/Exception
          19    56    19   Class java/lang/Exception

CFR and Procyon actually make a reasonable job of it, but are still both pretty wildly out.   Fernflower gives up completely and goes home.

You can see what the above does, and you can also see how it's a trivial transformation from the original bytecode - an automated obfuscator could use this trick with no work at all, and it's a lot more effective than simple renaming.

(For reference, you can get this test here).

Nov 6, 2014#8

lab27 wrote:

soulija boy wrote:

Bibl wrote:

lab27 wrote:

classic illegal java rewrites (like replacing a loop with a self-vectoring exception table).

what u mean

what u mean

This.

Take a loop, remove the back jump, replace it with a catch handler at the top.  That one's fairly easy to handle.  Then, wrap the body of the loop in a boolean so it only gets executed every other time via a forward jumping exception handler.

Here's an example:

  public static void main(java.lang.String[]);
    Code:
       0: new           #16                 // class java/lang/Exception
       3: dup           
       4: invokespecial #14                 // Method java/lang/Exception."<init>":()V
       7: astore        4
       9: getstatic     #17                 // Field java/lang/System.out:Ljava/io/PrintStream;
      12: astore_1      
      13: ldc           #11                 // int 10
      15: istore_2      
      16: iconst_0      
      17: istore_3      
      18: aconst_null   
      19: pop           
      20: iload_3       
      21: ifne          27
      24: aload         4
      26: athrow        
      27: aload_1       
      28: iload_2       
      29: dup_x1        
      30: invokevirtual #24                 // Method java/io/PrintStream.print:(I)V
      33: ifne          37
      36: return        
      37: aconst_null   
      38: pop           
      39: iconst_1      
      40: iload_3       
      41: dup           
      42: ifne          51
      45: iinc_w        2, -1
      51: isub          
      52: istore_3      
      53: aload         4
      55: athrow        
    Exception table:
       from    to  target type
          26    27    38   Class java/lang/Exception
          19    56    19   Class java/lang/Exception

CFR and Procyon actually make a reasonable job of it, but are still both pretty wildly out.   Fernflower gives up completely and goes home.

You can see what the above does, and you can also see how it's a trivial transformation from the original bytecode - an automated obfuscator could use this trick with no work at all, and it's a lot more effective than simple renaming.

(For reference, you can get this test here).

whats the performance for this method, it would be slower i assume?
also is there a paper or something on this concept

Nov 6, 2014#9

whats the performance for this method, it would be slower i assume?
also is there a paper or something on this concept

It would certainly be slower, yes.  That's often a price obfuscators are prepared to pay.

I can't remember off the top of my head where I first saw this described, however have a quick google. (eg).

http://www.zelix.com/klassmaster/docs/obfuscateOptions.html#exception

http://journal.info.unlp.edu.ar/journal/journal23/papers/JCST-Jul08-3.pdf (describes for msil, but the technique is obviously similar.)

For what it's worth - I don't actually test CFR against any obfuscated code due to potential legality issues - I test against my own implementations of concepts such as this, as well as other sorts of evil thoughts that pop into my head (i.e. putting completely inaccurate information in type table, marking every method as synthetic, etc.).

Got something to add?

Log in to post a reply.

Join the conversation