前言
在利用 uaf
漏洞时,为了达到任意内存读写,需要在内存中喷射布局 js
的对象,这里我研究几个主要的对象在内存中的布局以及创建过程。
环境
系统: win7 32bit SP1
浏览器: IE10
Array
下面的脚本喷射了很多的 array
对象,附加后运行:
<html> <head> <script language="javascript"> alert("Start"); var a = new Array(); for (var i = 0; i < 0x10000; ++i) { a[i] = new Array(0x1000/4); for (var j = 0; j < a[i].length; ++j) a[i][j] = 0x111; } alert("Done"); </script> </head> <body> </body> </html>
喷射完后可以使用 vmmap
查看内存状态,可以看到喷射的大块的内存,随意选择一个地址,查看地址内容:
0:013> dd 21c60000 21c60000 00000000 00001010 00000000 00000000 21c60010 00000000 00000400 00000400 00000000 21c60020 00000223 00000223 00000223 00000223 21c60030 00000223 00000223 00000223 00000223 21c60040 00000223 00000223 00000223 00000223 21c60050 00000223 00000223 00000223 00000223 21c60060 00000223 00000223 00000223 00000223 21c60070 00000223 00000223 00000223 00000223
0x21c60004
的 0x1010
是数组长度 0x1000
加上数组头长度 0x10
, 21c60014
处的两个 0x400
可能就是数组长度 0x1000/4
,但我们设置的 0x111
却变成了 0x223
,这次我们改变脚本中的一些参数再次调试:
<html> <head> <script language="javascript"> alert("Start"); var a = new Array(); for (var i = 0; i < 0x10000; ++i) { a[i] = new Array(0x1240/4); for (var j = 0; j < a[i].length; ++j) a[i][j] = 0x100; } alert("Done"); </script> </head> <body> </body> </html>
这次得到的结果:
0:005> dd 21c60000 21c60000 00000000 00001250 00000000 00000000 21c60010 00000000 00000490 00000490 00000000 21c60020 00000201 00000201 00000201 00000201 21c60030 00000201 00000201 00000201 00000201 21c60040 00000201 00000201 00000201 00000201 21c60050 00000201 00000201 00000201 00000201 21c60060 00000201 00000201 00000201 00000201 21c60070 00000201 00000201 00000201 00000201
这次的结果证实了判断,而且数字存储的方式是 原数*2+1
,那如果数字溢出的话会怎么样呢,再次修改脚本:
<html> <head> <script language="javascript"> alert("Start"); var a = new Array(); for (var i = 0; i < 0x10000; ++i) { a[i] = new Array(0x1240/4); a[i][0] = 0x7fffffff; a[i][1] = -2; a[i][2] = 1.2345; a[i][3] = document.createElement("div"); } alert("Done"); </script> </head> <body> </body> </html>
得到结果如下:
0:005> dd 21c60000 21c60000 00000000 00001250 00000000 00000000 21c60010 00000000 00000490 00000490 00000000 21c60020 02849070 fffffffd 02849080 21d1ec30 21c60030 00000000 00000000 00000000 00000000 21c60040 00000000 00000000 00000000 00000000 21c60050 00000000 00000000 00000000 00000000 0:005> ln poi(02849070) (610b5ff8) jscript9!Js::JavascriptNumber::`vftable' | (610b6130) jscript9!Js::BufferStringBuilder::WritableString::`vftable' Exact matches: jscript9!Js::JavascriptNumber::`vftable' = <no type information> 0:005> ln poi(02849080) (610b5ff8) jscript9!Js::JavascriptNumber::`vftable' | (610b6130) jscript9!Js::BufferStringBuilder::WritableString::`vftable' Exact matches: jscript9!Js::JavascriptNumber::`vftable' = <no type information> 0:005> ln poi(21d1ec30) (610b2ad0) jscript9!Js::CustomExternalObject::`vftable' | (610b2c18) jscript9!Js::PropertyString::`vftable' Exact matches: jscript9!Js::CustomExternalObject::`vftable' = <no type information> jscript9!Projection::ArrayObjectInstance::`vftable' = <no type information>
可以看到,对于溢出的数, Array
采用 JavascriptNumber
对象的方式存储,而 -2
则直接存储。 Array
这样存储的主要目的就是为了区分地址和数据。
在 21c60004
和 21c60014
两处地址下写入断点,看看数组是如何被创建的:
0:005> ba w4 21c60000+4 0:005> ba w4 21c60000+14 0:005> g Breakpoint 0 hit eax=21c60000 ebx=124f7b60 ecx=124f7b70 edx=21c60010 esi=21c60000 edi=00001250 eip=610ea743 esp=032eba18 ebp=032eba28 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206 jscript9!Recycler::LargeAlloc+0xa1: 610ea743 8b4514 mov eax,dword ptr [ebp+14h] ss:0023:032eba3c=00000000
先断在了中,这时 21c60004
已经被写入了数组的长度 0x1250
,跳出这个函数:
0:007> gu eax=21c60010 ebx=00000000 ecx=00000000 edx=21c60010 esi=025070e8 edi=00000490 eip=610b9a59 esp=032eba40 ebp=032eba44 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206 jscript9!Recycler::AllocZero+0x91: 610b9a59 c70000000000 mov dword ptr [eax],0 ds:0023:21c60010=00000000
再跳出一次:
0:007> gu eax=21c60010 ebx=00000000 ecx=00000000 edx=21c60010 esi=21b8e8e0 edi=00000490 eip=61164571 esp=032eba50 ebp=032eba84 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206 jscript9!Js::JavascriptArray::DirectSetItem_Full+0x3ed: 61164571 8b4de8 mov ecx,dword ptr [ebp-18h] ss:0023:032eba6c=00000490 0:007> p eax=21c60010 ebx=00000000 ecx=00000490 edx=21c60010 esi=21b8e8e0 edi=00000490 eip=61164574 esp=032eba50 ebp=032eba84 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206 jscript9!Js::JavascriptArray::DirectSetItem_Full+0x3f0: 61164574 c70000000000 mov dword ptr [eax],0 ds:0023:21c60010=00000000 0:007> p eax=21c60010 ebx=00000000 ecx=00000490 edx=21c60010 esi=21b8e8e0 edi=00000490 eip=6116457a esp=032eba50 ebp=032eba84 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206 jscript9!Js::JavascriptArray::DirectSetItem_Full+0x3f6: 6116457a 897804 mov dword ptr [eax+4],edi ds:0023:21c60014=00000000 0:007> eax=21c60010 ebx=00000000 ecx=00000490 edx=21c60010 esi=21b8e8e0 edi=00000490 eip=6116457d esp=032eba50 ebp=032eba84 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206 jscript9!Js::JavascriptArray::DirectSetItem_Full+0x3f9: 6116457d 894808 mov dword ptr [eax+8],ecx ds:0023:21c60018=00000000 0:007> eax=21c60010 ebx=00000000 ecx=00000490 edx=21c60010 esi=21b8e8e0 edi=00000490 eip=61164580 esp=032eba50 ebp=032eba84 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206 jscript9!Js::JavascriptArray::DirectSetItem_Full+0x3fc: 61164580 c7400c00000000 mov dword ptr [eax+0Ch],0 ds:0023:21c6001c=00000000 0:007> eax=21c60010 ebx=00000000 ecx=00000490 edx=21c60010 esi=21b8e8e0 edi=00000490 eip=61164587 esp=032eba50 ebp=032eba84 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206 jscript9!Js::JavascriptArray::DirectSetItem_Full+0x403: 61164587 8bd0 mov edx,eax 0:007> eax=21c60010 ebx=00000000 ecx=00000490 edx=21c60010 esi=21b8e8e0 edi=00000490 eip=61164589 esp=032eba50 ebp=032eba84 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00200206 jscript9!Js::JavascriptArray::DirectSetItem_Full+0x405: 61164589 894614 mov dword ptr [esi+14h],eax ds:0023:21b8e8f4=610be460
继续单步可以看到设置 21c60014
的过程,最后一句把我们创建的数组的地址放到了 [esi+14h]
,这里是一个对象:
0:007> ln poi(esi) (610b2f78) jscript9!Js::JavascriptArray::`vftable' | (610b30e0) jscript9!Js::JavascriptError::`vftable' Exact matches: jscript9!Js::JavascriptArray::`vftable' = <no type information>
在全部喷射完后再次查看这里的地址,
0:005> dd 21b8e8e0 21b8e8e0 610b2f78 02839a60 00000000 00000003 <= 21b8e8f0 00000490 21c60010 21c60010 00000000 21b8e900 610b2f78 02839a60 00000000 00000003 <= 21b8e910 00000490 21c62010 21c62010 00000000 21b8e920 610b2f78 02839a60 00000000 00000003 <= 21b8e930 00000490 21c64010 21c64010 00000000 21b8e940 610b2f78 02839a60 00000000 00000003 <= 21b8e950 00000490 21c66010 21c66010 00000000
这里可以明显的看到一个对象的大小是 0x20
,存储了数组的大小和地址等信息。
LargeHeapBlock
测试脚本:
<html> <head> <script language="javascript"> alert("Start"); var a = new Array(); for (var i = 0; i < 0x100; ++i) { a[i] = new Array(0x1000/4); a[i][0] = 0x7fffffff; a[i][1] = -2; a[i][2] = 1.2345; a[i][3] = document.createElement("div"); } alert("Done"); </script> </head> <body> </body> </html>
在 windbg
中搜索与 largeheapblock
有关的函数可以搜索到很多,这里选择两个看上去和内存分配有关的下断点:
0:005> bl 3 e 610ea785 0001 (0001) 0:**** jscript9!HeapInfo::AddLargeHeapBlock 4 e 612737af 0001 (0001) 0:**** jscript9!LargeHeapBlock::Alloc
这里开启堆页调试,在 AddLargeHeapBlock
断下后到函数返回后:
0:007> gu eax=0187ffa8 ebx=09f18fa8 ecx=071e4470 edx=071e0620 esi=071e0370 edi=00001250 eip=610ea708 esp=0548b8b0 ebp=0548b8c0 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 jscript9!Recycler::LargeAlloc+0x66: 610ea708 8bd8 mov ebx,eax 0:007> !heap -p -a @eax address 0187ffa8 found in _DPH_HEAP_ROOT @ 1861000 in busy allocation ( DPH_HEAP_BLOCK: UserAddr UserSize - VirtAddr VirtSize) 1861cc8: 187ffa8 54 - 187f000 2000 jscript9!LargeHeapBlock::`vftable' 6bef8e89 verifier!AVrfDebugPageHeapAllocate+0x00000229 ... 0:007> ln poi(eax) (610b1c7c) jscript9!LargeHeapBlock::`vftable' | (610b1ca0) jscript9!Segment::`vftable' Exact matches: jscript9!LargeHeapBlock::`vftable' = <no type information>
可以看到 AddLargeHeapBlock
分配了 0x54
大小的空间,是一个 LargeHeapBlock
对象。然后我们关闭堆页,在返回后的地址下断点:
0:015> bl 0 e 61baa708 0001 (0001) 0:**** jscript9!Recycler::LargeAlloc+0x66 ".printf \"new LargeHeapBlock: addr = 0x%p\\n\",eax;g" 0:015> g ... ... new LargeHeapBlock: addr = 0x01eb4af8 new LargeHeapBlock: addr = 0x01eb4b58 new LargeHeapBlock: addr = 0x01eb4bb8 new LargeHeapBlock: addr = 0x01eb4c18 new LargeHeapBlock: addr = 0x01eb4c78 new LargeHeapBlock: addr = 0x01eb4cd8 new LargeHeapBlock: addr = 0x01eb4d38 new LargeHeapBlock: addr = 0x01eb4d98
得到了一系列分配的地址,间隔为 0x60
就是对象大小加上头大小,这些内存如下:
01eb4af8 61b71c7c 00000003 03dac000 00000002 <= 01eb4b08 00000001 00000000 00000004 03dad020 01eb4b18 03dae000 01eb4a98 00000000 00000000 01eb4b28 00000000 00000000 01eaddc0 03dac000 01eb4b38 00000000 00000000 00000000 00000004 01eb4b48 00000000 00000000 77d0590a 8c000000 01eb4b58 61b71c7c 00000003 03dae000 00000002 <= 01eb4b68 00000001 00000000 00000004 03daf020 01eb4b78 03db0000 01eb4af8 00000000 00000000 01eb4b88 00000000 00000000 01eaddc0 03dae000 01eb4b98 00000000 00000000 00000000 00000004 01eb4ba8 00000000 00000000 77d05916 8c000000 01eb4bb8 61b71c7c 00000003 03db0000 00000002 <= 01eb4bc8 00000001 00000000 00000004 03db1020 01eb4bd8 03db2000 01eb4b58 00000000 00000000 01eb4be8 00000000 00000000 01eaddc0 03db0000 01eb4bf8 00000000 00000000 00000000 00000004 01eb4c08 00000000 00000000 77d059e2 8c000000
每个对象偏移 0x24
处的地址指向前一个对象。
ArrayBuffer & Int32Array
ArrayBuffer
表示数据的原始缓冲区,能够申请指定大小的内存,但无法直接读取或写入,需要将其传递到类型化数组创建数据化数组, Int32Array
就是一种,比如:
var buf = new ArrayBuffer(30); var a = new Int32Array(buf);
我们来喷射一些 Int32Array
对象:
<html> <head> <script language="javascript"> alert("Start"); var a = new Array(); for (var i = 0; i < 0x10000; ++i) { a[i] = new Int32Array(0x1000/4); for (var j = 0; j < a[i].length; ++j) a[i][j] = 0x123; } alert("Done"); </script> </head> <body> </body> </html>
喷射完后,内存中的对象:
12690000 323a4d40 010181cd ffeeffee 00000000 12690010 13660010 116c0010 004e0000 12690000 12690020 00000fd0 12690040 13660000 00000000 12690030 00000001 00000000 1365fff0 1365fff0 12690040 b232cd48 080181c5 116b0b18 0886ec48 12690050 00000012 f0e0d0c0 7ea2c967 88000000 12690060 00000123 00000123 00000123 00000123 12690070 00000123 00000123 00000123 00000123 12690080 00000123 00000123 00000123 00000123 12690090 00000123 00000123 00000123 00000123 126900a0 00000123 00000123 00000123 00000123 126900b0 00000123 00000123 00000123 00000123
搜索大小为 0x1000
的堆,能够搜索到很多:
0:015> !heap -flt s 100 _HEAP @ 180000 HEAP_ENTRY Size Prev Flags UserPtr UserSize - state ... ... 1581b530 0201 0201 [00] 1581b538 01000 - (busy) 1581c538 0201 0201 [00] 1581c540 01000 - (busy) 1581d540 0201 0201 [00] 1581d548 01000 - (busy) 1581e548 0201 0201 [00] 1581e550 01000 - (busy) 1581f550 0201 0201 [00] 1581f558 01000 - (busy) 15820558 0201 0201 [00] 15820560 01000 - (busy) 15821560 0201 0201 [00] 15821568 01000 - (busy) 15822568 0201 0201 [00] 15822570 01000 - (busy) 15823570 0201 0201 [00] 15823578 01000 - (busy) 15824578 0201 0201 [00] 15824580 01000 - (busy) 15825580 0201 0201 [00] 15825588 01000 - (busy) 15826588 0201 0201 [00] 15826590 01000 - (busy) 15827590 0201 0201 [00] 15827598 01000 - (busy) 15828598 0201 0201 [00] 158285a0 01000 - (busy) 158295a0 0201 0201 [00] 158295a8 01000 - (busy) 1582a5a8 0201 0201 [00] 1582a5b0 01000 - (busy) 1582b5b0 0201 0201 [00] 1582b5b8 01000 - (busy) 1582c5b8 0201 0201 [00] 1582c5c0 01000 - (busy) 1582d5c0 0201 0201 [00] 1582d5c8 01000 - (busy) 1582e5c8 0201 0201 [00] 1582e5d0 01000 - (busy) 1582f5d0 0201 0201 [00] 1582f5d8 01000 - (busy) 158305d8 0201 0201 [00] 158305e0 01000 - (busy) 158315e0 0201 0201 [00] 158315e8 01000 - (busy) 158325e8 0201 0201 [00] 158325f0 01000 - (busy) 158335f0 0201 0201 [00] 158335f8 01000 - (busy) 158345f8 0201 0201 [00] 15834600 01000 - (busy) 15835600 0201 0201 [00] 15835608 01000 - (busy) 15836608 0201 0201 [00] 15836610 01000 - (busy) 15837610 0201 0201 [00] 15837618 01000 - (busy) 15838618 0201 0201 [00] 15838620 01000 - (busy) 15839620 0201 0201 [00] 15839628 01000 - (busy) 1583a628 0201 0201 [00] 1583a630 01000 - (busy) 1583b630 0201 0201 [00] 1583b638 01000 - (busy) 1583c638 0201 0201 [00] 1583c640 01000 - (busy) 1583d640 0201 0201 [00] 1583d648 01000 - (busy) 1583e648 0201 0201 [00] 1583e650 01000 - (busy) 15840458 0201 0201 [00] 15840460 01000 - (busy) 15841460 0201 0201 [00] 15841468 01000 - (busy) 15842468 0201 0201 [00] 15842470 01000 - (busy) 15843470 0201 0201 [00] 15843478 01000 - (busy) 15844478 0201 0201 [00] 15844480 01000 - (busy) 15845480 0201 0201 [00] 15845488 01000 - (busy) 15846488 0201 0201 [00] 15846490 01000 - (busy) 15847490 0201 0201 [00] 15847498 01000 - (busy) 15848498 0201 0201 [00] 158484a0 01000 - (busy) 158494a0 0201 0201 [00] 158494a8 01000 - (busy) 1584a4a8 0201 0201 [00] 1584a4b0 01000 - (busy) 1584b4b0 0201 0201 [00] 1584b4b8 01000 - (busy) 1584c4b8 0201 0201 [00] 1584c4c0 01000 - (busy) 1584d4c0 0201 0201 [00] 1584d4c8 01000 - (busy) 1584e4c8 0201 0201 [00] 1584e4d0 01000 - (busy) 1584f4d0 0201 0201 [00] 1584f4d8 01000 - (busy) 158504d8 0201 0201 [00] 158504e0 01000 - (busy) 158514e0 0201 0201 [00] 158514e8 01000 - (busy) 158524e8 0201 0201 [00] 158524f0 01000 - (busy) 158534f0 0201 0201 [00] 158534f8 01000 - (busy) 158544f8 0201 0201 [00] 15854500 01000 - (busy) 15855500 0201 0201 [00] 15855508 01000 - (busy) ... 0:015> dd 15855508 15855508 00000123 00000123 00000123 00000123 15855518 00000123 00000123 00000123 00000123 15855528 00000123 00000123 00000123 00000123 15855538 00000123 00000123 00000123 00000123 15855548 00000123 00000123 00000123 00000123 15855558 00000123 00000123 00000123 00000123 15855568 00000123 00000123 00000123 00000123 15855578 00000123 00000123 00000123 00000123
确实是我们喷射的数据,在堆的头信息处下写入断点,看看这个堆是怎么创建的:
0:015> ba w4 15855500 0:015> g Breakpoint 0 hit eax=004e0000 ebx=6045434c ecx=15855500 edx=15855506 esi=0f710b98 edi=004ea840 eip=77a347c2 esp=02b3b7a0 ebp=02b3b7e4 iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000202 ntdll!RtlpSubSegmentInitialize+0x122: 77a347c2 c60200 mov byte ptr [edx],0 ds:0023:15855506=00 0:007> k ChildEBP RetAddr 02b3b7e4 77a3433d ntdll!RtlpSubSegmentInitialize+0x122 02b3b880 77a22e82 ntdll!RtlpLowFragHeapAllocFromContext+0x882 02b3b8f4 77b59d45 ntdll!RtlAllocateHeap+0x206 02b3b914 61dcfb8b msvcrt!malloc+0x8d 02b3b924 61bb2be4 jscript9!memset+0x349d3 02b3b93c 61d7dac4 jscript9!Js::JavascriptArrayBuffer::Create+0x3c 02b3b968 61d78a20 jscript9!Js::TypedArrayBase::CreateNewInstance+0x1cf 02b3b9e0 61ba6c47 jscript9!Js::TypedArray<int>::NewInstance+0x55 02b3ba0c 61d4bd6b jscript9!Js::InterpreterStackFrame::OP_LoopBodyStart+0x9f 02b3ba24 61b826f0 jscript9!Js::InterpreterStackFrame::OP_ProfiledLoopBodyStart+0x1a 02b3bb04 61b849e0 jscript9!Js::InterpreterStackFrame::Process+0x45a1 02b3bc3c 02430fe9 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x305
通过栈回溯发现堆由 malloc
创建,上层是由 jscript9!Js::JavascriptArrayBuffer::Create
调用的,在上层由 jscript9!Js::TypedArray<int>::NewInstance
调用,那么在 TypedArray<int>::NewInstance
下断点就可以看 Int32Array
的创建过程。
0:007> bm /a jscript9!Js::TypedArray<int>::NewInstance 1: 61d789cb @!"jscript9!Js::TypedArray<int>::NewInstance"
这次只创建一个对象:
<html> <head> <script language="javascript"> alert("Start"); var a = new Int32Array(0x1000/4); for (var i = 0; i < a.length; ++i) a[i] = 0x123; } alert("Done"); </script> </head> <body> </body> </html>
断下:
0:016> g Breakpoint 1 hit eax=00000002 ebx=02301660 ecx=00000801 edx=02b3b9d8 esi=00000002 edi=02b3bbb8 eip=61d789cb esp=02b3b9cc ebp=02b3ba1c iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 jscript9!Js::TypedArray<int>::NewInstance: 61d789cb 8bff mov edi,edi
搜索和 jscript9!Js::TypedArray<int>
有关的函数可以找到一个 jscript9!Js::TypedArray<int>::Creat
,看起来是创建对象的函数,下断点:
0:005> bm /a jscript9!Js::TypedArray<int>::Create 2: 61d09640 @!"jscript9!Js::TypedArray<int>::Create" 0:007> g Breakpoint 2 hit eax=00000400 ebx=04a6ae20 ecx=00000000 edx=00000000 esi=0cef0858 edi=00000400 eip=61d09640 esp=02b3b964 ebp=02b3b998 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 jscript9!Js::TypedArray<int>::Create: 61d09640 8bff mov edi,edi
单步可以跟到分配内存的地方:
0:007> eax=00001000 ebx=04a6ae20 ecx=01e070e8 edx=00000000 esi=0231b000 edi=04a6ae20 eip=61d0967f esp=02b3b950 ebp=02b3b960 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 jscript9!Js::TypedArray<int>::Create+0x3f: 61d0967f 6a24 push 24h 0:007> eax=00001000 ebx=04a6ae20 ecx=01e070e8 edx=00000000 esi=0231b000 edi=04a6ae20 eip=61d09681 esp=02b3b94c ebp=02b3b960 iopl=0 nv up ei pl zr na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000246 jscript9!Js::TypedArray<int>::Create+0x41: 61d09681 e8b5dfe6ff call jscript9!Recycler::Alloc (61b7763b) 0:007> p eax=046a00f0 ebx=04a6ae20 ecx=046a0030 edx=01e0b3a4 esi=0231b000 edi=04a6ae20 eip=61d09686 esp=02b3b950 ebp=02b3b960 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206 jscript9!Js::TypedArray<int>::Create+0x46: 61d09686 ffb61c010000 push dword ptr [esi+11Ch] ds:0023:0231b11c=023098a0
TypedArray<int>
对象大小为 0x24
,返回后的对象已经设置好了:
0:007> gu eax=046a00f0 ebx=04a6ae20 ecx=17f480a0 edx=00000000 esi=0cef0858 edi=00000400 eip=61d7dae6 esp=02b3b978 ebp=02b3b998 iopl=0 nv up ei pl nz na pe nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000206 jscript9!Js::TypedArrayBase::CreateNewInstance+0x1f1: 61d7dae6 8bf0 mov esi,eax 0:007> dd 046a00f0 l9 046a00f0 61b738c8 023098a0 00000000 00000003 046a0100 00000004 00000000 00000400 17f480a0 046a0110 04a6ae20 0:007> ln poi(046a00f0) (61b738c8) jscript9!Js::TypedArray<int>::`vftable' | (61b73a20) jscript9!Js::TypedArray<unsigned short>::`vftable' Exact matches: jscript9!Js::TypedArray<int>::`vftable' = <no type information>
TypedArray<int>
对象尾部的两个地址分别是存放 Int32Array
数据的缓冲区和 ArrayBuffer
对象:
0:007> ln poi(04a6ae20) (61bb2bf8) jscript9!Js::JavascriptArrayBuffer::`vftable' | (61d7e1c8) jscript9!Js::CopyOnWriteObject<Js::TypedArray<bool>,Js::NoSpecialProperties>::`vftable' Exact matches: jscript9!Js::JavascriptArrayBuffer::`vftable' = <no type information> 0:007> dd 04a6ae20 04a6ae20 61bb2bf8 02309a20 00000000 00000003 04a6ae30 17f480a0 00001000 00000000 00000000 04a6ae40 04a6ae60 00000000 00000000 00000000 0:007> dd 17f480a0-8 17f48098 79b770df 88000000 00000000 00000000 17f480a8 00000000 00000000 00000000 00000000 17f480b8 00000000 00000000 00000000 00000000 17f480c8 00000000 00000000 00000000 00000000 17f480d8 00000000 00000000 00000000 00000000
缓冲区的堆头已经设置好了,继续运行后就填入了数据:
0:005> dd 17f480a0-8 17f48098 79b770df 88000000 00000123 00000123 17f480a8 00000123 00000123 00000123 00000123 17f480b8 00000123 00000123 00000123 00000123 17f480c8 00000123 00000123 00000123 00000123 17f480d8 00000123 00000123 00000123 00000123 17f480e8 00000123 00000123 00000123 00000123 17f480f8 00000123 00000123 00000123 00000123 17f48108 00000123 00000123 00000123 00000123
总结一下:
TypedArray<int>: +0x00: 虚表 +0x18: 数组长度 +0x1c: 缓冲区地址 +0x20: ArrayBuffer对象地址 ArrayBuffer: +0x00: 虚表 +0x10: 缓冲区地址 +0x14: 缓冲区长度
注:本文内容来自互联网,旨在为开发者提供分享、交流的平台。如有涉及文章版权等事宜,请你联系站长进行处理。