Издательский дом ООО "Гейм Лэнд"ЖУРНАЛ ХАКЕР #85, ЯНВАРЬ 2006 г.

Жизнь после BSOD

Крис Касперски и Жирный Хомяк

Хакер, номер #085, стр. 085-114-3


[фрагмент драйвера-убийцы, пытающийся прочитать двойное слово по нулевому указателю из режима ядра]

NTSTATUS DriverEntry (PDRIVER_OBJECT pDriverObject,

PUNICODE_STRING pusRegistryPath)

{

return *((NTSTATUS *) 0);

}

Ну и зачем было ронять систему из-за такой ерунды?! Кому наш страшный убийца реально мешает?! Ведь целостность системы ничуть не пострадала! Как объяснить этой тупой NT, что в Багдаде все спокойно? Пора бы вернуться в user mode и продолжить работу в штатном режиме.

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

Если нажать «x» (или <Ctrl-D>), то немедленно после выхода из SoftICE вспыхнет синий экран, и чинить тогда будет уже нечего. Но пока мы находимся в отладчике еще можно кое-что предпринять. А предпринять можно следующее:

1) Определить место сбоя (обращение по нулевому указателю), исправить ситуацию (установить валидный указатель), вручную выйти из обработчика исключения, вернув CS:EIP на прежнее место: способ хороший, но, увы, требующий определенного интеллекта, которого у машины нет.

2) Зациклить текущий поток, воткнув в свободное место jmp $ и выйти из отладчика, разрешив прерывания командной r fl=I (если они вдруг были запрещены). Все будет ужасно тормозить, но ось продолжит работать и мы по крайней мере сможем корректно завершить ее работу.

3) Дождаться вызова функции KeBugCheckEx и сразу же выйти из нее, проигнорировав сбой и продолжив нормальное выполнение, правда, никаких гарантий, что система не рухнет окончательно, у нас нет.

4) Способ, предложенный ms-rem, дикий, но иногда работающий: отдать команды r eip=0/r cs=1B, переключающие процессор на прикладной режим.

Короче, вариантов много. Попробуем для начала воспользоваться первым способом. Мы знаем, что в данном случае авария произошла из-за ошибки нарушения доступа. Следовательно, процессор возбудил исключение, забросил на вершину стека EIP/CS/FLAGS и передал управление обработчику исключений, внутри которого мы сейчас и находимся.

Даем команду "d esp" для отображения содержимого стека и видим (для удобства рекомендую переключить окно дампа в режим двойных слов, воспользовавшись командой "dd"):

:d esp

0010:F7443C88 BE67C000 00000008 00200202 804A4431 ..g....... .1DJ.

0010:F7443C98 81116AD0 8649D000 BE8F1D08 BE8F1D08 .j....I.........

0010:F7443CA8 81480020 F7443D34 745FFFFF 83A49E60 .H.4=D..._t`...

Адрес инструкции, возбудившей исключение, лежит в первом двойном слове - BE67C000h (у тебя это значение наверняка будет другим). Селектор CS идет следом. Он должен быть равен 08h. Третье двойное слово хранит содержимое регистра флагов - EFLAGS.

Теперь мы знаем место сбоя и можем вывести дизассемблерный листинг на экран. В этом нам поможет команда "u *esp" (дизассемблировать содержимое памяти по адресу, который содержится в регистре esp) или "u be67c000":

[определение реального места сбоя]

:u *esp

0023:BE67C000 MOV EAX,[00000000]

0023:BE67C005 RET 0008

0023:BE67C008 NOP

Назад на стр. 085-114-2  Содержание  Вперед на стр. 085-114-4