1

While researching Java, bytecode editing in particular, I stumbled across this tutorial, which guides through the steps of editing compiled Java .class files with a hex editor. Intrigued, I gave it a go.

I made sure I typed everything in correctly, checked and double-checked, replaced the right bytes in my hex editor, etc. Everything's OK.

The first thing I noticed was that my hex dump was different than his, however, I expected this, as different Java versions would yield different results.

After inputting the correct bytes (replacing those for Hacking Java Bytecode! with those for l33t hax0r bro, and the three occurrences of 00 16 with 00 0E), I saved the file, and ran it. However, instead of getting the output of l33t hax0r bro, like the writer of the tutorial did, I got a rather ugly error:

Error: A JNI error has occurred, please check your installation and try again
Exception in thread "main" java.lang.ClassFormatError: Unknown constant tag 116 in class file User
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:760)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:467)
    at java.net.URLClassLoader.access$100(URLClassLoader.java:73)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:368)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:362)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:361)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:331)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    at sun.launcher.LauncherHelper.checkAndLoadMain(LauncherHelper.java:495)

Here is the Java source code I'm using:

public class User {
    protected int status = 0;

    public boolean setStatusTrue() {
        return this.status == 1;
    }

    public static void main(String[] args) {
        System.out.println("Hacking Java Bytecode!");
    }
}

The hexdump of the unedited User.class file:

00000000: cafe babe 0000 0034 0029 0700 0201 0004  .......4.)......
00000010: 5573 6572 0700 0401 0010 6a61 7661 2f6c  User......java/l
00000020: 616e 672f 4f62 6a65 6374 0100 0673 7461  ang/Object...sta
00000030: 7475 7301 0001 4901 0006 3c69 6e69 743e  tus...I...<init>
00000040: 0100 0328 2956 0100 0443 6f64 650a 0003  ...()V...Code...
00000050: 000b 0c00 0700 0809 0001 000d 0c00 0500  ................
00000060: 0601 000f 4c69 6e65 4e75 6d62 6572 5461  ....LineNumberTa
00000070: 626c 6501 0012 4c6f 6361 6c56 6172 6961  ble...LocalVaria
00000080: 626c 6554 6162 6c65 0100 0474 6869 7301  bleTable...this.
00000090: 0006 4c55 7365 723b 0100 0d73 6574 5374  ..LUser;...setSt
000000a0: 6174 7573 5472 7565 0100 0328 295a 0100  atusTrue...()Z..
000000b0: 0d53 7461 636b 4d61 7054 6162 6c65 0100  .StackMapTable..
000000c0: 046d 6169 6e01 0016 285b 4c6a 6176 612f  .main...([Ljava/
000000d0: 6c61 6e67 2f53 7472 696e 673b 2956 0900  lang/String;)V..
000000e0: 1800 1a07 0019 0100 106a 6176 612f 6c61  .........java/la
000000f0: 6e67 2f53 7973 7465 6d0c 001b 001c 0100  ng/System.......
00000100: 036f 7574 0100 154c 6a61 7661 2f69 6f2f  .out...Ljava/io/
00000110: 5072 696e 7453 7472 6561 6d3b 0800 1e01  PrintStream;....
00000120: 0016 4861 636b 696e 6720 4a61 7661 2042  ..Hacking Java B
00000130: 7974 6563 6f64 6521 0a00 2000 2207 0021  ytecode!.. ."..!
00000140: 0100 136a 6176 612f 696f 2f50 7269 6e74  ...java/io/Print
00000150: 5374 7265 616d 0c00 2300 2401 0007 7072  Stream..#.$...pr
00000160: 696e 746c 6e01 0015 284c 6a61 7661 2f6c  intln...(Ljava/l
00000170: 616e 672f 5374 7269 6e67 3b29 5601 0004  ang/String;)V...
00000180: 6172 6773 0100 135b 4c6a 6176 612f 6c61  args...[Ljava/la
00000190: 6e67 2f53 7472 696e 673b 0100 0a53 6f75  ng/String;...Sou
000001a0: 7263 6546 696c 6501 0009 5573 6572 2e6a  rceFile...User.j
000001b0: 6176 6100 2100 0100 0300 0000 0100 0400  ava.!...........
000001c0: 0500 0600 0000 0300 0100 0700 0800 0100  ................
000001d0: 0900 0000 3c00 0200 0100 0000 0a2a b700  ....<........*..
000001e0: 0a2a 03b5 000c b100 0000 0200 0e00 0000  .*..............
000001f0: 0e00 0300 0000 0100 0400 0200 0900 0100  ................
00000200: 0f00 0000 0c00 0100 0000 0a00 1000 1100  ................
00000210: 0000 0100 1200 1300 0100 0900 0000 3f00  ..............?.
00000220: 0200 0100 0000 0c2a b400 0c04 a000 0504  .......*........
00000230: ac03 ac00 0000 0300 0e00 0000 0600 0100  ................
00000240: 0000 0500 0f00 0000 0c00 0100 0000 0c00  ................
00000250: 1000 1100 0000 1400 0000 0300 010a 0009  ................
00000260: 0015 0016 0001 0009 0000 0037 0002 0001  ...........7....
00000270: 0000 0009 b200 1712 1db6 001f b100 0000  ................
00000280: 0200 0e00 0000 0a00 0200 0000 0900 0800  ................
00000290: 0a00 0f00 0000 0c00 0100 0000 0900 2500  ..............%.
000002a0: 2600 0000 0100 2700 0000 0200 28         &.....'.....(

The hexdump of the edited User.class file:

00000000: cafe babe 0000 0034 0029 0700 0201 0004  .......4.)......
00000010: 5573 6572 0700 0401 0010 6a61 7661 2f6c  User......java/l
00000020: 616e 672f 4f62 6a65 6374 0100 0673 7461  ang/Object...sta
00000030: 7475 7301 0001 4901 0006 3c69 6e69 743e  tus...I...<init>
00000040: 0100 0328 2956 0100 0443 6f64 650a 0003  ...()V...Code...
00000050: 000b 0c00 0700 0809 0001 000d 0c00 0500  ................
00000060: 0601 000f 4c69 6e65 4e75 6d62 6572 5461  ....LineNumberTa
00000070: 626c 6501 0012 4c6f 6361 6c56 6172 6961  ble...LocalVaria
00000080: 626c 6554 6162 6c65 0100 0474 6869 7301  bleTable...this.
00000090: 0006 4c55 7365 723b 0100 0d73 6574 5374  ..LUser;...setSt
000000a0: 6174 7573 5472 7565 0100 0328 295a 0100  atusTrue...()Z..
000000b0: 0d53 7461 636b 4d61 7054 6162 6c65 0100  .StackMapTable..
000000c0: 046d 6169 6e01 000e 285b 4c6a 6176 612f  .main...([Ljava/
000000d0: 6c61 6e67 2f53 7472 696e 673b 2956 0900  lang/String;)V..
000000e0: 1800 1a07 0019 0100 106a 6176 612f 6c61  .........java/la
000000f0: 6e67 2f53 7973 7465 6d0c 001b 001c 0100  ng/System.......
00000100: 036f 7574 0100 154c 6a61 7661 2f69 6f2f  .out...Ljava/io/
00000110: 5072 696e 7453 7472 6561 6d3b 0800 1e01  PrintStream;....
00000120: 000e 6c33 3374 2068 6178 3072 2062 726f  ..l33t hax0r bro
00000130: 0a0a 0020 0022 0700 2101 0013 6a61 7661  ... ."..!...java
00000140: 2f69 6f2f 5072 696e 7453 7472 6561 6d0c  /io/PrintStream.
00000150: 0023 0024 0100 0770 7269 6e74 6c6e 0100  .#.$...println..
00000160: 1528 4c6a 6176 612f 6c61 6e67 2f53 7472  .(Ljava/lang/Str
00000170: 696e 673b 2956 0100 0461 7267 7301 0013  ing;)V...args...
00000180: 5b4c 6a61 7661 2f6c 616e 672f 5374 7269  [Ljava/lang/Stri
00000190: 6e67 3b01 000a 536f 7572 6365 4669 6c65  ng;...SourceFile
000001a0: 0100 0955 7365 722e 6a61 7661 0021 0001  ...User.java.!..
000001b0: 0003 0000 0001 0004 0005 0006 0000 0003  ................
000001c0: 0001 0007 0008 0001 0009 0000 003c 0002  .............<..
000001d0: 0001 0000 000a 2ab7 000a 2a03 b500 0cb1  ......*...*.....
000001e0: 0000 0002 000e 0000 000e 0003 0000 0001  ................
000001f0: 0004 0002 0009 0001 000f 0000 000c 0001  ................
00000200: 0000 000a 0010 0011 0000 0001 0012 0013  ................
00000210: 0001 0009 0000 003f 0002 0001 0000 000c  .......?........
00000220: 2ab4 000c 04a0 0005 04ac 03ac 0000 0003  *...............
00000230: 000e 0000 0006 0001 0000 0005 000f 0000  ................
00000240: 000c 0001 0000 000c 0010 0011 0000 0014  ................
00000250: 0000 0003 0001 0a00 0900 1500 0e00 0100  ................
00000260: 0900 0000 3700 0200 0100 0000 09b2 0017  ....7...........
00000270: 121d b600 1fb1 0000 0002 000e 0000 000a  ................
00000280: 0002 0000 0009 0008 000a 000f 0000 000c  ................
00000290: 0001 0000 0009 0025 0026 0000 0001 0027  .......%.&.....'
000002a0: 0000 0002 0028                           .....(

The answer to this question suggests that the ClassFormatError is a bug in the Java 8 compiler. I am using Java 8, however, the answer also states that the bug was fixed in 8u60+. I am using 8u65.

In the end, how can I edit the .class file with my hex editor to get the desired output?

Additional system specs:

  • Fedora 23
  • javac -version: javac 1.8.0_65
  • java -version:

    java version "1.8.0_65"
    Java(TM) SE Runtime Environment (build 1.8.0_65-b17)
    Java HotSpot(TM) 64-Bit Server VM (build 25.65-b01, mixed mode)
    
Hatchet
  • 5,320
  • 1
  • 30
  • 42

1 Answers1

3

You're only supposed to replace the length field of the string you modified. That's the two bytes in front of the string you modified, The other instances of 00 16 are unrelated parts of the classfile, and editing them turned everything into garbage.

On a side note, I would highly recommend using an assembler. I've created and modified classes directly in a hex editor before, and it's a painstaking process that's very easy to mess up even if you know what you're doing. Furthermore, it's pretty much pointless nowadays, because the Krakatau assembler and disassembler let you create and modify arbitrary classfiles in a human readable format. (If you find something the JVM supports that Krakatau doesn't, please file a bug)

Antimony
  • 37,781
  • 10
  • 100
  • 107
  • Thank you! I guess I misunderstood the image in the tutorial. I'll be sure to look at Krakatau. – Hatchet Jan 16 '16 at 04:26