Работа кейлоггеров данного типа основана на установке специального драйвера, подключаемого к драйверу клавиатуры в качестве фильтра и данный шпион является одним из самых простых в плане как реализации, так и обнаружения.
Клавиатурный шпион этого типа может быть построен по одной из следующих схем:
• драйвер-фильтр в сочетании с управляющим приложением, которое выполняет установку, загрузку и настройку драйвера. Драйвер передает информацию о нажимаемых клавишах управляющему приложению, которое производит обработку и протоколирование полученных данных;
• полностью автономный драйвер самостоятельно ведет запись событий. В данном случае требуется только произвести первичную установку драйвера в систему, после чего установившее драйвер приложение может самоуничтожиться.
Возможно решение и без приложения-инсталлятора — в этом случае драйвер устанавливается при помощи INF-файла.
В момент загрузки драйвер должен подключиться к стеку клавиатурного драйвера посредством функций IoCreateDevice и IoAttachDevice. В большинстве известных реализаций фильтр подключается к стеку устройства «\\DeviceWKeyboardClassO», являющегося драйвером класса и реализующего общую функциональность для клавиатур различных типов (рис. 8.14).
Для клавиатурного шпиона будут представлять интерес только прерывания типа IRPMJREAD, поскольку на основе их анализа можно получить коды клавиш. Источником этих IRP-запросов является процесс csrss.exe, а точнее — принадлежащий этому процессу поток необработанного ввода RawInputThread. Посылаемое этим потоком прерывание сначала попадает к драйверу-фильтру шпиона (шаг 1), который устанавливает свой обработчик завершения при помощи функции IoSetCompletionRoutine и передает IRP драйверу Kbdclass (шаг 2). Тот, в свою очередь, помечает IRP как ожидающий завершения и ставит в очередь. При возникновении клавиатурных событий Kbdclass извлекает из очереди ожидающий завершения IRP, вносит в его буфер информацию о нажатых клавишах и завершает IRP. А поскольку в IRP установлен адрес обработчика завершения, то будет произведен вызов этого обработчика (шаг 3). Обработчик может проанализировать содержимое буфера и передать содержащуюся там информацию системе протоколирования (шаг 4). Далее IRP возвращается в поток RawInputThread, а затем весь процесс повторяется. Естественно, что наличие корректно написанного драйвера-фильтра никак не сказывается на работе приложений и обеспечивает глобальный перехват клавиатурного ввода.
Обнаружение описанного шпиона не представляет особой сложности, — для его поиска достаточно изучить стек клавиатурного драйвера на предмет наличия неопознанных драйверов-фильтров.
Принцип действия такого клавиатурного шпиона основан на перехвате ряда функций USER32.DLL для мониторинга их вызовов. Данные вредоносные программы пока не получили особого распространения, но это только вопрос времени. Опасность применения руткит-технологии в клавиатурном шпионе объясняется тем, что, во-первых, многие антикейлоггеры не рассчитаны на поиск шпионов такого типа и не способны им противодействовать, а во-вторых, антируткиты часто не проверяют перехваты функций библиотеки user32.dll.