[Из песочницы] Клавиатурный шпион на Arduino

Предисловие


Стоит сказать, что область применение данного устройства не так уж и велика. Для работы это мониторинг, контроль за рабочим временем, защита от утечки информации и, наверное, всё.

В быту эта вещь может хорошо облегчить жизнь. Например, нажали определённое сочетание клавиш — Arduino их распознало и… послало сигнал включить чайник. Если не чайник, то что-нибудь другое.
Но всё же, это банальное слежение (возможно, даже скрытое) за сотрудником, что с моральной точки зрения не есть хорошо. Но всё же, юридическая справка даёт «добро», если это прописано в трудовом договоре, если этот мониторинг происходит в трудовое время и на рабочем месте и если, конечно, сотрудник проинформирован и поставил свою галочку.

Ну, а в личной жизни вы вольны делать всё, что захочется, пока это касается вашей собственности.

Всё, юридически мы защищены, теперь я расскажу и покажу, что нам необходимо и как собрать вместе, чтобы получился простой перехватчик нажатий клавиш с клавиатуры.

Начнём


Итак, нам понадобится десяток проводов и две платы:

1) Arduino Leonardo

4326e7a669b146bfb9c60b038712e663.jpg

2) USB Host Shield

a8b074ec6b5a4003ad17e6905d199b5b.jpg

Почему Arduino Leonardo? Потому что она относительно дешёвая и в отличие от своих предшественников на ATmega32u4 имеет встроенную поддержку для USB соединения.

USB протокол определяет два типа устройств: хост (master, server) и периферия (slave, client). USB Host Shield управляет периферийными устройствами и обеспечивает их питанием. Например, когда вы подключаете клавиатуру к ПК, то ПК — это хост, который управляет клиентом, а клиент, в данном случае, — клавиатура.

А поддерживаемой перифирии довольно много. Самые интересные из них это:

1) HID устройства: клавиатура, мышь, джойстик и т. д.
2) Игровые контроллеры
3) ADK-совместимые Android телефоны и планшеты.

А за более подробной информацией прошу на официальный сайт.

В нашем случае — это клавиатура. Она относится к классу HID устройств. HID код для клавиатуры кодируется 8 байтами:

1) 1 байт — каждый бит соответствует своему модификатору (L Ctrl, R Ctrl, L Shift, R Shift и т. д.).
2) 2 байт — зарезервирован и нам не нужен, обычно он занулён.
3) 3–8 байты — содержат коды 6ти клавиш.

Более подробно об этом можно почитать здесь.

Всё, с теорией покончено, теперь можно и схему собрать.

2fa30843a2b74dc3b2a894cc64991ac4.png

Кстати, очень удобная программа для рисования схем, в которой и была нарисована эта схема, здесь.

Теперь стоит пояснить, что к чему.

У Arduino Leonardo есть небольшая особенность из-за которой мы не можем просто подключить её сверху: SPI разъёмы расположены на ICSP (те 6 разъёмов посередине справа) и из-за этого их приходится выводить на цифровые разъёмы USB Host Shield.

1) Жёлтый провод: пин 4 MOSI (подключён к 11 пину на USB Host shield).
2) Серый провод: пин 1 MISO (подключён к 12 пину на USB Host shield).
3) Зелёный провод: пин 3 SCK (подключён к 13 пину на USB Host shield).

Обеспечиваем питание нижними пятью проводами и одним фиолетовым:

1) Reset к Reset
2) 3.3V к 3.3V
3) 5V к 5V
4) GND к GND
5) VIN к VIN
6) Reset к D7

Теперь нам нужно подключить управляющие пины:
1) D7 к D7
2) D10 к D10

Это необходимый минимум, чтобы заставить её работать.

Так, схема есть, теперь нам нужно её как-то запрограммировать и это делается с помощью IDE от Arduino. Она совершенно бесплатна и находится в открытом доступе. Примеры программ и саму IDE можно найти на официальном сайте.

Для работы с USB Host Shield нам понадобится дополнительная библиотека (здесь).

Сам код максимально прост:

#include 
#include 
#include 

// Отправляет коды клавиш на ПК.
class KeyboardOut
{
  private:
    KeyReport _keyReport; // Собственно наши 8 байт для кодировки.
    
    void send_report();
    
  public:
    size_t press(uint8_t mod, uint8_t key);
    size_t release(uint8_t mod, uint8_t key);
};

KeyboardOut keyboard_out;

// Отправляет код нажатия на компьютер.
size_t KeyboardOut::press(uint8_t mod, uint8_t key) {
  uint8_t i;
  
  _keyReport.modifiers |= mod;
  
  if (_keyReport.keys[0] != key && _keyReport.keys[1] != key && 
    _keyReport.keys[2] != key && _keyReport.keys[3] != key &&
    _keyReport.keys[4] != key && _keyReport.keys[5] != key) {

    for (i=0; i<6; i++) {
      if (_keyReport.keys[i] == 0x00) {
        _keyReport.keys[i] = key;
        break;
      }
    }
    if (i == 6) {
      return 0;
    }   
  }
  send_report();
  return 1;
}

// Отправляет код отжатия на компьютер.
size_t KeyboardOut::release(uint8_t mod, uint8_t key) {
  uint8_t i;
  
  _keyReport.modifiers &= mod;
  
  for (i=0; i<6; i++) {
    if (0 != key && _keyReport.keys[i] == key) {
      _keyReport.keys[i] = 0x00;
    }
  }
  send_report();
  return 1;
}

void KeyboardOut::send_report()
{
  HID_SendReport(2, &_keyReport, sizeof(KeyReport));    // Отправляем код клавиши на ПК.
}

// Принимает коды клавиш с USB Host Shield.
class KeyboardIn : public KeyboardReportParser
{
  protected:
    void OnKeyDown  (uint8_t mod, uint8_t key);
    void OnKeyUp  (uint8_t mod, uint8_t key);
};

KeyboardIn keyboard_in;

// Принимает код нажатия с USB Host Shield.
void KeyboardIn::OnKeyDown(uint8_t mod, uint8_t key)
{
  keyboard_out.press(mod, key);
  
  uint8_t c = OemToAscii(mod, key);    // Собственно наш символ с клавиатуры
  PrintHex(key, 0x80);            // А это его шестнадцатеричное представление
}

// Принимает код отжатия с USB Host Shield.
void KeyboardIn::OnKeyUp(uint8_t mod, uint8_t key)
{
  keyboard_out.release(mod, key);
  
  uint8_t c = OemToAscii(mod, key);
  PrintHex(key, 0x80);
}

USB     UsbHost;

HIDBoot    HidKeyboard(&UsbHost);

void setup()
{
  UsbHost.Init();
  
  delay( 200 );

  HidKeyboard.SetReportParser(0, (HIDReportParser*)&keyboard_in);
}

void loop()
{
  UsbHost.Task();
}


Осталось только подключить через USB Arduino к ПК, а клавиатуру к USB Host Shield, загрузить программу на Arduino при помощи IDE и всё! Key Catcher готов!

Итоги:

1) Arduino даёт множество возможностей при своей низкой цене и множеству разнообразных модулей и датчиков.
2) Данное устройство может позволить превратить вашу клавиатуру в пульт управления, например, телевизором, электрочайником, лампой, только докупить пару модулей придётся.

© Geektimes