Перехват сигнала с клавиатуры — программное получение событий ввода до передачи их активному окну. В Windows реализуется через WinAPI (SetWindowsHookEx, RegisterRawInputDevices), в Linux — через подсистему evdev в /dev/input и XGrabKey под X11. Каждый метод требует определённого уровня привилегий и решает свой класс задач: горячие клавиши, ассистивные технологии, тестирование.
- Аппаратный уровень и путь сигнала до ОС
- Windows-API: WH_KEYBOARD_LL, Raw Input и polling
- Опрос через GetAsyncKeyState
- Linux: подсистема evdev и X11 XGrabKey
- Ограничения Wayland-композиторов
- Ограничения и требования безопасности
- Сравнение методов работы с клавиатурой
- Как перехватить сигнал с клавиатуры — пошагово
- Легальные и запрещённые сценарии
- Вопрос-ответ
Аппаратный уровень и путь сигнала до ОС
Физическая клавиатура посылает контроллеру сигнал по протоколу PS/2 или USB HID. В архитектуре x86 контроллер клавиатуры исторически подключён к прерыванию IRQ 1, которое обрабатывает драйвер операционной системы. Спецификация USB HID (Usage Page 0x07 «Keyboard/Keypad») стандартизирована USB-IF в документе HID Usage Tables версии 1.22 от 4 января 2022 года и описывает Usage ID для каждой клавиши.
До операционной системы код скан-клавиши проходит несколько слоёв: контроллер, драйвер шины, драйвер ввода. В Windows это стек kbdclass.sys → kbdhid.sys, в Linux — модуль usbhid и подсистема input в ядре. По данным документации kernel.org (Documentation/input/input.rst), каждое событие превращается в структуру input_event с полями type, code, value.
Перехват сигнала на уровне драйвера возможен, но требует загрузки собственного модуля ядра или фильтр-драйвера. Такие механизмы используются антивирусами и корпоративными DLP-системами. Для прикладных задач достаточно API пользовательского режима, о которых пойдёт речь ниже.
Windows-API: WH_KEYBOARD_LL, Raw Input и polling
Windows предоставляет три основных механизма для приложений пользовательского режима. Первый — низкоуровневый хук WH_KEYBOARD_LL, который устанавливается функцией SetWindowsHookEx из библиотеки user32.dll. Хук получает все нажатия во всех процессах текущей десктопной сессии и вызывает callback до передачи события окну. Согласно документации Microsoft Learn (docs.microsoft.com, раздел Windows App Development), обработчик должен возвращать управление за 300 миллисекунд, иначе система снимает обработчик.
Второй механизм — Raw Input API, зарегистрированный через RegisterRawInputDevices с UsagePage=0x01 и Usage=0x06. В отличие от хука, перехват сигнала через Raw Input работает только когда окно приложения имеет фокус или явно запрошен фоновый режим флагом RIDEV_INPUTSINK. Этот API предпочтителен для игровых движков и утилит горячих клавиш: он даёт данные напрямую от драйвера HID без прохода через message loop.
Опрос через GetAsyncKeyState
Третий вариант — периодический опрос через GetAsyncKeyState. Функция возвращает текущее состояние клавиши в момент вызова и не гарантирует, что промежуточные нажатия будут зафиксированы. По сравнению с хуком и Raw Input polling проигрывает по точности, но не требует установки обработчика и работает без прав администратора. Такой перехват применяется в простых утилитах, где допустима потеря событий между опросами.
Linux: подсистема evdev и X11 XGrabKey
В Linux все события ввода публикуются подсистемой ядра в устройствах /dev/input/eventN. Формат описан в Documentation/input/event-codes.rst на kernel.org. Прикладная библиотека libevdev от freedesktop.org предоставляет удобную обёртку: приложение открывает файл устройства, читает структуры input_event и обрабатывает сигналы клавиатуры. Доступ к /dev/input/event* по умолчанию ограничен группой input — без включения пользователя в эту группу чтение невозможно.
Под графической оболочкой X11 стандартный способ — функция XGrabKey из библиотеки libX11. Она регистрирует конкретную комбинацию клавиш глобально для всей сессии X-сервера и вызывает событие KeyPress в приложении-получателе. XGrabKey не позволяет обрабатывать произвольную клавишу без указания комбинации — это ограничение спецификации X Window System Protocol (X11R7.7).
Ограничения Wayland-композиторов
Wayland-композиторы отказались от глобального перехвата сигнала из соображений безопасности. Спецификация wayland.freedesktop.org не содержит аналога XGrabKey: приложение получает события только когда его поверхность имеет фокус. Для горячих клавиш в Wayland предлагается интерфейс XDG Desktop Portal (portal.freedesktop.org, раздел GlobalShortcuts), требующий явного согласия пользователя.
Ограничения и требования безопасности
Перехват сигнала клавиатуры вне окна собственного приложения — привилегированная операция. В Windows установка WH_KEYBOARD_LL с 2018 года флагается антивирусными продуктами как поведение потенциально нежелательной программы, если приложение не подписано и не находится в белом списке. Microsoft Defender, согласно бюллетеням MSRC, применяет поведенческий анализ и блокирует неподписанные хуки в контексте Windows 11 Enterprise.
Установить обработчик без прав администратора можно только для процессов той же сессии и того же уровня целостности (integrity level). Перехват ввода в окне UAC-приглашения невозможно ни при каких условиях: диалог работает на Secure Desktop, к которому пользовательские процессы не имеют доступа. Это гарантирует, что кейлоггер не получит пароль администратора и не сохранит его в лог.
Сравнение методов работы с клавиатурой
Три подхода различаются по требованиям к правам, точности данных и латентности.
WH_KEYBOARD_LL — глобальный обработчик до окна назначения. Работает быстрее опроса, требует только прав пользователя. По сравнению с Raw Input даёт возможность модифицировать или подавить событие возвратом ненулевого значения из обработчика. Основное ограничение — обработчик обязан отвечать за 300 мс, иначе перехват сигнала прекращается автоматически.
Raw Input — доступ к данным драйвера HID. Работает быстрее WH_KEYBOARD_LL по латентности (нет посредника в виде message loop), но требует активного окна или явного разрешения RIDEV_INPUTSINK. В отличие от хука не позволяет блокировать событие — только читать сигналы.
GetAsyncKeyState — опрос состояния. Медленнее и менее точен, чем событийные модели: между двумя вызовами клавиша может успеть нажаться и отпуститься. Зато прост в реализации и работает в любом окне без установки обработчика или регистрации устройства.
Как перехватить сигнал с клавиатуры — пошагово
Процедура состоит из четырёх шагов, одинаковых для WH_KEYBOARD_LL и Raw Input.
Шаг 1. Определите цель работы: горячая клавиша, ассистивная технология, тестовый автомат. От цели зависит выбор API. Для одной комбинации — RegisterHotKey. Для полного потока событий — Raw Input. Для модификации ввода до окна — WH_KEYBOARD_LL. Перехват сигнала полного потока требует Raw Input с RIDEV_INPUTSINK.
Шаг 2. Установите обработчик. В Windows вызовите SetWindowsHookEx с параметром WH_KEYBOARD_LL и указателем на callback. В Linux откройте /dev/input/eventN файловым дескриптором и запустите epoll_wait для чтения сигналов.
Шаг 3. Обработайте событие. В callback читайте структуру KBDLLHOOKSTRUCT (Windows) или input_event (Linux), извлекайте скан-код и флаги. Не выполняйте в обработчике длительных операций — передавайте данные в очередь для отдельного потока.
Шаг 4. Снимите обработчик при завершении. В Windows вызовите UnhookWindowsHookEx, в Linux закройте дескриптор. Забытый хук остаётся в памяти до перезагрузки сессии и деградирует отзывчивость системы. Перехват сигнала должен завершаться корректно, иначе следующее приложение получит ошибку установки.
Легальные и запрещённые сценарии
Перехват сигнала клавиатуры разрешён для ассистивных технологий (экранных клавиатур, программ для людей с ограниченной подвижностью), утилит горячих клавиш (AutoHotkey, PowerToys), автоматизированного тестирования UI, IDE и текстовых редакторов. Все эти классы приложений явно уведомляют пользователя об установке обработчика и не работают в скрытом режиме.
Использование хука для скрытой записи ввода без согласия пользователя квалифицируется как создание вредоносного ПО. В РФ это статья 273 УК РФ, в США — Computer Fraud and Abuse Act (18 U.S.C. §1030). Публикация полного работающего кода кейлоггера не входит в задачу справочной статьи; описанные API документированы Microsoft и freedesktop.org для легального применения.
Промежуточный слой между легальным и запрещённым — корпоративные системы мониторинга сотрудников. Такие продукты требуют письменного согласия работника при трудоустройстве и внесения в локальные акты. По данным Роскомнадзора, скрытая установка хука на рабочий компьютер сотрудника без такого согласия нарушает статью 152.2 ГК РФ о защите частной жизни. Это отдельно проверяется в судебной практике по трудовым спорам.
Вопрос-ответ
Можно ли перехватить сигнал с клавиатуры без прав администратора? Да, для процессов текущей пользовательской сессии и того же уровня целостности. Установка WH_KEYBOARD_LL и Raw Input работает от обычного пользователя. Права администратора не дают доступа к Secure Desktop и не отменяют изоляцию сессий.
Какой API даёт наименьшую задержку? По данным Microsoft, Raw Input работает быстрее WH_KEYBOARD_LL, так как получает данные напрямую от драйвера HID, минуя message loop. Для игр и профессиональных инструментов рекомендуется именно Raw Input.
Почему антивирус блокирует моё приложение с хуком? Поведенческий анализ Microsoft Defender флагает установку WH_KEYBOARD_LL неподписанными приложениями. Решение — цифровая подпись Authenticode и внесение исполняемого файла в исключения через Group Policy.
Работает ли перехват сигнала в Wayland так же, как в X11? Нет. Спецификация Wayland не содержит аналога XGrabKey. Приложение получает события только при фокусе. Для глобальных горячих клавиш используется портал XDG Desktop Portal GlobalShortcuts с явным согласием пользователя.
