티스토리 뷰

본 문서는 원문 저자인 Massimiliano Tomassoli의 허락 하에 번역이 되었으며, 원문과 관련된 모든 저작물에 대한 저작권은 원문 저자인 Massimiliano Tomassoli에 있음을 밝힙니다. 


http://expdev-kiuhnm.rhcloud.com



최신 윈도우즈 익스플로잇 개발 13. IE 10 (IE 리버싱)


hackability.kr (김태범)

hackability_at_naver.com or ktb88_at_korea.ac.kr

2016.07.22



이번 익스플로잇을 위해 가상 머신에 윈도우즈 7 64비트 서비스팩 1 IE 10을 이용합니다.

 

IE 10을 성공적으로 익스플로잇 하기 위해서는 ASLR DEP 모두 우회를 해야 합니다. 배열의 크기를 조작하기 위해 UAF (Use After Free)를 익스플로잇해서 전체 프로세스 주소 공간에 대해 읽고 쓰기를 할 것입니다. 우리가 원하는 위치의 읽기/쓰기를 하는 것은 굉장한 능력입니다. 여기에 2가지 방법이 있습니다.


1. ActiveX 객체 실행 (God 모드)

2. 일반적인 쉘 코드 실행


UAF 이후 임의 읽기/쓰기는 링크에 있는 방법을 이용할 것입니다.

  • https://cansecwest.com/slides/2014/The%20Art%20of%20Leaks%20-%20read%20version%20-%20Yoyo.pdf


이 방법을 완전히 이해 하기 위해 논문을 읽는 것만으로는 부족한데 그 이유는 몇몇 세부 사항이 빠져 있기 때문입니다. 여기서 저는 이론과 실무의 차이점을 몇 개 찾았습니다.

 

저의 목표는 단지 방법을 기술하는게 아니라 완벽한 익스플로잇을 만들기 위한 모든 작업을 보여드리고 싶습니다. 먼저 WinDbg로 조사를 하고 다음으로는 메모리에 객체들이 어떻게 구성되는지 보도록 하겠습니다.



IE 리버싱


분석할 객체는 다음과 같습니다.

  • Array
  • LargeHeapBlock
  • ArrayBuffer
  • Int32Array

WinDbg 설정


이제 WinDbg에 익숙해 지셨고 알맞게 설정되어 있겠지만 확실하게 해보도록 하겠습니다. 먼저 WinDbg (항상 관리자 권한의 32비트 버전)로 열어 CTRL-S 를 누르고 symbol path에 다음을 넣습니다.


SRV*C:\WinDbgSymbols*http://msdl.microsoft.com/download/symbols


기억하실 점은 첫 번째는 원격 서버에서 다운 받은 심볼들 캐쉬들을 위한 로컬 디렉토리 입니다.

 

OK 를 누르고 workspace 를 저장합니다. (File -> Save Workspace)

 

이제 IE 10을 실행 하고 WinDbg에서 F6을 눌러 Attach to process로 이동합니다. 프로세스 리스트를 보시면 iexplore.exe 2개가 있음을 볼 수 있습니다. 첫 번째 iexplore.exe는 메인 프로세스이며 두 번째 iexplore.exe IE에서 열린 첫 번째 tab 과 관련된 프로세스 입니다. 다른 tab을 더 열게 되면 동일한 프로세스를 더 볼 수 있을 것 입니다. 위에서 얘기한 2번째 인스턴스를 선택하시면 다음과 같습니다.



저는 WinDbg 를 다음과 같이 사용하고 있습니다.



원하는 배열로 WinDbg를 구성 한뒤에 workspace를 다시 저장해주세요.


Array


배열 객체 부터 시작해보도록 하겠습니다. 다음과 같은 html 파일을 생성합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head>
<script language="javascript">
  alert("Start");
  var a = new Array(0x123);
  for (var i = 0; i < 0x123++i)
    a[i] = 0x111;
  alert("Done");
</script>
</head>
<body>
</body>
</html>
cs


IE에서 위 파일을 열고 차단된 컨텐츠 허용을 하신다음 Start 팝업 메시지가 뜨면 WinDbg에서 F6을 눌러 위에서 한 것 처럼 iexplore.exe에 디버거를 붙입니다. F5를 눌러 계속 진행하고 팝업 메시지를 닫습니다. 이제 Done 이라는 두 번째 메시지가 나오게 될 겁니다.

 

WinDbg로 돌아가 배열의 내용을 메모리에서 검색합니다. 소스 코드를 보면 배열은 0x111 을 갖습니다. 아래는 검색을 위한 명령어 입니다.


0:004> s-d 0 L?ffffffff 111 111 111 111


아무것도 얻지 못했습니다! 정말 이상하군요... 만약 메모리에서 배열을 찾았다면 할당이 일어나는 코드의 위치를 알 수 있었을 겁니다. 좀 더 똑똑하게 진행해 보도록 하겠습니다.

 

힙 스프레잉을 하면 어떨까요? 코드를 좀 변경해보도록 하겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<head>
<script language="javascript">
  alert("Start");
  var a = new Array();
  for (var i = 0; i < 0x10000++i) {
    a[i] = new Array(0x1000/4);     // 0x1000 bytes = 0x1000/4 dwords
    for (var j = 0; j < a[i].length++j)
      a[i][j] = 0x111;
  }
  alert("Done");
</script>
</head>
<body>
</body>
</html>
cs


html 파일을 수정한 뒤에, WinDbg에서 F5를 눌러 계속 진행하여 Done 메시지 박스를 닫고 페이지를 다시 로드 합니다. Start 메시지 박스가 나오면 닫고 다음 메시지 박스가 나올 때 까지 기다립니다. 이제 작업 관리자 (Task Manager)를 열어 IE의 메모리 사용량을 확인해봅니다.



우리는 550M 정도 할당을 했습니다. VMMap을 이용하면 그래픽적으로 힙 스프레잉을 볼 수 있습니다.

 

VMMap을 열어 iexplore.exe를 선택하면 다음과 같은 화면을 볼 수 있습니다.



View -> Fragmentation View로 가면 다음과 같은 화면을 볼 수 있습니다.



노란색 영역은 힙 스프레잉에 의해 할당된 메모리 영역을 뜻합니다. 우리 데이터의 중간에있는0x1ffd0000 주소의 메모리를 분석해 보도록 하겠습니다.


 

이 부분이 정말 우리 배열 중 하나인지를 확인하기 위해 코드를 좀 수정합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<html>
<head>
<script language="javascript">
  alert("Start");
  var a = new Array();
  for (var i = 0; i < 0x10000++i) {
    a[i] = new Array(0x1234/4);     // 0x1234/4 = 0x48d
    for (var j = 0; j < a[i].length++j)
      a[i][j] = 0x123;
  }
  alert("Done");
</script>
</head>
<body>
</body>
</html>
cs


위 과정을 다시 하면 다음과 같은 결과를 얻을 수 있습니다.



보시면, 배열이 0x247 값을 갖고 있음을 알 수 있습니다. 다른 방식으로 해보도록 하겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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] = j;
  }
  alert("Done");
</script>
</head>
<body>
</body>
</html>
cs


그러면 다음과 같은 결과를 얻을 수 있습니다.



배열이 1부터 시작해서 홀수를 갖고 있습니다. 이제 우리 배열이 숫자를 가지고 있음을 알고 있는데


1 2 3 4 5 6 7 8 9 ...


이렇게 숫자를 얻어야 하는데 실제로는 다음과 같이 얻어 집니다.


3 5 7 9 11 13 15 17 19 ...


숫자 n n * 2 + 1 로 되어 있음을 볼 수 있습니다. 왜 이럴까요? 한 가지 알아야 할 것은 배열이 숫자 외에 객체들의 참조들을 가질 수도 있기 때문에 정수나 주소로 표현할 수 있어야 합니다. 주소들은 4의 배수로 되기 때문에 정수는 홀수로 표현되며 이를 통해 참조들에 대해 혼동되지 않을 수 있습니다. 하지만 2의 보수 체계에서 0x7fffffff 같은 큰 양수는 어떻게 표현할까요? 한 번 실험해 보도록 하겠습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>
<head>
<script language="javascript">
  alert("Start");
  var a = new Array();
  for (var i = 0; i < 0x10000++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>
cs


배열은 다음과 같이 나타납니다.



0x7fffffff는 직접 저장하기엔 너무 커서 IE 에서는 JavascriptNumber 객체를 가리키는 참조에 대해 저장합니다. 숫자 -2 는 바로 저장되는데 그 이유는 최상위 비트가 설정되어 있어 주소와 혼동될 일이 없기 때문입니다.

 

이제 알아야 할 것은, 오브젝트의 첫 dword는 보통 해당 객체의 vtable의을 가리킵니다. 그림에서 보시다시피, 이것은 객체의 식별에 도움을 줍니다.

 

이제 어떤 코드에서 배열을 할당 했는지 찾아 보도록 하겠습니다. 보시면 아마 2개의 해더들을 볼 수 있을 겁니다.



첫 번째 해더는 할당된 블록이 0x1010 바이트임을 알려줍니다. 할당된 블록은 0x10바이트 해더와0x1000 바이트의 실제 데이터를 갖습니다. 우리는 우리의 배열 중 하나가 0x1ffd0000에 있음을 알기 때문에 두 헤더들에 write 에 대한 hardware breakpoints를 걸어 둡니다. 이 방식을 이용하여 블록을 할당하는 코드와 오브젝트를 할당하는 코드에 대해 찾을 수 있습니다.

 

페이지를 다시 로드하고 Start 메시지 박스가 나타나면 멈춥니다. WinDbg에서 실행 멈춤 (CTRL + Break)을 합니다. 아래 2 hardware breakpoints를 설정합니다.


0:004> ba w4 1ffd0000+4

0:004> ba w4 1ffd0000+14

0:004> bl

 0 e 1ffd0004 w 4 0001 (0001)  0:****

 1 e 1ffd0014 w 4 0001 (0001)  0:****


F5 (에러 메시지들은 무시하세요)를 누르고 IE의 메시지 박스를 닫습니다. 첫 번째 breakpoint가 작동되면 콜 스택을 확인해봅니다.


0:007> k 20

ChildEBP RetAddr  

0671bb30 6ea572d8 jscript9!Recycler::LargeAlloc+0xa1      <----------------------

0671bb4c 6eb02c47 jscript9!Recycler::AllocZero+0x91       <----------------------

0671bb8c 6ea82aae jscript9!Js::JavascriptArray::DirectSetItem_Full+0x3fd     <----------------- (*)

0671bc14 05f2074b jscript9!Js::JavascriptOperators::OP_SetElementI+0x1e0

WARNING: Frame IP not in any known module. Following frames may be wrong.

0671bc48 6ea77461 0x5f2074b

0671bde4 6ea55cf5 jscript9!Js::InterpreterStackFrame::Process+0x4b47

0671bf2c 05f80fe9 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x305

0671bf38 6ea51f60 0x5f80fe9

0671bfb8 6ea520ca jscript9!Js::JavascriptFunction::CallRootFunction+0x140

0671bfd0 6ea5209f jscript9!Js::JavascriptFunction::CallRootFunction+0x19

0671c018 6ea52027 jscript9!ScriptSite::CallRootFunction+0x40

0671c040 6eafdf75 jscript9!ScriptSite::Execute+0x61

0671c0cc 6eafdb57 jscript9!ScriptEngine::ExecutePendingScripts+0x1e9

0671c154 6eafe0b7 jscript9!ScriptEngine::ParseScriptTextCore+0x2ad

0671c1a8 069cb60c jscript9!ScriptEngine::ParseScriptText+0x5b

0671c1e0 069c945d MSHTML!CActiveScriptHolder::ParseScriptText+0x42

0671c230 069bb52f MSHTML!CJScript9Holder::ParseScriptText+0x58

0671c2a4 069cc6a4 MSHTML!CScriptCollection::ParseScriptText+0x1f0

0671c394 069cc242 MSHTML!CScriptData::CommitCode+0x36e

0671c40c 069cbe6e MSHTML!CScriptData::Execute+0x233

0671c420 069c9b49 MSHTML!CHtmScriptParseCtx::Execute+0x89

0671c498 067d77cc MSHTML!CHtmParseBase::Execute+0x17c

0671c4c4 755862fa MSHTML!CHtmPost::Broadcast+0x88

0671c5c4 069c3273 user32!InternalCallWinProc+0x23

0671c5dc 069c31ff MSHTML!CHtmPost::Run+0x1c

0671c5f4 069c34f3 MSHTML!PostManExecute+0x5f

0671c610 069c34b2 MSHTML!PostManResume+0x7b

0671c650 06830dc9 MSHTML!CHtmPost::OnDwnChanCallback+0x3a

0671c660 0677866c MSHTML!CDwnChan::OnMethodCall+0x19

0671c6b4 067784fa MSHTML!GlobalWndOnMethodCall+0x169

0671c700 755862fa MSHTML!GlobalWndProc+0xd7

0671c72c 75586d3a user32!InternalCallWinProc+0x23


여기서 3가지 내용을 파악 할 수 있습니다.

1. IE custom allocator 를 사용합니다.

2. 배열은 jscript9!Js::JavascriptArray 타입 입니다.

3. 배열의 첫 아이템의 값이 설정될 때 아마 블록이 할당 됩니다. (*)


Shift + F11을 이용하여 현재 호출에 대해 종료 하면 다음 위치에 도착하게 됩니다.


6e9e72ce 6a00            push    0

6e9e72d0 50              push    eax

6e9e72d1 51              push    ecx

6e9e72d2 56              push    esi

6e9e72d3 e80f34ffff      call    jscript9!Recycler::LargeAlloc (6e9da6e7)

6e9e72d8 c70000000000    mov     dword ptr [eax],0    ds:002b:1ffd0010=00000000    <----- we are here

6e9e72de 5e              pop     esi

6e9e72df 5d              pop     ebp

6e9e72e0 c20400          ret     4


다시 Shift + F11을 누르면


6ea92c3f 51              push    ecx

6ea92c40 8bca            mov     ecx,edx

6ea92c42 e89a67f4ff      call    jscript9!Recycler::AllocZero (6e9d93e1)

6ea92c47 8b55e8          mov     edx,dword ptr [ebp-18h] ss:002b:04d2c058=04d2c054  <----- we are here

6ea92c4a 8b0a            mov     ecx,dword ptr [edx]

6ea92c4c c70000000000    mov     dword ptr [eax],0


EAX가 버퍼를 가리키고 있기 때문에 6ea92c47 breakpoint를 걸어 둡니다. 먼저, EIP는 모듈의 특정 기본 주소에 의존적이지 않기 때문에 EIP의 주소를 써보도록 합니다. jscript9에서 다음과 같은 내용을 얻을 수 있습니다.


0:007> !address @eip


                                     

Mapping file section regions...

Mapping module regions...

Mapping PEB regions...

Mapping TEB and stack regions...

Mapping heap regions...

Mapping page heap regions...

Mapping other regions...

Mapping stack trace database regions...

Mapping activation context regions...



Usage:                  Image

Base Address:           6e9d1000

End Address:            6ec54000

Region Size:            00283000

State:                  00001000  MEM_COMMIT

Protect:                00000020  PAGE_EXECUTE_READ

Type:                   01000000  MEM_IMAGE

Allocation Base:        6e9d0000

Allocation Protect:     00000080  PAGE_EXECUTE_WRITECOPY

Image Path:             C:\Windows\SysWOW64\jscript9.dll

Module Name:            jscript9        <-----------------------------------------

Loaded Image Name:      C:\Windows\SysWOW64\jscript9.dll

Mapped Image Name:      

More info:              lmv m jscript9

More info:              !lmi jscript9

More info:              ln 0x6ea92c47

More info:              !dh 0x6e9d0000


Unloaded modules that overlapped the address in the past:

    BaseAddr  EndAddr     Size

    6ea90000 6ebed000   15d000 VBoxOGL-x86.dll

    6e9b0000 6eb0d000   15d000 VBoxOGL-x86.dll



Unloaded modules that overlapped the region in the past:

    BaseAddr  EndAddr     Size

    6ebf0000 6eccb000    db000 wined3dwddm-x86.dll

    6ea90000 6ebed000   15d000 VBoxOGL-x86.dll

    6e940000 6ea84000   144000 VBoxOGLcrutil-x86.dll

    6eb10000 6ebeb000    db000 wined3dwddm-x86.dll

    6e9b0000 6eb0d000   15d000 VBoxOGL-x86.dll


그러면, RVA는 다음과 같습니다.


0:007> ? @eip-jscript9

Evaluate expression: 797767 = 000c2c47


배열 (추출 되어야 할)의 생성이 다음 breakpoints에 의해 남겨지게 됩니다.


bp jscript9+c2c47 ".printf \"new Array Data: addr = 0x%p\\n\",eax;g"


여기서 우리는 스트링 내부에 쌍따옴표나 역슬래쉬가 있기 때문에 이를 피해 주어야 합니다. 또한, breakpoint가 발생된 뒤에 로그 메시지를 찍고 실행이 멈추게 하지 않기 위해 g (go) 명령이 사용됩니다.

 

이제 우리가 했던 것들로 다시 돌아 가봅니다. 우리는 2개의 hardware breakpoint를 설정했고 첫 번째만 작동이 되었습니다. 자 이제 시작해보죠.

 

F5를 한 번 더 누른 뒤에, 두 번째 breakpoint가 작동하면 콜 스택이 다음과 같습니다.


0:007> k 20

ChildEBP RetAddr  

0671bb8c 6ea82aae jscript9!Js::JavascriptArray::DirectSetItem_Full+0x40b    <----------------

0671bc14 05f2074b jscript9!Js::JavascriptOperators::OP_SetElementI+0x1e0

WARNING: Frame IP not in any known module. Following frames may be wrong.

0671bc48 6ea77461 0x5f2074b

0671bde4 6ea55cf5 jscript9!Js::InterpreterStackFrame::Process+0x4b47

0671bf2c 05f80fe9 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x305

0671bf38 6ea51f60 0x5f80fe9

0671bfb8 6ea520ca jscript9!Js::JavascriptFunction::CallRootFunction+0x140

0671bfd0 6ea5209f jscript9!Js::JavascriptFunction::CallRootFunction+0x19

0671c018 6ea52027 jscript9!ScriptSite::CallRootFunction+0x40

0671c040 6eafdf75 jscript9!ScriptSite::Execute+0x61

0671c0cc 6eafdb57 jscript9!ScriptEngine::ExecutePendingScripts+0x1e9

0671c154 6eafe0b7 jscript9!ScriptEngine::ParseScriptTextCore+0x2ad

0671c1a8 069cb60c jscript9!ScriptEngine::ParseScriptText+0x5b

0671c1e0 069c945d MSHTML!CActiveScriptHolder::ParseScriptText+0x42

0671c230 069bb52f MSHTML!CJScript9Holder::ParseScriptText+0x58

0671c2a4 069cc6a4 MSHTML!CScriptCollection::ParseScriptText+0x1f0

0671c394 069cc242 MSHTML!CScriptData::CommitCode+0x36e

0671c40c 069cbe6e MSHTML!CScriptData::Execute+0x233

0671c420 069c9b49 MSHTML!CHtmScriptParseCtx::Execute+0x89

0671c498 067d77cc MSHTML!CHtmParseBase::Execute+0x17c

0671c4c4 755862fa MSHTML!CHtmPost::Broadcast+0x88

0671c5c4 069c3273 user32!InternalCallWinProc+0x23

0671c5dc 069c31ff MSHTML!CHtmPost::Run+0x1c

0671c5f4 069c34f3 MSHTML!PostManExecute+0x5f

0671c610 069c34b2 MSHTML!PostManResume+0x7b

0671c650 06830dc9 MSHTML!CHtmPost::OnDwnChanCallback+0x3a

0671c660 0677866c MSHTML!CDwnChan::OnMethodCall+0x19

0671c6b4 067784fa MSHTML!GlobalWndOnMethodCall+0x169

0671c700 755862fa MSHTML!GlobalWndProc+0xd7

0671c72c 75586d3a user32!InternalCallWinProc+0x23

0671c7a4 755877c4 user32!UserCallWinProcCheckWow+0x109

0671c804 7558788a user32!DispatchMessageWorker+0x3bc


이 전의 2개의 스택 트레이스와 비교해보면 여전히 같은 jscript9!Js::JavascriptArray::DirectSetItem_Full을 호출함을 볼 수 있습니다. DirectSetItem_Full jscript9!Recycler::AllocZero를 통해 0x1010 블록을 할당하고 객체를 초기화 합니다.

 

하지만 만약 이 모든일이 jscript9!Js::JavascriptArray::DirectSetItem_Full에서 이루어진다면 JavascriptArray 인스턴스는 벌써 생성되었을 것입니다. 생성자에서 멈추고 정말 존재하는지 확인해보도록 하겠습니다.


0:007> x jscript9!Js::JavascriptArray::JavascriptArray

6ea898d6          jscript9!Js::JavascriptArray::JavascriptArray (<no parameter info>)

6ead481d          jscript9!Js::JavascriptArray::JavascriptArray (<no parameter info>)

6eb28b61          jscript9!Js::JavascriptArray::JavascriptArray (<no parameter info>)


우리는 여기서 3개 주소를 얻을 수 있습니다.

 

bc * 명령을 이용하여 이전 breakpoints를 모두 지우고 F5 이후 IE 에서 페이지를 다시 불러옵니다. 첫 번째 메시지 박스가 뜨면 다시 WinDbg로 돌아 갑니다. 이제 아래 3개의 주소에 각각 breakpoint를 설정합니다.


0:006> bp 6ea898d6          

0:006> bp 6ead481d          

0:006> bp 6eb28b61          

0:006> bl

 0 e 6ea898d6     0001 (0001)  0:**** jscript9!Js::JavascriptArray::JavascriptArray

 1 e 6ead481d     0001 (0001)  0:**** jscript9!Js::JavascriptArray::JavascriptArray

 2 e 6eb28b61     0001 (0001)  0:**** jscript9!Js::JavascriptArray::JavascriptArray


F5를 누르고 메시지 박스를 닫습니다. ... Done 박스가 나타나고 어떤 breakpoints 들도 작동하지 않았습니다. 이상하네요... 심볼들의 리스트 중에 뭔가 좀 흥미로운것이 있는지 보도록 하죠.


0:006> x jscript9!Js::JavascriptArray::*

6ec61e36          jscript9!Js::JavascriptArray::IsEnumerable (<no parameter info>)

6eabff71          jscript9!Js::JavascriptArray::GetFromIndex (<no parameter info>)

6ec31bed          jscript9!Js::JavascriptArray::BigIndex::BigIndex (<no parameter info>)

6ec300ee          jscript9!Js::JavascriptArray::SetEnumerable (<no parameter info>)

6eb94bd9          jscript9!Js::JavascriptArray::EntrySome (<no parameter info>)

6eace48c          jscript9!Js::JavascriptArray::HasItem (<no parameter info>)

6ea42530          jscript9!Js::JavascriptArray::`vftable' = <no type information>

6ec31a2f          jscript9!Js::JavascriptArray::BigIndex::SetItem (<no parameter info>)

6ec301d1          jscript9!Js::JavascriptArray::IsDirectAccessArray (<no parameter info>)

6eacab83          jscript9!Js::JavascriptArray::Sort (<no parameter info>)

6ecd5500          jscript9!Js::JavascriptArray::EntryInfo::Map = <no type information>

6eb66721          jscript9!Js::JavascriptArray::EntryIsArray (<no parameter info>)

6ec2fd64          jscript9!Js::JavascriptArray::GetDiagValueString (<no parameter info>)

6ec2faeb          jscript9!Js::JavascriptArray::GetNonIndexEnumerator (<no parameter info>)

6ec3043a          jscript9!Js::JavascriptArray::Unshift<Js::JavascriptArray::BigIndex> (<no parameter info>)

6eb4ba72          jscript9!Js::JavascriptArray::EntryReverse (<no parameter info>)

6eaed10f          jscript9!Js::JavascriptArray::SetLength (<no parameter info>)

6eacaadf          jscript9!Js::JavascriptArray::EntrySort (<no parameter info>)

6ec306c9          jscript9!Js::JavascriptArray::ToLocaleString<Js::JavascriptArray> (<no parameter info>)

6eb5f4ce          jscript9!Js::JavascriptArray::BuildSegmentMap (<no parameter info>)

6ec2fef5          jscript9!Js::JavascriptArray::Freeze (<no parameter info>)

6ec31c5f          jscript9!Js::JavascriptArray::GetLocaleSeparator (<no parameter info>)

6ecd54f0          jscript9!Js::JavascriptArray::EntryInfo::LastIndexOf = <no type information>

6eb9b990          jscript9!Js::JavascriptArray::EntryUnshift (<no parameter info>)

6ec30859          jscript9!Js::JavascriptArray::ObjectSpliceHelper<unsigned int> (<no parameter info>)

6ec31ab5          jscript9!Js::JavascriptArray::BigIndex::operator+ (<no parameter info>)

6ea898d6          jscript9!Js::JavascriptArray::JavascriptArray (<no parameter info>)

6eb5f8f5          jscript9!Js::JavascriptArray::ArrayElementEnumerator::ArrayElementEnumerator (<no parameter info>)

6ec30257          jscript9!Js::JavascriptArray::IndexTrace<unsigned int>::SetItem (<no parameter info>)

6ead481d          jscript9!Js::JavascriptArray::JavascriptArray (<no parameter info>)

6eac281d          jscript9!Js::JavascriptArray::ConcatArgs<unsigned int> (<no parameter info>)

6ecd5510          jscript9!Js::JavascriptArray::EntryInfo::Reduce = <no type information>

6ea9bf88          jscript9!Js::JavascriptArray::DirectSetItem_Full (<no parameter info>)

6eb9d5ee          jscript9!Js::JavascriptArray::EntryConcat (<no parameter info>)

6ecd5490          jscript9!Js::JavascriptArray::EntryInfo::ToString = <no type information>

6eb49e52          jscript9!Js::JavascriptArray::GetEnumerator (<no parameter info>)

6ecd5430          jscript9!Js::JavascriptArray::EntryInfo::Reverse = <no type information>

6eb66c77          jscript9!Js::JavascriptArray::EntryIndexOf (<no parameter info>)

6eb93fa5          jscript9!Js::JavascriptArray::EntryEvery (<no parameter info>)

6ecd53e0          jscript9!Js::JavascriptArray::EntryInfo::IsArray = <no type information>

6ec31e6d          jscript9!Js::JavascriptArray::JoinOtherHelper (<no parameter info>)

6ec31d73          jscript9!Js::JavascriptArray::sort (<no parameter info>)

6eb94d8c          jscript9!Js::JavascriptArray::EntryFilter (<no parameter info>)

6ec32052          jscript9!Js::JavascriptArray::EntryToLocaleString (<no parameter info>)

6ec61e52          jscript9!Js::JavascriptArray::IsConfigurable (<no parameter info>)

6ecd5410          jscript9!Js::JavascriptArray::EntryInfo::Join = <no type information>

6ec31d56          jscript9!Js::JavascriptArray::CompareElements (<no parameter info>)

6eb5f989          jscript9!Js::JavascriptArray::InternalCopyArrayElements<unsigned int> (<no parameter info>)

6eaef6d1          jscript9!Js::JavascriptArray::IsItemEnumerable (<no parameter info>)

6eb9d4cb          jscript9!Js::JavascriptArray::EntrySplice (<no parameter info>)

6eacf7f0          jscript9!Js::JavascriptArray::EntryToString (<no parameter info>)

6eb5f956          jscript9!Js::JavascriptArray::CopyArrayElements (<no parameter info>)

6ec325e0          jscript9!Js::JavascriptArray::PrepareDetach (<no parameter info>)

6ecd53f0          jscript9!Js::JavascriptArray::EntryInfo::Push = <no type information>

6ec30a8b          jscript9!Js::JavascriptArray::ObjectSpliceHelper<Js::JavascriptArray::BigIndex> (<no parameter info>)

6ec301f7          jscript9!Js::JavascriptArray::DirectSetItemIfNotExist (<no parameter info>)

6ec30083          jscript9!Js::JavascriptArray::SetWritable (<no parameter info>)

6ec30019          jscript9!Js::JavascriptArray::SetConfigurable (<no parameter info>)

6ec31b1d          jscript9!Js::JavascriptArray::BigIndex::operator++ (<no parameter info>)

6ecd54b0          jscript9!Js::JavascriptArray::EntryInfo::IndexOf = <no type information>

6eba1498          jscript9!Js::JavascriptArray::EntryPush (<no parameter info>)

6ecd5460          jscript9!Js::JavascriptArray::EntryInfo::Sort = <no type information>

6ec2fcbb          jscript9!Js::JavascriptArray::SetItemAttributes (<no parameter info>)

6ea8497f          jscript9!Js::JavascriptArray::ArrayElementEnumerator::Init (<no parameter info>)

6ecd5350          jscript9!Js::JavascriptArray::EntryInfo::NewInstance = <no type information>

6eac0596          jscript9!Js::JavascriptArray::EntryPop (<no parameter info>)

6ea82f23          jscript9!Js::JavascriptArray::GetItem (<no parameter info>)

6ec2ffb1          jscript9!Js::JavascriptArray::SetAttributes (<no parameter info>)

6eae718b          jscript9!Js::JavascriptArray::GetItemReference (<no parameter info>)

6ec2fd46          jscript9!Js::JavascriptArray::GetDiagTypeString (<no parameter info>)

6eb61889          jscript9!Js::JavascriptArray::DeleteItem (<no parameter info>)

6ecd5450          jscript9!Js::JavascriptArray::EntryInfo::Slice = <no type information>

6ec319be          jscript9!Js::JavascriptArray::BigIndex::SetItemIfNotExist (<no parameter info>)

6ecd5530          jscript9!Js::JavascriptArray::EntryInfo::Some = <no type information>

6eb16a13          jscript9!Js::JavascriptArray::EntryJoin (<no parameter info>)

6ecd5470          jscript9!Js::JavascriptArray::EntryInfo::Splice = <no type information>

6ec2fc89          jscript9!Js::JavascriptArray::SetItemAccessors (<no parameter info>)

6ec2ff1d          jscript9!Js::JavascriptArray::Seal (<no parameter info>)

6eb5b713          jscript9!Js::JavascriptArray::GetItemSetter (<no parameter info>)

6eb49dc0          jscript9!Js::JavascriptArray::GetEnumerator (<no parameter info>)

6ec30284          jscript9!Js::JavascriptArray::InternalCopyArrayElements<Js::JavascriptArray::BigIndex> (<no parameter info>)

6ec318bb          jscript9!Js::JavascriptArray::BigIndex::DeleteItem (<no parameter info>)

6eb94158          jscript9!Js::JavascriptArray::EntryLastIndexOf (<no parameter info>)

6eba4b06          jscript9!Js::JavascriptArray::NewInstance (<no parameter info>)  <---------------------

6ecd5520          jscript9!Js::JavascriptArray::EntryInfo::ReduceRight = <no type information>

6ecd54e0          jscript9!Js::JavascriptArray::EntryInfo::ForEach = <no type information>

6ec31d27          jscript9!Js::JavascriptArray::EnforceCompatModeRestrictions (<no parameter info>)

6ecd5440          jscript9!Js::JavascriptArray::EntryInfo::Shift = <no type information>

6eab5de1          jscript9!Js::JavascriptArray::SetProperty (<no parameter info>)

6ecd5400          jscript9!Js::JavascriptArray::EntryInfo::Concat = <no type information>

6ea5b329          jscript9!Js::JavascriptArray::GetProperty (<no parameter info>)

6ec2ff43          jscript9!Js::JavascriptArray::SetAccessors (<no parameter info>)

6ec2fcea          jscript9!Js::JavascriptArray::SetItemWithAttributes (<no parameter info>)

6ea4768d          jscript9!Js::JavascriptArray::IsObjectArrayFrozen (<no parameter info>)

6eae0c2c          jscript9!Js::JavascriptArray::GetNextIndex (<no parameter info>)

6eab5c21          jscript9!Js::JavascriptArray::Is (<no parameter info>)

6ec3177e          jscript9!Js::JavascriptArray::CopyArrayElements (<no parameter info>)

6ec3251d          jscript9!Js::JavascriptArray::SetLength (<no parameter info>)

6eb28b61          jscript9!Js::JavascriptArray::JavascriptArray (<no parameter info>)

6eaeb83a          jscript9!Js::JavascriptArray::ArraySpliceHelper (<no parameter info>)

6eac3a16          jscript9!Js::JavascriptArray::AllocateHead (<no parameter info>)

6eaffed4          jscript9!Js::JavascriptArray::SetPropertyWithAttributes (<no parameter info>)

6ead00ce          jscript9!Js::JavascriptArray::HasProperty (<no parameter info>)

6ecd54d0          jscript9!Js::JavascriptArray::EntryInfo::Filter = <no type information>

6ec3190f          jscript9!Js::JavascriptArray::BigIndex::SetItem (<no parameter info>)

6eae60d3          jscript9!Js::JavascriptArray::EntryMap (<no parameter info>)

6eb16a9c          jscript9!Js::JavascriptArray::JoinHelper (<no parameter info>)

6ec31b46          jscript9!Js::JavascriptArray::BigIndex::ToNumber (<no parameter info>)

6ea84a80          jscript9!Js::JavascriptArray::ArrayElementEnumerator::ArrayElementEnumerator (<no parameter info>)

6ea8495b          jscript9!Js::JavascriptArray::IsAnyArrayTypeId (<no parameter info>)

6ec2fd1c          jscript9!Js::JavascriptArray::GetSpecialNonEnumerablePropertyName (<no parameter info>)

6ec31bd5          jscript9!Js::JavascriptArray::BigIndex::IsSmallIndex (<no parameter info>)

6eba157a          jscript9!Js::JavascriptArray::EntryForEach (<no parameter info>)

6ea83044          jscript9!Js::JavascriptArray::SetItem (<no parameter info>)

6ec3050a          jscript9!Js::JavascriptArray::ToLocaleString<Js::RecyclableObject> (<no parameter info>)

6ea534e0          jscript9!Js::JavascriptArray::DirectGetItemAt (<no parameter info>)

6ecd5420          jscript9!Js::JavascriptArray::EntryInfo::Pop = <no type information>

6ea59b2d          jscript9!Js::JavascriptArray::ForInLoop (<no parameter info>)

6eafff78          jscript9!Js::JavascriptArray::GetSetter (<no parameter info>)

6eb4ec30          jscript9!Js::JavascriptArray::ArraySegmentSpliceHelper (<no parameter info>)

6eb78e45          jscript9!Js::JavascriptArray::EntryReduce (<no parameter info>)

6eb6697d          jscript9!Js::JavascriptArray::DirectGetItemAtFull (<no parameter info>)

6ec32167          jscript9!Js::JavascriptArray::EntryReduceRight (<no parameter info>)

6eba717f          jscript9!Js::JavascriptArray::EntryShift (<no parameter info>)

6eb99706          jscript9!Js::JavascriptArray::MarshalToScriptContext (<no parameter info>)

6ecd54c0          jscript9!Js::JavascriptArray::EntryInfo::Every = <no type information>

6ec3196b          jscript9!Js::JavascriptArray::BigIndex::DeleteItem (<no parameter info>)

6eb7c0ba          jscript9!Js::JavascriptArray::PreventExtensions (<no parameter info>)

6ecd5480          jscript9!Js::JavascriptArray::EntryInfo::ToLocaleString = <no type information>

6eb93f8b          jscript9!Js::JavascriptArray::DeleteProperty (<no parameter info>)

6ec303b9          jscript9!Js::JavascriptArray::Unshift<unsigned int> (<no parameter info>)

6ea849d5          jscript9!Js::JavascriptArray::FillFromPrototypes (<no parameter info>)

6ea5b3cf          jscript9!Js::JavascriptArray::GetPropertyReference (<no parameter info>)

6ec317e1          jscript9!Js::JavascriptArray::TruncateToProperties (<no parameter info>)

6eabfc81          jscript9!Js::JavascriptArray::EntrySlice (<no parameter info>)

6eae20b0          jscript9!Js::JavascriptArray::JoinToString (<no parameter info>)

6ec30ca8          jscript9!Js::JavascriptArray::ConcatArgs<Js::JavascriptArray::BigIndex> (<no parameter info>)

6ea5c2be          jscript9!Js::JavascriptArray::OP_NewScArray (<no parameter info>)

6eb1682e          jscript9!Js::JavascriptArray::JoinArrayHelper (<no parameter info>)

6ec31f63          jscript9!Js::JavascriptArray::GetFromLastIndex (<no parameter info>)

6eb618a1          jscript9!Js::JavascriptArray::DirectDeleteItemAt (<no parameter info>)

6ead497d          jscript9!Js::JavascriptArray::MakeCopyOnWriteObject (<no parameter info>)

6eb4c512          jscript9!Js::JavascriptArray::EnsureHeadStartsFromZero (<no parameter info>)

6ec31c24          jscript9!Js::JavascriptArray::ToLocaleStringHelper (<no parameter info>)

6eae0be6          jscript9!Js::JavascriptArray::GetBeginLookupSegment (<no parameter info>)

6ecd54a0          jscript9!Js::JavascriptArray::EntryInfo::Unshift = <no type information>

아래의 심볼이 괜찮아 보입니다.


6eba4b06          jscript9!Js::JavascriptArray::NewInstance (<no parameter info>)


해당 위치에 breakpoint를 설정하고 우리의 운을 시험해 봅시다.


0:006> bc *

0:006> bp jscript9!Js::JavascriptArray::NewInstance


IE 에서 발생된 메시지를 닫고 페이지를 다시 부른뒤에 start 메시지 박스를 닫습니다. 이번엔 모든것이 계획대로 동작한 것 같습니다.



코드를 따라가다 보면 다음 코드를 볼 수 있습니다.


6eb02a3c 682870a46e      push    offset jscript9!Recycler::Alloc (6ea47028)

6eb02a41 ff770c          push    dword ptr [edi+0Ch]

6eb02a44 6a20            push    20h

6eb02a46 e84546f4ff      call    jscript9!operator new<Recycler> (6ea47090)     <-------------------

6eb02a4b 8bf0            mov     esi,eax   <--------- ESI = allocated block

6eb02a4d 83c40c          add     esp,0Ch

6eb02a50 85f6            test    esi,esi

6eb02a52 0f841d210a00    je      jscript9!Js::JavascriptArray::NewInstance+0x390 (6eba4b75)

6eb02a58 8b8f00010000    mov     ecx,dword ptr [edi+100h]

6eb02a5e 894e04          mov     dword ptr [esi+4],ecx

6eb02a61 c706b02fa46e    mov     dword ptr [esi],offset jscript9!Js::DynamicObject::`vftable' (6ea42fb0)

6eb02a67 c7460800000000  mov     dword ptr [esi+8],0

6eb02a6e c7460c01000000  mov     dword ptr [esi+0Ch],1

6eb02a75 8b4118          mov     eax,dword ptr [ecx+18h]

6eb02a78 8a4005          mov     al,byte ptr [eax+5]


할당 연산은 다음과 같이 호출됩니다.


operator new(20h, arg, jscript9!Recycler::Alloc);


할당 연산의 코드를 보면 다음과 같습니다.


jscript9!operator new<Recycler>:

6ea47090 8bff            mov     edi,edi

6ea47092 55              push    ebp

6ea47093 8bec            mov     ebp,esp

6ea47095 ff7508          push    dword ptr [ebp+8]      <----- push 20h

6ea47098 8b4d0c          mov     ecx,dword ptr [ebp+0Ch]

6ea4709b ff5510          call    dword ptr [ebp+10h]    <----- call jscript9!Recycler::Alloc

6ea4709e 5d              pop     ebp

6ea4709f c3              ret


main 코드로 돌아 가보면


6eb02a3c 682870a46e      push    offset jscript9!Recycler::Alloc (6ea47028)

6eb02a41 ff770c          push    dword ptr [edi+0Ch]

6eb02a44 6a20            push    20h

6eb02a46 e84546f4ff      call    jscript9!operator new<Recycler> (6ea47090)     <-------------------

6eb02a4b 8bf0            mov     esi,eax   <--------- ESI = allocated block

6eb02a4d 83c40c          add     esp,0Ch

6eb02a50 85f6            test    esi,esi

6eb02a52 0f841d210a00    je      jscript9!Js::JavascriptArray::NewInstance+0x390 (6eba4b75)

6eb02a58 8b8f00010000    mov     ecx,dword ptr [edi+100h]

6eb02a5e 894e04          mov     dword ptr [esi+4],ecx

6eb02a61 c706b02fa46e    mov     dword ptr [esi],offset jscript9!Js::DynamicObject::`vftable' (6ea42fb0)

6eb02a67 c7460800000000  mov     dword ptr [esi+8],0

6eb02a6e c7460c01000000  mov     dword ptr [esi+0Ch],1

6eb02a75 8b4118          mov     eax,dword ptr [ecx+18h]

6eb02a78 8a4005          mov     al,byte ptr [eax+5]

6eb02a7b a808            test    al,8

6eb02a7d 0f85e8200a00    jne     jscript9!Js::JavascriptArray::NewInstance+0x386 (6eba4b6b)

6eb02a83 b803000000      mov     eax,3

6eb02a88 89460c          mov     dword ptr [esi+0Ch],eax

6eb02a8b 8b4104          mov     eax,dword ptr [ecx+4] ds:002b:060e9a64=060fb000

6eb02a8e 8b4004          mov     eax,dword ptr [eax+4]

6eb02a91 8b4918          mov     ecx,dword ptr [ecx+18h]

6eb02a94 8bb864040000    mov     edi,dword ptr [eax+464h]

6eb02a9a 8b01            mov     eax,dword ptr [ecx]

6eb02a9c ff5014          call    dword ptr [eax+14h]

6eb02a9f 8b4e04          mov     ecx,dword ptr [esi+4]

6eb02aa2 8b4918          mov     ecx,dword ptr [ecx+18h]

6eb02aa5 8b4908          mov     ecx,dword ptr [ecx+8]

6eb02aa8 3bc1            cmp     eax,ecx

6eb02aaa 0f8f0d9f1900    jg      jscript9!memset+0x31562 (6ec9c9bd)

6eb02ab0 8b4604          mov     eax,dword ptr [esi+4]

6eb02ab3 c7063025a46e    mov     dword ptr [esi],offset jscript9!Js::JavascriptArray::`vftable' (6ea42530)

6eb02ab9 c7461c00000000  mov     dword ptr [esi+1Ch],0

6eb02ac0 8b4004          mov     eax,dword ptr [eax+4]


여기서 중요한 명령은 다음과 같습니다.


6eb02ab3 c7063025a46e    mov     dword ptr [esi],offset jscript9!Js::JavascriptArray::`vftable' (6ea42530)


이것은 메모리 블록의 첫 dword JavascriptArray vftable로 덮어 씁니다.

 

또 다른 중요한 코드는 다음과 같습니다.


6eb02ac3 8b4004          mov     eax,dword ptr [eax+4]

6eb02ac6 8b8864040000    mov     ecx,dword ptr [eax+464h]

6eb02acc 6a50            push    50h        <------- 50h bytes?

6eb02ace c7461000000000  mov     dword ptr [esi+10h],0

6eb02ad5 e80769f4ff      call    jscript9!Recycler::AllocZero (6ea493e1)    <------ allocates a block

6eb02ada c70000000000    mov     dword ptr [eax],0

6eb02ae0 c7400400000000  mov     dword ptr [eax+4],0

6eb02ae7 c7400810000000  mov     dword ptr [eax+8],10h

6eb02aee c7400c00000000  mov     dword ptr [eax+0Ch],0

6eb02af5 894618          mov     dword ptr [esi+18h],eax   <------ look at the following picture

6eb02af8 894614          mov     dword ptr [esi+14h],eax   <------ look at the following picture

6eb02afb e951200a00      jmp     jscript9!Js::JavascriptArray::NewInstance+0x24f (6eba4b51)


아래 그림은 코드에서 어떤일이 벌어 지는지 보여줍니다.



이제 우리는 2개의 중요한 주소를 얻었습니다.


239d9340          address of the JavascriptArray

2c1460a0          structure pointed to by the JavascriptArray


breakpoint를 지우고 프로그램을 계속 진행 시킵니다. Done 메시지 박스가 뜨면 WinDbg로 돌아갑니다. WinDbg에서 실행을 멈추고 239d9340h 주소를 살펴봅니다.



보시다시피, 우리의 JavascriptArray (오프셋 0x14 0x18)는 다른 주소를 가리키고 있습니다. JavascriptArray는 커질 수 있기 때문에 만약 더 큰 버퍼가 할당 된다면 0x14 0x18의 포인터는 새로운 버퍼를 가리키도록 갱신됩니다. 239d9340에 있는 JavascriptArray javascript 코드의 배열 a와 동일합니다. 이는 다른 배열들을 가리키는 10000h 개의 참조를 가지고 있습니다.

 

JavascriptArray 객체 jscript9!Js::JavascriptArray::NewInstance에서 할당 됩니다.


6eb02a46 e84546f4ff      call    jscript9!operator new<Recycler> (6ea47090)     <-------------------

6eb02a4b 8bf0            mov     esi,eax   <--------- ESI = allocated block


만약 이 시점에서 jscript9!Js::JavascriptArray::NewInstance에서 Shift + F11로 빠져 나오면 다음과 같은 코드를 볼 수 있습니다.


6ea125cc ff75ec          push    dword ptr [ebp-14h]

6ea125cf ff75e8          push    dword ptr [ebp-18h]

6ea125d2 ff55e4          call    dword ptr [ebp-1Ch]   (jscript9!Js::JavascriptArray::NewInstance)

6ea125d5 8b65e0          mov     esp,dword ptr [ebp-20h] ss:002b:04d2c0e0=04d2c0c4


NewInstance 호출 이후 EAX JavascriptArray 구조를 가리키고 있습니다. 따라서, 6eb02a4b 또는 6ea125d5 breakpoint를 설정합니다. 후자를 선택해보죠.


bp jscript9+425d5 ".printf \"new Array: addr = 0x%p\\n\",eax;g"


여기까지 우리가 알 수 있는 것은 다음과 같습니다.



LargeHeapBlock


LargeHeapBlock이 뭘까요? 관련된 심볼들을 찾아 보도록 하겠습니다.


0:007> x jscript9!*largeheapblock*

6f696af3          jscript9!HeapInfo::DeleteLargeHeapBlockList (<no parameter info>)

6f5d654d          jscript9!HeapInfo::ReinsertLargeHeapBlock (<no parameter info>)

6f6a8699          jscript9!LargeHeapBlock::SweepObjects<2> (<no parameter info>)

6f6ab0cf          jscript9!LargeHeapBlock::IsValidObject (<no parameter info>)

6f6a82a8          jscript9!LargeHeapBlock::SweepObjects<1> (<no parameter info>)

6f755d4d          jscript9!LargeHeapBlock::GetHeader (<no parameter info>)

6f5a160e          jscript9!LargeHeapBlock::ResetMarks (<no parameter info>)

6f5a0672          jscript9!LargeHeapBlock::Rescan (<no parameter info>)

6f59f32f          jscript9!LargeHeapBlock::IsObjectMarked (<no parameter info>)

6f59a7ca          jscript9!HeapInfo::AddLargeHeapBlock (<no parameter info>)    <------------------------

6f657a87          jscript9!LargeHeapBlock::AddObjectToFreeList (<no parameter info>)

6f755f80          jscript9!LargeHeapBlock::Alloc (<no parameter info>)    <--------------------------

6f755dba          jscript9!LargeHeapBlock::GetObjectHeader (<no parameter info>)

6f755b43          jscript9!HeapBucket::EnumerateObjects<LargeHeapBlock> (<no parameter info>)

6f755daf          jscript9!LargeHeapBlock::GetRealAddressFromInterior (<no parameter info>)

6f755dee          jscript9!LargeHeapBlock::SetMemoryProfilerOldObjectBit (<no parameter info>)

6f755d9b          jscript9!LargeHeapBlock::GetObjectSize (<no parameter info>)

6f5a096b          jscript9!HeapInfo::Rescan<LargeHeapBlock> (<no parameter info>)

6f696b24          jscript9!LargeHeapBlock::ReleasePagesShutdown (<no parameter info>)

6f755e23          jscript9!LargeHeapBlock::SetObjectMarkedBit (<no parameter info>)

6f755eaf          jscript9!LargeHeapBlock::FinalizeObjects (<no parameter info>)

6f59ef52          jscript9!LargeHeapBlock::SweepObjects<0> (<no parameter info>)

6f755e66          jscript9!LargeHeapBlock::TestObjectMarkedBit (<no parameter info>)

6f755daf          jscript9!LargeHeapBlock::MarkInterior (<no parameter info>)

6f596e18          jscript9!LargeHeapBlock::`vftable' = <no type information>


가장 유력한 함수들은 다음과 같습니다.


6f59a7ca          jscript9!HeapInfo::AddLargeHeapBlock (<no parameter info>)

6f755f80          jscript9!LargeHeapBlock::Alloc (<no parameter info>)


두 함수에 모두 breakpoint를 걸고 IE 에서 페이지를 다시 불러옵니다. Start 메시지 박스가 뜨면 첫 번째 breakpoint가 작동되며 다음 위치에 다다르게 됩니다.


6f59a7c5 90              nop

6f59a7c6 90              nop

6f59a7c7 90              nop

6f59a7c8 90              nop

6f59a7c9 90              nop

jscript9!HeapInfo::AddLargeHeapBlock:

6f59a7ca 8bff            mov     edi,edi     <------------ we are here

6f59a7cc 55              push    ebp

6f59a7cd 8bec            mov     ebp,esp

6f59a7cf 83ec1c          sub     esp,1Ch

6f59a7d2 53              push    ebx

6f59a7d3 56              push    esi

6f59a7d4 8b750c          mov     esi,dword ptr [ebp+0Ch]


스택 트레이스를 보면 다음과 같습니다.


0:007> k 10

ChildEBP RetAddr  

04dbbc90 6f59a74d jscript9!HeapInfo::AddLargeHeapBlock

04dbbcb4 6f5a72d8 jscript9!Recycler::LargeAlloc+0x66

04dbbcd0 6f652c47 jscript9!Recycler::AllocZero+0x91

04dbbd10 6f5d2aae jscript9!Js::JavascriptArray::DirectSetItem_Full+0x3fd

04dbbd98 6f5fed13 jscript9!Js::JavascriptOperators::OP_SetElementI+0x1e0

04dbbf34 6f5a5cf5 jscript9!Js::InterpreterStackFrame::Process+0x3579

04dbc084 03fd0fe9 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x305

WARNING: Frame IP not in any known module. Following frames may be wrong.

04dbc090 6f5a1f60 0x3fd0fe9

04dbc110 6f5a20ca jscript9!Js::JavascriptFunction::CallRootFunction+0x140

04dbc128 6f5a209f jscript9!Js::JavascriptFunction::CallRootFunction+0x19

04dbc170 6f5a2027 jscript9!ScriptSite::CallRootFunction+0x40

04dbc198 6f64df75 jscript9!ScriptSite::Execute+0x61

04dbc224 6f64db57 jscript9!ScriptEngine::ExecutePendingScripts+0x1e9

04dbc2ac 6f64e0b7 jscript9!ScriptEngine::ParseScriptTextCore+0x2ad

04dbc300 6e2db60c jscript9!ScriptEngine::ParseScriptText+0x5b

04dbc338 6e2d945d MSHTML!CActiveScriptHolder::ParseScriptText+0x42


매우 흥미롭군요! LargeHeapBlock LargeAlloc (AllocZero라 불리는)에 의해 생성되며 JavascriptArray의 첫 번째 항목이 할당됩니다. Shift + F11 AddLargeHeapBlock을 나오고 EAX가 가리키는 메모리를 살펴보면 다음과 같습니다.


0:007> dd eax

25fcbe80  6f596e18 00000003 046b1000 00000002

25fcbe90  00000000 00000000 00000004 046b1000

25fcbea0  046b3000 25fcbee0 00000000 00000000

25fcbeb0  00000000 00000000 04222e98 00000000

25fcbec0  00000000 00000000 00000000 00000004

25fcbed0  00000000 00000000 734a1523 8c000000

25fcbee0  6f596e18 00000003 046a6000 00000003

25fcbef0  00000002 00000000 00000004 046a8820

0:007> ln poi(eax)

(6f596e18)   jscript9!LargeHeapBlock::`vftable'   |  (6f596e3c)   jscript9!PageSegment::`vftable'

Exact matches:

    jscript9!LargeHeapBlock::`vftable' = <no type information>


EAX는 방금 생성된 LargeHeapBlock을 가리키고 있습니다. 이 블록이 heap에 직접 할당되는지 확인해보도록 하겠습니다.


0:007> !heap -p -a @eax

    address 25fcbe80 found in

    _HEAP @ 300000

      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state

        25fcbe78 000c 0000  [00]   25fcbe80    00054 - (busy)

          jscript9!LargeHeapBlock::`vftable'


예쓰! 크기는 0x54 바이트이며 할당 헤더 8바이트 (UserPtr – HEAP_ENTRY == 8)앞에 존재합니다. 이부분이 우리가 알아야할 전부입니다.

 

이제 AddLargeHeapBlock 바로 직후에 breakpoint를 설정합니다.


bp jscript9!Recycler::LargeAlloc+0x66 ".printf \"new LargeHeapBlock: addr = 0x%p\\n\",eax;g"


LargeHeapblock을 보면, 먼저 자바스크립트 코드를 좀 수정하여 좀 더 적은 LargeHeapBlock이 생성되록 합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>
<head>
<script language="javascript">
  alert("Start");
  var a = new Array();
  for (var i = 0; i < 0x100++i) {     // <------ just 0x100
    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>
cs


방금 위치에 breakpoint를 설정합니다.



bp jscript9!Recycler::LargeAlloc+0x66 ".printf \"new LargeHeapBlock: addr = 0x%p\\n\",eax;g"


이제 IE에서 페이지를 다시 불러오고 첫 번째 메시지 박스를 닫습니다.

 

출력이 아래와 유사하게 나올 겁니다.


new LargeHeapBlock: addr = 0x042a7368

new LargeHeapBlock: addr = 0x042a73c8

new LargeHeapBlock: addr = 0x042a7428

new LargeHeapBlock: addr = 0x042a7488

new LargeHeapBlock: addr = 0x042a74e8

new LargeHeapBlock: addr = 0x042a7548

new LargeHeapBlock: addr = 0x042a75a8

new LargeHeapBlock: addr = 0x042a7608

new LargeHeapBlock: addr = 0x042a7668

new LargeHeapBlock: addr = 0x042a76c8


<생략>


new LargeHeapBlock: addr = 0x1364ede0

new LargeHeapBlock: addr = 0x1364ee40

new LargeHeapBlock: addr = 0x1364eea0

new LargeHeapBlock: addr = 0x1364ef00

new LargeHeapBlock: addr = 0x1364ef60

new LargeHeapBlock: addr = 0x1364efc0

new LargeHeapBlock: addr = 0x1364f060

new LargeHeapBlock: addr = 0x1364f0c0

new LargeHeapBlock: addr = 0x1364f120

new LargeHeapBlock: addr = 0x1364f180

new LargeHeapBlock: addr = 0x1364f1e0

new LargeHeapBlock: addr = 0x1364f240

new LargeHeapBlock: addr = 0x1364f2a0

new LargeHeapBlock: addr = 0x1364f300

new LargeHeapBlock: addr = 0x1364f360

new LargeHeapBlock: addr = 0x1364f3c0


마지막 6개 주소를 보면


new LargeHeapBlock: addr = 0x1364f1e0

new LargeHeapBlock: addr = 0x1364f240

new LargeHeapBlock: addr = 0x1364f2a0

new LargeHeapBlock: addr = 0x1364f300

new LargeHeapBlock: addr = 0x1364f360

new LargeHeapBlock: addr = 0x1364f3c0


첫 번째로, 이들은 0x08 바이트는 할당 해더이고 0x58 LargeHeapBlock 객체 0x60 바이트를 갖습니다. 메모리의 마지막 6 LargeHeapBlocks를 보시면 다음과 같습니다.



보시다시피, 각각의 LargeHeapBlock 0x24 오프셋 위치에 이전 LargeHeapBlock을 가리키고 있습니다. 이 포인터는 추후에 LargeHeapBlock 자기 자신의 주소를 결정하는데 사용됩니다.


ArrayBuffer & Int32Array 


MDN (Mozilla Developer Network)에서는 ArrayBuffer에 대해 다음과 같이 설명합니다.


ArrayBuffer 객체는 고정된 크기의 바이너리 데이터 버퍼를 표현하는데 사용됩니다. ArrayBuffer의 내용은 직접 수정할 수는 없고 특정 포멧의 DataView 객체 typed array 객체를 생성하여 버퍼의 내용을 읽거나 쓸수 있습니다.



아래 예를 보시기 바랍니다.


1
2
3
4
5
6
// This creates an ArrayBuffer manually.
buf = new ArrayBuffer(400*1024*1024);
= new Int32Array(buf);
 
// This creates an ArrayBuffer automatically.
a2 = new Int32Array(100*1024*1024);
cs


배열 a와 배열 a2는 동일하고 같은 크기를 갖습니다. ArrayBuffer를 직접 생성할 때, 바이트 단위로 크기를 지정해주어야 하고 Int32Array를 생성할 때, 요소들(32비트 정수)의 수를 명시합니다. Int32Array를 생성할 때, ArrayBuffer가 내부적으로 생성되며 Int32Array에서 사용됩니다.

 

어떤 코드에서 ArrayBuffer를 생성하는지 확인하기 위해, 이전과 동일하게 힙 스프레잉을 합니다. 다음과 같은 javascript 코드를 이용합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<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>
cs


Done 메시지 박스가 뜨면 VMMap에서 다음과 같은 메모리 상태를 볼 수 있습니다.



이번에는 Heap (Private Data)라고 하는데 이는 힙에 ArrayBuffer가 직접 할당되었음을 뜻합니다. WinDbg에서 f650000를 살펴보면


0f650000: 03964205 0101f3c5 ffeeffee 00000000 10620010 0e680010 00450000 0f650000

0f650020: 00000fd0 0f650040 10620000 0000000f 00000001 00000000 10610ff0 10610ff0

0f650040: 839ec20d 0801f3cd 0a73f528 0c6dcc48 00000012 f0e0d0c0 39682cf0 88000000

0f650060: 00000123 00000123 00000123 00000123 00000123 00000123 00000123 00000123

0f650080: 00000123 00000123 00000123 00000123 00000123 00000123 00000123 00000123

0f6500a0: 00000123 00000123 00000123 00000123 00000123 00000123 00000123 00000123

0f6500c0: 00000123 00000123 00000123 00000123 00000123 00000123 00000123 00000123

0f6500e0: 00000123 00000123 00000123 00000123 00000123 00000123 00000123 00000123

우리의 데이터가 f650060 에서 시작하고 이는 힙 이기 때문에 !heap 을 사용합니다.


0:012> !heap -p -a f650060

    address 0f650060 found in

    _HEAP @ 450000

      HEAP_ENTRY Size Prev Flags    UserPtr UserSize - state

        0f650058 0201 0000  [00]   0f650060    01000 - (busy)


항상 그렇듯, 할당 헤더 8바이트가 존재합니다. IE 에서 페이지를 다시 부르고 WinDbg로 돌아 가면 변경사항이 없음을 확인할 수 있습니다.


0f650000: 03964205 0101f3c5 ffeeffee 00000000 10620010 0e680010 00450000 0f650000

0f650020: 00000fd0 0f650040 10620000 000000cc 00000004 00000000 10310ff0 10610ff0

0f650040: 839ec20d 0801f3cd 129e0158 11119048 00000012 f0e0d0c0 2185d880 88000000

0f650060: 00000123 00000123 00000123 00000123 00000123 00000123 00000123 00000123

0f650080: 00000123 00000123 00000123 00000123 00000123 00000123 00000123 00000123

0f6500a0: 00000123 00000123 00000123 00000123 00000123 00000123 00000123 00000123

0f6500c0: 00000123 00000123 00000123 00000123 00000123 00000123 00000123 00000123

0f6500e0: 00000123 00000123 00000123 00000123 00000123 00000123 00000123 00000123


이는 0f650058 (HEAP_ENTRY) hardware breakpoint를 설정할 수 있고 힙에 할당하는 코드에서 멈출수 있음을 뜻합니다. IE 에서 페이지를 다시 불러와 WinDbg에서 다음과 같이 breakpoint를 설정합니다.


0:013> ba w4 f650058


IE에서 메시지 박스를 닫은 뒤, 우리는 다음 위치에 멈춰 있습니다.


772179ff 331da4002e77    xor     ebx,dword ptr [ntdll!RtlpLFHKey (772e00a4)]

77217a05 c6410780        mov     byte ptr [ecx+7],80h

77217a09 33d8            xor     ebx,eax

77217a0b 33de            xor     ebx,esi

77217a0d ff4df4          dec     dword ptr [ebp-0Ch]

77217a10 8919            mov     dword ptr [ecx],ebx

77217a12 c60200          mov     byte ptr [edx],0           ds:002b:0f65005e=00  <----------- we are here

77217a15 75be            jne     ntdll!RtlpSubSegmentInitialize+0xe5 (772179d5)

77217a17 8b5d08          mov     ebx,dword ptr [ebp+8]

77217a1a 8b45f8          mov     eax,dword ptr [ebp-8]

77217a1d baffff0000      mov     edx,0FFFFh

77217a22 66895108        mov     word ptr [ecx+8],dx

77217a26 668b4df0        mov     cx,word ptr [ebp-10h]

77217a2a 66894e10        mov     word ptr [esi+10h],cx


스택 트레이스는 다음과 같습니다.


0:004> k 10

ChildEBP RetAddr  

057db90c 77216e87 ntdll!RtlpSubSegmentInitialize+0x122

057db9a8 7720e0f2 ntdll!RtlpLowFragHeapAllocFromContext+0x882

057dba1c 75de9d45 ntdll!RtlAllocateHeap+0x206

057dba3c 6f7f4613 msvcrt!malloc+0x8d

057dba4c 6f643cfa jscript9!memset+0x3a4c2

057dba64 6f79fc00 jscript9!Js::JavascriptArrayBuffer::Create+0x3c   <----------------

057dba90 6f79af10 jscript9!Js::TypedArrayBase::CreateNewInstance+0x1cf   <----------------

057dbb08 6f5c7461 jscript9!Js::TypedArray<int>::NewInstance+0x55   <----------------

057dbca4 6f5a5cf5 jscript9!Js::InterpreterStackFrame::Process+0x4b47

057dbdd4 04a70fe9 jscript9!Js::InterpreterStackFrame::InterpreterThunk<1>+0x305

WARNING: Frame IP not in any known module. Following frames may be wrong.

057dbde0 6f5a1f60 0x4a70fe9

057dbe60 6f5a20ca jscript9!Js::JavascriptFunction::CallRootFunction+0x140

057dbe78 6f5a209f jscript9!Js::JavascriptFunction::CallRootFunction+0x19

057dbec0 6f5a2027 jscript9!ScriptSite::CallRootFunction+0x40

057dbee8 6f64df75 jscript9!ScriptSite::Execute+0x61

057dbf74 6f64db57 jscript9!ScriptEngine::ExecutePendingScripts+0x1e9


완벽합니다! ArrayBuffer C malloc에 의해 할당되는 것을 볼 수 있습니다이것은jscript9!Js::JavascriptArrayBuffer::Create.TypedArray<int> TypedArrayBase 내부에서 호출되었는데 아마 우리가 넣은 Int32Array와 이것의 기본 클래스 일것 입니다.

 

따라서, jscript9!Js::TypedArray<int>::NewInstance는 새로운 Int32Array와 새로운 JavascriptArrayBuffer를 생성합니다. 이제 우리는 메모리에서 Int32Array를 볼 수 있습니다. 이제 우리는 더이상 힙에 스프레잉 할 필요가 없고 코드를 약간 바꿔줍니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
<html>
<head>
<script language="javascript">
  alert("Start");
  a = new Int32Array(0x1000);
  for (var j = 0; j < a.length++j)
    a[j] = 0x123;
  alert("Done");
</script>
</head>
<body>
</body>
</html>
cs


새로운 Int32Array의 생성에 breakpoint를 설정합니다.


0:013> bp jscript9!Js::TypedArray<int>::NewInstance

Couldn't resolve error at 'jscript9!Js::TypedArray<int>::NewInstance'

The breakpoint expression "jscript9!Js::TypedArray<int>::NewInstance" evaluates to the inline function.

Please use bm command to set breakpoints instead of bp.


bm 명령어를 사용해보도록 하겠습니다.


0:013> bm jscript9!Js::TypedArray<int>::NewInstance

  1: 6f79aebb          @!"jscript9!Js::TypedArray<int>::NewInstance"

0:013> bl

 1 e 6f79aebb     0001 (0001)  0:**** jscript9!Js::TypedArray<int>::NewInstance


잘 동작하는 것 같습니다. IE에서 페이지를 다시 불러옵니다. 메시지 박스를 닫으면 jscript9!::Js::TypedArray<int>::NewInstance에서 멈추게 됩니다. 아래는 전체 함수에 대한 내용입니다.


0:004> uf 6f79aebb

jscript9!Js::TypedArray<int>::NewInstance:

6f79aebb 8bff            mov     edi,edi

6f79aebd 55              push    ebp

6f79aebe 8bec            mov     ebp,esp

6f79aec0 83e4f8          and     esp,0FFFFFFF8h

6f79aec3 83ec0c          sub     esp,0Ch

6f79aec6 53              push    ebx

6f79aec7 8b5d08          mov     ebx,dword ptr [ebp+8]

6f79aeca 8b4304          mov     eax,dword ptr [ebx+4]

6f79aecd 8b4004          mov     eax,dword ptr [eax+4]

6f79aed0 8b4804          mov     ecx,dword ptr [eax+4]

6f79aed3 56              push    esi

6f79aed4 57              push    edi

6f79aed5 6a00            push    0

6f79aed7 51              push    ecx

6f79aed8 8b8934020000    mov     ecx,dword ptr [ecx+234h]

6f79aede ba00040000      mov     edx,400h

6f79aee3 e8b2e7e0ff      call    jscript9!ThreadContext::ProbeStack (6f5a969a)

6f79aee8 8d4510          lea     eax,[ebp+10h]

6f79aeeb 50              push    eax

6f79aeec 8d7d0c          lea     edi,[ebp+0Ch]

6f79aeef 8d742414        lea     esi,[esp+14h]

6f79aef3 e8cb93e0ff      call    jscript9!Js::ArgumentReader::ArgumentReader (6f5a42c3)

6f79aef8 8b4304          mov     eax,dword ptr [ebx+4]

6f79aefb 8b4004          mov     eax,dword ptr [eax+4]

6f79aefe 6850bd726f      push    offset jscript9!Js::TypedArray<int>::Create (6f72bd50)

6f79af03 6a04            push    4

6f79af05 ff7004          push    dword ptr [eax+4]

6f79af08 8bc6            mov     eax,esi

6f79af0a 50              push    eax

6f79af0b e8214b0000      call    jscript9!Js::TypedArrayBase::CreateNewInstance (6f79fa31)

6f79af10 5f              pop     edi

6f79af11 5e              pop     esi

6f79af12 5b              pop     ebx

6f79af13 8be5            mov     esp,ebp

6f79af15 5d              pop     ebp

6f79af16 c3              ret


jscript9!Js::TypedArrayBase::CreateNewInstance 내부로 들어 가보면 jscript9!::Js::TypedArray<int>::Create 호출을 볼 수 있습니다.


6f79fc16 ffb608060000    push    dword ptr [esi+608h]

6f79fc1c 57              push    edi

6f79fc1d 51              push    ecx

6f79fc1e 53              push    ebx

6f79fc1f ff5514          call    dword ptr [ebp+14h]  ss:002b:057dba9c={jscript9!Js::TypedArray<int>::Create (6f72bd50)}


jscript9!Js::TypedArray<int>::Create 내부로 들어 가보면 Alloc 호출을 볼 수 있습니다.


6f72bd88 8b7514          mov     esi,dword ptr [ebp+14h] ss:002b:057dba64=04b6b000

6f72bd8b 8b4e0c          mov     ecx,dword ptr [esi+0Ch]

6f72bd8e 6a24            push    24h      <----------------- 24h bytes

6f72bd90 e893b2e6ff      call    jscript9!Recycler::Alloc (6f597028)

6f72bd95 ffb61c010000    push    dword ptr [esi+11Ch]

6f72bd9b ff7510          push    dword ptr [ebp+10h]

6f72bd9e ff750c          push    dword ptr [ebp+0Ch]

6f72bda1 57              push    edi

6f72bda2 50              push    eax

6f72bda3 e898f7ffff      call    jscript9!Js::TypedArray<int>::TypedArray<int> (6f72b540)

6f72bda8 5f              pop     edi

6f72bda9 5e              pop     esi

6f72bdaa c9              leave

6f72bdab c21000          ret     10h


보시면 TypedArray<int> 객체 0x24 바이트이며, 먼저 할당된 이후에 생성자에 의해 초기화 됩니다.

 

Int32Array가 생성될 때 메시지를 출력하기 위해 jscript9!Js::TypedArray<int>::NewInstance breakpoint를 설정하고 이 후, jscript9!Js::TypedArrayBase::CreateNewInstance로 호출합니다. (이전에 설정했던 것을 다시 확인 해보시면 됩니다)


jscript9!Js::TypedArray<int>::NewInstance:

6f79aebb 8bff            mov     edi,edi

6f79aebd 55              push    ebp

6f79aebe 8bec            mov     ebp,esp

6f79aec0 83e4f8          and     esp,0FFFFFFF8h

6f79aec3 83ec0c          sub     esp,0Ch

6f79aec6 53              push    ebx

6f79aec7 8b5d08          mov     ebx,dword ptr [ebp+8]

6f79aeca 8b4304          mov     eax,dword ptr [ebx+4]

6f79aecd 8b4004          mov     eax,dword ptr [eax+4]

6f79aed0 8b4804          mov     ecx,dword ptr [eax+4]

6f79aed3 56              push    esi

6f79aed4 57              push    edi

6f79aed5 6a00            push    0

6f79aed7 51              push    ecx

6f79aed8 8b8934020000    mov     ecx,dword ptr [ecx+234h]

6f79aede ba00040000      mov     edx,400h

6f79aee3 e8b2e7e0ff      call    jscript9!ThreadContext::ProbeStack (6f5a969a)

6f79aee8 8d4510          lea     eax,[ebp+10h]

6f79aeeb 50              push    eax

6f79aeec 8d7d0c          lea     edi,[ebp+0Ch]

6f79aeef 8d742414        lea     esi,[esp+14h]

6f79aef3 e8cb93e0ff      call    jscript9!Js::ArgumentReader::ArgumentReader (6f5a42c3)

6f79aef8 8b4304          mov     eax,dword ptr [ebx+4]

6f79aefb 8b4004          mov     eax,dword ptr [eax+4]

6f79aefe 6850bd726f      push    offset jscript9!Js::TypedArray<int>::Create (6f72bd50)

6f79af03 6a04            push    4

6f79af05 ff7004          push    dword ptr [eax+4]

6f79af08 8bc6            mov     eax,esi

6f79af0a 50              push    eax

6f79af0b e8214b0000      call    jscript9!Js::TypedArrayBase::CreateNewInstance (6f79fa31)

6f79af10 5f              pop     edi      <---------------------- breakpoint here

6f79af11 5e              pop     esi

6f79af12 5b              pop     ebx

6f79af13 8be5            mov     esp,ebp

6f79af15 5d              pop     ebp

6f79af16 c3              ret


breakpoint는 다음과 같습니다.


bp jscript9+20af10 ".printf \"new TypedArray<int>: addr = 0x%p\\n\",eax;g"


jscript9!Js::JavascriptArrayBuffer::Create 를 보시면 다음과 같습니다.


0:004> uf jscript9!Js::JavascriptArrayBuffer::Create

jscript9!Js::JavascriptArrayBuffer::Create:

6f643cbe 8bff            mov     edi,edi

6f643cc0 55              push    ebp

6f643cc1 8bec            mov     ebp,esp

6f643cc3 53              push    ebx

6f643cc4 8b5d08          mov     ebx,dword ptr [ebp+8]

6f643cc7 56              push    esi

6f643cc8 57              push    edi

6f643cc9 8bf8            mov     edi,eax

6f643ccb 8b4304          mov     eax,dword ptr [ebx+4]

6f643cce 8b4004          mov     eax,dword ptr [eax+4]

6f643cd1 8bb064040000    mov     esi,dword ptr [eax+464h]

6f643cd7 01be04410000    add     dword ptr [esi+4104h],edi

6f643cdd e85936f5ff      call    jscript9!Recycler::CollectNow<402722819> (6f59733b)

6f643ce2 6a18            push    18h     <----------- 18h bytes

6f643ce4 8bce            mov     ecx,esi

6f643ce6 e8b958f5ff      call    jscript9!Recycler::AllocFinalized (6f5995a4)

6f643ceb ff353cb1826f    push    dword ptr [jscript9!_imp__malloc (6f82b13c)]   <--------------------

6f643cf1 8bf0            mov     esi,eax

6f643cf3 8bcb            mov     ecx,ebx

6f643cf5 e863010000      call    jscript9!Js::ArrayBuffer::ArrayBuffer<void * (__cdecl*)(unsigned int)> (6f643e5d)

6f643cfa 5f              pop     edi

6f643cfb c706103d646f    mov     dword ptr [esi],offset jscript9!Js::JavascriptArrayBuffer::`vftable' (6f643d10)

6f643d01 8bc6            mov     eax,esi

6f643d03 5e              pop     esi

6f643d04 5b              pop     ebx

6f643d05 5d              pop     ebp

6f643d06 c20400          ret     4    <----------- put a breakpoint here


ArrayBuffer 0x18 바이트 이며 jscript9!Recycler::AllocFinalized를 통해 할당됩니다. 분명한 것은 ArrayBuffer는 메모리 블록을 가리키는 포인터를 갖는데 이 메모리에 유저 데이터가 존재합니다. 사실 jscript9!_imp__malloc ArrayBuffer의 생성자로 전달되고 우리는 이제 알고 있듯이 버퍼는 정말 C malloc으로 할당됩니다.

 

이제 우리는 함수의 마지막에 breakpoint를 설정할 수 있습니다.


bp jscript9!Js::JavascriptArrayBuffer::Create+0x48 ".printf \"new JavascriptArrayBuffer: addr = 0x%p\\n\",eax;g"


이 객체들은 분석하기 쉽습니다. 아래는 우리가 학습한 내용입니다.



댓글