В кейлогере usb клавиатуры цепляю свою функцию обработчик на ...->DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] которая, в свою очередь, меняет CompletionRoutine в irp на мою собственную. Обнаружил непонятный феномен - CompletionRoutine функция вызывается только для следующей нажатой клавиши, т.е., внутри обработчиков IRP_MJ_INTERNAL_DEVICE_CONTROL CompletionRoutine поставил DbgPrint. При нажатии на первую клавишу вижу, что был вызван только IRP_MJ_INTERNAL_DEVICE_CONTROL, при нажатии на следущую клавишу вызывается и IRP_MJ_INTERNAL_DEVICE_CONTROL и CompletionRoutine. Собственно хотелось бы понять - почему при нажатии на первую клавишу не вызывается CompletionRoutine?
...->DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL Вызывается за долго до нажатия на клавиши и у IRP пакета будет статус ожидающий завершения (pending), а завершится он или вызовется CompletionRoutine в момент возникновения событий на клавиатуре. Вот почитай тогда поймешь как все работает. wasm.ru/article.php?article=drvw2k15
lev Спасибо! Очень помогло! Кстати, может кто знает, как интерпретировать данные получаемые в UserBuffer в CompletionRoutine? Эмпирически, понял, что когда клавиша нажимается, UserBuffer[2] содержит код нажатой клавиши: 4 - 'a', 5 - 'b', 6 - 'c' и т.д. Когда клавиша отжимается - UserBuffer обнулен. Когда одновременно нажато две клавиши - код первой в UserBuffer[2], второй в UserBuffer[3]. Аналогичным образом и для трёх. Проблемы начинаются когда одновременно нажимается четыре и больше клавиш. UserBuffer содержит информацию которую я не могу понять
Эмпирически не пытайся - зря время потратишь. Данные у HID-девайсов передаются в репортах. Репорт представляет из себя битовую структуру. Для интерпретации этих репортов нужен доступ к HID Report Descriptor'у, в котором расписано какие данные содержатся в полях репорта. Стандарта на формат репортов нет, поэтому у одной клавы один формат, у другой - другой формат. Это как производитель захочет. Не имея доступа к HID Report Descriptor'у, прямо или косвенно, невозможно интерпретировать репорты. Дока по репортам и дескрипторам "Device Class Definition for HID 1.11", берется http://www.usb.org/developers/hidpage/. Это если вручную парсить HID Report Descriptor и вручную парсить репорты. Предупреждаю - там сложно. Мелкомякгая реализация протокола HID http://www.microsoft.com/whdc/device/input/default.mspx. Для косвенной интерпретации можно заюзать HIDClass support routines, но нужен открытый хендл девайса. Для клавы и мыши это невозможно, т.к. винда открываетя эти девайсы эксклюзивно.
Four-F спасибо! Извиняюсь за надоедливость - за ёлками не видно леса. Т.е. как привязать то, что у мeня есть в настоящий момент (IRP в CompleteionRoutine) к обработке протокола? Есть какой то API?
Для парсинга репортов есть HidP_Xxx API, доступный для драйверов и юзермоды http://msdn.microsoft.com/en-us/library/ms790932.aspx. Схема такая (шоб тебе врубиться): 1. Открыть девайс; 2. Получить preparsed data; 3. Юзать HidP_Xxx, скармливая им репорт (то, что у тебя в UserBuffer) и preparsed data; Как это привязить к CompleteionRoutine и можно ли, я не знаю. В HID Samples есть толковые примеры работы HID-девайсами из юзермоды (из ядра не знаю). Вобщем ройся в разделе Human Input Devices.
Katrus можешь определить что ты все таки хочешь получить если неплохой кейлогер дак есть исходники на рутките и выдумывать не чего не надо.
lev Цель больше теоретическая. Из спортивного интереса пытаюсь написать максимально низкоуровневой кейлогер. Ну и понять - что и как в драйверах. Просто читать книгу - слишком сухо. Нужно некое "преодоление". Понятное дело, что использовать такое для "практического" применения - как из пушки по воробьям. Four-F Но ведь девайс клавиаты нельзя открыть (?)
Ну да. Вобщем это правильно. Нафига нужно обращение к клаве или мыши. Это чисто системные девайсы для общения юзера с операционкой. Джойстики, UPS, планшеты и прочие открывайте на здоровье.
Ты не понял. Тебя спросили почему ты советуешь "открыть девайс" если "девайс открывать нельзя", нестыковочка получается.
Да я не советую. Просто API этого требует. Я просто тупо объяснил алгоритм работы с системным парсером.