По следам MS IE OBJECT tag exploit'а

Роем вглубь


Берем файл MSHTML.DLL (он находится в каталоге WINNT\System32) и загружаем его в IDA Pro или другой дизассемблер (но лучше, чем IDA Pro вы все равно ничего не найдете). Michal Zalewski в своем сообщении жаловался на отсутствие исходных текстов, серьезно затрудняющих анализ. Что ж, исходных текстов IE в нашем распоряжении действительно нет, но отладочные символы получить можно. В них содержатся имена всех неэкспортируемых функций и объявления объектов и структур.

Рисунок 7 основное окно дизассемблера IDA Pro 5.0 по умолчанию. ну и как с ним работать?! переход в нормальный режим осуществляется нажатием на пробел

IDA Pro 5.0 (см. рис. 7) автоматически сгружает отладочные символы всех системных файлов с msdl.microsoft.com, стоит только сказать: file à load file à PDB file. В более древних версиях это приходится делать вручную. Для начала нам потребуется пакет "Debugging Tools for Windows", бесплатно распространяемый Microsoft: www.microsoft.com/whdc/devtools/debugging/. Скачиваем версию для "своей" операционной системы, устанавливаем, заходим в каталог /bin, находим там утилиту symchk.exe и запускаем ее на следующий манер:

set src=C:\WINNT\SYSTEM32\MSHTML.DLL

symchk %src% /s srv*.\*http://msdl.microsoft.com/download/symbols -v

Листинг 7 ручная загрузка символьной информации

Программа лезет в сеть, возбужденно подмигивая огоньками модема, и вскоре (или не вскоре — это уж от вашего канала зависит!) на диске образуются два новых каталога: .\mshtml.dbg\38D12257243000 с файлом mshtml.dbg и .\mshtml.pdb\38051D9A2 c mshtml.pdb c размерами 2.8 Мбайт и 2.1 Мбайт соответственно. На самом деле, файлы передаются в сжатом виде, поэтому реально скачивается всего ~1,5 Мбайта. Ну, dbg-файл нам совершенно неинтересен (там содержатся адреса машинных команд, соответствующие номерам строк исходных текстов, которых у нас все равно нет), а вот pdb мы сейчас и загрузим в IDA Pro вместе со всей символьной информацией, которой решила поделиться с нами Microsoft.
Перед этим рекомендуется скопировать динамическую библиотеку dbghelp.dll из Debugging Tools в коревой каталог IDA Pro, иначе плагин pdb.plw может не сработать.

Но прежде, чем загружать символы, перейдем на место сбоя и посмотрим как выглядит оригинальный дизассемблерный текст. Нажимаем <G> (goto) и вводим адрес "75ACC4DA", сообщенный Др. Ватсоном. Мы оказываемся в уже знакомой нам процедуре (см. листинг 8), вызывающей безымянную функцию 75A9211Dh о назначении которой пока можно только гадать:

.text:75ACC4C0 sub_75ACC4C0 proc near            ; CODE XREF: sub_75AB7EE6+1E2p

.text:75ACC4C0                                         ; sub_75AC4C20+2Ep ...



.text:75ACC4C0             push   esi

.text:75ACC4C1             mov    esi, ecx

.text:75ACC4C3             call   sub_75A9211D

.text:75ACC4C8              mov    si, [esi+6Ch]

.text:75ACC4CC             test   si, si

.text:75ACC4CF             jz     short loc_75ACC4E9

.text:75ACC4D1             movzx  ecx, si

.text:75ACC4D4             imul   ecx, 98h

.text:75ACC4DA             mov    eax, [eax+420h]      ; ß место сбоя

.text:75ACC4E0             pop    esi

.text:75ACC4E1             lea    eax, [ecx+eax-98h]

.text:75ACC4E8             retn

.text:75ACC4E9 ; -------------------------------------------------------------------

.text:75ACC4E9

.text:75ACC4E9 loc_75ACC4E9:                           ; CODE XREF: sub_75ACC4C0+Fj

.text:75ACC4E9             mov    eax, offset unk_75C8D1A0

.text:75ACC4EE             pop    esi

.text:75ACC4EF             retn

.text:75ACC4EF sub_75ACC4C0    endp

.text:75ACC4EF

Листинг 8 дизассемблерный текст до загрузки символьной информации

После загрузки символьной информации (file à load file à PDB file) листинг радикально преображается (см. листинг 9) и мы получаем вполне осмысленные имена:

 ; struct INSTANTCLASSINFO * __thiscall COleSite::GetInstantClassInfo(void)



.text:75ACC4C0 ?GetInstantClassInfo@COleSite@@QAEPAUINSTANTCLASSINFO@@XZ

proc near

.text:75ACC4C0             push   esi

.text:75ACC4C1             mov    esi, ecx

.text:75ACC4C3             call   ?GetDocPtr@CElement@@QBEPVCDoc@@XZ;CElement::GetDocPtr()

.text:75ACC4C8             mov    si, [esi+6Ch]

.text:75ACC4CC             test   si, si

.text:75ACC4CF             jz     short loc_75ACC4E9

.text:75ACC4D1             movzx  ecx, si

.text:75ACC4D4             imul   ecx, 98h

.text:75ACC4DA             mov    eax, [eax+420h]      ; ß место сбоя

.text:75ACC4E0             pop    esi

.text:75ACC4E1             lea    eax, [ecx+eax-98h]

.text:75ACC4E8             retn

.text:75ACC4E9 ; --------------------------------------------------------------------

.text:75ACC4E9

.text:75ACC4E9 loc_75ACC4E9:

.text:75ACC4E9             mov    eax, offset ?g_ciNull@@3UCLASSINFO@@A;CLASSINFO g_ciNull

.text:75ACC4EE             pop    esi

.text:75ACC4EF       retn

.text:75ACC4EF ?GetInstantClassInfo@COleSite@@QAEPAUINSTANTCLASSINFO@@XZ

endp

Листинг 9  тот же дизассемблерный текст после загрузки символьной информации

Теперь мы знаем, что сбой произошел в функции COleSite::GetInstantClassInfo(void), возвращающей указатель на структуру INSTANTCLASSINFO. К сожалению, описаний структур в pdb-файле нет (коварство Microsoft не знает границ!), но даже неполная символьная информация _намного_ лучше, чем совсем никакой!

Немного побурчав для приличия, займемся дизассемблированием функции CElement::GetDocPtr(void), возвратившей в регистре EAX ноль, и посмотрим кто ей сорвал крышу и почему (см. листинг 10):

.text:75A9211D ?GetDocPtr@CElement@@QBEPAVCDoc@@XZ proc near; CElement::GetDocPtr()

.text:75A9211D             mov    eax, [ecx+10h]

.text:75A92120             mov    ecx, [ecx+1Ch]

.text:75A92123             test   cl, 2

.text:75A92126             jz     short loc_75A9212B

.text:75A92128             mov    eax, [eax+0Ch]

.text:75A9212B



.text:75A9212B loc_75A9212B:

.text:75A9212B             test   cl, 1

.text:75A9212E             jz     short locret_75A92133

.text:75A92130             mov    eax, [eax+2Ch]

.text:75A92133

.text:75A92133 locret_75A92133:

.text:75A92133             retn

.text:75A92133 ?GetDocPtr@CElement@@QBEPAVCDoc@@XZ endp

Листинг 10 дизассемблерный текст функции CElement::GetDocPtr(void)

Функция проста как провинциальная девушка, приехавшая покорять Москву. Используя регистр ECX, как указатель на объект, она извлекает из него еще один указатель, грузит его в EAX, а затем, используя полученный EAX как указатель, возвращает в том же самом EAX указатель на объект, который она должна возвратить, но в нашем случае возвращается ноль, что указывает на разрушение сложной иерархии структур данных.

Дизассемблер не позволяет сказать на каком этапе произошло разрушение. Может быть разрушен как базовый блок, на который указывает ECX, так и блок, расположенный по адресу *(ECX+10h). А, быть может, разрушение произошло еще раньше, но программа рухнула только сейчас. Чтобы не гадать на кофейной гуще, воспользуемся just-in-time отладчиком, в роли которого выступит популярный OllyDbg (http://www.ollydbg.de/).


Содержание раздела