- PVSM.RU - https://www.pvsm.ru -

Пишем простой Keylogger для Windows на C++

Здравствуйте, Хабровчане.

Решил написать программный логгер клавиатуры на C++ с использованием WinAPI. Не могу сказать, что преследовал какую-нибудь шпионскую цель, когда писал его, скорее знакомился с хуками на WinAPI. Так как получилось не так уж и плохо, а на Хабре нет статьи про программные логгеры, решил написать свою.

Как это сделано?

Для отлавливания нажатия клавиш был использован клавиатурный хук [1].

HHOOK WINAPI SetWindowsHookEx(
  _In_  int idHook,
  _In_  HOOKPROC lpfn,
  _In_  HINSTANCE hMod,
  _In_  DWORD dwThreadId
);

Для того, чтобы перехватывать нажатия всех клавиатурных клавиш, в качестве параметра idHook удобно указать WH_KEYBOARD или WH_KEYBOARD_LL. Разница лишь в том, что WH_KEYBOARD_LL также перехватывает нажатия системных клавиш (т.е Alt или любая клавиша при зажатом Alt), поэтому его мы и выберем.

lpfn — указатель на функцию, обрабатывающую перехваченные сообщения (в нашем случае нажатия клавиш).
hMod — дескриптор экземпляра приложения, содержащий обрабатывающую функцию.
dwThreadId — идентификатор потока, сообщения которого мы хотим перехватывать. Нужно установить данный параметр в 0, чтобы перехватывать сообщения всех потоков.

Возвращаемое значение — дескриптор нашего хука, который при выходе нужно будет освободить функцией UnhookWindowsHookEx.
Обратившись за справкой в MSDN [2], мы видим прототип функции, обрабатывающей сообщения данного хука.

LRESULT CALLBACK LowLevelKeyboardProc(
  _In_  int nCode,
  _In_  WPARAM wParam,
  _In_  LPARAM lParam
);

Параметр nCode должен быть равен HC_ACTION, иначе сообщение предоставляется другому процессу.
wParam — это одно из следующих значений WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, или WM_SYSKEYUP.
lParam — указатель на структуру KBDLLHOOKSTRUCT, в полях которой нас интересуют только 2 параметра: vkCode(виртуальный код) и scanCode нажатой клавиши.
Данная функция должна вернуть значение функции CallNextHookEx, в противном же случае, следующий обрабатывающий событие хук, может получить неверные параметры сообщения.
Каждый раз при нажатии клавиши, наша программа будет перехватывать это событие и обрабатывать нашей процедурой LowLevelKeyboardProc.

Для того, чтобы ретранслировать виртуальный и скан код клавиши в символьный вид, нам понадобится функция ToAsciiEx [3].

int WINAPI ToAsciiEx(
  _In_      UINT uVirtKey,
  _In_      UINT uScanCode,
  _In_opt_  const BYTE *lpKeyState,
  _Out_     LPWORD lpChar,
  _In_      UINT uFlags,
  _In_opt_  HKL dwhkl
);

Первые 2 параметра — виртуальный и скан коды клавиши соответственно.
lpKeyState — состояние клавиатуры, проверяет какие клавиши нажаты/активны.
lpChar — указатель на двойное слово, в которое функция запишет символьное представление клавиши.
uFlags — параметр, указывающий на активность меню.
dwhkl — идентификатор раскладки клавиатуры.
Возвращаемое значение — количество символов, записанных в буфер lpChar. Нас интересует случай, когда записан 1 символ.
В принципе, это 3 основные функции, требуемые для самого простого клавиатурного логгера.

Немного о программе

Программа компилируется без RTL в Visual Studio 2013. Таким образом, мы получаем небольшой объём исполняемого файла и невозможность сборки в debug-версии. Данные записываются в лог файл в тот же каталог, где находится .exe файл. Для удобства логгер каждый раз создает новый файл при записи, записывает время нажатия клавиш, имя окна, в котором вводились символы и останавливается по нажатию LSHIFT+RSHIFT. Данный сниффер не адаптирован под полную клавиатуру, некоторые служебные клавиши, например F13 или NUM_LOCK, могут писаться, как [unknown]. Думаю те, кто хоть немного знаком с C/C++ смогут запросто их добавить. Более того, Вы можете полностью изменить код так, как Вам удобно.

Ссылки на Bitbucket: исходник [4], бинарник [5], проект на vs 2013 [6]

Программа не требует прав администратора, поэтому её можно втихую поставить на любой компьютер друга под управлением Windows.

Автор: Skapix

Источник [7]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/c-3/69194

Ссылки в тексте:

[1] клавиатурный хук: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx

[2] MSDN: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644985(v=vs.85).aspx"

[3] ToAsciiEx: http://msdn.microsoft.com/en-us/library/windows/desktop/ms646318(v=vs.85).aspx

[4] исходник: https://bitbucket.org/skapix/logger/downloads/keyboard_logger_for_habr-source.zip

[5] бинарник: https://bitbucket.org/skapix/logger/downloads/keyboard_logger_for_habr-bin.zip

[6] проект на vs 2013: https://bitbucket.org/skapix/logger/downloads/keyboard_logger_for_habr.zip

[7] Источник: http://habrahabr.ru/post/236145/