Thursday, February 6, 2014

Java Bytecode Manipulation

There are many instances where obfuscated JAVA exploits are encountered. In such cases where analysis becomes difficult we resort to manual analysis. But manual analysis can also take a lot of time. In such cases we can fall back to Java Bytecode Manipulation. We can manipulate the Bytecode of Java (Add/Modify/Delete) to our needs to output certain required parts of the code. Consider the below simple example where the code is responsible for decrypting the URL that's passed via PARAM tag to the Jar file.


One could witness that the function "PAt" is responsible for returning the decoded URL. There are number of possibilities to decode this URL,

1. Rip the code into a separate Java file and get the decoded URL
2. Write a similar logic in any scripting language for decoding the URL
3. Use Java Bytecode Manipulation to decode the URL

There are plenty of examples out there for (1) & (2), so let's fall back to the Bytecode Manipulation approach.

Java bytecode is the form of instructions that the Java virtual machine executes. Each bytecode opcode is one byte in length, although some require parameters, resulting in some multi-byte instructions. So to get the desired output in the example that's taken we need to introduce few bytecodes that will be interpreted by Java during run-time.

Multitude of tools are available that can assist in Manipulation of Java Bytecode. One such tool that we are about to witness is JBE. JBE is a Java Tool that assists in Java Bytecode Addition/Modification/Deletion.

In this example we will add few bytecodes to the CLASS file that will print the decoded URL to the "Java Console". The syntax for printing a String to the console in native "Java" code is "System.out.println(string)". The catch here is to convert this native code to Java Bytecode and adding the same to the CLASS file. Consider the below Java code that prints "Hello World" on to the console.
 import java.applet.Applet;  
 public class ex_print extends Applet  
 {  
   public void init()   
      {  
   String str1 = "Hello World";  
      System.out.println(str1);  
      }  
 }  

When you compile this code and load the output class file into JBE you will see the below.

 ldc "Hello World" ----------------> push string "Hello World" onto stack  
 astore_1 -----------------> pops object reference off the stack and store it in local variable  
 getstatic java/lang/System/out Ljava/io/PrintStream;  --------------------> get the static filed for System/out  
 aload_1  --------------------> load the object reference held in local variable (in this case "Hello World")  
 invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V ----------------> invoke the function that does the print  
 return  

We need to use similar kind of bytecodes that is seen above in our CLASS file to print the decoded URL. The bytecode of the CLASS file looks like this.

 ldc "cjft_/vwy6a92p=m8gr3s.?ud4:e&hxi1nz-0bk5ql7o"  
 astore_1  
 ldc "qwertyuiopasdfghjklzxcvb"  
 ldc "nm0123456789.-=_/:?&"  
 invokevirtual java/lang/String/concat(Ljava/lang/String;)Ljava/lang/String;  
 astore_2  
 ldc ""  
 astore_3  
 iconst_0  
 istore 4  
 iload 4  
 aload_0  
 invokevirtual java/lang/String/length()I  
 if_icmpge 32  
 new java/lang/StringBuilder  
 dup  
 invokespecial java/lang/StringBuilder/<init>()V  
 aload_3  
 invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;  
 aload_2  
 aload_1  
 aload_0  
 iload 4  
 invokevirtual java/lang/String/charAt(I)C  
 invokevirtual java/lang/String/indexOf(I)I  
 invokevirtual java/lang/String/charAt(I)C  
 invokevirtual java/lang/StringBuilder/append(C)Ljava/lang/StringBuilder;  
 invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;  
 astore_3  
 iinc 4 1  
 goto 11  
 aload_3 ---------------------> loads the decoded URL and returns it  
 areturn  

In the bytecode we can witness that "aload_3" loads the decoded URL and returns the same. We need to introduce bytecodes at this point to get the decoded URL. After introduction of the bytecodes the code looks like

 ldc "cjft_/vwy6a92p=m8gr3s.?ud4:e&hxi1nz-0bk5ql7o"  
 astore_1  
 ldc "qwertyuiopasdfghjklzxcvb"  
 ldc "nm0123456789.-=_/:?&"  
 invokevirtual java/lang/String/concat(Ljava/lang/String;)Ljava/lang/String;  
 astore_2  
 ldc ""  
 astore_3  
 iconst_0  
 istore 4  
 iload 4  
 aload_0  
 invokevirtual java/lang/String/length()I  
 if_icmpge 32  
 new java/lang/StringBuilder  
 dup  
 invokespecial java/lang/StringBuilder/<init>()V  
 aload_3  
 invokevirtual java/lang/StringBuilder/append(Ljava/lang/String;)Ljava/lang/StringBuilder;  
 aload_2  
 aload_1  
 aload_0  
 iload 4  
 invokevirtual java/lang/String/charAt(I)C  
 invokevirtual java/lang/String/indexOf(I)I  
 invokevirtual java/lang/String/charAt(I)C  
 invokevirtual java/lang/StringBuilder/append(C)Ljava/lang/StringBuilder;  
 invokevirtual java/lang/StringBuilder/toString()Ljava/lang/String;  
 astore_3  
 iinc 4 1  
 goto 11  
 aload_3  
 getstatic java/lang/System/out Ljava/io/PrintStream; --------------------> added code  
 aload_3   -------------------------> added code, load the decoded URL  
 invokevirtual java/io/PrintStream/println(Ljava/lang/String;)V  ---------------------> print the decoded URL to the console  
 areturn  

After the code is added the changes need to be saved.


Later make a JAR files out with all the remaining CLASS files using the below JAR command

 jar -cf <jar_file_name> *.class  

Load the modified JAR using the APPLET in the browser.

 <applet code = 'Using' archive = '222.jar'  width = 300 height = 300>   
 <param name='param' value='m__6lqqhama?ft0ffd=afdaw_0yraja06rlz:z&qhi&h:0.y4'>  
 </applet>  

When the browser loads up check the "Java Console" to get the decoded URL


The same approach can be put into use for heavily obfuscated JAR files where manual analysis consumes lot of time.

No comments:

Post a Comment