8(495)909-90-01
8(964)644-46-00
pro@sio.su
Главная
Системы видеонаблюдения
Охранная сигнализация
Пожарная сигнализация
Система пожаротушения
Система контроля удаленного доступа
Оповещение и эвакуация
Контроль периметра
Система домофонии
Парковочные системы
Проектирование слаботочных сетей
Аварийный
контроль
Раздел: Документация

0 ... 86 87 88 89 90 91 92 ... 102

text:6C2991Bl

push

eox

: wMsgFilterMax

.text:6C299JC0

push

ebx

wMsgFil*„er.4in

.text.-602991X1

push

ebx

: hirtid

.text:6C2991C2

push

ebp

: lpMsg

.text:6C2991C3

cell

ds:PeekMessagcA

.text:6C299IC9

test

eax. eax

text:6C2991CB

jnz

short r.2k irasnlate main

text:6C299iCD

Таким образом, функция Run ожидает получить указатель на двойное слово, указывающее на таблицу виртуальных методов, элементы 0x19 и 0x1В которой представляют собой функции PumpMessage и IsIdleMessage соответственно (или переходники к ним). Адреса импортируемых функций, если только динамическая библиотека не была перемещена, можно узнать в том же дизассемблере; в противном случае следует отталкиваться от базового адреса модуля, отображаемого отладчиком по команде Modules. При условии, что эти две функции не были перекрыты программистом, поиск нужной нам виртуальной таблицы не составит никакого труда.

По непонятным причинам библиотека MFC42.DLL не экспортирует символьных имен функций, и эту информацию нам приходится добывать самостоятельно. Обработав библиотеку MFC42.LIB утилитой dumpbin, запущенной с ключом / ARCH, мы определим ординалы обеих функций (ординат PumpMessage — 5307, a IsIdleMessage - 4079). Остается найти эти значения в экспорте библиотеки MFC42.DLL (dumpbin /EXPORTS mfc42.dll > mfc42.txt), из чего мы узнаем, что адрес функции PumpMessage — 6C291194h, a IsIdleMessage — 6C292583h. Теперь мы должны найти указатели на функции PumpMessage/IsIdleMessage в памяти, а точнее — в секции данных, базовый адрес которой содержится в заголовке РЕ-файла, только помните, что в х86-процессорах наименее значимый байт располагается по меньшему адресу, то есть все числа записываются задом наперед. К сожалению, отладчик Microsoft Visual Studio Debugger не поддерживает операцию поиска в памяти, и нам приходится действовать обходным путем — копировать содержимое дампа в буфер обмена, вставлять его в текстовый файл и, нажав F7, искать адреса уже там.

Долго ли, коротко ли, но интересующие нас указатели обнаруживаются по адресам 403044h/40304Ch (естественно, у вас эти адреса могут быть и другими). Причем обратите внимание: расстояние между указателями в точности равно расстоянию между указателями на [EAX + 64h] и [EAX + 6Chl, а очередность их размещения в памяти обратна порядку объявления виртуальных методов. Это хороший признак, и мы, скорее всего, находимся на правильном пути (листинг А. 16).

Листинг А.16. Адреса функций IsIdleMessagq/PumpMessage, найденные в секции данных ОС403044 6C2911D4 6С292583 6С291194 : IsIdleMessage/PumpMessage 00403050 6C2913D0 6С299144 6С297129 ОЭ43305С 6С297129 6С297129 6С291А47


Указатели на адреса 403048h/40304Ch, очевидно, и будут «кандидатами» в члены искомой таблицы виртуальных методов класса CWinThread. Расширив сферу ц0. иска всем адресным пространством отлаживаемого процесса, мы обнаруживаем два следующих переходника (листинг А.17).

Листинг А.17. Переходники к функциям IsIdleMessage/PumpMessage, найденные там же

00401А20 jrro dword ptr ds:[403044h] IsIdleMessage

00401A26 jmp dwo-d Dtr ds:L403048h]

00401A2C jmp dword ptr ds:L40304Ch] : PumpMessage

Ага, уже теплее! Мы нашли не сами виртуальные функции, но переходники к ним. Раскручивая этот запутанный клубок (листинг А. 18), попробуем отыскать ссылки на 401A26h/401A2Ch, которые передают управление па приведенный ранее код.

Листинг А.18. Виртуальная таблица класса CWinThread

00403490:0С401А9Е 00401040 004015FO <г 0x0. 0x1. 0x2 элементы

0040349С00401390 004015F0 С0401А9В «- 0x3. 0x4. 0x5 элементы

004С34А800401А92 00401А8С 00401А86 <- 0x6. 0x7. 0x8 элементы

004034В400401А80 00401А7А 0С401А74 «- 0x9. ОхА. ОхВ элементы

904034CD00401010 00401А6Е 00401А68 «- OxC. OxD. OxF элементы

004034СС00401А62 00401А5С 00401А56 <- OxF. 0x10. 0x11 элементы

004034D800401А50 00401А4А 00401А44 «- 0x12. 0x13. 0x14 элементы

304334Е400401АЗЕ С04010В0 00401А38 <- 0x15. 0x16. 0x17 элементы

004Q34FO00401А32 00401А2С С0401А26 «- 0x18. 0x19. 0х1А элементы (PumpMessage)

C04034FC00401А20 0G401A1A 00401А14 «- 0x1В. OxlC. OxlD элементы (IsIdleMessage)

Даже неопытный исследователь программ распознает в этой структуре данных таблицу виртуальных функций. Указатели на переходники к PumpMessage/ IsIdleMessage разделяются ровно одним элементом, как того и требуют условия задачи. Предположим, что эта виртуальная таблица нам и нужна. Для проверки этого предположения отсчитаем 0x19 элементов вверх от 4034F4h и попытаемся найти указатель, ссылающийся на ее начало. Если повезет и он окажется экземпляром класса CWinThread, то программа сможет корректно продолжить свою работу:

ШС5СВ8 00403490 С0С00001 00000000 004050С4 00000000 00000000 00000001

Действительно, в памяти обнаруживается нечто похожее. Записываем в регистр ЕСХ значение 4050B8h, находим в памяти функцию Run (как уже говорилось, ео только она не была перекрыта, ее адрес - 6C299l64h — известен). НажиМ3 Ctrl+G, затем 0х6С299164 и в контекстном меню, вызванном правой к-павиШм мыши, выбираем Set Next Statement. Программа, отделавшись легким ucllBaCi продолжает свое исполнение, ну а мы на радостях идем нить пиво (кофе 1 чай — по вкусу).

Аналогичным путем можно вернуть к жизни и зависшие приложения, потер" шие нить управления и не реагирующие ни на мышь, ни на клавиатуру-


КАК ПОДКЛЮЧИТЬ ДАМП ПАМЯТИ

...в отделе программ весь пол был усеян дырочками от перфокарт, и какие-то мужики ползали по раскатанной по полу 20-метровой распечатке ааарийного дампа памяти с целью обнаружения ошибки в распределителе памяти ОС-360. К президенту подошел начальник отдела и сообщил, что есть надежда сделать это еще к обеду.

Ю. Антонов. «Юность Гейтса»

Дамп памяти (memory dump, также называемый корой [от английского core — «сердцевина»], crash- или аварийным дампом), сброшенный системой при возникновении критической ошибки, — не самое лучшее средство для выявления причин катастрофы, но ничего другого в руках администратора зачастую просто нет. Последний «вздох» операционной системы, похожий на дурно пахнущую навозную кучу, из которой высовывается чей-то наполовину разложившийся труп, мгновенным снимком запечатленный в момент неустранимого сбоя, — вот что такое дамп памяти! Копание в нем вряд ли доставит вам удовольствие. Не исключено, что истинного виновника краха системы вообще не удастся найти. Допустим, некий некорректно работающий драйвер вторгся в область памяти, принадлежащую другому драйверу, и наглым образом затер критические структуры данных, сделав из чисел винегрет. К тому моменту, когда драйвер-жертва пойдет вразнос, драйвер-хищник может быть вообще выгружен из системы, и определить его причастность к крушению системы но одному лишь дампу практически нереально.

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

Первым делом необходимо войти в конфигурацию системы — Панель управления ► Система (Control Panel ► System) и убедиться, что настройки дампа соответствуют предъявляемым к ним требованиям — Дополнительно ► Загрузка и восстановление ► Отказ системы (Startup ► Shutdown ► Recovery) в Windows 2000 RUS и (Windows NT 4.0 ENG) соответственно. Операционная система Windows 2000 поддерживает три разновидности дампов памяти:

•малый дамп памяти (small memory dump);

•дамп памяти ядра (kernel memory dump);

•полный дат памяти (complete dump memory).

Для изменения настроек дампа вы должны иметь права администратора. МАЛЫЙ ДАМП ПАМЯТИ

Малый дамп памяти занимает всего 64 Кбайт (а отнюдь не 2 Мбайт, как утверждает контекстная помощь) и включает в себя:



0 ... 86 87 88 89 90 91 92 ... 102