drivers

колем дрова без помощи топора

крис касперски, ака мыщъх, akasouriz, no-email

если бы Microsoft строила автомобили, или здания… нашей цивилизации уже бы давно пришел конец. а все потому, что Microsoft _никогда_ бы не стоила ни того, ни другого. максимум предоставляя железобетонный каркас с шасси, на которых инженеры-пионеры цепляют что-то совершенно непотребное. в пресловутых экранах смерти и нестабильной работе Windows в подавляющем большинстве случаев виноваты драйвера _сторонних_ производителей и сейчас мыщъх расскажет как их обнаружить и удалить из системы

Дефекты проектирования драйвером могут носить самый разный характер от выпадений в голубой экран смерти (BSOD – BlueScreenofDeath), до замедления работы компьютера и странностей поведения некоторых, совсем не связанных с драйвером прикладных приложений.

Голубой Экран Смерти замечателен (без всякой иронии!) тем, что явным образом сигнализирует о наличие серьезной проблемы и дает наводку откуда рыть. Зачастую (но далеко не всегда) имя «провинившегося» драйвера высвечивается непосредственно в правом верхнем углу Экрана Голубой Смерти (см. рис. 1), однако, там его может и не быть или, что еще хуже, стоят имя совершенно постороннего драйвера.

Рисунок 1 Голубой Экран Смерти, высвечивающий имя сбойного драйвера (в данном случае w2k_kill.sys)

В частности, на мыщъх'иной машине драйвер от видео-карты Matrox G450 имеет тенденцию разрушать базовые структуры графической подсистемы Windows 2000, в результате чего, в BSOD'е отображается имя системного драйвера win32k.sys (см. рис. 2), в котором реализована значительная часть функций USER и GDI и который, естественно, тут совсем ни при чем. Так что интерпретация показаний Экраном Голубой Смерти это и магия, и интуиция, и наука, и искусство — всего понемножку.

Рисунок 2 Голубой Экран Смерти, высвечивающий имя базового системного драйвера (win32k.sys), пострадавшего из-за нападки другого драйвера, который нам еще предстоит найти

Помимо дефектов драйверов, Голубые Экраны Смерти могут так же вызываться отказами железа, например, разогнанным процессором, неисправной оперативной памятью, кривым контроллером жесткого диска, не до конца воткнутой в слот PCI-картой, неконтактом в одном из разъемов, плохим блоком питания, «вздутых» электролитических конденсаторов на материнской плате (а дуются они по разным причинам: перегрев от рядом расположенного процессора, недостатком керамических конденсаторов, «недоложенных» производителем, в результате чего ВЧ-составляющая идет через электролит и сильно его разогревает, наконец, утечкой ключевых транзистор в узле стабилизатора).

Поэтому, прежде, чем колоть дрова необходимо убедиться, что железо, на котором мы сидим полностью исправно. А как это можно сделать?

Голубые Экраны Смерти, вызванные сбоями железа, носят стихийный характер, появляясь в непредсказуемое время, не связанное ни с какими конкретными действиями пользователя. Прикладные приложения так же начинают выдавать критические ошибки в самых разных местах, причем (и это самое главное!) коды ошибок, адреса и другая информация выдаваемая системой во всех случаях будет различной!!! (Кстати говоря, драйвера, обрабатывающие асинхронные запросы от устройств ввода/вывода, например беспроводных сетей, ведут себя практически точно так же). Голубые Экраны Смерти, вызванные дефективными драйверами, как правило, возникают при совершении определенного набора действий и содержат более или менее постоянную информацию.

Чтобы снять с железа все подозрения, достаточно подключить к системе еще один жесткий диск, установить на него девственно чистую Windows и поработать на ней некоторое время. Если Голубые Экраны Смерти не исчезнут, значит, действительно, виновато железо и его пришла пора менять. Поиск дефективных компонентов — тема для отдельного разговора, который мы оставим на следующий раз, а пока, засучив рукава, вплотную возьмемся за эти коварные драйвера.

Весь комплект инструментария, необходимый для разработки драйверов (DDK – DriverDevelopmentKit) Microsoft бесплатно распространяет бесплатно вместе с сопутствующей ему документацией, позволяющий любому заточить «как бы» драйвер, с позволения сказать, «как бы» работающий, то есть, ни хвоста не работающий, а постоянно падающий.

Вот чтобы этого беспредела не происходило, Microsoft еще в годы неопалита ввела процедуру сертификации драйверов на соответствие предъявляемых к нем требованиям, после которой драйверу выдавалась цифровая подпись, или… не выдавалась и он отправлялся на доработку. И хотя сертификация — всего лишь формальная процедура, не гарантирующая отсутствие фатальных ошибок и дефектов разработки, часть откровенно «пионерских» драйверов она все-таки отсеивает.

В идеале, в системе следует держать только драйвера, заверенные цифровой подписью. И хотя цифровая подпись ‑ не страховой полис, ее наличие уже указывает на определенный уровень культуры разработки. Драйвера без цифровой подписи — это хуже, чем кот с кошкой в мешке и от них по возможности следует избавляться (тем более, что многие из них являются зловредными программами, устанавливаемыми rootkit'ами или агрессивными защитными механизмами, глубоко проникающих в систему и вызывающих ее нестабильность). Короче, не будет разводить демагогии, а попробуем ответить на один простой вопрос — как составить список драйверов без цифровой подписи?

В этом нам поможет утилита «sigverif.exe», входящая в штатный комплект поставки операционной системы и располагающаяся в каталоге WINNT\System32. Запускаем ее и видим следующее диалоговое окно (см. рис. 3).

Рисунок 3 штатная утилита sigverif.exe для поверки цифровой подписи драйверов и прочих системных файлов

Нажимаем кнопку «Дополнительно» и во вкладке «Поиск» настраиваем критерии отбора, перемещая радио-кнопку из положения «уведомлять о неподписанных системных файлов» (где она и прозябала по умолчанию) в положение «искать другие файлы, не подписанные цифровой подписью» (см. рис. 4), после чего в «параметрах поиска» открываем бокс «искать файлы следующего типа» и выбираем «*.sys», а ниже указываем папку для поиска «C:\WINNT», _обязательно_ отметив галочку «включая подпапки».

Рисунок 4 задание параметров поиска неподписанных драйверов

Вообще-то, строго говоря, драйвера не обязаны иметь расширение sys и далеко не всегда ограничиваются каталогом «WINNT», находясь в каталогах «своих» приложений, а некоторые приложения и вовсе хранят драйвера… внутри себя! Сразу же после запуска (или в любое другое время) они сохраняют файл на диск в текущую или временную директорию, загружают драйвер в память и… тут же удаляют его с диска! Так поступают не только зловредные вирусы, но и вполне респектабельные программы, вроде некоторых утилит известного исследователя недр Windows Марка Руссиновича.

Поэтому, для чистоты эксперимента нам совсем не помешает получить список драйверов, находящийся в данный момент в памяти и сравнить их с драйверами, находящимися на диске. Слова «в данным момент» ключевые, поскольку, загрузка/выгрузка драйверов может происходить бесплатно _без_ перезагрузки операционной системы, эту операцию желательно выполнить несколько раз, запуская утилиту командной строки «drivers.exe», входящую в состав DDK, который можно бесплатно скачать с сервера копании Microsoft.

Запущенная без каких-либо ключей командой строки, утилита drives.exe вываливает всю информацию на экран, что не есть хорошо, поскольку драйверов в системе обычно присутствует _очень_ много и на экран они не помещаются (см. рис. 5), однако, религия нам позволяет перенаправить поток вывода в текстовой файл («drivers.exe >file-name.txt»), открываемый любым текстовым редактором — хоть Word'ом, хоть «Блокнотом». Затем остается только выделить вертикальный блок (чего «Блокнот» не позволяет) и получить список драйверов. Готовенький! Только что из топки! В смысле прямо из ядра операционной системы!

Рисунок 5 построение списка загруженных драйверов с помощью утилиты drivers.exe из комплекта поставки DDK

Если хотя бы один из этих драйверов отсутствует в каталоге C:\WINNT\, то его цифровая подпись проверена не будет!!! Естественно, такой драйвер сразу же привлекает к себе внимание и у нас появляется резонный вопрос — откуда он берется? Сначала сканируем все каталоги на диске и если его там нет, устанавливаем точку останова на функцию CreateFileW в soft-ice и смотрим на передаваемые ей аргументы. Рано или поздно мы встретим наш «незаконнорожденный» драйвер, после чего останется только взглянуть в правый нижний угол экрана soft-ice, где высвечивается имя процесса, породившего его. Впрочем, описание процесса поиска «незаконнорожденных» драйверов выходит за рамки данной статьи. Интересующихся мы отошлем к мыщъхиной книге «техника отладки программ без исходных текстов», электронную копию которой можно найти в мыщъхиной норе на ftp сервере nezumi.org.ru, так же в процессе написания этой статьи, мыщъх воздвиг http сервер, находящийся по тому же адресу — nezumi.org.ru – и пока работающий в тестовом режиме. Так что желающие приглашаются на раскурку травы, а с остальными мы продолжим терзать утилиту sigverif.exe.

После нажатия на «ОК», «Пуск» на экране появится градусник, отображающий ход прогресса и жесткий диск начнет шуршать всеми своими головками, какие у него только есть (см. рис. 6).

Рисунок 6 отображения хода прогресса проверки цифровой подписи драйверов

По завершении работы будет составлен список драйверов _без_ цифровой подписи и выведен на экран (см. рис. 7).

Рисунок 7 список драйверов, не заверенных цифровой подписью

Некоторые горячие головы предлагают в порядке очищения системы от ереси, удалить все неподписанные драйвера, тогда, мол, все проблемы как хвостом снимет. А как их можно удалить? Самое грубое решение — просто взять их и удалить с диска через FAR'а или проводника (естественно, обладая правами администратора!), но… последствия такой операции могут оказаться весьма плачевными и лучше, кликнув правой клавишей мыши на иконку драйвера в проводнике, найти в «свойствах» имя производителя, по которому можно установить что за приложение/железка установила этот драйвер и де-инсталлировать ее цивилизованным путем, правда, здесь есть одно «но».

На приведенном виде рисунке 7, выделен драйвер g400m.sys, идущий вместе с картой Matrox G450, и несмотря на то, что Matrox совсем не хилая компания, цифровую подпись она не получила (то ли Microsoft не дала, то ли сама Matrox не захотела заморачиваться). Естественно, после удаления его из системы, о SVGA режиме придется забыть. Можно, правда, сходить к самому Matrox'у, скачав самую последнюю версию драйвера (она уже снабжена цифровой подписью), только вот… и подписанная, и неподписанные версии содержат множество фатальных ошибок, в частности, при стечении определенных обстоятельствах при попытке перейти в overlaymode, система падает в BSOD, поскольку драйвер пытается освободить уже освобожденную память.

Таким образом, наличие/отсутствие цифровой подписи само по себе еще ни о чем не говорит и даже если мы используем только подписанные драйвера, никаких гарантий стабильности это нам не дает.

Вот тут-то мы и переходим ко второй части статьи, а именно — тестированию драйверов в условиях, приближенным к боевым.

В состав DDK входит замечательная утилита «DriverVerifier», ставящая драйвера раком, то есть создающая для них максимально суровые условия, граничащие с суицидом и экстремалом, в которых вероятность отказа — максимальна, а имя дефективного драйвера определяется с наивысшей точностью (даже если он из-за дефектов разработки не страдает сам, но рушит структуру данных чужих драйверов).

Важно отметить, что «DriverVerifier» — это не лекарство, а только средство диагностики. От сбоев оно все равно не спасет (напротив, увеличит их интенсивность на пару порядков), но зато поможет выявить «подлый» драйвер с достаточной степенью достоверности.

Итак, запускаем «verifier.exe», видим окно «DriverVerifierManager», идем в закладку «Setting» (см. рис. 8) и переводим радио-кнопку в положение «Verifyalldrivers», после чего давим кнопку «Preferred Setting», устанавливающую следующие типы проверок («verification type»): «Specialpool» – проверяем драйверам будет отведена специальная область памяти для выделения, не очень быстро работающая, зато способная обнаруживать большинство типов разрушений своих и чужих данных; «Force IRQL checking» – IRQL это уровень запроса прерываний (InterruptRequestLevel), и _наиболее_ частой ошибкой разработчиков драйверов является попытка обратится к памяти на таком уровне IRQL, на котором менеджер подкачки не работает и если требуемая страница вдруг окажется вытесненной на диск, система обручится в голубой экран с надписью «IRQL_LESS_OR_EQULAR», форсирование этого режима принудительно вытесняет страницы драйвера на диск, чтобы дефект разработки проявлялся в 100% случаев. Так же полезно взвести галочку «Lowresourcesimulation», чтобы посмотреть как драйвер будет вести себя при катастрофической нехватке системных ресурсов, однако, этого можно и не делать, а вот галочку «Pooltracking» (отслеживание корректности обращения с пулом памяти лучше оставить). Ошибки ввода/вывода («I/Overification») составляют ничтожную часть от ошибок других типов, поэтому положение этой галки в общем-то совершенно некритично.

Покончив с выбором настроек, нажимаем кнопку «Apply» (применить) и, как нам и предлагают, перезагружаемся.

Рисунок 8 выбор проверяемых драйверов и типов проверок

Сразу же после начала загрузки, работа системы _ощутимо_ замедлиться, но это так и должно быть, поскольку сейчас ядро выполняет намного больше проверок чем обычно. При обнаружении ошибок вспыхивает Голубой Экран Смерти с имеем драйвера и некоторой другой информацией, полезной для разработчиков, но бесполезной для нас. Все, что мы можем сделать — обновить драйвер до самой последней версии или отказаться от использования программы (железки), использующей его. Вообще-то, у нас имеется чуть-чуть больше возможностей по розжигу сырых дров, но об этом — чуть позже.

Узнать статус проверки можно в любой момент запуском verifier.exe. В закладке «DriverStatus» перечислен статус всех обнаруженных драйверов с пояснением текущей оперативной ситуации. Статус «Loaded» означает, что данный драйвер был загружен и проверен по крайней мере один раз (но, возможно, не полностью, т. е. не все участки драйвера успели отработать). Статус «Unloaded» готовит о том, что драйвер был загружен, проверен (по крайней мере частично) и выгружен системой/программой, использующей его, или по своему собственному желанию. Последнее особенно характерно для драйверов, оставшихся от оборудования которое было удалено путем варварского выдергивая платы расширения из слота, т. е. без выполнения деинсталляции. Оставшийся в живых драйвер сканирует шину, пытаясь нащупать «свое» оборудование, обламывается с поиском, после чего выгружает себя из памяти, кстати говоря, замедляя загрузку системы (иногда очень значительно) и конфликтуя с другими драйверами. Однако, не всякий статус «unloaded» признак ненормальности ситуации и прежде, чем удалять такой драйвер, сначала нужно разобраться что это за северный олень такой и откуда от вообще тут взялся, понимаешь.

Статус «NeverLoaded» указывает на то, что данный драйвер еще не был загружен, а значит, не был и проверен, следовательно, надо подождать, запуская различные программы, которые могут быть с ним связаны. Впрочем, некоторые драйвера (особенно некорректно деинсталлированные) не загружаются и, соответственно, не проверяются никогда.

Рисунок 9 просмотр текущего статуса проверки

Поработав с системой в режиме «жесткой проверки» некоторое время (от нескольких часов до нескольких дней) мы выявим практически все дефектные драйвера, от которых страдали ранее, записав их имена на бумажку.

Вернуть систему нормальный режим (т. е. без дополнительных проверок, сжирающих производительность), можно с помощью все того же verifier'а. Возвращаемся к закладке «Setting», переводим радио-кнопку в положение «Verifyselecteddrivers» (при этом никакой драйвер не должен быть выделен), давим на «ResetAll», затем «Apply» и перезагружаемся. Все! Теперь система работает с нормальной скоростью, но без проверок.

А, действительно, что можно сделать с дефектным драйвером? Хакеры, умеющие держать отладчик в руках, при наличии достаточно количества свободного времени, могут дизассемблировать драйвер (благо, по объему драйвера обычно небольшие), найти ошибку, и придумать способ как ее исправить, но… это слишком сложный и трудоемкий путь.

Выбрасывать драйвер (вместе с тем железом/программой, что его использует) тоже не вариант, хотя… если известно, что в Голубых Экранах Смерти виновата звуковая карта неизвестного китайского производителя за 20$, то у нас появляется вполне весомая мотивация ее заменить на что-то более достойное. Но это, собственно говоря, всем и так понятно и в дополнительных комментариях не нуждается.

Зато далеко не каждый знает, что огромное количество сбоев и Голубых Экранов Смерти связано с тем, что драйвер, разработанный (и протестированных) в однопроцессорной среде, ставят на двухпроцессорную машину. Под «двухпроцессорностью» здесь понимается как реальная платформа с двумя камнями, так и Hyper-Threading/многоядерные процессоры. Известно (и подтверждено большим количеством тестов), что домашнему компьютеру два процессора совершенно ни к чему и на подавляющем большинстве приложений увеличение производительности практически не наблюдается.

Поэтому, если система работает нестабильно, а избавиться от дефектного драйвера по тем или иным обстоятельствам никак не удается, можно попробовать залезть в BIOS Setup, превратив свою «виртуальную двухпроцессорную» машину в «однопроцессорную». Аналогичного эффекта можно добиться, открыв файл boot.ini (на компьютерах с Windows NT, Windows 2000 и Windows XP он расположен в корневом каталоге логического диска, на котором установлена система) и добавить к нему ключ /ONECPU (см. листинг 1), после чего перезагрузиться, в надежде, что ошибки исчезнут.

[boot loader]

timeout=30

default=multi(0)disk(0)rdisk(0)partition(1)\WINNT

[operating systems]

multi(0)disk(0)rdisk(0)partition(1)\WINNT=«Windows 2000 Pro» /fastdetect /SOS

Листинг 1 пример типичного файла boot.ini

[boot loader]

timeout=30

default=multi(0)disk(0)rdisk(0)partition(1)\WINNT

[operating systems]

multi(0)disk(0)rdisk(0)partition(1)\WINNT=«Windows 2000 Pro» /fastdetect /SOS /ONECPU

Листинг 2 пример файла boot.ini, настраивающего систему на использование только одного процессора из всех имеющихся

А вот на Windows Vista файла boot.ini нет и хотя существует (временная) возможность сконфигурировать ее загрузочные настройки с помощью специальной утилиты, Microsoft планирует полностью отказаться от этой лазейки, так что остается только BIOS Setup. Впрочем, что касается Vista, то к моменту перехода на нее, разработчики драйверов наверняка обзаведутся многопроцессорными машинами (поскольку, других просто не останется в продаже) и будут тестировать свои изваяния в многопроцессорном окружении.

Еще один тонкий момент. Помните, мы выше говорили, что наиболее часто встречающаяся ошибка разработчиков драйверов — обращение к вытесняемой памяти на том уровне IRQL, на котором менеджер подкачки не работает и если запрашиваемая страница отсутствует в памяти наступает крах? Очевидным решением будет увеличение оперативной памяти до того объема, при котором вытеснение страниц на диск практически не происходит. При нынешних ценах на память прикупить пару новых «плашек» может позволить себе практически каждый. Но существует и более дешевое (и более элегантное) решение проблемы. А именно — если параметр «DisablePagingExecutive», находящийся в следующей ветке реестра HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\MemoryManagement, равен 1 (по умолчанию 0), ядерные компоненты вытесняться не будут! Просто запускаем Редактор Реестр, меняем этот заветный параметр и перезагружаемся (изменения вступают в силу только после перезагрузки), надеясь, что это поможет решить проблему сбоев. А быть может и нет…

То, что операционные системы семейства Windows (вместе со всем их окружением) падучи и нестабильны — факт, не требующий доказательств. Но вместо того, чтобы ругать Билла Гейтса и криворуких программистов, лучше попробовать разобраться в проблеме и устранить ее самостоятельно. Это гораздо эффективнее любых матерных слов и проклятий.