Клавиатурный шпион на базе руткит-технологии в UserMode
Драйвер-фильтр
Работа кейлоггеров данного типа основана на установке драйвера, подключаемого к драйверу клавиатуры в качестве фильтра. Пример реализации фильтра клавиатуры приведен в DDK, и данный шпион является одним из самых простых в плане как реализации, так и обнаружения.
Клавиатурный шпион этого типа может быть построен по одной из двух схем:
- драйвер-фильтр в сочетании с управляющим приложением, которое выполняет установку, загрузку и настройку драйвера. Драйвер передает информацию о нажимаемых клавишах управляющему приложению, которое производит обработку и протоколирование полученных данных;
- полностью автономный драйвер самостоятельно ведет запись событий. В данном случае требуется только произвести первичную установку драйвера в систему, после чего установившее драйвер приложение может самоуничтожиться. Возможно решение и без приложения-инсталлятора — в этом случае драйвер устанавливается при помощи INF-файла.
В момент загрузки драйвер должен подключиться к стеку клавиатурного драйвера посредством функций IoCreateDevice и IoAttachDevice. В большинстве известных реализаций фильтр подключается к стеку устройства «\\Device\\KeyboardClass0», являющегося драйвером класса и реализующего общую функциональность для клавиатур различных типов (рис. 1).
Рис. 1
Для клавиатурного шпиона будут представлять интерес только прерывания типа IRP_MJ_READ, поскольку на основе их анализа можно получить коды клавиш. Источником этих IRP-запросов является процесс csrss.exe, а точнее — принадлежащий этому процессу поток необработанного ввода RawInputThread. Посылаемое этим потоком прерывание сначала попадает к драйверу-фильтру шпиона (шаг 1), который устанавливает свой обработчик завершения при помощи функции IoSetCompletionRoutine и передает IRP драйверу Kbdclass (шаг 2). Тот, в свою очередь, помечает IRP как ожидающий завершения и ставит в очередь. При возникновении клавиатурных событий Kbdclass извлекает из очереди ожидающий завершения IRP, вносит в его буфер информацию о нажатых клавишах и завершает IRP. А поскольку в IRP установлен адрес обработчика завершения, то будет произведен вызов этого обработчика (шаг 3). Обработчик может проанализировать содержимое буфера и передать содержащуюся там информацию системе протоколирования (шаг 4). Далее IRP возвращается в поток RawInputThread, а затем весь процесс повторяется. Естественно, что наличие корректно написанного драйвера-фильтра никак не сказывается на работе приложений и обеспечивает глобальный перехват клавиатурного ввода.
Обнаружение описанного шпиона не представляет особой сложности, — для его поиска достаточно изучить стек клавиатурного драйвера на предмет наличия неопознанных драйверов-фильтров.
Подмена драйвера клавиатуры
Данный метод в действительности основан на подмене драйвера Kbdclass или одного из низкоуровневых драйверов клавиатуры драйвером собственной разработки. Сложность реализации указанного метода состоит в том, что заранее неизвестен тип применяемой пользователем клавиатуры, а потому подмену драйвера сравнительно просто обнаружить. Вследствие этого подобный метод практически не встречается.
Выводы
Итак, мы рассмотрели несколько эффективных методик, которые могут применяться при построении клавиатурных шпионов. На основании вышеизложенного можем дать следующие рекомендации:
- следует акцентировать внимание на перехватах функций user32.dll;
- необходим контроль штатных драйверов по каталогу Microsoft для своевременного обнаружения подмены драйвера;
- нужно производить анализ на предмет наличия KernelMode-перехватов и модификации машинного кода win32k.sys при помощи антируткитов;
- вследствие того что практически любой клавиатурный шпион сохраняет протоколы, мониторинг файловых операций в процессе активного ввода информации с клавиатуры позволяет обнаружить кейлоггер почти любого типа. Исключение составляют специализированные программы, протоколирующие ввод только в определенных приложениях или в заданных окнах, например в окне ввода пароля.
Выводы
Известно, что сегодня существует универсальная и надежная методика, позволяющая обойти аппаратный клавиатурный шпион, — это использование экранной клавиатуры и иных способов ввода информации без применения клавиатуры. Следует отметить, что большинство современных антикейлоггеров специально для этих целей содержат собственную встроенную экранную клавиатуру.
Поиск аппаратных кейлоггеров непременно следует включить в должностные обязанности сотрудников службы информационной безопасности. При этом, естественно, необходимо иметь в виду, что вероятность установки аппаратного кейлоггера прямо пропорциональна ценности информации, вводимой на рабочем месте.
Драйвер-фильтр
Работа кейлоггеров данного типа основана на установке драйвера, подключаемого к драйверу клавиатуры в качестве фильтра. Пример реализации фильтра клавиатуры приведен в DDK, и данный шпион является одним из самых простых в плане как реализации, так и обнаружения.
Клавиатурный шпион этого типа может быть построен по одной из двух схем:
- драйвер-фильтр в сочетании с управляющим приложением, которое выполняет установку, загрузку и настройку драйвера. Драйвер передает информацию о нажимаемых клавишах управляющему приложению, которое производит обработку и протоколирование полученных данных;
- полностью автономный драйвер самостоятельно ведет запись событий. В данном случае требуется только произвести первичную установку драйвера в систему, после чего установившее драйвер приложение может самоуничтожиться. Возможно решение и без приложения-инсталлятора — в этом случае драйвер устанавливается при помощи INF-файла.
В момент загрузки драйвер должен подключиться к стеку клавиатурного драйвера посредством функций IoCreateDevice и IoAttachDevice. В большинстве известных реализаций фильтр подключается к стеку устройства «\\Device\\KeyboardClass0», являющегося драйвером класса и реализующего общую функциональность для клавиатур различных типов (рис. 1).
Рис. 1
Для клавиатурного шпиона будут представлять интерес только прерывания типа IRP_MJ_READ, поскольку на основе их анализа можно получить коды клавиш. Источником этих IRP-запросов является процесс csrss.exe, а точнее — принадлежащий этому процессу поток необработанного ввода RawInputThread. Посылаемое этим потоком прерывание сначала попадает к драйверу-фильтру шпиона (шаг 1), который устанавливает свой обработчик завершения при помощи функции IoSetCompletionRoutine и передает IRP драйверу Kbdclass (шаг 2). Тот, в свою очередь, помечает IRP как ожидающий завершения и ставит в очередь. При возникновении клавиатурных событий Kbdclass извлекает из очереди ожидающий завершения IRP, вносит в его буфер информацию о нажатых клавишах и завершает IRP. А поскольку в IRP установлен адрес обработчика завершения, то будет произведен вызов этого обработчика (шаг 3). Обработчик может проанализировать содержимое буфера и передать содержащуюся там информацию системе протоколирования (шаг 4). Далее IRP возвращается в поток RawInputThread, а затем весь процесс повторяется. Естественно, что наличие корректно написанного драйвера-фильтра никак не сказывается на работе приложений и обеспечивает глобальный перехват клавиатурного ввода.
Обнаружение описанного шпиона не представляет особой сложности, — для его поиска достаточно изучить стек клавиатурного драйвера на предмет наличия неопознанных драйверов-фильтров.
Подмена драйвера клавиатуры
Данный метод в действительности основан на подмене драйвера Kbdclass или одного из низкоуровневых драйверов клавиатуры драйвером собственной разработки. Сложность реализации указанного метода состоит в том, что заранее неизвестен тип применяемой пользователем клавиатуры, а потому подмену драйвера сравнительно просто обнаружить. Вследствие этого подобный метод практически не встречается.
Клавиатурный шпион на базе руткит-технологии в UserMode
Принцип действия такого клавиатурного шпиона основан на перехвате ряда функций USER32.DLL для мониторинга их вызовов. Данные вредоносные программы пока не получили особого распространения, но это только вопрос времени. Опасность применения руткит-технологии в клавиатурном шпионе объясняется тем, что, во-первых, многие антикейлоггеры не рассчитаны на поиск шпионов такого типа и не способны им противодействовать, а во-вторых, антируткиты часто не проверяют перехваты функций библиотеки user32.dll.
Принцип работы шпиона достаточно прост: при помощи любой из известных руткит-технологий производится перехват одной или нескольких функций, позволяющих получить контроль над вводимой с клавиатуры информацией. Самым простым является перехват функций GetMessage и PeekMessage (рис. 2).
Рис. 2
Работа шпиона организована следующим образом. Приложение вызывает функцию PeekMessage для того, чтобы узнать, есть ли в очереди сообщения указанного типа. Этот вызов перехватывается по руткит-принципу (методика в данном случае не имеет значения). Затем перехватчик вызывает реальную функцию PeekMessage из user32.dll и анализирует возвращаемые результаты. Если функция возвращает true, это означает, что сообщение было в очереди и что оно извлечено в тот буфер, указатель на который передается в качестве первого параметра функции. В этом случае перехватчик проверяет сообщения в буфере на предмет обнаружения сообщений типа WM_KEYDOWN (нажатие клавиши), WM_KEYUP (отпускание клавиши), WM_CHAR (посылается окну после обработки WM_KEYDOWN при помощи TranslateMessage). При выявлении подобного сообщения можно узнать код нажимаемой клавиши и передать его системе протоколирования и анализа (шаг 4). Далее управление возвращается приложению (шаг 5), которое не знает о наличии перехватчика.
Подобный клавиатурный шпион очень опасен, так как:
- он не обнаруживается стандартными методиками поиска клавиатурных шпионов;
- возможно внедрение перехватчика по определенным условиям, в результате чего он внедряется не во все GUI-процессы, а в строго определенные (например, в процессы браузера или в приложение типа WebMoney);
- против него бесполезны экранные клавиатуры и прочие средства борьбы с клавиатурными шпионами;
- кроме перехвата функций PeekMessage и GetMessage, могут быть перехвачены функции копирования информации при работе с буфером обмена (OpenClipboard, CloseClipboard, GetClipboardData, SetClipboardData), опроса состояния клавиатуры (GetKeyState, GetAsyncKeyState, GetKeyboardState) и другие функции user32.dll, что усиливает опасность шпиона, а перехват функций типа CreateWindow позволяет отслеживать создание окон.