Данный материал представляет собой своего рода исследование, попытку разобраться в одной, набившей уже оскомину, загадке этапа загрузки операционной системы Windows. Многие специалисты согласятся со мной, что на практике довольно часто приходится наблюдать сбой при котором станция, загружаясь в безопасном режиме, отображает на экране монитора список загруженных драйверов (последним из которых часто выводится classpnp.sys) и сообщение "Подождите, пожалуйста...", после чего благополучно подвисает:
При этом, та же проблема имеет зеркальное отображение и в обычном (нормальном) режиме загрузки: в редких случаях загрузка останавливается на анимированном логотипе (значке) Windows (bootscreen), который может "видоизменяться" на экране приветствия бесконечно долго:
намного чаще же система подвисает на более позднем этапе, когда на черном фоне остается графический курсор мыши:
Настроение в этот момент, надо признаться, стремительно падает, поскольку приходит понимание, что это один из самых тяжелых общих случаев в практике любого технического специалиста и, по традиции, предстоит много работы. Подобного рода сбои относятся к категории общих не случайно, поскольку причиной их возникновения является целый комплекс источников, поэтому, в идеале, они тянут за собой диагностику аппаратного и программного уровней персонального компьютера. Сама по себе процедура диагностирования непроста, до сих пор не выработано какого-либо универсального алгоритма, а значит нас опять ждет копание в заметках, занудные поиски в Сети в надежде составить матрицу решений, одно из которых должно дать положительный результат. Ну что же, время принятия кардинальных решений рано или поздно настает.
Теория
На данный исторический момент уровень моих знаний оставляет желать лучшего, тем не менее, все же попытаемся выйти за привычные рамки теории. В очередной раз не перестаешь удивляться отсутствию у одной из самых популярных настольных операционных систем продуманной диагностической подсистемы. Удивляюсь, конечно же, не я один.. на официальных форумах Microsoft по теме зависания на classpnp.sys можно встретить достаточно много вопросов, к примеру, пользователь с ником Дима_413 пишет:
Справедливо, поскольку зависание на classpnp.sys, наряду с черным экраном смерти и штормом прерываний, является примером недоработок в архитектуре системы Windows 7, вероятно ведущих свою родословную из недостатков архитектуры x86. Странно другое, ведь на ранних стадиях загрузки операционной системы (начиная с кода сектора MBR, Bootmgr) уже обеспечена простая диагностика, которая выводит сообщения в текстовом режиме в качестве реакции на ошибки. Получается, что отсутствие подобного подхода при зависании на classpnp.sys наблюдается по причине возникновения блокировок в коде ядра в части обработки ошибок/таймаутов от сторонних драйверов [устройств] на раннем этапе загрузки, вероятно разработчики посчитали подобный код бессмысленными, поскольку он все-равно не сможет отработать? Поэтому:
Во всех ветках обсуждений на тему зависания на classpnp.sys, найденных в Сети, все обычно сводится к рассуждениям относительно природы этого драйвера, структуры, функциональных задач, роли, которую он играет в процессе загрузки и, главное, как можно привести его (обратно) в работоспособное состояние? Очевидно что драйвер уже однозначно определен в виновники происходящего зависания, при том, что во всех дискуссиях попросту отсутствует исследовательская (практическая) доказательная часть, что, конечно же, понижает объективность данных теорий. Ну что же, давайте и мы последуем в рамках описанного "слепого" тренда и начнем повествование с попытки описания функциональных особенностей драйвера.
Что есть сам classpnp.sys?
Из определения следует, что любой драйвер, относящийся к классу устройств хранения информации (магнитных, ленточных, оптических), использует функции данной библиотеки в процессе функционирования. Действительно, образ представляет собой типовую системную библиотеку (DLL), содержащую набор устройствонезависимых процедур (функций), используемых классом отмеченных ранее устройств. Похоже что данная библиотека - это библиотека, функции которой используются всеми драйверами накопителей (устройств хранения) в операционной системе Windows. Библиотека обеспечивает для системных/сторонних драйверов уровня ядра общие процедуры работы с устройствами хранения на уровне обслуживания пакетов IRP, поддержки функций PnP и управления питанием, выполнения общих алгоритмов работы с памятью, чтения, записи, инициализации, конфигурации устройств, работа с уровнями IRQL, обработку ошибок и много прочей аналогичной необходимой требухи.
В Windows XP и последующих операционных системах, некоторые из наиболее часто используемых сервисов, ранее предоставляемых прямыми вызовами к библиотеке classpnp.sys, теперь предоставляются драйвером класса. Поэтому в Windows XP (и более поздних системах) обычно нет необходимости прямого вызова функции classpnp.sys из сторонних минипорт-драйверов.
Ну что же, бегло ознакомились с функциональными особенностями мнимого виновника торжества? Теперь нам необходимо разобраться со структурой данного "драйвера", понять как и когда он загружается и загружается ли вообще.
Общая теория загрузки
Перед тем как понять, какое же место classpnp.sys занимает в системе, нам необходимо освежить в памяти общую теорию загрузки. Из неё мы знаем, что весь процесс запуска операционной системы Windows 7 на начальных стадиях можно описать следующим образом (упрощенное представление):
- Выполняется код микропрограммы BIOS/UEFI (POST);
- Выполняется код сектора MBR;
- Выполняется код сектора(ов) PBR;
- Выполняется код модуля Bootmgr.exe(.efi);
- Выполняется код модуля Winload.exe(.efi);
- Выполняется инициализация ядра (ntoskrnl.exe | ntkrnpa.exe | ntkrnlmp.exe | ntkrpamp.exe)
- Ядро создает/запускает процесс SMSS, который создает сессии:
- Сессия 0
- запускается копия процесса CSRSS:
- Wininit
- SCM (services.exe)
- LSASS
- LSM
- Сессия 1
- запускается копия процесса CSRSS:
- WinLogon
- LogonUI.exe
- UserInit
- оболочка (explorer.exe)
- Приложения автозагрузки
Есть примета, что если зависает на classpnp.sys - это к апгрейду :) Если серьезно, то за все время компьютерной практики относительно данной темы накопилось несколько наблюдений:
- В разные периоды практики удавалось понаблюдать очень похожие между собой сбои, когда возникали ситуации, в которых загрузка в безопасном режиме зависала не на самом драйвере classpnp.sys, а на следующих за ним, то есть этот драйвер не был последним в списке (например, иногда загрузка вставала на agp440.sys).
- На нормально загружающихся в безопасном режиме системах периодически наблюдал картину, когда текстовый режим кончался на выводе строки classpnp.sys с надписью "Подождите, пожалуйста...", после чего присутствовала совсем уж короткая пауза и загрузка уходила в графический режим и продолжалась. Делаем выводы, что приведенная строка ожидания характеризует конец одного (визуально определяемого нами как "текстовый") этапа загрузки и переход к следующему (визуально "графическому").
Каково, а? Первый пункт, я бы сказал, просто расшатывает столпы веры в то, что виновником является именно драйвер classpnp.sys. Отсюда непременно возникает один резонный вопрос: действительно ли причина зависания кроется в тех драйверах, которые мы наблюдаем в списке на экране монитора? Или то что мы видим является ли истинной причиной происходящего?
Этап Winload
Где же впервые в коде модулей запуска встречается загрузка каких-либо системных или сторонних драйверов/библиотек? Очевидно что на этапе Winload.exe, поскольку именно в коде данного модуля впервые начинают загружаться системные драйвера с флагом BOOT_START. С целью анализа нам придется изучать исходный код, для этого расчехляем IDA и дизассемблируем код модуля Winload.exe. После продолжительного изучения алгоритмов можно прийти к выводу, что исполнение кода модуля начинается с точки входа в процедуре OslMain. Уже из этой процедуры вызывается дочерняя функция OslInitializeCodeIntegrity, которая проверяем целостность модулей, участвующих в загрузке. В коде основной функции встречается интересная вложенная функция под названием OslpLoadAllModules, которая используется разнообразным кодом для обеспечения загрузки системных модулей (они же - драйвера/библиотеки режима ядра). Могу ошибаться, но мне показалось, что все модули, загружаемые через неё на начальной стадии, делятся на:
- жестко заданные во внутренней переменной OslMicrosoftBootImages;
- загружаемые уже при подключении и разборе ветви реестра HKLM\SYSTEM\CurrentControlSet\services;
- загружаемые при разборе зависимостей используемых функций;
Непосредственно сама загрузка производится через вложенную функцию OslLoadImage (и подчиненную LoadImageEx). Теперь настало время ознакомиться с полным списком загружаемых кодом модуля Winload.exe драйверов:
Имя | Официальное описание | Зависимости |
---|---|---|
ntoskrnl.exe | NT Kernel & System | pshed.dll, hal.dll, bootvid.dll, kdcom.dll, clfs.sys, ci.dll |
hal.dll | Hardware Abstraction Layer DLL | ntoskrnl.exe, pshed.dll, kdcom.dll |
kdcom.dll | Serial Kernel Debugger | ntoskrnl.exe, hal.dll |
pshed.dll | Драйвер аппаратных ошибок, специфичных для платформы | ntoskrnl.exe, hal.dll |
bootvid.dll | VGA Boot Driver | ntoskrnl.exe, hal.dll |
ci.dll | Code Integrity Module | ntoskrnl.exe |
clfs.sys | Common Log File System Driver | ntoskrnl.exe, hal.dll |
fileinfo.sys | Fileinfo Filter Driver | ntoskrnl.exe, hal.dll, fltmgr.sys |
fltmgr.sys | Диспетчер фильтров файловых систем Майкрософт | ntoskrnl.exe, hal.dll |
atapi.sys | ATAPI IDE Miniport Driver | ntoskrnl.exe, ataport.sys |
ataport.sys | ATAPI Driver Extension | ntoskrnl.exe, hal.dll |
wmilib.sys | WMILIB WMI support library DLL | ntoskrnl.exe |
amdxata.sys | Storage Filter Driver | ntoskrnl.exe, hal.dll |
mountmgr.sys | Диспетчер точек подключения | ntoskrnl.exe, hal.dll |
msahci.sys | MS AHCI 1.0 Standard Driver | ntoskrnl.exe, pciidex.sys |
pciide.sys | Generic PCI IDE Bus Driver | ntoskrnl.exe, pciidex.sys |
pciidex.sys | PCI IDE Bus Driver Extension | ntoskrnl.exe, hal.dll |
msisadrv.sys | ISA Driver | ntoskrnl.exe, wdfldr.sys |
wdfldr.sys | Kernel Mode Driver Framework Loader | ntoskrnl.exe, hal.dll |
acpi.sys | ACPI драйвер для NT | ntoskrnl.exe, hal.dll, wmilib.sys |
partmgr.sys | Partition Management Driver | ntoskrnl.exe, hal.dll, wmilib.sys |
pci.sys | NT Plug and Play PCI-перечислитель | ntoskrnl.exe, hal.dll, pshed.dll |
vdrvroot.sys | Корневой перечислитель виртуальных дисков | ntoskrnl.exe, wdfldr.sys |
volmgr.sys | Volume Manager Driver | ntoskrnl.exe, hal.dll, wmilib.sys |
volmgrx.sys | Драйвер расширения диспетчера томов | ntoskrnl.exe, hal.dll |
wdf01000.sys | Среда выполнения платформы драйвера режима ядра | ntoskrnl.exe, hal.dll, wdfldr.sys |
msrpc.sys | Kenrel Remote Procedure Call Provider | ntoskrnl.exe |
cng.sys | Kernel Cryptography, Next Generation | ntoskrnl.exe, hal.dll |
pcw.sys | Perfomance Counters for Windows Driver | ntoskrnl.exe |
fs_rec.sys | File System Recognizer Driver | ntoskrnl.exe |
ndis.sys | Драйвер NDIS 6.20 | ntoskrnl.exe, hal.dll, netio.sys |
ksecpkg.sys | Kernel Security Support Provider Interface Packages | ntoskrnl.exe, ksecdd.sys, cng.sys |
ksecdd.sys | Kernel Security Support Provider Interface Packages | ntoskrnl.exe, hal.dll, msrpc.sys |
tcpip.sys | Драйвер TCP/IP | ntoskrnl.exe, hal.dll, msrpc.sys, ksecdd.sys, fwpkclnt.sys, fltmgr.sys, ndis.sys, netio.sys |
fwpkclnt.sys | FWP/IPSec Kernel-Mode API | ntoskrnl.exe, hal.dll, msrpc.sys, ndis.sys, netio.sys |
netio.sys | Network I/O Subsystem | ntoskrnl.exe, hal.dll, ndis.sys, msrpc.sys |
vmstorfl.sys | Virtual Storage Filter Driver | ntoskrnl.exe, hal.dll, wdfldr.sys |
volsnap.sys | Драйвер теневого копирования тома | ntoskrnl.exe, hal.dll |
spldr.sys | loader for security processor | ntoskrnl.exe |
rdyboost.sys | ReadyBoost Driver | ntoskrnl.exe, hal.dll, ksecdd.sys |
mup.sys | Драйвер поставщика множественных UNC-имен | ntoskrnl.exe, hal.dll |
hwpolicy.sys | Hardware Policy Driver | ntoskrnl.exe |
fvevol.sys | BitLocker Drive Encryption Driver | ntoskrnl.exe, hal.dll |
disk.sys | PnP Disk Driver | ntoskrnl.exe, hal.dll, classpnp.sys |
classpnp.sys | SCSI Class System DLL | ntoskrnl.exe, hal.dll |
В таблице представлены (сведены) драйверы, у которых соответствующий параметр START
выставлен в значение 0, то есть приведенные в таблице драйвера можно смело назвать группировкой драйверов режима загрузки (BOOT). Столбец зависимостей приведен в таблице не случайно, он то как раз нужен нам с целью определения функциональных взаимосвязей (зависимостей на уровне функций) того или иного драйвера.
Одним из первых загружается образ ядра (ntoskrnl.exe) и уровень аппаратных абстракций HAL.DLL, но секции импорта у этих модулей на данном этапе не разрешаются (то есть указанные модули просто подгружаются в память без связывания). Соответственно и код библиотеки на этом этапе всего-лишь загружается в адресное пространство ядра, для того что бы в последствии, после инициализации, функции были "видимыми" (доступными) для кода других драйверов. Затем, таблица импорта актуального модуля ядра (ntoskrnl.exe и аналогичные) заполняется и связывается (при помощи функции LoadImports и вложенной в неё BindImportRefences). После того, как все подобные подготовительные процедуры отработали, управление передается ядру при помощи функции OslArchTransferToKernel. То есть, давайте резюмируем данный этап загрузки:
Отсюда рождается ряд вопросов:
- может ли этот этап (Winload.exe) загрузки зависнуть по причине какого-либо типа повреждения файлов подгружаемых драйверов (в том числе и библиотеки classpnp.sys)?
- если да, то по каким именно причинам: повреждение записи файла в файловой системе ntfs? неправильная версия classpnp.sys? нулевая длина файла?
Этап ntoskrnl
Собственно, это ни что иное как ядро операционной системы. На самом деле имя ntoskrnl.exe используется только в одноядерной системе (без режимов SMP/PAE). Имена ядра определяются следующим образом:
- ntoskrnl.exe -- (1 ядро ЦП);
- ntkrnlmp.exe -- (N ядер ЦП, SMP);
- ntkrnlpa.exe -- (1 ядро ЦП, PAE);
- ntkrpamp.exe -- (N ядер ЦП, SMP, PAE);
Как мы знаем из теории загрузки операционной системы Windows, после передачи управления на код модуля ядра, в нем происходит последовательная инициализация множества подсистем ядра. Поэтому дизассемблируем и начинаем изучать исходный текст актуального (на моей тестовой конфигурации это был ntkrnlpa.exe) ядра. Если честно, задача перед нами стоит не такая уж и тривиальная и по уму нам предстоит проанализировать множество этапов загрузки операционной системы и попытаться связать кодовые ветвления с событиями, происходящими на экране монитора. Тем не менее, при отсутствии исходников на языке C и знаний по декомпиляции кода из машинного языка в листинг на C, разобраться в дизассемблированных исходных кодах будет непросто, благо что разработчиком предоставляются символы ядра.
Итак, выше мы уже упоминали, что визуально на экране надпись "Подождите, пожалуйста..." знаменует окончание какого-то одного этапа загрузки и переход к следующему, при том что деление это чисто формальное, но для нас оно требуется с целью упрощения понимания происходящего. Теперь, за неимением другой внятной логики, нам надо визуально привязаться к тому, что происходит на экране, но как отследить момент начала текстового этапа и его конец? Поскольку я не умею пока работать с удаленной отладкой, был использован следующий алгоритм действий: мы будем расставлять так называемые "точки зацикливания" (точки "подвисания"), представляющие собой пару машинных опкодов EB FE (команда "прыжка на месте" - jmp $) и вводящие процессор в бесконечный цикл выполнения.
Первая точка останова
Как уже было рассмотрено, процесс загрузки некоторых драйверов категории BOOT_START начинается на этапе работы модуля winload.exe. Поэтому было решено начать с модуля winload.exe и попытаться обнаружить в нем участок кода, в котором процесс загрузки может подвиснуть на том самом текстовом участке (после вывода списка драйверов и сообщения "Подождите, пожалуйста.."). Далее, мы постараемся модифицировать найденный фрагмент таким образом, чтобы ввести в бесконечный цикл (подвесить), тем самым найдя первую точку останова. Самая удачная, по моему мнению, точка - это непосредственно перед передачей управления коду ядра ntoskrnl.exe. Где осуществляется передача управления? Для выяснения этого стартуем с начала основной процедуры OslMain и доходим до её финальной части, где код передачи управления происходит через вызов процедуры OslArchTransferToKernel. Вот так выглядит обрамляющий участок кода:
1 2 3 4 5 6 7 8 9 10 |
.text:00401781 loc_401781: .text:00401781 8B 70 1C mov esi, [eax+1Ch] .text:00401784 E8 AC 7C 00 00 call _BlBdStop@0 .text:00401789 56 push esi .text:0040178A 53 push ebx .text:0040178B E8 50 72 04 00 call near ptr _OslArchTransferToKernel@8 .text:00401790 .text:00401790 loc_401790: .text:00401790 EB FE jmp short loc_401790 .text:00401790 _OslpMain@4 endp |
после непродолжительного оттупления, было решено заменить два маркированных (выделены цветом) пуша на инструкцию зацикленного прыжка jmp $
(опкоды EB FE). Изменения выполняем в шестнадцатеричном редакторе методом поиска длинной сигнатуры и замены (двух) байтов. После сохраняем изменений в Winload.exe, обязательно модифицируем контрольную сумму (CRC) образа, затем перезагружаемся, загрузка в безопасном режиме и.. результат:
Удача!! Произошло зависание процесса загрузки внутри "текстового" этапа на строке, содержащей имя драйвера classpnp.sys. Значит, мы попали своей модификацией в нужное место. Условимся, что отправная первая точка останова найдена.
Вторая точка останова
Теперь давайте попробуем определиться со второй точкой останова.
Судя по всему, ядро принимает от кода модуля Winload.exe управление в собственной точке входа, которая является первой инструкцией функции KiSystemStartup. После этого процесс инициализации ядра системы проходит несколько внутренних этапов, во время которых на экране отображается все тот же "текстовый" режим (с уже знакомым нам списком загруженных драйверов). Затем происходит переключение в графический режим с разрешением 640x480 и выводом анимированного логотипа загрузки (bootscreen). Анимация этого логотипа обеспечивается группой функций с суффиксом Invb*, которые занимаются инициализацией драйвера видеокарты и последующим выводом разнообразных графических примитивов. Например, функция InbvUpdateProgressBar в определенном режиме обновляет прогресс-бар времени загрузки.
Но это все представляет для нас лишь опосредованный интерес, поскольку после текстового режима загрузка уходит в графический режим далеко не сразу. Этап с выводом логотипа находится в модуле ядра, а вот переход к следующему (графическому) этапу происходит позже, во время загрузки диспетчера (менеджера) сессий SMSS (модуль smss.exe). Вычислил я это экспериментальным путем, проставляя точки останова по ходу исполнения этапов инициализации ядра. В конце концов я обнаружил интересную процедуру с именем Phase1Initialization, в которой происходит вызов вложенной процедуры Phase1InitializationDiscard, в конце которой мы находим следующий фрагмент кода:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
. . . INIT:007C9378 loc_7C9378: ; CODE XREF: Phase1InitializationDiscard(x)+DCDj INIT:007C9378 6A 5A push 5Ah INIT:007C937A E8 B3 D9 C3 FF call _InbvUpdateProgressBar@4 ; InbvUpdateProgressBar(x) INIT:007C937F E8 BB 00 00 00 call _StartFirstUserProcess@0 ; StartFirstUserProcess() INIT:007C9384 FF 05 30 4B 57 00 inc _InitializationPhase INIT:007C938A 53 push ebx ; Tag INIT:007C938B FF 74 24 34 push [esp+0B8h+P] ; P INIT:007C938F E8 2A 47 D6 FF call _ExFreePoolWithTag@8 ; ExFreePoolWithTag(x,x) INIT:007C9394 53 push ebx ; Argument2 INIT:007C9395 53 push ebx ; Argument1 INIT:007C9396 FF 35 28 6E 54 00 push _ExCbPhase1InitComplete ; CallbackObject INIT:007C939C E8 B6 83 C6 FF call _ExNotifyCallback@12 ; ExNotifyCallback(x,x,x) INIT:007C93A1 39 1D 20 CE 54 00 cmp _ViVerifierEnabled, ebx INIT:007C93A7 74 07 jz short loc_7C93B0 INIT:007C93A9 6A 05 push 5 INIT:007C93AB E8 DB D0 F7 FF call _VfNotifyVerifierOfEvent@4 ; VfNotifyVerifierOfEvent(x) . . . |
Как помечено цветовой маркировкой, тут у нас вызывается функция _StartFirstUserProcess которая и создает процесс SMSS (Диспетчер сеанса/сессии, Session Manager Subsystem Service). Фактически именно в коде данной функции и происходит (визуально) переключение из графического режима 640x480 в "родное" разрешение установленного монитора (при условии, что установлены драйвера видеоадаптера и выставлено правильное разрешение). Таким образом, инструкция вызова функции _StartFirstUserProcess и знаменует собой:
- в безопасном режиме: окончание "текстового" этапа загрузки модуля ядра;
- в нормальном режиме: начало этапа анимированного логотипа (bootscreen);
Но поскольку мы сейчас разбираем именно безопасный режим загрузки, то данная функция является последней точкой блока кода, зависание внутри которого подвешивает загрузку со списком драйверов на экране. Таким образом мы (вероятно) получили вторую точку останова, тем самым обозначив участок возникновения проблем!!
Между точками: инициализация драйвера classpnp.sys
Помните мы говорили, что загрузка большинства драйверов происходит на этапе работы модуля Winload.exe, а вот связывание и инициализация этих драйверов происходит уже на этапе работы модуля ядра (ntoskrnl.exe). Выходит что и инициализация интересующей нас библиотеки classpnp.sys происходит на этапе функционирования ядра. Давайте проверим, могут ли проблемы с инициализацией быть причиной зависания, для этого изучим внутреннюю структуру драйвера classpnp.sys. Как и в любом другом драйвере, после загрузки в адресное пространство ядра, требуется выполнить инициализацию, поэтому вызывается процедура инициализации драйвера, которая традиционно носит название DriverEntry.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
. . . INIT:0002F048 _GsDriverEntry@8 proc near INIT:0002F048 INIT:0002F048 DriverObject = dword ptr 8 INIT:0002F048 RegistryPath = dword ptr 0Ch INIT:0002F048 INIT:0002F048 8B FF mov edi, edi INIT:0002F04A 55 push ebp INIT:0002F04B 8B EC mov ebp, esp INIT:0002F04D E8 BD FF FF FF call ___security_init_cookie INIT:0002F052 5D pop ebp INIT:0002F053 EB B0 jmp short _DriverEntry@8 INIT:0002F053 _GsDriverEntry@8 endp . . . |
и код вызываемой подфункции:
1 2 3 4 5 6 |
. . . INIT:0002F005 _DriverEntry@8 proc near INIT:0002F005 33 C0 xor eax, eax INIT:0002F007 C2 08 00 retn 8 INIT:0002F007 _DriverEntry@8 endp . . . |
Ну и что мы тут видим? Помимо сервисной функции __security_init_cookie, которая, по заверению разработчиков, предназначается для защиты от переполнения буфера (При входе в функцию с защитой от переполнения cookie-файл помещается в стек, а при выходе значение в стеке сравнивается с глобальным cookie-файлом. Любое различие между ними указывает, что произошло переполнение буфера, что приводит к немедленному завершению работы программы), процедура инициализации этого драйвера не выполняет никаких специфических действий, по большому счету не делает вообще ничего, что могло бы её подвесить, даже не инициализирует привычных структур драйвера и не содержит никаких вложенных вызовов, просто-напросто возвращает управление с кодом STATUS_SUCCESS (EAX=0). И о чем нам это может говорить? Это говорит нам о том, что:
Такое возможно, однако требуется дополнительное подтверждение. Вспоминаем, что драйвер classpnp.sys является библиотекой класса устройств и его функции вызываются из других драйверов. Надо проверить все драйвера режима BOOT_START на предмет использования функций данной библиотеки. Судя по всему, функции библиотеки classpnp.sys на начальном "текстовом" этапе использует всего один-лишь драйвер disk.sys.
Между точками: инициализация драйвера disk.sys
Ну что же, тогда перейдем к драйверу disk.sys и проверить гипотезу о причастности его к подвисанию, с этой целью дизассемблируем и заглянем в код. Данный драйвер является драйвером класса дисковых накопителей и обеспечивает монтирование сконфигурированных в системе дисковых томов. В драйвере процедура инициализации (DriverEntry) выглядит уже намного сложнее, в ней мы обнаруживаем вызовы функции ClassInitialize, которая не является собственной внутренней функцией драйвера, а импортируется из библиотеки класса устройств classpnp.sys. Возможно что функция ClassInitialize может вызываться любым драйвером класса устройства при выполнении его собственной функции инициализации драйвера DriverEntry.
Хорошо, переключаемся на изучение исходного кода драйвера classpnp.sys и анализируем код функции ClassInitialize, а вот он то как раз ужасающе огромен :) Но ошибочные коды возврата все же удалось обнаружить:
- Функция возвращает C0000059 (STATUS_REVISION_MISMATCH): в случае расхождения размера структуры InitializationData, фактически проверка версии файла classpnp.sys.
- Функция возвращает C0000059 (STATUS_REVISION_MISMATCH): если требуемые поля структуры (фактически ссылки на соответствующие функции драйвера) нулевые (NULL).
- Функция возвращает C000009A (STATUS_INSUFFICIENT_RESOURCES): если нулевое значение буфера RegistryPath.Buffer в расширениях
driverExtension
. То есть похоже не выделился буфер по каким-то причинам. - Функция возвращает C0000035 (STATUS_OBJECT_NAME_COLLISION): в любом ином случае.
Драйвер disk.sys обеспечивает функционирование стека устройств хранения в операционной системе Windows, и ниже данного драйвера в стеке располагаются:
- драйверы многопутевого ввода-вывода (MPIO-драйвера, обеспечивающие доступность томов по нескольким путям) (mpio.sys и прч.);
- драйверы порта (обеспечивает поддержку транспортного протокола: SCSI/SAS/SATA/ATAPI);
- драйвер минипорта (обеспечивает функциональность контроллера на материнской плате);
Что еще между точками?
Ну хорошо, помимо инициализации вышеописанных драйверов, что у нас еще расположено между найденными нами точками останова? Да там адская прорва кода!! Получается, что весь код, размещающийся от начала кода модуля ядра в функции KiSystemStartup и до окончания в функции Phase1InitializationDiscard (фактически всей фазы 1), может, потенциально, являться причиной изучаемого нами подвисания (в безопасном режиме). Да уж, тут, что называется, без комментариев!!
Но не все так страшно, как кажется на первый взгляд. В большинстве расположенного на этом участке кода ядра выполняется обработка возникающих ошибок, что тем или иным образом (в виде сообщений) становится известно пользователю. А вот где действительно могут скрываться "мертвые" зависания процесса загрузки, так это на стыке хорошо отлаженного кода ядра и кода сторонних драйверов (то есть на этапе загрузки/инициализации драйверов сторонних разработчиков). Судя по всему в ядре существуют несколько цепочек кода загрузки подобных драйверов:
Start
= 0 (режим BOOT_START) : цепочка вызова функций IoInitSystem → IopInitializeBootDrivers → PnpInitializeBootStartDriver → IopInitializeBuiltinDriver;Start
= 1 (режим SYSTEM_START) : цепочка вызова функций IoInitSystem → IopInitializeSystemDrivers → IopLoadDriver → MmLoadSystemImage;Start
= 2 (режим AUTO_START) : цепочка вызова функций NtLoadDriver → IopLoadUnloadDriver → IopLoadDriver → MmLoadSystemImage;Start
= 3 (режим DEMAND_START) : ???
Вот перечисленные то функции нам в первую очередь и интересны. В дополнение участвует функция MmLoadSystemImage, которая выполняет загрузку исполняемого образа драйвера в адресное пространство ядра (создает секции и производит связывание, заполняет таблицы импорта, перемещения, выполняет проверки безопасности и прочие задачи.). Еще одна функция IopLoadDriver работает с реестром, ответственная за открытие файла драйвера, создание объекта драйвера и передачу управления на точки входа (вызов процедуры инициализации DriverEntry). Для драйверов режима BOOT_START, функции IopLoadDriver и MmLoadSystemImage не участвуют в процессе, поскольку, как мы писали ранее, данные драйвера загружаются еще на этапе winload.exe.
. . .
. . .
Общие причины
Общие причины подвисания следующие:
- установленное на станции железо: после загрузки общих библиотек/драйверов (в том числе и classpnp.sys) начинается перечисление устройств и загрузка драйверов к ним.
- подключение системных томов: возможно ядро не может проинициализировать устройство (накопитель), на котором располагается один из сконфигурированных в системе разделов.
- установленное на станции железо: возможно загрузка какого-либо драйвера устройства проводит первичную инициализацию устройства (через вызов инициализации драйвера и вложенных процедур), которая не может завершиться, подвешивая весь процесс запуска системы.
Частные причины [решения]
предположение: проблема как то связана с загрузочным носителем либо контроллером или шлейфом.. одним словом с дисковой подсистемой.
решения:
- BIOS: перепрошивка BIOS на последнюю версию + сброс всех настроек в [Factory] Default (умолчание);
- BIOS: замена механизма подключения дисков с AHCI → IDE (и наоборот);
- BIOS: смена режима работы контроллера с Compatible (Legacy) Mode → Enhanced (Native) mode (и наоборот);
- BIOS: смена режима загрузки CSM (Legacy) ↔ UEFI;
- Железо: вышедшие из строя сторонние аппаратные модули (например: WIFI/Bluetooth/CardReader): отключение их в BIOS или (при возможности) физически на материнской плате;
- Железо: попробовать использовать для загрузочного диска другой порт IDE/SATA на материнской плате;
- Железо: в случае наличия в системе нескольких накопителей - поочередное отключение носителей (HDD/SSD);
Железо: заменить кабели данных/питания;- Железо: проверка утилитами SMART-мониторинга состояния основного загрузочного диска (замена в случае наличия существенных проблем);
- Железо: проблема с модулями ОЗУ (RAM) + нестандартные настройки таймингов при использовании "нестандартных" модулей/разгоне;
- ОС: загрузиться с LiveCD, подцепить реестр сбойной машины, в ветке HKLM\SYSTEM\CurrentControlSet\services пройтись по всем ключам и для каждого драйвера с параметром START = 0 проверить физическое наличие в файловой системе соответствующего файла.
- ОС: загрузиться с LiveCD, подцепить реестр сбойной машины (ветка HKLM\SYSTEM\CurrentControlSet\services), пробежаться по всем ключам и для каждого драйвера этапа BOOT_START (список выше в статье) проверить чтобы параметр START был равен 0.
- ОС: проверка файловой системы диска (команда: chkdsk c: /f /r);
- ОС: подмена/повреждение драйверов этапа загрузки:
- замена всего набора файлов classpnp.sys/disk.sys и остальных драйверов начальной загрузки из единого доверенного источника - работоспособной ОС аналогичной редакции (с сохранением старых, конечно же).
- отключение проверки подписей драйверов. в меню начальной загрузки (клавиша F8 на старте) нужно отключить проверку подписей драйверов;
- ОС: Разнообразные модификации ключевых структур разметки жесткого диска: например, сокрытие/отображение дисков при помощи сторонних утилит (Acronis);
- ОС: Отключение любого ПО, способного вмешиваться в ранние этапы загрузки ОС: антивирусы, оптимизаторы, системы обнаружения вторжений и прочее подобное;
Выводы
При изучении некоторых функций модулей загрузки, я вышел на некий термин Adding Event Tracing to Kernel-Mode Drivers, вероятно возможность появилась начиная с версии Windows Vista. ETW и WPP - два инструмента диагностики для системных приложений (в том числе и драйверов). Интересно, можно включить через утилиту perfmon логгирование для classpnp/disk? Памятка: Группы сборщиков данных - сеансы отслеживания событий - ПКМ - создать - группа сборщиков данных - создать вручную (для опытных) - далее - в окне поставщики жмем добавить - Disk Class Driver Tracing Provider и Classpnp. Тем не менее, тут же возникает резонный вопрос: как это применимо к уже подвисающим станциям? Как на них можно включить логгирование и получить отчет?
К тому же, интересно, описанная в статье проблема зависания на classpnp.sys решена в Windows 10? И как та же логика реализована в Windows 10, имеются ли там "визуальные" зависания этапа загрузки и как изменился алгоритм обработки отказа в загрузке сторонних драйверов?
Доброго времени суток!
Поможете обывателю с проблемным classpnp.sys? :)
Win7 64 enterprise стала останавливать загрузку на черном экране, иногда доходит до логотипа starting windows.
Скорее всего произошло вскоре после самопроизвольного рестарта связанного с подвисанием системы в ходе бенчтеста linx64(проверял стабильность системы после измененичя настроек частоты шины в биос), или после проверки Malwarebytes ADWcleaner.
Все попытки загрузиться в безопасный режим, включая CMD виснут на classpnp.sys или на второй фазе подгрузки файлов - индикаторе(светлая полоска на черном экране с надписью loading files.)
Бэкапа нет, попытка починить Windows, как и последняя рабочая конфигурация уходят в зависание.
попытка загрузиться с установочного диска с ОС уходит в зависание на фазе загрузка файлов.
Замена целой папки drivers в system32 на папку из заведомо рабочей win 7 64 pro про блемный диск заменить не дает, убрать маркер "только чтение" с папки windows и вложений так же не получается.
Из предпринятых далььнейших мер:
Выкорчевал из системного блока все флешки и карты расширений, обрубил концы всем остальным дискам кроме системного толку при запуске 0.
Путем установки проблемного системного диска во второй пк под ХР произвел chkdsk /f /r по окончанию ошибок и битых сеторов нет.
Victoria 4.73 обнаружила 4 зеленых блока(все до 159мс).
AHCI системная плата проблемного пк(AM2 m2n32sli deluxe) не поддерживает nforce590?.
bios последний 5002.
биос сбрасывал(возможно забыл в нем отключить не используемый 1394).
кабель питания не менял по причине недавней замены бп на новый 750Вт, низкошумный со стандартом голд(интересно, но с заменой заметно уменьщился стрекот жестких дисков).
Проблемный системный диск в других сата разъемах не пробывал.
С Лайв Цд не знаком, какой выбать не знаю.
В Win XP на втором Пк с подключеным проблемным диском запускал MrbCheck из комплекта Hiren's Boot disk 15.2
MrbCheck в отношении пробленого физического диска пишет Unknown mrb code и Found non-standard or infected MRB
Попытка востановить МБР код на проблемном диске стандартным бут кодом(функция Mrbcheck) проводит без ошибок, но при попытке запуска Win 7 проблема не решена.
HDHacker при чтении сектора физического диска(MBR) выдает следующую тарабарщину:
".3.Ž...|‹.P.P.....................€<€t.€<.u.ƒ....u...‹.‹L.‹.ƒ....t.€<.t.....<.t.V.......^.......`j.j..v..v.j.h.|j.j..B.€‹...aas.3...Ou...........}=U.u..R|=FAu.GG€=Tt...|=NTu@GG=FSu8`...€....|..Š.2.‰.OOƒ.?‰.a`j.j..v..v.j.h.|j.j..C.€‹...aa‹...|..Error!.D210A615-ACFD-414a-BDF1-FC9F2A85F076......................................................................................................................................................1.1..€.......?....=“.................................................U." - * без кавычек
Мат плата ведь не могла повредится от повышения фсб на 10-20%? (при стандартном напряжении и мер поснижении частот Озу, Pci, Pci-e)
Помогите пожалуйста с дальнейшими шагами решить проблему с запуском Win 7, третий день не могу понять, что и куда копать.
вот что подозрительно: "попытка загрузиться с установочного диска с ОС уходит в зависание на фазе загрузка файлов". я так понимаю, это флешка или dvd?
Пока выводы делать рано, но очень похоже на "временные" аппаратные проблемы дисковой подсистемы.
LiveCD: MS Dart например, в сети можно легко найти..
MBR тут не причем, потому как: "виснут на classpnp.sys или на второй фазе подгрузки файлов - индикаторе(светлая полоска на черном экране с надписью loading files.". Не знаю, что вы уже с загрузочным сектором могли сделать разными mbrcheck'ами :) но надеюсь он рабочий.
можно попробовать загрузить с MS Dart, и далее по статье: http://datadump.ru/black-screen-of-death/
Спасибо что откликнулись!
Про МБР не волнуйтесь, следую золотому правилу "7 раз отреж, один, раз отмерь!" :)
Исходя из этого МБР Чеком сначала читал состояние диска, расшифровывал об чем там речь и затем оккуратно пытался восстанавливать в соттветсвии с версией и разрядностью своей родной ОС. С Викторией тоже чисто платонически, сканировал бед блоки в режиме игнор(т.е. без ремапа блоков и т.п.)
Ваш совет однозначно бы помог, но я вас немного опередил с MsDaRT.
Вчера удалось найти старый рабочий образ erd 7.0(с MsDaRT в комплекте) для моей win7 64.
Окончательно раздел системный блок, оставил только бут флешку с ERD, проблемный диск, Пси-е видео и одну планку рам.
Удалось с нее загрузиться и успешно прогнать автоматическую проверку.
По окончанию автоматической проверки, вышло сообщение, что Вин не может автоматически устранить неполадки с рекомендацией отсоединить все устройства (к примеру камеру) от ПК и перезагрузится. В логах проверки все тесты пройдены без ошибок.
Затем в пункте Параметры восстановления системы воспользовался пунктом Восстановление запуска.
После перезагрузки в такой спартанской (1 планка рам, проблемный хдд, видео карта) и проделанных процедур ОС загрузилась с проблемного диска.
ИЗ СТРАННОСТЕЙ после успешного запуска ОС:
Поставил обратно к вышеупомянутой компоновке, недостающие 3 планки рам, Sata DVD привод и второй SATA жесткий диск-хранилище(с ремонтированным - приклеенным разъемом т.е. контакты целые пластиковая Г-образная подложка приклеена), голый SSD и опять не удалось запуститься. Отключил в первую очередь диск-хранилище - система зависла на логотипе Стартинг Вин, убрал DVD тот же эффект, попытался загрузиться с ERD USB не грузит. Убрал ССД, после чего удалось загрузиться c ERD USB.
Пока провожу повторно автоматическое востановление загрузки
Копаю Sata разъемы и то что на них весит?
П.с.
По поводу ваших сомнений
а что за модель SSD? не увидел в постах..
а вот при удачной загрузке с SSD там уже стояли все драйвера от чипсета и прочего?
СумСанг 860 Про, честно не обратил внимание на драйвера. Кстати система почему то его определила ка SCSI Device. На мат. плате поддержка только до Сата2.
"вот что подозрительно: "попытка загрузиться с установочного диска с ОС уходит в зависание на фазе загрузка файлов". я так понимаю, это флешка или dvd?"
USB - возможно изначально кривые образы из интернета, грузиться с них на втором ПК не стал.
Вот, опять удалось запустить ОС.
Сейчас верну ОЗУ и в обратной последовательности по одному буду подключат Сата устройства.
И так по итогам вскрытия и манипуляций с ОЗУ:
Из минусов - несколько убитых вечеров.
Из плюсов - протертый от пыли корпус, красиво уложенные провода, рабочий ПК
Методом исключительно научного тыка ОЗУ в одноканал и двуканал была выявлена причина. После дальнейшего изучения Биос обнаружено, что виновниками возникновения зависания на classpnp.sys явились слетевшие настройки в биос Ganged Ram mode(1х128бит), и совместимость Т2.
Искренняя благодарность автору статьи!
Пoжалуй следует отметить, что ОЗУ в системе довольно хитрые. Конкретнее это DDR2 от дяди Ляо под торговой маркой Klissre 800, на модулях памяти SEC и с пометкой Amd only(на Интел действительно не работает по причине отсутсвия какого то там модуля обработки в ЦП Интела).
Так что наверное нужно было их брать в расчет с самого начала. :)
неожиданно! :-)
Прекрасный анализ.
Мне помогло (включил csm в bios).
не совсем понятно как у вас загрузилось? до этого UEFI режим стоял исключительно и при этом "вис на classpnp.sys"?
Благодарю! У меня на старой матери с BGA процессором (bios максимально урезан), помогло включение CSM. Причем Zalman и диски/флешки с MBR компьютер не понимает. Vista понимает и MBR и GPT, но зависает как у ТС. Помогло включение CSM, проверка chkdsk /f /r на другом компьютере, загрузка в разных режимах на проблемном компьютере.
Десятка ругается на дрова для видеокарты. Проблема вроде бы ушла с переустановкой системы. На семёрке вылетал экран смарти. Потом сообщение перезагрузить или выбрать бот девайс с медиа либо нажмите любую кнопку. В безопасном режиме комп висел на classpnp, иногда не грузился совсем. Антивирь AVZ, исправлял на разрешение на запуск с хдд и сменных носителей, хз почему.
1. Ругань на дрова ни о чем не говорит.
2. Желательно делать полный дамп при синьке.
------
тем не менее, было бы интересно посмотреть дамп.
Парни помогите советом.Сервер 2008 R2.В обычном режиме не грузится зависает на логотипе.В безопасном загружается (но на classpnp.sys висит секунд 15).Что можно сделать?
попаду пальцем в небо: загрузиться с LiveCD, поизучать журналы системы (.evtx), искать проблемы старта сервисов (служб) с флагами загрузки AUTO_START, DEMAND_START.
Красавчик, всегда приятно когда человек знает свое дело и это приподносит другим четко по пунктам и в тоже время с нужными деталями
Приятно читать. Редко ныне встречаешь умного человека способного разбираться в сложных проблемах. И толково донести результат исследования. Вношу вас в красный список интернета. Спасибо!
Красную книгу сети Интернет? :)
Проблема с асусом n540r, который официально не поддержке win7. Семёрка устанавливается но при запуске виснит эмблема стартинг Виндоус. Прикол в том что я слышу звуки приветствия и винда по сути загружается и я могу через alt+f4 выключить ноут. Возможно такое что в семёрке не хватает каких-то драйверов?И возможно ли их туда как-то примостырить))Я не разбираюсь в коде и всём остальном и проблема необходимости семёрки решится покупкой соответствующего прибора,но факт того что семёрка запускается без графического сопровождения вызывает любопытство и ощущение , что где-то что-то чуть-чуть подправить и всё заработает)))
"Возможно такое что в семёрке не хватает каких-то драйверов?" - возможно.. были довольно хорошие, чистые (без мусора) сборки Win7 с драйверами под новые ноуты.. конечно для всех моделей не панацея, но чем черт не шутит, как говорится :) я думаю в вашем случае можно попробовать их. найдете самостоятельно?
Та же проблема: ноутбук ASUS R465KA-EK060W(90NB0VH2-M001B0) - установлена при покупке Windows 11 ознакомительная. Загрузиться с флэшки легко, начать установку Windows легко, но НЕ устанавливается Windows 7, установка проходит. но при первом запуске ноутбук зависает на картинке ФЛАГ windows - подождите....., а при загрузке в safe mod, зависает при загрузке на CLASSPNP.SYS.
bios ноутбука современный только UEFI, никаких режимов совместимости.
Винчестер SSD GPT, пробовал грузиться с флэшки и форматировать его (полностью удалять windows 11)/. Переделывал
его в MBR (тогда Windows не ставится, пишет интерфейс не тот : ) только UEFI . А биос перепрошивать на старый (если он существует) я не решился. Да и еще, драйвера на данный ноут на сайте ASUS есть только начиная с Windows 10 . Это я к тому что когда я установил Windows 10 на ноутбук, то в СИСТЕМЕ, в ДИСПЕТЧЕРЕ УСТРОЙСТВ было 10 НЕ опознанных устройств. И пришлось качать и ставить драйвера с сайта ASUS.
P.S. советую перед тем как начнешь экспериментировать с установкой Windows , сделать образ ВИНЧЕСТЕРА. мне
это очень пригодилось.
Как у меня решилась эта проблема:
...) тыщу предложенный в сети вариантов ( не помогло )
1)Прогнал диск через Victoria с исправлением ошибок ( в итоге были выявлены только 2 красных )
2)После виктории сразу зашел в биос и поменял ide на мой изначальный ahci ( при ide выскакивал синий экран в момент загрузки windows ). и в этот момент внизу в подменю заметил, что все порты sata - disabled... т.е. выключены, выявил порт на котором мой жесткий и сделал его enabled.
После этого система загрузилась. Что меня удивило так это то, что все драйверы отсутствовали, система была как будто новая. ( Возможно я сам стал виновником их исчезновения когда до этого рылся в системе через разные live cd программы )
Теперь главное: стала ли Victoria причиной исправления этой ошибки, или включение сата порта ( он так и был выключен все это время ? тогда я не замечал то, что было прямо перед носом) - я так и не понял, решил сразу отдать комп хозяину не копаясь во всем этом.
да уж, вопросов больше чем ответов :) как же при отключенных sata вообще диск виделся? или это были режимы вроде sata hotplug?
Помогите пожалуйста, решил переустановить винду, с флешки, теперь ноутбук завис на логотипе запуск виндовс, все способы уже перепробовал что делать?
слишком много неизвестных. какой ноутбук, какая винда (откда образ, версия)?
Прочитав весь текст выяснил важную информацию: classpnp.sys трогает всякие другие файлы, и вероятность поломки hardware . Мне повезло буквально с 3ей попытки, заработало отключив второй SSD(не системный). Попробую ещё его в другом компьютере. Автору спасибо, остальным удачи.
да, у данной проблемы есть изрядная доля аппаратных причин!!
Здравствуйте! В реестре в ветке отсутствует запись ClassPnP, как быть?
Система виснет в безопасном режиме именно на classpnp.sys.
в конце статьи есть список.
Хорошая статья и комментарии.
Мне помогло решить проблему не такой глубокий анализ. Посидел, подумал, стал отстегивать жесткие диски и чудо свершилось, всё прошло. Осталось решить вопрос с заглючившим диском.
Интересно есть ещё активность тут? Тоже столкнулся с этой проблемой. Зависание изначально было на каком-то драйвере аваста, всё это дело вычистил, теперь зависаем на classpnp, также была проблема из-за севшей батарейки, меняю режимы диска, во всех диск виден, но всё равно не грузится. Планка памяти одна, менял гнезда, ноль эффекта, гнезда сата для винта также менял. Ощущение что проблема с драйверами, но какими конкретно не понятно и что с ними можно сделать. Помогите кто чем может)
есть, но низкая :) а что делали то из перечисленного?