IE: все по-старому Крис Касперски ака мыщъх Хакер, номер #090, стр. 090-055-7 75A9212E 74 03 JE SHORT mshtml.75A92133 75A92130 8B40 2C MOV EAX,DWORD PTR DS:[EAX+2C] 75A92133 C3 RETN 00E552B0 00000000 стек -> 0006DB9C 75ACC4C8 RETURN to mshtml.75ACC4C8 00E552B4 00000000 0006DBA0 00E552B0 00E552B8 00000001 0006DBA4 75ACC889 RETURN to mshtml.75ACC889 00E552BC FFFFFFFF 0006DBA8 00E552B0 00E552C0 00000000 0006DBAC 000BA054 00E552C4 00000000 <- дамп 0006DBB0 75A9BFD3 RETURN to mshtml.75A9BFD3 00E552C8 00000000 0006DBB4 00000004 00E552CC FFFFFFFF 0006DBB8 00000007 00E552D0 00000000 0006DBBC 000BA054 00E552D4 00E55524 0006DBC0 00000001 00E552D8 00000652 0006DBC4 000B9EE8 00E552DC 00000000 0006DBC8 000B0001 Нажав <Shift-F9>, мы можем проигнорировать исключение и продолжить выполнение программы, только ни ей, ни нам лучше от этого не станет, ведь структуры данных превратились в бессмысленную мешанину байт, и неизвестно, в какой момент они были разрушены. Приходится реконструировать скелет динозавра буквально по косточкам. Прежде всего нам необходимо выяснить, куда указывал ECX в момент вызова GetDocPtr(). Смотрим на стек: на его вершине находится адрес возврата в материнскую процедуру 75ACC4C8h. Ходим сюда дизассемблером (или самим отладчиком по <CTRL-G>, 75ACC4C8h) и видим, что перед вызовом функции GetDocPtr регистр ECX был сохранен в регистре ESI: Исследование материнской функции, вызывающей GetDocPtr .text:75ACC4C1 mov esi, ecx .text:75ACC4C3 call GetDocPtr@CElement@@QBEPAVCDoc@@XZ;CElement::GetDocPtr() .text:75ACC4C8 mov si, [esi+6Ch] Следовательно, в момент сбоя регистр ESI указывает на структуру, из которой загружаются регистры ECX и EAX. Тройным нажатием <TAB> переходим в окно дампа, нажимаем <CTRL-G> и вводим регистр ESI или его непосредственное значение 00E552B0h. Это и есть та структура данных, с которой мы уже сталкивались в дизассемблере, и которая, судя по карте памяти, лежит где-то в куче (на самом деле, OllyDbg не умеет работать с кучей, и необходимо иметь определенный исследовательский опыт, чтобы выделить блоки динамической памяти из общей массы. SoftICE показал бы намного больше информации, но мы уже решили использовать Olly, так что не будем менять коней на переправе). Команда MOV EAX, [ECX+10], которая должна возвращать указатель, возвратила ноль, в результате чего следующая за ней команда MOV EAX, [EAX+0Ch] оказалась источником сбоя. Это самое настоящее разрушение объекта CElement, но вот кто его разрушил и почему, нам еще предстоит узнать. Во всяком случае, объект не был затерт строкой "AAA...AAA", иначе в дампе присутствовали бы соответствующие ей ASCII-коды 41h, а их там нет. Как это нет?! Куда подевалась наша строка? А вот сейчас найдем ее в памяти и узнаем! Нажимаем <ALT-M> для вызова окна "memory", переходим в начало адресного пространства по клавише "home" и давим <CTRL-B> для поиска. Искать, конечно же, нужно в Unicode. Строка находится дважды. Первый раз — в стеке, по адресу 000С00F0h, вместе с "<OBJECT type=" и всеми остальными строками, второй раз — в куче, по адресу 00E51A60h, где следом за ней идет еще одна строка "AAA...AAA" и... больше ничего. Ага! Судя по всему, IE смог обработать только два объекта, после чего наступило переполнение, ведущее к исключению и аварийному завершению работы. Обратите внимание, что строка "AAA...AAA" (00E50600h) лежит в непосредственной близости от структуры данных, на которую указывает ECX – 00E552B0h, однако их разделяет порядочное количество байт, и если переполнение происходит, то явно не здесь. Что ж, будем копать дальше! Тем более что у нас есть замечательная возможность начать следствие до начала преступления, установив точку останова на... |