티스토리 뷰
본 문서는 원문 저자인 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 (항상 관리자 권한의 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); a = 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"
이 객체들은 분석하기 쉽습니다. 아래는 우리가 학습한 내용입니다.
'Projects > Exploit Development' 카테고리의 다른 글
[익스플로잇 개발] 15. IE 10 (God Mode 1) (0) | 2016.07.22 |
---|---|
[익스플로잇 개발] 14. IE 10 (한 바이트 쓰기로 전체 메모리 읽기/쓰기) (3) | 2016.07.22 |
[익스플로잇 개발] 12. EMET 5.2 (0) | 2016.07.22 |
[익스플로잇 개발] 11. Exploitme5 (힙 스프레잉 & UAF) (3) | 2016.07.22 |
[익스플로잇 개발] 10. Exploitme4 (ASLR) (0) | 2016.07.19 |
- Total
- Today
- Yesterday
- IE 10 리버싱
- Windows Exploit Development
- IE 10 Exploit Development
- Use after free
- shellcode
- 쉘 코드 작성
- 2015 School CTF
- School CTF Writeup
- IE 10 God Mode
- 데이터 마이닝
- IE UAF
- 쉘 코드
- IE 10 익스플로잇
- 윈도우즈 익스플로잇 개발
- expdev 번역
- TenDollar
- heap spraying
- 힙 스프레잉
- CTF Write up
- WinDbg
- 2014 SU CTF Write UP
- IE 11 exploit
- shellcode writing
- Mona 2
- IE 11 UAF
- IE 11 exploit development
- TenDollar CTF
- data mining
- School CTF Write up
- UAF
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |