Жизнь после BSOD Крис Касперски и Жирный Хомяк Хакер, номер #085, стр. 085-114-4 0023:BE67C009 NOP 0023:BE67C00A NOP 0023:BE67C00B NOP Вот она! Инструкция, вызвавшая сбой! А давай ее перепрыгнем, продолжив выполнение с RET 08h? Сказано - сделано. Но для начала нужно выйти из обработчика исключения. Для этого в SoftICE необходимо выполнить следующие команды: 1) r eip = *esp + sizeof(mov eax,[0]); // устанавливаем регистр EIP на RET 2) r cs = *(esp + 4); // устанавливаем селектор CS (не обязательно) 3) r FL = I; // разрешаем прерывания; 4) r esp = esp + C // снимаем со стека 3 двойных слова, заброшенные туда CPU 5) x // выходим из отладчика После выполнения этой магической последовательности команд, система продолжит свою нормальную работу, и синий экран уже не появится. Фантастика! Невероятно! Мы только что избежали гибели, которая казалась неотвратимой! Один маленький нюанс. Моя (и, возможно, твоя) версия SoftICE не умеет восстанавливать регистр ESP в обработчике исключения. Отладчик игнорирует команду r esp=esp +C, на самом деле только имитируя ее выполнение! А это значит, что стек остается несбалансированным, и, несмотря ни на какие усилия медиков, система все-таки грохается. Приходится хитрить. Мы видим, что за RET 08h расположена длинная цепочка NOP'ов. А что если воткнуть сюда команду "ADD ESP,0Ch", чтобы стек сбалансировал сам процессор? Говорим отладчику 'A BE67C008' (ассемблировать, начиная с адреса BE67C008) и вводим следующее: ADD ESP,0C<ENTER>JMP BE67C005<ENTER> и еще один <ENTER> для завершения ввода. Переустанавливаем EIP на начало нашей заплатки - r eip = BE67C008 и выходим из SoftICE. На этот раз у нас все получается! Вот последовательность команд по реанимации системы. Напоминаю, что она применима только в этом случае: [реанимация системы в условиях, приближенных к боевым] u *esp r eip = *esp r eip = eip + 9 a eip add esp,0c jmp BE67C005h ; адрес команды RET 8, в твоем случае будет другим <ENTER> r fl=I x [автоматизируем нашу работу] Способ ручного восстановления, только что описанный выше, хорошо сочетается с духом системных программистов, постоянно пасущих SoftICE и умеющих фехтовать регистрами, как рапирой. А вот простым юзерам такой подход смерти подобен. Но почему бы нам не написать для них утилиту, зацикливающую сбойный поток или замыкающую KeBugCheckEx? Написать такую штуку несложно (и мы действительно напишем ее), но это все равно, что подложить полено под аварийный клапан. Если система пойдет вразнос, ее уже ничего не остановит. Может пострадать даже файловая система (пусть это будет хоть NTFS). Конечно, вероятность такой трагедии крайне мала, но она все-таки возможна - имей это в виду. Тем не менее, рискнуть все-таки стоит, особенно в тех случаях, когда ты уверен, что это можно сделать. Вот, например, возник у меня как-то конфликт между криво написанным драйвером DSL-модема и драйвером видеокарты, а из-за этого при просмотре видео иногда выскакивал BSOD. Поскольку нормальных дров найти не удалось, я временно ограничился тем, что закоротил KeBugCheckEx перемычкой, изготовленной из команды JMP и, ты не поверишь, это прижилось! |