Well Java is said to be safe since JVM commonly takes care of everything (loading, resolution and so on). Actually it is. However this does not mean that Java is safe from careless usage.When JVM loads a class file, it does not take for granted that it was produced by some kind of Java compiler. It actually is interested in checking its file format.This process is known as bytecode verification and it is supposed to prevent from invoking code that seems to be messed up.
Whatever class fails the verification it is really a bad Java class. But this does not mean that classes that pass it are ok.
To demonstrate this I am going to develop a useful but harmless example to test a case where we compile Java source code and subsequently we deform the class file to alter its functionality.
Here is the code...
public class JavaHack {
public static void main(String[] args){
int a=6;
int b = DivideBy2(a);
int c = DivideBy3(a);
System.out.println(""+a+"/2 = "+b);
System.out.println(""+a+"/3 = "+c);
}
public static int DivideBy2(int i) {return i/2;}
public static int DivideBy3(int j) {return j/3;}
}
If compiled and run successfully we will finally get the output:
6/2=3
6/3=2
Now use a Hex editor, like HxD Editor.
Open the JavaHack class with the editor and search for the sequence: 0xB8 0x00 0x02 0x3D 0x1B ... and alter 0x02 byte to 0x03.
Then immediately(no more compilation) run the JavaHack class. The output will be:
6/2=2 (!)
6/3=2
The function DivideBy2 seems to be returning wrong results. What is actually going on is that we do not call this method any more. To explain, every method has an index into the method table in the class file. The DivideBy2 has id 2 and DivideBy3 has id 3. The sequence 0xB8 0x00 0x02 is actually invokestatic #2 in JVM code, meaning that it invokes the static method with id 2. Changing the value 0x02 to 0x03 actually calls the function DivideBy3, which eventually is called twice!! This explains the strange result of the modified class file.
The example can be easily extended and generalized to create more complex hacks (e.g. find out values of un-initialized variables and so on)