6

I am little bit curious about that what happen if I manually changed something into bytecode before execution. For instance, let suppose assigning int type variable into byte type variable without casting or remove semicolon from somewhere in program or anything that leads to compile time error. As I know all compile time errors are checked by compiler before making .class file. So what happen when I changed byte code after successfully compile a program then changed bytecode manually ? Is there any mechanism to handle this ? or if not then how program behaves after execution ?

EDIT :-
As Hot Licks, Darksonn and manouti already gave correct satisfy answers.Now I just conclude for those readers who all seeking answer for this type question :-

Every Java virtual machine has a class-file verifier, which ensures that loaded class files have a proper internal structure. If the class-file verifier discovers a problem with a class file, it throws an exception. Because a class file is just a sequence of binary data, a virtual machine can't know whether a particular class file was generated by a well-meaning Java compiler or by shady crackers bent on compromising the integrity of the virtual machine. As a consequence, all JVM implementations have a class-file verifier that can be invoked on untrusted classes, to make sure the classes are safe to use.

Refer this for more details.

Vikas Verma
  • 3,626
  • 6
  • 27
  • 40
  • Are you essentially asking whether there's some error check similar to the compiler's checking that's run at error time? If you edited in illegal code, you'd get an exception just as you would with something that wasn't caught by the compiler. Your question is broad and not exactly clear. – Sam Hanley Aug 13 '14 at 17:33
  • Accessing an array out of bounds is not a good example as it is something that exists as a runtime exception anyway. And syntax errors make code not compileable. Introducing a "syntax" error in the compiled code basically means destroying the file randomly. – Ingo Bürk Aug 13 '14 at 17:36

4 Answers4

6

You certainly can use a hex editor (eg, the free "HDD Hex Editor Neo") or some other tool to modify the bytes of a Java .class file. But obviously, you must do so in a way that maintains the file's "integrity" (tables all in correct format, etc). Furthermore (and much trickier), any modification you make must pass muster by the JVM's "verifier", which essentially rechecks everything that javac verified while compiling the program.

The verification process occurs during class loading and is quite complex. Basically, a data flow analysis is done on each procedure to assure that only the correct data types can "reach" a point where the data type is assumed. Eg, you can't change a load operation to load a reference to a HashMap onto the "stack" when the eventual user of the loaded reference will be assuming it's a String. (But enumerating all the checks the verifier does would be a major task in itself. I can't remember half of them, even though I wrote the verifier for the IBM iSeries JVM.)

(If you're asking if one can "jailbreak" a Java .class file to introduce code that does unauthorized things, the answer is no.)

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
2

You will most likely get a java.lang.VerifyError:

Thrown when the "verifier" detects that a class file, though well formed, contains some sort of internal inconsistency or security problem.

M A
  • 71,713
  • 13
  • 134
  • 174
1

You can certainly do this, and there are even tools to make it easier, like http://set.ee/jbe/. The Java runtime will run your modified bytecode just as it would run the bytecode emitted by the compiler. What you're describing is a Java-specific case of a binary patch.

The semicolon example wouldn't be an issue, since semicolons are only for the convenience of the compiler and don't appear in the bytecode.

Community
  • 1
  • 1
RedGreenCode
  • 2,195
  • 1
  • 25
  • 33
  • but how it behave for instance if am accessing array that out of bount so execution environment let me access this ? – Vikas Verma Aug 13 '14 at 17:36
  • See the comment above from @ingo-bürk. Runtime exceptions will be thrown as usual. – RedGreenCode Aug 13 '14 at 17:39
  • 1
    @VikasVerma - Things like array out of bounds are checked by the JVM at runtime, and cannot be bypassed by modifying the bytecodes. – Hot Licks Aug 13 '14 at 17:40
1

Either the bytecode executes normally and performs the instructions given or the jvm rejects them.

I played around with programming directly in java bytecode some time ago using jasmin, and I noticed some things.

If the bytecode you edited it into makes sense, it will of coursse run as expected. However there are some bytecode patterns that are rejected with a VerifyError.

For the specific examble of out of bounds access, you can compile code with out of bounds just fine. They will get you an ArrayIndexOutOfBoundsException at runtime.

int[] arr = new int[20];
for (int i = 0; i < 100; i++) {
    arr[i] = i;
}

However you can construct bytecode that is more fundamentally flawed than that. To give an example I'll explain some things first.

The java bytecode works with a stack, and instructions works with the top elements on the stack.
The stack naturally have different sizes at different places in the program but sometimes you might use a goto in the bytecode to cause the stack to look different depending on how you reached there.

The stack might contain object, int then you store the object in an object array and the int in an int array. Then you go on and from somewhere else in that bytecode you use a goto, but now your stack contains int, object which would result in an int being passed to an object array and vice versa.

This is just one example of things that could happen which makes your bytecode fundamentally flawed. The JVM detects these kinds of flaws when the class is loaded at runtime, and then emits a VerifyError if something dosen't work.

Alice Ryhl
  • 3,574
  • 1
  • 18
  • 37