Wednesday, July 16, 2008

Java ByteCode Manipulation

WARNING - Contents of this file are for educational purposes only. It is strongly suggested that you do not use this knowledge for illegal purposes!


There are two ways to modify the compiled java code (assume you don't have the source or have loss it):

  • Decompile all dependent file, make any modification to .java files created, then recompile.
    Pros:
    • Easy to manage your modification.

    • You don't have to decompile them next time you want to modify again.

    Cons:
    • Hard/Impossible to do that on obfuscated file.


  • Make any modification directly to .class file.
    Pros:
    • It's so easy to do on obfuscated file.


    Cons:
    • You have to learn about bytecode.

    • It will be hard at beginning.



The method I will be discuss right now is option (b), handling .class file directly.
Now let's we begin with simple example.
public class bytecode1 {
public static void main(String[] a) {
System.out.println("Hello Worlf");
System.out.println("Hello Worlf");
System.out.println("Hello Worlf");
}
}

Save it with the name bytecode1.java, then compile it, you will got bytecode1.class. Now you may run it, by executing: java bytecode1

See the result? I've made typo mistake, it should display "Hello World", not "Hello Worlf".
It's too easy, isn't it? You can just use any hex editor to replace the "f" to "d". But how if I want only one "Hello World" line displayed? Can hex editor handling it? maybe yes, maybe no. I don't want to think about it while there are more elegant way to do it.

The tools I use are BCEL and CCK. Both of them are quite old version, but still usable. So download it, and run CCK. Select Menu File>Open, then click Choose File .... Open bytecode1.class file.
java bytecode

From menu above, select Code from main methods. The right side panel will display content of main method.
java bytecode

You see the pattern? System.out.println is consist of getstatic, ldc, and invokevirtual.
java bytecode

So what I'm going to do now is remove two System.out.println routines. This should be tricky, when you are trying to remove getstatic routine, it will say "cannot remove...still has targeter".

If you select "Line Numbers" from left panel, it will show you dependencies from source code to bytecode. Remove the coresponding line where you want to remove the code.

Assume I want to remove the last two System.out.println routines (The first won't removed), that is with offset 8 to 21, so in the "Line Numbers" section, I will remove source index 4 and 5 that link to the offset 8-21.
java bytecode

if you done that, go back to Code, and then delete offset 8-21.
java bytecode

Done. save it with File>Save Menu.

That's enough for today, I will cover another technique next time.

3 comments:

Raimo 'RayRay' Pregel said...

This is really interesting :)
I´ve recently started learning java and programming overall and.. this subject actually kinda went through my head at one point and I can´t wait to test it out myself :)

Thanks, peace!=)

Anonymous said...

Hi there!

Very useful info :)
CCK rules!

Thanks!

Anonymous said...

Veru useful, thank you for your time.

border=0
Free Advertising