Методы борьбы с BSOD для начинающих

Источник материала:  
14.05.2010 — Новости Hi-Tech
Курс молодого бойца

Так уж сложилось, что подрабатываю я в маленькой компании: студенческая жизнь не сахар, сами понимаете. Да и работа не пыльная - в зоне моей ответственности всего десять компьютеров и один сервер. Но в любой бочке меда найдется своя ложка дегтя: сервер работает под управлением Windows Server 2003, который умудряется "падать" чуть ли не каждый день, радостно приветствуя всех желающих синим экраном, а меня - высаживая на конкретную измену.

Руководствуясь принципом, что все хорошее уже придумали за нас, я полез в Интернет в поисках ответа на мучающий меня вопрос, как же бороться с бесконечными BSOD'ами, не перезагружая сервер по пять раз на неделе. И, как всегда, ответ лежал на поверхности: "Используй SoftICE - и будет тебе счастье", - сказали мне на форуме моего любимого wasm.ru. Но SoftICE - порочный путь, решил я, так как поддержка программы официально прекращена, и заставить ее работать под Windows 7, Vista или Server 2k8R2 - занятие крайне трудоемкое и к тому же мало оплачиваемое. Спасение пришло в виде термоядерного отладчика Syser, рекомендованного как качественная замена SoftICE на все том же сайте. Сказано - сделано: с www.sysersoft.com я скачал trial-версию отладчика и погряз в изучении исходного кода драйвера-убийцы, предложенного в качестве тестового примера. Кстати, не обольщайтесь - по ссылке "download freeware" на сайте компании вы скачиваете версию syser, которая умеет работать только в ring 3. Тестовая же версия рассчитана ровно на семь дней, после чего попросит вас либо купить лицензию (что я настоятельно рекомендую), либо удалить сам отладчик. Где взять деньги? Как мне кажется, любая приличная контора при правильном объяснении, куда же уйдут запрошенные средства, купит лицензию на использование отладчика. А если нет.... Задумайтесь, а стоит ли работать в такой компании?

Но вначале - немного истории. Помнится, в далеком прошлом борьбой с неприятельскими экранами смерти у меня на компьютерах занимался любимейший многими отладчик от компании NuMega, и назывался он SoftICE. Многие, включая автора этой статьи, познавали азы отладки именно в "мягком льде". Но настал злосчастный 2006 год, и отладчик тихо умер, так как поддержка его, осуществляемая компанией Compuware (к тому моменту купившей NuMega), была приостановлена. А в далеком-далеком Китае нашлись двое предприимчивых реверсеров, вовремя сообразивших, что отладчик уровня ядра, работающий в новой операционной системе от Microsoft, обязательно купят. И именно тогда Wu Yan Feng и Chen Jun Hao выпустили достойную замену SoftICE, назвав ее Syser Kernel Debugger. Унаследовав лучшее из своего предшественника, Syser успешно вышел на enterprise-рынок. Сочетая в себе подсветку листинга дизассемблера, абсолютно все команды из старичка SoftICE, работу с многопроцессорными системами и толковую поддержку юникода, отладчик от китайских разработчиков является полноценной заменой "мягкому льду". И именно за эти неоспоримые преимущества я и выбрал его героем сегодняшней статьи.

Как нам уже давно известно, театр начинается с вешалки, а Stop Screen (или же Blue Screen of Death ("синий экран смерти")) появляется в случае возникновения некой проблемы, решить которую самостоятельно ядро операционной системы не в состоянии. Это, кстати, кардинально отличает Windows-системы от их *nix собратьев. В то время, как правильные операционные системы выгружают из памяти модуль, из-за которого и возникла проблема, предпочитая впадать в kernel panic лишь в самых безвыходных обстоятельствах, Windows свято исповедует подход "где ошибка - там и BSOD". Конечно, если критическая ошибка, из-за которой и появляется stop screen, таится в дисковой подсистеме, то излечиться от этого достаточно трудно в любой ОС, и, зачастую, гораздо проще заменить весь сервер, чем оплачивать труд обслуживающего его администратора. Конечно, такое встречается крайне редко, чаще всего проблема носит куда более тривиальный характер, и камнем преткновения становится программное обеспечение, установленное пользователем либо администратором. Именно сторонний софт, к слову, открывает большинство брешей в безопасности, которые с удовольствием эксплуатируют хакеры.

Операционная система Windows намного безопаснее, чем принято считать в народе, и большинство ошибок в ней возникает именно благодаря стороннему программному обеспечению. В число "неблагонадежных" можно записать, как ни странно, также и драйверы. Производители железа зачастую выпускают на рынок "сырые" версии драйвера, дорабатывая его в обновлениях, но далеко не каждый администратор может позволить себе перезагружать сервер по десять раз на неделе. Ошибка в драйвере нашей звуковой карты не фатальна для операционной системы в целом, однако же суровые редмондские парни даже и не думают спрашивать нас, хотим ли мы продолжить работу, сходу убивая как саму ОС, так и десятки (или же сотни - кому что ближе) сторонних приложений. И, что самое главное, по закону подлости администратор практически никогда не успевает сохранить важные данные.

Если вы внимательно читали MSDN, то должны знать, что дамокловым мечом любой NT-подобной системы служит функция KeBugCheckEx, с нужными параметрами вызываемая ядром из тысячи мест. А если вдоволь "накуриться" NTDDK, мы узнаем, что KeBugCheckEx имеет всего пять аргументов, причем только BugCheckCode содержит проблемный код, а остальные четверо - лишь стороннюю информацию наподобие "в котором часу по местному времени вы могли наблюдать результат". И самое неприятное состоит в том, что под рукой всегда нужно иметь документацию (я уже который год использую для подобных целей PDA, пусть и говорят, что они безнадежно устарели), так как количество специфических BugCheck-аргументов достигает порядка сотни, а держать их все в памяти практически нереально. Возвращаясь к NTDDK, мы узнаем, что BugCheck-коды можно условно разделить на две подгруппы: первая содержит адрес машинной инструкции, вызвавшей исключение; вторая же, наоборот, не содержит, так как ядро диагностирует аварийную ситуацию на последней стадии, что затрудняет поиск "виноватой" инструкции. Представьте, что отладчик поймал надвигающийся stop screen, и вы точно знаете, из-за чего он, собственно, появился. За примером далеко ходить не надо: исключение произошло по адресу 1Eh:KMODE_EXCEPTION_NOT_HANDLED. В этом случае нам не составит труда заглянуть отладчиком прямиком на место катастрофы и буквально за несколько минут восстановить жизнеспособность системы, избежав тем самым и злосчастного синего экрана, и, как следствие, потери важных данных. Естественно, без глубокого знания ассемблера и опыта написания драйверов под NT-системы нам не обойтись. Но это же прекрасный повод вспомнить молодость!

А если все гораздо хуже? Если BugCheck, к примеру, C2h:BAD_POOL_CALLER? Конкретных данных о том, что стало причиной исключения, мы получить не в состоянии, и единственное, что доподлинно известно, - инструкция вызывается из функции распределения памяти. Теоретически можно перейти с ядерного режима на прикладной, где с разрушенным пулом мы сможем поработать минут пять-десять. Этого, в теории, должно хватить на то, чтобы успеть спасти какие-то данные, однако риск обрушения дискового тома сводит всю затею на "нет", заставляя компьютер уходить на перезагрузку, а нас - беспомощно откинуться на спинку кресла.

Но вернемся к нашим баранам. Внимательно изучив исходный код предлагаемого мне драйвера-убийцы, я собрал его при помощи штатного компилятора, входящего в состав NTDDK, который должен быть под рукой у любого уважающего себя Windows-администратора. Обидно, конечно, но поэкспериментировать на рабочем сервере мне никто не дал, а домашняя машина уже который год работает под управлением openBSD, так что я воспользовался старушкой VMWare, уже не раз меня выручавшей. В качестве гостевой операционной системы использовал Microsoft Windows XP Professional SP3, и проблем с установкой отладчика не возникло. Тот, кто хоть раз устанавливал SoftICE на виртуальную машину, думаю, меня поймет.

Предположим, что вы уже скомпилировали наш драйвер и вовсю жаждете приступить к экспериментам. Так чего же мы ждем! Загружаем отладчик и сразу же переходим в консоль, приказывая отладчику перехватывать вызов системной функции KeBugCheckEx командой "bmp KeBugCheckEx x". В прикладном режиме воспользуемся замечательной функцией отладчика, именуемой quick driver load, которая поможет нам загрузить в систему наш драйвер. Если читатель хоть немного знаком с ассемблером, то он уже понял, что драйвер обращается к памяти по нулевому указателю (что противоречит Windows-дхарме), соответственно, выполняя машинную команду MOV EAX, [EAX].

Естественно, обратившись к памяти таким образом, мы тутже получаем исключение, высаживающее операционную систему на конкретную измену. Дабы переместиться обратно на прикладной уровень 1Bh (а ядро работает с кодовым селектором 08h), необходимо сделать следующее: находим функцию KeBugCheckEx и командуем отладчику "d eip". После этого заменяем три первых байта на "С2h 14h 00h". В принципе, нам уже можно возвращаться на прикладной уровень, где, в относительном затишье, сохранить все данные и плавно уйти на перезагрузку. Но если попробовать изменить регистр CS с 08h на 1Bh? Как ни прискорбно, чаще всего это приводит к появлению синего экрана, что бы там ни писали на wasm.ru. Проверено на личном опыте. При наличии упорства и хорошей кармы сие действие можно повторять до бесконечности - рано или поздно можно дождаться штиля и продолжить работу в прикладном режиме. Но не кажется ли вам, что предложенный выше вариант намного более надежен?

С появлением Windows 7 и Windows Server 2k8R2 технологии борьбы с синими экранами шагнули далеко вперед, по сравнению с Windows Vista или, тем более, Windows XP. Но, все равно, универсальное решение для борьбы со stop screen, осенним листопадом падающих на компьютеры пользователей, еще не изобретено, поэтому стоит взять на вооружение вышеописанный метод - поверьте, он не раз спасет "жизнь" операционной системы, установив планку перезагрузки компьютера на отметку "раз-два в месяц". Но нет худа без добра: знание ассемблера все равно понадобится, а это лишний повод открыть запылившийся учебник!

Кристиан КАРМАК


Код драйвера
.686 .MMX .model flat, stdcall extern DbgPrint:PROC .code DriverEntry proc ; INT 03 push offset to_die CALL DbgPrint pop eax XOR EAX,EAX MOV EAX,[EAX]; //вызванный нами BSOD push offset happy CALL DbgPrint pop eax mov eax, 0C0000182h; STATUS_DEVICE_CONFIGURATION_ERROR; RET;  RETN 8; DriverEntry endp .data to_die DB "*] good die young! [*",0Dh,0Ah,0 happy DB "*] welcome to real world, boy! [*",0Dh,0Ah,0 mystring1 DD offset DriverEntry end DriverEntry

←Ликбез по GNU/Linux

Лента Новостей ТОП-Новости Беларуси
Яндекс.Метрика