MS11-002 Pwn2Own heap overflow
Today Microsoft patched the heap overflow I used in pwn2own 2010. The vulnerability was a int wrap during heap allocation. The small allocation was later used to store a bit more information then would fit in there.
<XML ID="xmlid1"> <Devices> <Device> <AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA /> </Device> </Devices> </XML></pre>
Inside an HTML file would give you access to what is called an XML Data Island. This is actually acts as an database interface. You can query the XML data, retrieve rows and data and add more rows. The underlying object is an MSAdo object.
The db objects exposes a property called ‘CacheSize’ that you can use to determine how many records it should keep in its cache. Internally the CacheSize is multiplied by 0x4 and then 0x10 is added (I am typing this from memory so I might be a bit off, but the rough data is correct).
By specifying a big size for the CacheSize property an intwrap will occur and there will only be a small amound of memory reserved to hold the data. The data being stored in the CacheSize buffer is the row number of the cashed row.
You can add rows to the Cache by calling functions that move you through the records, like ‘MoveFirst’, ‘MoveNext’ or similar methods. It will ofcourse not write more record numbers to the cache then there are available.
So you can reliable overflow as much bytes as you want by adding new records and issuing a command that moves to the next records to cache it. I had best success with the MoveFirst method.
The cache buffer resides in a ‘private’ heap and not in the default IE8 heap so the normal heapspray technics dont work. Since I wanted to use this vulnerability to bypass ASLR I needed to find some way to elevate this into information disclosure. On the private heap the buffer resides there are also some C++ Objects and Strings.
I overwrote the \00\00 bytes of one of the strings on the heap to get the vtable address of one of the objects on the heap that gave me enough information to know the location of msado.dll in memory, and that was all I needed for a DEP evasion trick.
To overwrite the \00\00 byes of the string you do need a rather high record number, ie: higher then 0x00010001. I simply added and removed enough records untill I had reached that number. I removed them because I didnt want to write 0x00010001 records all to the cache at once.
This will of course require you to layout the heap in the right order: [cachebuffer][string][objects] I managed to do this and it was working and stable when I ran it on the pwn2own machine, but it is probly specific for only one exact IE8 & Windows 7 patch level so dont be too suprised if the POC does not work right away.
A little trick I did find out was the fact that you can create ‘holes’ in the private heap by specifying a certain CacheSize for an XML Data Island and then closing the RecordSet. This allows some control over the heap layout.
Also: I only used the heap overflow for the information disclosure, but there are enough options to turn this into RCE, at least for WinXP, and maybe also for Windows 7. But for the actual RCE I used a use-after-free bug that has been patched a few months ago: http://www.microsoft.com/technet/security/bulletin/MS10-035.mspx
I have several versions of the exploit on my HD and I have no idea which was the final version that actually worked, so I just dump one out here.
Also: the DEP evasion that I used is based in the msado.dll version that was shipped with W7 at the time of pwn2opwn, and basically did a VirtualProtect call on my Aligned heap spray and turned it executable.
Remember, this is the raw code, and it was written when I was pretty busy so it is both ugly, inefficient and probably full of weird variable names. Also, it needs Alex Sotirovs heapLib.js to run.