На какой уровень теоритически можно опуститься в стэке драверов,чтобы перехватывать сообщения о нажатых клавишах?Может кто-нибудь работал в этом направлении и знает способы отличные от присоединению к kbdclass?
Ага. И поддерживает максимум один callback. Поэтому если позднее найдётся умник, который захочет зарегистрировать собственный callback, старый будет перезаписан.
Ну тогда вот такие ещё мысли. Сам по себе kbdclass.sys логически является классовым драйвером, но технически он выполнен в виде верхнего фильтра для класса "Keyboard", таким образом, если необходимо именно сесть ниже этого драйвера, то достаточно прописать себя как нижний фильтр для класса "Keyboard". Можно пойти дальше и вспомнить, что драйвер i8042prt.sys является драйвером порта, который реализует управление соответствующим контроллером, но сам контроллер приаттачен к определённой шине (в случае с i8042, если не ошибаюсь, это шина PCI). Таким образом, если сесть фильтром на драйвер этой шины, то мы опять же окажемся ниже любого из классовых фильтров. Такие дела.
А такое отловит? Code (Text): BYTE keyScanCode = 0; __asm { in al, 0x64 test al, 1 jz key_not_present in al, 0x60 mov keyScanCode, al key_not_present: }
x64 Это было просто примечание. С какой это стати? К стандартной адресной шине и к шине данных он приаттачен. Общение с ним через его собственные фиксированные порты же, а не через PCI-транзакции. А что бы это дало? Прерывания приходят от контроллера, а не от шины.
l_inc Да, извиняюсь, попутал с устройствами хранения, там данные как раз по шине бегают, а здесь нет. Чисто программно стек девайсов клавиатуры выглядит так: Т.е. ниже i8042prt.sys только если acpi.sys. Я не знаю точно, как устроен i8042prt.sys внутри, но боюсь, что команды с клавиатуры он получает от контроллера через собственные прерывания, таким образом, даже если сесть нижним фильтром на его девайсы, это ничего не даст, также как ничего не даст и фильтрация acpi.sys. Другими словами, в данном случае никаких других вариантов нет, т.е. либо указанный выше хук, либо сесть нижним фильтром класса "Keyboard".
Получается,что ниже Kbdclass не сесть?... А если перехватывать процедуру обработки прерывания i8042prt?
Напрямую это не получится, т.к. патч IDT на 64-битных системах ни к чему хорошему не приводит (не, ну если сильно надо, то, конечно, можно). Также можно попробовать перехватить вызов IoConnectInterrupt() и подменить ISR там, но это опять же патч кода ядра, с которым имеются некоторые проблемы, и ещё неизвестно, использует ли её i8042prt.sys, или он патчит IDT вручную (маловероятно, т.к. в импорте этот вызов у него есть). Ну а во втором сообщении я указал способ, как сделать это легально, но у него есть недостатки, указанные в #3.
Я даже скажу какие конкретно, а именно - контроль целостности кода ядра - PatchGuard. Как он работает и как обойти эту штуку, можете погуглить (например тут). Конечно трюки которые описаны - потихоньку закрываются и исправляются обновлениями.