Как завести игрушку?
Недавно, без каких-либо заметных причин перестал запускаться King's Bounty. Запускаешь — а в ответ тишина: ни окошка, ни сообщения. «Непорядок!» — подумал я и решил разобраться.
Судя по task manager, главный процесс kb.exe запускался, после чего IO Read/Write Bytes увеличивался до 1974529/144, после чего активность прекращалась. В Process Explorer, тем не менее, по kernel time удалось заметить, что активность не прекращается совсем, что исключило дедлок. По стеку ничего внятного заметить не удалось, кроме того, что проблема возникла в ntoskrnl.exe!ExReleaseResourceLite+0x1a3.
В поисках источника проблемы kb.exe был запущен из под OllyDbg (обещают вскоре 2.0!), и в нужный момент было просмотрено состояние стека. В нем обнаружилось, что зависание происходит при ZwReadFile 12 байт из hFile=0xF8. Второй тред в это время терпеливо дожидался эвента kb_startup. Просмотреть, что это за хандл 0xF8 с помощью OllyDbg не удалось, он завис. Зато Process Explorer сообщил, что это \Device\00000082, но тем же зависанием не дал его закрыть.
Увы, внятных упоминаний о \Device\00000082 не удалось найти ни в гугле, ни в реестре, ни в диспетчере устройств, ни в Lavalys Everest. Зато удалось узнать, что это PDO name, а внятных упоминаний о том, как его перевести в Device ID из ring3, найти тоже не удалось. Зато было обнаружено, что утилита dmdiag выводит список таких имен. Найти прямую ссылку на dmdiag на сайте MS через гугл было не трудно. Действительно, среди кучи информации о диске выводится и информация о \Device, но по конкретно интересующему устройству ничего, кроме типа (Device) выяснено не было. Зато дизассемблер, после поиска вхождения строки \Device, выводившейся в заголовке списка, нашел, что перечисление происходит через NtOpenDirectoryObject. Следующим предположением было открыть устройство через CreateFile, а затем, использовав DeviceIoControl с параметром IOCTL_CHANGER_GET_PRODUCT_DATA, получить название устройства. Но ни одно имя файла \Device\00000082, \\.\Device\00000082, \\.\00000082 не позволило открыть файл.
Так может, файл был создан не по этому имени?! Раз читается он через ZwReadFile, тогда, наверно, и создан был через ZwCreateFile. Ставим на него бряк, и после нескольких остановок на нем kb.exe зависает с теми же значениями IO Read/Write Bytes. Название файла при последнем бряке (последних трех, вернее) — \\?\hid#myvirtualhiddevice#1&2d595ca7&0&0000#{4d1e55b2-f16f-11cf-88cb-0011110000 30}. Лезем в device manager и видим, что это недавно купленный планшет Genius G-Pen F610. Дизаблим его и... о, чудо! Игра запускается!
Теперь можно добавить немного мыльной оперы, и можно приглашать Хью Лори на главную роль :)
Судя по task manager, главный процесс kb.exe запускался, после чего IO Read/Write Bytes увеличивался до 1974529/144, после чего активность прекращалась. В Process Explorer, тем не менее, по kernel time удалось заметить, что активность не прекращается совсем, что исключило дедлок. По стеку ничего внятного заметить не удалось, кроме того, что проблема возникла в ntoskrnl.exe!ExReleaseResourceLite+0x1a3.
В поисках источника проблемы kb.exe был запущен из под OllyDbg (обещают вскоре 2.0!), и в нужный момент было просмотрено состояние стека. В нем обнаружилось, что зависание происходит при ZwReadFile 12 байт из hFile=0xF8. Второй тред в это время терпеливо дожидался эвента kb_startup. Просмотреть, что это за хандл 0xF8 с помощью OllyDbg не удалось, он завис. Зато Process Explorer сообщил, что это \Device\00000082, но тем же зависанием не дал его закрыть.
Увы, внятных упоминаний о \Device\00000082 не удалось найти ни в гугле, ни в реестре, ни в диспетчере устройств, ни в Lavalys Everest. Зато удалось узнать, что это PDO name, а внятных упоминаний о том, как его перевести в Device ID из ring3, найти тоже не удалось. Зато было обнаружено, что утилита dmdiag выводит список таких имен. Найти прямую ссылку на dmdiag на сайте MS через гугл было не трудно. Действительно, среди кучи информации о диске выводится и информация о \Device, но по конкретно интересующему устройству ничего, кроме типа (Device) выяснено не было. Зато дизассемблер, после поиска вхождения строки \Device, выводившейся в заголовке списка, нашел, что перечисление происходит через NtOpenDirectoryObject. Следующим предположением было открыть устройство через CreateFile, а затем, использовав DeviceIoControl с параметром IOCTL_CHANGER_GET_PRODUCT_DATA, получить название устройства. Но ни одно имя файла \Device\00000082, \\.\Device\00000082, \\.\00000082 не позволило открыть файл.
Так может, файл был создан не по этому имени?! Раз читается он через ZwReadFile, тогда, наверно, и создан был через ZwCreateFile. Ставим на него бряк, и после нескольких остановок на нем kb.exe зависает с теми же значениями IO Read/Write Bytes. Название файла при последнем бряке (последних трех, вернее) — \\?\hid#myvirtualhiddevice#1&2d595ca7&0&0000#{4d1e55b2-f16f-11cf-88cb-0011110000
Теперь можно добавить немного мыльной оперы, и можно приглашать Хью Лори на главную роль :)