+ Reply to Thread
Results 1 to 1 of 1

Thread: Exploit Development Course Part 13 [Internet Explorer 10]: Reverse Engineering IE (Перевод: klaus)

  1. #1
    klaus's Avatar

    Default Exploit Development Course Part 13 [Internet Explorer 10]: Reverse Engineering IE (Перевод: klaus)

    Перейти к содержанию

    IE10: Reverse Engineering IE


    Для этого эксплойта я использую VirtualBox VM с Windows 7 64-bit SP1 и версия Internet Explorer 10 скачана отсюда.

    Что бы успешно эксплуатировать IE 10 над надо обойти ASLR и DEP. Мы собираемся эксплуатировать UAF для модификации длины массива так, чтобы мы могли читать и записывать через всё адресное пространство процесса. Способность читать/записывать куда мы захотим, это очень мощная способность.

    Оттуда мы можем пойти двумя путями:
    1. Запустить ActiveX объекты (God mode)
    2. Выполнить обычный шелл-код

    Для фазы UAF – произвольного чтения/записи мы будем использовать метод описанный здесь.

    Чтение этого файла не обязательно для полного понимания метода из-за того, что я нашел различия между теорией и практикой. Моя цель не просто описать метод, но и показать весь процесс по созданию полноценного эксплойта. Первыми шагами будет маленькое расследование с WinDbg и исследования того, как массивы и другие объекты размещены в памяти.

    Реверс инженерия IE

    Объекты которые мы хотим проанализировать:
    • Array
    • LargeHeapBlock
    • ArrayBuffer
    • Int32Array

    Настройка WinDbg

    На данный момент вы должны быть знакомы с WinDbg и уметь настраивать его соответствующим образом. Но давайте всё-таки уверимся. Сперва, загрузите WinDbg (всегда 32-х битную версию, как администратор), нажмите Ctrl + S и введите symbol path.
    Вот мой к примеру:

    Code:
    SRV*C:\WinDbgSymbols*http://msdl.microsoft.com/download/symbols
    Помните что первая часть, это локальная директория для кэширования скачанных символов из сервера.

    Нажмите ОК и потом сохраните рабочее окружение выполнив File→Save Workspace. Теперь запустите Internet Explorer 10 и в WinDbg нажмите F6 для присоединения к процессу (Attach to process). Вы увидите что iexplore.exe появился дважды в списке. Первый экземпляр iexplore.exe это главный процесс, в то время когда второй, это процесс ассоциируемый с первой открытой вкладкой (tab) в IE. Если вы откроете другие вкладки, вы увидите другие экземпляры. Выберите второй экземпляр как показано на изображении ниже:

    В WinDbg я использую такую структуру окон:


    Настройте структуру окон как вам нравится и сохраните рабочее окружение.

    Array

    Давайте начнем с объекта Array. Создайте html файл следующего содержания:

    Code:
    <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>
    Откройте файл в IE, разрешите заблокированный контент, и когда диалоговое окно с текстом Start всплывет, тогда запустите WinDbg, нажмите F6 и присоединитесь отладчиком ко второму экземпляру iexplore.exe как делали ранее. Нажмите F5 для продолжения выполнения и закройте диалоговое окно в IE. Теперь вы должны видеть второе диалоговое окно с сообщением Done.
    Вернитесь в WinDbg и попробуйте найти память с содержимым массива. Как вы видите, смотря в исходный код, массив содержит последовательность из 0x111.

    Вот что мы получили:
    Code:
    0:004> s-d 0 L?ffffffff 111 111 111 111
    Мы ничего не получили! Странно… Но даже если бы мы нашли массив в памяти, этого было бы не достаточно для того что бы найти код который выделяет память. Нам нужен другой путь.

    Почему бы не распылить кучу? Давайте изменим код:

    Code:
    <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>
    После обновления html файла, продолжите выполнение в WinDbg (F5), закройте Done диалоговое окно в IE и перезагрузите страницу (F5). Закройте диалоговое окно (Start) и ждите следующего. Теперь посмотрим на использования памяти IE открыв менеджер задач:


    Мы выделили приблизительно 550 МБ. Мы можем использовать приложения под названием VMMap (скачать) для получения графического изображения нашего распыления кучи (heap spray).

    Откройте VMMap и выберите нужный экземпляр iexplore.exe как показано на изображении ниже:


    Теперь перейдите в View→Fragmentation View. Вы увидите что-то типа этого:

    Область закрашенная в желтый это память, выделенная через распыление кучи. Давайте попробуем проанализировать память по адресу 0x1ffd0000, что является серединой наших данных:

    Убедимся, что это один из наших массивов изменив немного код:

    Code:
    <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>
    Повторим процесс и вот результат:


    Как видим, массив теперь содержит значение 0x247. Попробуем нечто другое:
    Code:
    <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>
    Теперь мы получили следующее:
    Массив содержит непарные числа начиная с 1. Мы знаем что наш массив содержит числа:
    Code:
    1 2 3 4 5 6 7 8 9 ...
    но мы получили:
    Code:
    3 5 7 9 11 13 15 17 19 ...
    Здесь ясно что число n является представлением n*2 + 1. Почему так? Вы должны знать что массивы также могут содержать ссылки на объекты, по этому должен быть для разделения адресов и целых чисел. Начиная с адреса кратного 4, представляя любое целочисленное нечетное значение, он никогда не спутается с ссылкой. Но что насчет номера вида 0x7fffffff который является наибольшим позитивным числом по дополнению к двум?

    Давайте немного поэкспериментируем:

    Code:
    <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>
    Вот как наш массив выглядит сейчас:

    Число 0x7fffffff слишком большое что бы хранится напрямую, вместо этого IE хранит ссылку на объект JavascriptNumber. Число -2 хранится напрямую из-за того, что его невозможно перепутать с адресом (установлен старший бит).
    Как вы теперь уже знаете, первый DWORD объекта – это обычно указатель на его vftable. На картинке выше можно увидеть, это полезно для определения идентификатора объекта.

    Теперь давайте узнаем какой код выделяет массив. Мы видим что там скорее всего есть два заголовка:

    Первый заголовок о размере выделенного блока в 0x1010 байт. Действительно, выделенный блок содержит 0х10 байт заголовка и 0х1000 байт самых данных. Из-за того, что мы знаем о расположении одного из массивов по адресу 0x1ffd0000, мы можем установить аппаратную точку останова (на запись) на поля двух заголовков. Таким образом мы узнаем кто выделяет блок и какой код создает объект.

    Сперва перезагрузим страницу и остановимся перед Start диалогом. Переходим в WinDbg b останавливаем выполнением (Ctrl + Break). Теперь устанавливаем две точки останова:
    Code:
    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. Когда сработает первая точка останова, выведите стек:

    Code:
    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
    Здесь мы видим три вещи:
    1. IE использует стандартные средства выделения памяти.
    2. Массив типа jscript9!Js::JavascriptArray.
    3. Блок, вероятно, выделен в момент, когда мы установили значение первого элемента массива (*).

    Вернемся из текущего вызова с помощью Shift + F11. Таким образом перейдем сюда:

    Code:
    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    <----- мы здесь
    6e9e72de 5e              pop     esi
    6e9e72df 5d              pop     ebp
    6e9e72e0 c20400          ret     4
    Нажмем Shift + F11 снова:
    Code:
    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  <----- мы здесь
    6ea92c4a 8b0a            mov     ecx,dword ptr [edx]
    6ea92c4c c70000000000    mov     dword ptr [eax],0
    EAX указывает на буфер, поэтому мы можем установить точку останова на адрес 6ea92c47. Давайте запишем адрес EIP так, что бы он не зависел от конкретного базового адреса модуля. Для начала нужно сказать что мы в jscript9, убедимся:

    Code:
    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 следующий:

    Code:
    0:007> ? @eip-jscript9
    Evaluate expression: 797767 = 000c2c47
    Создание массива (его данных если быть точными) можно зарегистрировать следующей точкой останова:

    Code:
    bp jscript9+c2c47 ".printf \"new Array Data: addr = 0x%p\\n\",eax;g"
    Следует избигать двойных кавычек и обратных слешей из-за того, что мы внутри строки. Также, команда g (go) используется для продолжения выполнения после срабатывания точки останова. Мы хотим вывести сообщение без останова выполнения.

    Вернемся к тому что мы делали. Мы установили две аппаратные точки останова и только одна сработала, давайте продолжим. После нажатия F5 сработала вторая точка останова и стек приобрел следующий вид:

    Code:
    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
    Сравнивая два последних вывода стека видим то, что мы всё еще в том же самом вызове jscript9!Js::JavascriptArray::DirectSetItem_Full. DirectSetItem_Full сперва выделяет блок 0х1010 байт через jscript9!Recycler::AllocZero и потом инициализирует объект. Но если всё это случится внутри jscript9!Js::JavascriptArray::DirectSetItem_Full, тогда экземпляр JavascriptArray сразу бы создался. Попробуем прервать выполнение конструктора. Но сперва убедимся существует ли он:

    Code:
    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>)
    Мы получили три адреса. Удалим предыдущую точку остановас помощью bc *, далее нажмите F5 и перезагрузите страницу в IE. При первом диалоговом окне вернитесь в WinDbg. Теперь установите точку останова на каждый из трех адресов:

    Code:
    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 появилось и никакие точки останова не сработали. Как странно…

    Давайте посмотрим не нашли ли мы что-то интересное в списке символов:

    Code:
    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>
    Данная строка выглядит многообещающе:

    Code:
    6eba4b06          jscript9!Js::JavascriptArray::NewInstance (<no parameter info>)
    Установим на неё точку останова и попытаем удачу.

    Code:
    0:006> bc *
    0:006> bp jscript9!Js::JavascriptArray::NewInstance
    Закройте диалоговое окно в IE, перезагрузите страницу и закройте стартовое диалоговое окно. Теперь всё идет по плану:


    Трассируя код мы получили такой вот кусок:

    Code:
    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]
    Оператор new вызывает следующим образом:

    Code:
    operator new(20h, arg, jscript9!Recycler::Alloc);
    Посмотри на код в области оператора new:

    Code:
    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
    
    Давайте вернемся к основному коду:
    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 = выделенный блок
    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]
    Важной инструкцией является:

    Code:
    6eb02ab3 c7063025a46e    mov     dword ptr [esi],offset jscript9!Js::JavascriptArray::`vftable' (6ea42530)
    которая переписывает первый DWORD блока памяти таблицой vftable объекта JavascriptArray.

    Другая важная часть кода такая:

    Code:
    6eb02ac3 8b4004          mov     eax,dword ptr [eax+4]
    6eb02ac6 8b8864040000    mov     ecx,dword ptr [eax+464h]
    6eb02acc 6a50            push    50h        <------- 50h байт?
    6eb02ace c7461000000000  mov     dword ptr [esi+10h],0
    6eb02ad5 e80769f4ff      call    jscript9!Recycler::AllocZero (6ea493e1)    <------ выделяет блок
    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   <------ смотрим на картинке
    6eb02af8 894614          mov     dword ptr [esi+14h],eax   <------ смотрим на картинкеpicture
    6eb02afb e951200a00      jmp     jscript9!Js::JavascriptArray::NewInstance+0x24f (6eba4b51)
    Изображение ниже иллюстрирует происходящее в коде выше:


    Теперь у нас есть два важных адреса:
    Code:
    239d9340          address of the JavascriptArray
    2c1460a0          structure pointed to by the JavascriptArray
    Удалим точки останова и продолжим выполнение программы. Когда диалоговое окно Done появится, вернитесь в WinDbg. Теперь прервите выполнение в WinDbg и посмотрите по адресу 239d9340h:


    Как видно с рисунка, наш JavascriptArray (по смещению 0x14 и 0x18) указывает на разные адреса. Из-за того, что JavascriptArray рассширяемый, вполне вероятно, что при выделении большего буфера два указателя 0x14 и 0x18 начинают указывать на новый буфер. Так же можно увидеть что JavascriptArray по адресу 239d9340 соответствует массиву a в javascript-коде. Он в самом деле содержит 10000h ссылок на другие массивы.

    Мы увидели что объект JavascriptArray выделен в функции jscript9!Js::JavascriptArray::NewInstance:

    Code:
    6eb02a46 e84546f4ff      call    jscript9!operator new<Recycler> (6ea47090)     <-------------------
    6eb02a4b 8bf0            mov     esi,eax   <--------- ESI = выделенный блок
    Если в данном месте вы вернемся из jscript9!Js::JavascriptArray::NewInstance нажатием комбинации клавиш Shift + F11, мы увидим следующий код:

    Code:
    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.

    Выберем второе:
    Code:
    bp jscript9+425d5 ".printf \"new Array: addr = 0x%p\\n\",eax;g"
    Вот полная картина того что мы обнаружили до теперешнего времени:

    LargeHeapBlock

    Что такое LargeHeapBlock? Попробуем найти какие-то относящиеся к этому символы:

    Code:
    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>
    Вот наиболее подходящии на первый взгляд функции:
    Code:
    6f59a7ca          jscript9!HeapInfo::AddLargeHeapBlock (<no parameter info>)
    6f755f80          jscript9!LargeHeapBlock::Alloc (<no parameter info>)
    Поставит точки останова на них обеих и перезагрузим страницу в IE. Когда вы закроем диалоговое окно Start, сработает первая точка останова и в конечном итоге мы окажемся здесь:

    Code:
    6f59a7c5 90              nop
    6f59a7c6 90              nop
    6f59a7c7 90              nop
    6f59a7c8 90              nop
    6f59a7c9 90              nop
    jscript9!HeapInfo::AddLargeHeapBlock:
    6f59a7ca 8bff            mov     edi,edi     <------------ мы здесь
    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]
    Также взглянем на трассировку стека:

    Code:
    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. Вернемся из AddLargeHeapBlock прожав Shift+F11 и посмотрим на память по указателю из EAX:

    Code:
    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. Посмотрем был ли данный блок выделен прямо в куче:

    Code:
    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:
    Code:
    bp jscript9!Recycler::LargeAlloc+0x66 ".printf \"new LargeHeapBlock: addr = 0x%p\\n\",eax;g"
    Мы должны взгянуть на LargeHeapBlock. Сперва давайте изменим javascript-код так, что бы LargeHeapBlock создавался меньшее количество раз:

    Code:
    <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>
    Установим точку останова о которой только что говорили:

    Code:
    bp jscript9!Recycler::LargeAlloc+0x66 ".printf \"new LargeHeapBlock: addr = 0x%p\\n\",eax;g"
    Теперь перезагрузите страницу IE и закройте первое диалоговое окно.

    Ваш вывод должен быть схожим с этим:
    Code:
    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 = 0x042a7728
    new LargeHeapBlock: addr = 0x042a7788
    new LargeHeapBlock: addr = 0x042a77e8
    new LargeHeapBlock: addr = 0x042a7848
    new LargeHeapBlock: addr = 0x042a78a8
    new LargeHeapBlock: addr = 0x042a7908
    new LargeHeapBlock: addr = 0x042a7968
    new LargeHeapBlock: addr = 0x042a79c8
    new LargeHeapBlock: addr = 0x042a7a28
    new LargeHeapBlock: addr = 0x042a7a88
    new LargeHeapBlock: addr = 0x042a7ae8
    new LargeHeapBlock: addr = 0x042a7b48
    new LargeHeapBlock: addr = 0x042a7ba8
    new LargeHeapBlock: addr = 0x042a7c08
    new LargeHeapBlock: addr = 0x042a7c68
    new LargeHeapBlock: addr = 0x042a7cc8
    new LargeHeapBlock: addr = 0x042a7d28
    new LargeHeapBlock: addr = 0x042a7d88
    new LargeHeapBlock: addr = 0x042a7de8
    new LargeHeapBlock: addr = 0x042a7e48
    new LargeHeapBlock: addr = 0x042a7ea8
    new LargeHeapBlock: addr = 0x042a7f08
    new LargeHeapBlock: addr = 0x042a7f68
    new LargeHeapBlock: addr = 0x042a7fc8
    new LargeHeapBlock: addr = 0x042a8028
    new LargeHeapBlock: addr = 0x042a8088
    new LargeHeapBlock: addr = 0x042a80e8
    new LargeHeapBlock: addr = 0x134a9020
    new LargeHeapBlock: addr = 0x134a9080
    new LargeHeapBlock: addr = 0x134a90e0
    new LargeHeapBlock: addr = 0x134a9140
    new LargeHeapBlock: addr = 0x134a91a0
    new LargeHeapBlock: addr = 0x134a9200
    new LargeHeapBlock: addr = 0x134a9260
    new LargeHeapBlock: addr = 0x134a92c0
    new LargeHeapBlock: addr = 0x134a9320
    new LargeHeapBlock: addr = 0x134a9380
    new LargeHeapBlock: addr = 0x134a93e0
    new LargeHeapBlock: addr = 0x134a9440
    new LargeHeapBlock: addr = 0x134a94a0
    new LargeHeapBlock: addr = 0x134a9500
    new LargeHeapBlock: addr = 0x134a9560
    new LargeHeapBlock: addr = 0x134a95c0
    new LargeHeapBlock: addr = 0x134a9620
    new LargeHeapBlock: addr = 0x134a9680
    new LargeHeapBlock: addr = 0x134a96e0
    new LargeHeapBlock: addr = 0x134a9740
    new LargeHeapBlock: addr = 0x134a97a0
    new LargeHeapBlock: addr = 0x134a9800
    new LargeHeapBlock: addr = 0x134a9860
    new LargeHeapBlock: addr = 0x134a98c0
    new LargeHeapBlock: addr = 0x134a9920
    new LargeHeapBlock: addr = 0x134a9980
    new LargeHeapBlock: addr = 0x134a99e0
    new LargeHeapBlock: addr = 0x134a9a40
    new LargeHeapBlock: addr = 0x134a9aa0
    new LargeHeapBlock: addr = 0x134a9b00
    new LargeHeapBlock: addr = 0x134a9b60
    new LargeHeapBlock: addr = 0x134a9bc0
    new LargeHeapBlock: addr = 0x134a9c20
    new LargeHeapBlock: addr = 0x134a9c80
    new LargeHeapBlock: addr = 0x134a9ce0
    new LargeHeapBlock: addr = 0x134a9d40
    new LargeHeapBlock: addr = 0x134a9da0
    new LargeHeapBlock: addr = 0x134a9e00
    new LargeHeapBlock: addr = 0x134a9e60
    new LargeHeapBlock: addr = 0x134a9ec0
    new LargeHeapBlock: addr = 0x134a9f20
    new LargeHeapBlock: addr = 0x134a9f80
    new LargeHeapBlock: addr = 0x1380e060
    new LargeHeapBlock: addr = 0x1380e0c0
    new LargeHeapBlock: addr = 0x1380e120
    new LargeHeapBlock: addr = 0x1380e180
    new LargeHeapBlock: addr = 0x1380e1e0
    new LargeHeapBlock: addr = 0x1380e240
    new LargeHeapBlock: addr = 0x1380e2a0
    new LargeHeapBlock: addr = 0x1380e300
    new LargeHeapBlock: addr = 0x1380e360
    new LargeHeapBlock: addr = 0x1380e3c0
    new LargeHeapBlock: addr = 0x1380e420
    new LargeHeapBlock: addr = 0x1380e480
    new LargeHeapBlock: addr = 0x1380e4e0
    new LargeHeapBlock: addr = 0x1380e540
    new LargeHeapBlock: addr = 0x1380e5a0
    new LargeHeapBlock: addr = 0x1380e600
    new LargeHeapBlock: addr = 0x1380e660
    new LargeHeapBlock: addr = 0x1380e6c0
    new LargeHeapBlock: addr = 0x1380e720
    new LargeHeapBlock: addr = 0x1380e780
    new LargeHeapBlock: addr = 0x1380e7e0
    new LargeHeapBlock: addr = 0x1380e840
    new LargeHeapBlock: addr = 0x1380e8a0
    new LargeHeapBlock: addr = 0x1380e900
    new LargeHeapBlock: addr = 0x1380e960
    new LargeHeapBlock: addr = 0x1380e9c0
    new LargeHeapBlock: addr = 0x1380ea20
    new LargeHeapBlock: addr = 0x1380ea80
    new LargeHeapBlock: addr = 0x1380eae0
    new LargeHeapBlock: addr = 0x1380eb40
    new LargeHeapBlock: addr = 0x1380eba0
    new LargeHeapBlock: addr = 0x1380ec00
    new LargeHeapBlock: addr = 0x1380ec60
    new LargeHeapBlock: addr = 0x1380ecc0
    new LargeHeapBlock: addr = 0x1380ed20
    new LargeHeapBlock: addr = 0x1380ed80
    new LargeHeapBlock: addr = 0x1380ede0
    new LargeHeapBlock: addr = 0x1380ee40
    new LargeHeapBlock: addr = 0x1380eea0
    new LargeHeapBlock: addr = 0x1380ef00
    new LargeHeapBlock: addr = 0x1380ef60
    new LargeHeapBlock: addr = 0x1380efc0
    new LargeHeapBlock: addr = 0x16ccb020
    new LargeHeapBlock: addr = 0x16ccb080
    new LargeHeapBlock: addr = 0x16ccb0e0
    new LargeHeapBlock: addr = 0x16ccb140
    new LargeHeapBlock: addr = 0x16ccb1a0
    new LargeHeapBlock: addr = 0x16ccb200
    new LargeHeapBlock: addr = 0x16ccb260
    new LargeHeapBlock: addr = 0x16ccb2c0
    new LargeHeapBlock: addr = 0x16ccb320
    new LargeHeapBlock: addr = 0x16ccb380
    new LargeHeapBlock: addr = 0x16ccb3e0
    new LargeHeapBlock: addr = 0x16ccb440
    new LargeHeapBlock: addr = 0x16ccb4a0
    new LargeHeapBlock: addr = 0x16ccb500
    new LargeHeapBlock: addr = 0x16ccb560
    new LargeHeapBlock: addr = 0x16ccb5c0
    new LargeHeapBlock: addr = 0x16ccb620
    new LargeHeapBlock: addr = 0x16ccb680
    new LargeHeapBlock: addr = 0x16ccb6e0
    new LargeHeapBlock: addr = 0x16ccb740
    new LargeHeapBlock: addr = 0x16ccb7a0
    new LargeHeapBlock: addr = 0x16ccb800
    new LargeHeapBlock: addr = 0x16ccb860
    new LargeHeapBlock: addr = 0x16ccb8c0
    new LargeHeapBlock: addr = 0x16ccb920
    new LargeHeapBlock: addr = 0x16ccb980
    new LargeHeapBlock: addr = 0x16ccb9e0
    new LargeHeapBlock: addr = 0x16ccba40
    new LargeHeapBlock: addr = 0x16ccbaa0
    new LargeHeapBlock: addr = 0x16ccbb00
    new LargeHeapBlock: addr = 0x16ccbb60
    new LargeHeapBlock: addr = 0x16ccbbc0
    new LargeHeapBlock: addr = 0x16ccbc20
    new LargeHeapBlock: addr = 0x16ccbc80
    new LargeHeapBlock: addr = 0x16ccbce0
    new LargeHeapBlock: addr = 0x16ccbd40
    new LargeHeapBlock: addr = 0x16ccbda0
    new LargeHeapBlock: addr = 0x16ccbe00
    new LargeHeapBlock: addr = 0x16ccbe60
    new LargeHeapBlock: addr = 0x16ccbec0
    new LargeHeapBlock: addr = 0x16ccbf20
    new LargeHeapBlock: addr = 0x16ccbf80
    new LargeHeapBlock: addr = 0x16ccc020
    new LargeHeapBlock: addr = 0x16ccc080
    new LargeHeapBlock: addr = 0x16ccc0e0
    new LargeHeapBlock: addr = 0x16ccc140
    new LargeHeapBlock: addr = 0x16ccc1a0
    new LargeHeapBlock: addr = 0x16ccc200
    new LargeHeapBlock: addr = 0x16ccc260
    new LargeHeapBlock: addr = 0x16ccc2c0
    new LargeHeapBlock: addr = 0x16ccc320
    new LargeHeapBlock: addr = 0x16ccc380
    new LargeHeapBlock: addr = 0x16ccc3e0
    new LargeHeapBlock: addr = 0x16ccc440
    new LargeHeapBlock: addr = 0x16ccc4a0
    new LargeHeapBlock: addr = 0x16ccc500
    new LargeHeapBlock: addr = 0x16ccc560
    new LargeHeapBlock: addr = 0x16ccc5c0
    new LargeHeapBlock: addr = 0x16ccc620
    new LargeHeapBlock: addr = 0x16ccc680
    new LargeHeapBlock: addr = 0x16ccc6e0
    new LargeHeapBlock: addr = 0x16ccc740
    new LargeHeapBlock: addr = 0x16ccc7a0
    new LargeHeapBlock: addr = 0x16ccc800
    new LargeHeapBlock: addr = 0x16ccc860
    new LargeHeapBlock: addr = 0x16ccc8c0
    new LargeHeapBlock: addr = 0x16ccc920
    new LargeHeapBlock: addr = 0x16ccc980
    new LargeHeapBlock: addr = 0x16ccc9e0
    new LargeHeapBlock: addr = 0x16ccca40
    new LargeHeapBlock: addr = 0x16cccaa0
    new LargeHeapBlock: addr = 0x16cccb00
    new LargeHeapBlock: addr = 0x16cccb60
    new LargeHeapBlock: addr = 0x16cccbc0
    new LargeHeapBlock: addr = 0x16cccc20
    new LargeHeapBlock: addr = 0x16cccc80
    new LargeHeapBlock: addr = 0x16cccce0
    new LargeHeapBlock: addr = 0x16cccd40
    new LargeHeapBlock: addr = 0x16cccda0
    new LargeHeapBlock: addr = 0x16ccce00
    new LargeHeapBlock: addr = 0x16ccce60
    new LargeHeapBlock: addr = 0x16cccec0
    new LargeHeapBlock: addr = 0x16cccf20
    new LargeHeapBlock: addr = 0x16cccf80
    new LargeHeapBlock: addr = 0x1364e060
    new LargeHeapBlock: addr = 0x1364e0c0
    new LargeHeapBlock: addr = 0x1364e120
    new LargeHeapBlock: addr = 0x1364e180
    new LargeHeapBlock: addr = 0x1364e1e0
    new LargeHeapBlock: addr = 0x1364e240
    new LargeHeapBlock: addr = 0x1364e2a0
    new LargeHeapBlock: addr = 0x1364e300
    new LargeHeapBlock: addr = 0x1364e360
    new LargeHeapBlock: addr = 0x1364e3c0
    new LargeHeapBlock: addr = 0x1364e420
    new LargeHeapBlock: addr = 0x1364e480
    new LargeHeapBlock: addr = 0x1364e4e0
    new LargeHeapBlock: addr = 0x1364e540
    new LargeHeapBlock: addr = 0x1364e5a0
    new LargeHeapBlock: addr = 0x1364e600
    new LargeHeapBlock: addr = 0x1364e660
    new LargeHeapBlock: addr = 0x1364e6c0
    new LargeHeapBlock: addr = 0x1364e720
    new LargeHeapBlock: addr = 0x1364e780
    new LargeHeapBlock: addr = 0x1364e7e0
    new LargeHeapBlock: addr = 0x1364e840
    new LargeHeapBlock: addr = 0x1364e8a0
    new LargeHeapBlock: addr = 0x1364e900
    new LargeHeapBlock: addr = 0x1364e960
    new LargeHeapBlock: addr = 0x1364e9c0
    new LargeHeapBlock: addr = 0x1364ea20
    new LargeHeapBlock: addr = 0x1364ea80
    new LargeHeapBlock: addr = 0x1364eae0
    new LargeHeapBlock: addr = 0x1364eb40
    new LargeHeapBlock: addr = 0x1364eba0
    new LargeHeapBlock: addr = 0x1364ec00
    new LargeHeapBlock: addr = 0x1364ec60
    new LargeHeapBlock: addr = 0x1364ecc0
    new LargeHeapBlock: addr = 0x1364ed20
    new LargeHeapBlock: addr = 0x1364ed80
    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 адресов:
    Code:
    new LargeHeapBlock: addr = 0x1364f1e0
    new LargeHeapBlock: addr = 0x1364f240
    new LargeHeapBlock: addr = 0x1364f2a0
    new LargeHeapBlock: addr = 0x1364f300
    new LargeHeapBlock: addr = 0x1364f360
    new LargeHeapBlock: addr = 0x1364f3c0
    Стоит заметить, что они разделены по 0х60 байт: 0х8 байт для выделенного заголовка и 0х58 для объекта LargeHeapBlock. Вот последние 6 LargeHeapBlocks в памяти:

    Как видно из рисунка выше, каждый LargeHeapBlock содержит смещение 0х24 и указатель на предыдущий LargeHeapBlock. Этот указатель будет использовать позже, с целью определения адреса самого LeageHeapBlock.

    ArrayBuffer & Int32Array

    Вот что говорит MDN (Mozilla Developer Network) о ArrayBuffer:

    Объект ArrayBuffer используется для представления обобщенного, фиксированной длины буфера необработанных бинарных данных. Вы не можете напрямую обрабатывать содержимое ArrayBuffer; вместо этого вам надо создать типизированный массив объектов или DataView объект, который представляет буфер в определенном формате, и использовать его для чтения/записи из/в буфер.
    Рассмотрим следующий пример:

    Code:
    // Создает ArrayBuffer вручную.
    buf = new ArrayBuffer(400*1024*1024);
    a = new Int32Array(buf);
     
    // Создает ArrayBuffer автоматически.
    a2 = new Int32Array(100*1024*1024);
    Массивы a и а2 эквивалентны и имеют одинаковый размер. При создании ArrayBuffer напрямую, нам надо указать размер в байтах, в отличии от Int32Array, где надо указать длину количеством элементов (32-х битных целых чисел - integer). Стоит обратить внимание на тот факт, что при создании Int32Array, ArrayBuffer создает внутри и Int32Array использует его.

    Что бы разобраться какой код создает ArrayBuffer, нам надо произвести «распыление кучи» (heap spray) до этого. Воспользуемся следующим javascript кодом:

    Code:
    <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>
    Когда диалоговое окно Done появится, мы сможем посмотреть на память используя VMMap.

    Вот что мы увидим:


    В этот раз нам говорят Heap (Private D …, что значит - ArrayBuffers выделен прямо в куче. Если посмотрим по адресу f650000 в WinDbg, мы увидим следующее:

    Code:
    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:
    Code:
    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, мы увидим что ситуация изменилась:

    Code:
    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) и прерватся в коде который производит выделение блоков памяти в куче. Перезагрузите страницу в IE и установите точку останова в WinDbg:

    Code:
    0:013> ba w4 f650058
    После закрытия диалогового окна в IE, мы окажемся здесь:

    Code:
    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  <----------- мы здесь
    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
    Вывод стека:

    Code:
    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 выделен с помощью функции malloc языка программирования С, которая была вызвана внутри jscript9!Js::JavascriptArrayBuffer::Create. TypedArray<int> скорее всего наш Int32Array и TypedArrayBase его базовый класс. Следуя этому, jscript9!Js::TypedArray<int>::NewInstance создает новый Int32Array и новый JavascriptArrayBuffer. Теперь мы должны взглянуть на Int32Array в памяти. Нам больше не нужно выполнять распыление кучи, просто изменим код:

    Code:
    <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>
    Установим точку останова на момент создания нового Int32Array:

    Code:
    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.
    Попробуем использовать mb вместо bp:
    Code:
    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.

    Код функции целиком:

    Code:
    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:

    Code:
    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 байта
    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> равен 24h байтов. Заметьте что объект сперва был выделен, а потом инициализирован конструктором.
    Что бы вывести сообщение при создании Int32Array, мы просто установим точку останова на конец jscript9!Js::TypedArray<int>::NewInstance, сразу после вызова jscript9!Js::TypedArrayBase::CreateNewInstance (смотрите на указатель в коде):

    Code:
    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
    Вот точка останова:

    Code:
    bp jscript9+20af10 ".printf \"new TypedArray<int>: addr = 0x%p\\n\",eax;g"
    Мы также должны обратить внимание на jscript9!Js::JavascriptArrayBuffer::Create:

    Code:
    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    <----------- ставим точку останова тут
    Из вывода следует что ArrayBuffer это объект размером в 18h выделенный через jscript9!Recycler::AllocFinalized. Можно с уверенностью сказать, что ArrayBuffer содержит указатель на блок памяти с пользовательсскими данными. По сути, вы можете видеть как jscript9!_imp__malloc передается в конструктор ArrayBuffer и мы знаем что буфер с необработанными данными действительно выделяется с помощью С функции malloc.

    Теперь мы можем поставить точку останова на конец функции:
    Code:
    bp jscript9!Js::JavascriptArrayBuffer::Create+0x48 ".printf \"new JavascriptArrayBuffer: addr = 0x%p\\n\",eax;g"
    Эти объекти легки для анализа. Вот что мы изучили на протяжении статьи:

    © Translated by klaus (r0 Crew)
    Do not follow the ancient masters, seek what they sought. (c) Matsuo Bashō

  2. 4 пользователя(ей) сказали cпасибо:
    dukeBarman (06-07-2015) gavz (05-03-2016) root (09-07-2015) Æterno (07-07-2015)
+ Reply to Thread

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
All times are GMT. The time now is 01:25
vBulletin® Copyright ©2000 - 2018
www.reverse4you.org