· Начало · Отвђтить · Статистика · Поиск · FAQ · Правила · Установки · Язык · Выход · WASM.RU · Noir.Ru ·

 WASM Phorum —› WASM.HEAP —› Необходимо определить адреса возвратов из стека.

Посл.отвђт Сообщенiе


Дата: Июл 26, 2004 10:40:25

Начну, как говорил Ф.М. Достоевский из далека, напишу наверно много, но попрощу дочитать и помощь хорошим советом:
Написал недавно Delphi компонент для локализации места ошибки (название процедуры, модуль, строка в модуле (парсинг мап-файла)), сбора информации о системе (всякой-разной), снятия скриншота и автоматической отправки всей этой инфы на мыло разработчикам. Компонент успешно работает в куче задач и майлы от юзеров приходят регулярно. То есть компонент выполняет все те функции, которые сотрудник отдела сопровождения обычно высняет у юзера:
1. Где произошла ошибка.
2. Что вы делали, перед тем как она произошла.
3. Что вы видите на экране.

И все бы было хорошо, если бы...
В общем фича в том, что адрес ошибки не всегда дает хорошее пояснение о причине ошибки.
Поясню примером:
Процедура1 (из юзерского интерфейса) вызывает Процедуру2(из какой-то общей библиотеки), та в свою очередь вызывает Процедуру3(из другой общей библиотеки). Процедура3 вызывает исключительную ситуацию, адрес которой я собственно и получаю.
Теперь следующий вариант:
Процедура4 (другой юзерский интерфейс) вызывает Процедуру2, та вызывает Процедуру3 которая вызывает исключительную ситуацию в том же месте, то есть с тем же адресом ошибки.
В общем, получается, что я не могу по адресу ошибки понять из какого юзерского интерфейса были произведены вызовы процедур возбуждающих exception.
А фиксить нужно именно юзерский интерфейс, для того чтобы при вводе юзером инвалидных данных давать ему человеческое объяснение, что он сильно заблуждается в данном конкретном случае, что по таким данным нельзя что либо рассчитать и почему.

А теперь собственно что касается моей идеи для решения этой ситуации: Как известно, при вызове процедуры из Delphi, в с стеке валяются переменные и адреса возврата в вызывающие процедуры. Реально ли написать дизассемблер и проанализировать код на предмет работы со стеком, для того чтобы выделить из него адреса возврата? Может быть существует какой нибудь еще способ определить вызывающие процедуры в Delphi?


Дата: Июл 26, 2004 11:38:39

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


Дата: Июл 26, 2004 11:44:19

Чисто теоретически да. Выдает же Soft Ice по команде stack спосок возвратов. В Delphi вроде как есть в настройках генерировать stack frames при это можно отследить через цепочку SEH.
Надеюсь я ничего не напутал. Если что профи меня поправят :)


Дата: Июл 26, 2004 14:41:40

Чисто практически это не всегда возможно, но с большой долей вероятности получить call stack не так уж и сложно - перребрать все адреса в стэке которые попадают в образ проги, и проверить что за нужное количество байт до адреса есть байты соответствующие опкодам call (E8, FF 15, FF D0, etc)


Дата: Июл 27, 2004 02:53:53

а что их перебирать? сканируем паять от EIP до RETN, при этом подсчитывая кол-во PUSH/POP и ADD/SUB ESP,xxx, после чего получаем тот адрес который должен быть снять со стека RETN (т.е. как бы пишем небольшой эмулятор CPU), перемещаемся по этому адресу в материнскую процедуру и повторяем ту же самую операцию пока не надоест. мы получим последовательность вызовов функций с аргументами...
естественно, стек должен быть не загажен и EIP/ESP валидны, что случается далеко не всегда. например, имело место переполнение буфера, которое и вызвало исключение. тогда EIP будет указывать черте-куда, в стеке будет черте-что... короче, мрак полный...
возьми любой отладчик в сорцах (хоть от юникса, хоть от винды, хоть от доса в прот-моде) - оттуда можно выдрать реализацию "раскрутки" стека, а можно использвоать и StackWalk из DBGHELP.DLL которая все сделает сама


Дата: Июл 27, 2004 09:03:10

В Delphi вроде как есть в настройках генерировать stack frames

MoKC0DeR, а можно чуть подробнее про это. Я поставил эту гайку, но что то не заметил изменений в стеке. Что такое stack frames?

Dr.Golova, kasperskyСначала я тоже думал анализировать пуши и попы. Но млин, "т.е. как бы пишем небольшой эмулятор CPU", вот именно, эмулятор CPU небольшим быть не может. А без, ну хоть и не эмулятора, а даже дизассемблера понять являетются ли данные опкодом или аргументом машинной инструкции не возможно, нужно ведь каким то образом все равно длинну инструкции расчитывать. А вот за идею анализации call-ов, Dr.Golova, большой респект. Вчера начал делать и уже хорошие результаты.
Сейчас, навскидку, вижу только 2 проблемы (которые еще не тестировал):

1. Передача в процедуру адреса процедуры, в качестве входного параметра.
2. Рекурсивный вызов процедуры.


Дата: Июл 27, 2004 09:04:08

2 kaspersky. Есть опыт написания эмулятора CPU?


Дата: Июл 29, 2004 02:47:00

> Сначала я тоже думал анализировать пуши и попы.
и еще ADD/SUB'ы, INC/DEC'и и RET x'ы, не говоря уже о всяком другом изврате...

> Но млин, "т.е. как бы пишем небольшой эмулятор CPU",
> вот именно, эмулятор CPU небольшим быть не может.
почему? если не брать в расчет хакерские программы, то для программ, созданных нормальными компиляторами, хватит проэмулировать десяток инструкций, остальные необходимо лишь декодировать (пока не декодируем, не сможем определить начало след. инструкции)

> А вот за идею анализации call-ов, Dr.Golova, большой респект.
к сожалению, этот метод не очень надежен и имеет много проблем... лучше уж юзать DBGHELP.DLL

> 1. Передача в процедуру адреса процедуры, в качестве входного параметра.
ну это как раз не проблема, т.к. адрес возврата указывает на конец call, а указатель на функцию как правило указывает на конец ret

> 2. Рекурсивный вызов процедуры.
ну и что? кол-во адресов указажет на кол-во вызовов функции до ее краха...


Дата: Июл 29, 2004 02:48:20

> Есть опыт написания эмулятора CPU?
а у кого его сейчас нет ;)
возьми хотя бы dos-box - там окейный эмуль ЦП с иходниками, который легко приспосоить под собственные нужды


Дата: Июл 29, 2004 03:50:59

> возьми любой отладчик в сорцах (хоть от юникса, хоть от винды, хоть от доса в прот-моде)

А можно глянуть сорцы винды, если мне память не изменяет там есть исходник дебаггера( may be Dr.Watson?)


Дата: Июл 30, 2004 08:45:03

1. Передача в процедуру адреса процедуры, в качестве входного параметра.
Всего лишь другой сall. Так как передающиеся процедуры (а точнее передаются только их адреса) это тоже параметры, то Delphi компилит call [ebp+xx]

2. Рекурсивный вызов процедуры.
(вообще не проблема)


Дата: Июл 30, 2004 09:03:02

Что же касается эмулятора CPU, то решение проблемы этим способом вообще не возможно, так как я имею только адрес, а значения части регистров потеряны.

Мне кстати пришла в голову идея, возможно не новая. А можно эмулировать в обратном направлении.
Ну то есть если мы встречаем

mov eax, [eax]

, то эмулировать будем как

mov [eax], eax

интересно, это возможно теоретически?


Дата: Июл 30, 2004 09:20:38

Zervide
„интересно, это возможно теоретически?“
только до того момента пока не встретим что-то типа and eax,ebx


Powered by miniBB 1.6 © 2001-2002
Время загрузки страницы (сек.): 0.151