Совсем удаленная отладка драйверов или safe mode — наше все.
Вспоминается анекдот-загадка:
Сколько нужно программистов чтобы вкрутить лампочку?
Ответ: Ни одного. Программисты не решают апаратные проблемы.
С удаленной отладкой примерно также: сколько нужно компьютеров, чтобы удаленно отлаживать драйвера? Ответ: три.
Почему 3, а не 2? Да потому что, если это настоящая удаленная отладка, то драйвер выполняется на машине у клиента, а вы конектитесь на еще одну удаленную машину, которая через COM или Firewire подключена к первому. Итого: 2 компа у клиента, и один у вас.
Но это мечта программиста, в реальности обычно используется 2:
1) ваш, на котором «все работает»
2) комп клиента, на котором все не работает.
Как же с этим жить и успешно фиксить баги?
В моем случае был драйвер файловой системы который по правилам блокировал все и вся. А так же по правилам разрешал или запрещал запуск процессов. Компьютер работал 24/7, и проблем было море:
1) Обычный Remote Desktop, который mstsc, при подключении к нему, порождал кучу действий, которые нарушали правила драйвера, он их блокировал. И в общем ничего не работало.
2) Забрать крэш дамп было тоже проблематично, потому что нужно было перезагружаться в safe mode, где этот драйвер не запущен, чтобы не бороться с его правилами
3) В safe mode не работает удаленный рабочий стол, законектиться некак, и нужно было просить чтобы ручками перезагружали тачку, забирали файл, а потом перезагружали обратно. Мне ли рассказывать, что такое упрашивать клиента собрать инфу…
4) Некак посмотреть дебажный лог драйвера, если он не пишет его на диск. Писать на диск с DISPATCH_LEVEL’а вообще как-то не очень получается. Выдумывать свой хитромудрый файловый лог, который будет многопоточным, не будет снижать производительность, и который сможет на любом IRQL работать, да еще и не привнесет новых багов — это надо ооочень хорошо постараться. А использовать Event Log нереально — вы ограничены ~ 110 байтами. Больше за раз записать нельзя. В общем логов нет 😦
5) Нужно как-то обновлять драйвер, а это опять же перезагрузка в safe mode, чтобы не бороться с правилами.
В общем надеюсь уже достаточно демотивирует 🙂
Итого: нужно было как-то перезагружать машину в safe mode без участия клиента, в safe mode иметь удаленный рабочий стол и каким-то образом получать дебажные логи ядра.
Начнем с конца.
Как получать логи?
На помощь идет как ни странно DbgView. Его можно запускать на логирование в файл с коммандной строки:
dbgview /c /t /l путь к файлу
Прописываем это дело в автозагрузку и получаем при каждом запуске новый лог. У dbgview есть также режим создавания нового лога каждый час, так что при желании можно завалиться логами.
Как сделать удаленный рабочий стол в safe mode?
Намучавшись с виндовым рабочим столом я перешел на ultravnc. Но как же его запустить в safe mode? Ответ в реестре.
Есть ветка:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot
которая описывает службы и драйвера, которые должны запускаться в различных безопасных режимах.
Нас собственно интересует:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot\Network
«Безопасный режим с загрузкой сетевых драйверов»
Создаем в нем раздел для сервиса ultravnc:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SafeBoot\Network\uvnc_service
и в этом разделе прописываем значение «(По умолчанию)» = «Service» (без кавычек).
Вот и все, теперь при входе в «Безопасный режим с загрузкой сетевых драйверов» будет запускаться UltraVnc. Естественно нужно сделать чтобы компьютер автоматически логинился, потому что некому будет ввести пароль. Используем проверенный метод:
control userpasswords2
И конечно отключить UAC, потому что бороться с ним удаленно — весело.
Кому сильно нужен виндовый remote desktop — флаг в руки, выясняйте какие ему надо сервисы, прописывайте в реестр. Но имхо оно в safe mode работать не сможет.
А как же перезагружать компьютер в safe mode?
В Vista (до Seven руки не дошли) это делается довольно просто:
bcdedit /set {current} safeboot Network
и все, текущая загрузочная запись нас будет всегда перезагружать в safe mode. Поэтому, когда попали в safemode используем:
bcdedit /deletevalue {current} safeboot
чтобы сделать текущую загрузочную запись снова «нормальной».
На XP немного сложнее, надо редактировать boot.ini. И дописывать к параметрам загрузочной записи дополнительные параметры:
/safeboot:network /sos /bootlog /noguiboot
то есть должно быть вот как-то так:
multi(0)disk(0)rdisk(0)partition(1)\WINDOWS="Microsoft Windows XP Professional" /noexecute=optin /fastdetect /safeboot:network /sos /bootlog /noguiboot
Потом в safe mode соответственно, удалять их.
Но это в теории, на практике XP при старте в safe mode выводит сообщение типа «Мы щас в safe mode, а хотите запустить консоль восстановления да/нет?». И кто будет на эту месагу у нас нажимать? Служба ultravnc не будет запущена пока не будет нажато «да». Вот такая подлянка от разработчиков винды. И никак это не отключается, кроме как если пропатчить explorer.exe, но мы этим заниматься не будем.
Explorer, перед тем как вывести эту месагу, обрабатывает ключ RunOnce. Да-да в safe mode можно запускать не только свои сервисы, но и обычные приложения! Для этого просто нужно прописать в ключ:
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce
свое строковое значение, но оно должно начинаться со зведочки(*), то есть имя ключа должно быть к примеру «*MyOnceKey».
Но как нам ответить «Да»? А вот так:
HMODULE module=LoadLibraryEx("c:\\windows\\explorer.exe", 0, LOAD_LIBRARY_AS_IMAGE_RESOURCE); wchar_t desktopName[100]; const UINT desktopNameResourceId=524; //localized name of desktop LoadStringW(module, desktopNameResourceId, desktopName, _countof(desktopName)); FreeLibrary(module); for (int i=0;i<10;i++) //dumb, but much easier to implement :) { HWND msgBoxWnd=FindWindowW(L"#32770",desktopName); if (msgBoxWnd!=NULL) { SendMessage(msgBoxWnd,WM_COMMAND,IDYES,0); break; } Sleep(1000); }
Запускаемся, ждем пока появится окошко и шлем ему месагу, что было нажато YES. 🙂
Хорошо, есть программа, но руками это все прописывать задалбывает уже где-то на 3-й раз. Поэтому была написана программа для автоматизации всего этого дела.
Брать вместе с сорцами тут:
http://extint.narod.ru/Files/BootSafe.rar
Как использовать:
1) скопировать файлы BootSafe.exe и TestOnce.exe в корень диска C:
2) запустить BootSafe.exe
3) перезагрузить для перехода в safe mode
4) в safe mode просто перезагрузить чтобы вернуться в нормальный режим.
Дополнение:
Как оказалось, сервисы на XP запускаются и без нажатия на клавишу «Да», поэтому эта фича в общем не обязательна 🙂
Вот написал это все и думаю: это ведь малварь за не фиг делать может это все юзать… Перезагружаешься в safe mode чтобы почистить комп, а там тебя уже ждут…
Так вроде же, то же конфикер использовал сейф мод, чтобы узер не смог почистить свой пк.
У меня его не было, не знаю 🙂 Но раз уже было, значит «как страшно жить» (с)