Java Reverse Engineering Tutorial#3: Cracking simple password check using bytecode patching
23 Jul 2012Aim:
In this tutorial we will learn how to patch the bytecode present in the class file of the simple crackme which we used in the previous tutorial.Input:
You are given a simple crackme (Java .class file)
Tools:
- JavaBite - My favourite Java bytecode viewer/editor
Tutorial:
- Lets first run the given crackme file (SimplePasswordCheck.class) and see what happens:
2. If we type "john" as password, it results in "ACESS DENIED" that means the password "john" is wrong.
3. Now open the class file in JavaBite by navigating to 'Classes | Add Java Class' in the menu. We will not use any java decompiler(like we did in previous tutorial) as we are going to study the class file at a more granular i.e. assembly(java opcode) level.
4. After opening the file you will see something like this:
5. In the left-hand side column, expand the tree by navigating from the class file to 'Methods | main'. After selecting 'main', the bytecodes of 'main()' method will be loaded in the right-hand side column. This is the opcode/assembly representation of the body of the 'main()' method. After loading, it should like this:
6. In the loaded bytecode, there are 3 columns:
3. Now open the class file in JavaBite by navigating to 'Classes | Add Java Class' in the menu. We will not use any java decompiler(like we did in previous tutorial) as we are going to study the class file at a more granular i.e. assembly(java opcode) level.
4. After opening the file you will see something like this:
5. In the left-hand side column, expand the tree by navigating from the class file to 'Methods | main'. After selecting 'main', the bytecodes of 'main()' method will be loaded in the right-hand side column. This is the opcode/assembly representation of the body of the 'main()' method. After loading, it should like this:
6. In the loaded bytecode, there are 3 columns:
- '#' - The bytecode index (in hex).
- 'ByteCode' - The actual hex representation of the bytcode.
- 'Disassembled' - The disassembled representation of the java opcodes.
8. As we have know from the previous tutorial that this crackme has 'shubham' as the password, we see the same string as being the argument to 'ldc' instruction at bytecode index '000B' in the loaded bytecode.(See below):
# | ByteCode | Disassembled |
000B | 1205 | ldc #0005<shubham> |
See the specification for the 'ldc' instruction at http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc8.html
Short Explanation: The argument (number) '0005' is a reference to the string literal "shubham" in the constant pool of the loaded class file.
9. Traversing down in the loaded opcodes, we see a line of our interest the 'ifeq' check ! This is the appropriate line to patch as it is a validation check for the password.
# | ByteCode | Disassembled |
0020 | 99000E | ifeq 0000002E |
See the specification for the 'if<cond>' instruction at http://docs.oracle.com/javase/specs/jvms/se5.0/html/Instructions2.doc6.html
Short Explanation: The eq succeeds if and only if value = 0. That means if the comparison with 0(false) succeeds then it branches to the address given in the argument. So in above e.g., if the condition is false then it jumps to bytecode index '0000002E' that is at line:
002E B20006 getstatic #0006<java.io.PrintStream java.lang.System.out>'
10. Next we see that the string "ACCESS DENIED :-(" is loaded. This confirms that the current line(bytecode index '0031') is the line inside the 'else' block of the 'if-else' statement.
11. So we now, actually patch the 'ifeq' line at bytecode index '0020' as shown below:
Select the line. Righclick and choose 'Edit instruction'.
12. Now the 'Edit Instruction' box will pop up. Select 'ifne' from the 'Instruction' dropdown list.
13. Also double click the 'BRANCH_OFFSET' item in the 'Parameters' tab and a 'Edit Branch Offset' box will pop up. Select '002E - getstatic' from the 'Branch to line' dropdown list of the 'Branch Offset' tab.(see below)
14. Thats it!
Conclusion:
We have changed the 'ifeq' conditional instruction to the 'ifne' conditional instruction i.e. we have inverted the conditional check. But why ? What we have done is that we have patched the crackme such that for every password input other than the original("shubham") the crackme will result in displaying the message "ACCESS GRANTED :-)" that means for any password(except original) the true case of if-else check is executed.
Notes:
If you have not understood this tutorial then you must be lacking the knowledge of Java opcodes. Please go thoroughly from the 'Java Virtual Machine Instruction Set'.