В свете удаленной работы, на все VDI в офисе расставили агента, определяющего активность пользователя. Первая мысль, которая пришла в голову - сделать имитатор мыши, благо в RDP или ICA сессии невозможно определить откуда именно пришли перемещения.
Программных реализаций мышкодвигателей - полно, так что в этот раз мне захотелось реализовать именно аппаратное решение.
Мысль была следующая. Arduino и подобные платы разработки видятся системой как USB to COM интерфейс. А в Windows, включая Windows 10, до сих пор присутствует поддержка Serial Mouse. Поэтому ничего сложного не составит сэмулировать подобную мышь без какой-либо пайки, а только штатными средствами имеющейся в наличии платы.
Протокол у мыши примитивный, есть готовый пример на Хабре. В примере, кстати, ошибка, которая проявляется эффектом, описанным самим автором:
необходимо поменять 0x1F на 0x3F, так как передаются нижние 6 бит, а не 5.
В качестве Arduino я взял имевшийся в загашнике Arduino Nano v3. Свой код привожу ниже.
Согласно мышиному протоколу, общение с хостом идет на скорости последовательного порта 1200 бит/сек, 7 битов данных, 2 стоп бита. Пойдет и "классический" режим 8 битов данных и 1 стоп, как в моем коде.
Так как COM порт не является Plug and Play устройством, в диспетчере устройств Windows необходимо явно нажать на "Scan for Hardware Changes":
Хост в момент детекта устройства производит определенные манипуляции с линиями DTR и RTS, что в нашем случае приводит к резету Arduino Nano, и, соответственно, запуску функции setup(). Согласно мышиному протоколу, при этом необходимо отправить латинскую букву 'M' (я на всякий случай делаю это 200 раз), и в системе появляется "Microsoft Serial Mouse". На скриншоте также виден COM4 от Arduino, через который и идет "общение" с псевдо-мышью.
Далее - код функции loop() отправляет в цикле дельты перемещения курсора согласно массиву d[][2] - в данном случае это квадрат.
Так как "классические" Serial Mouse не работали со скоростью выше 200 перемещений в секунду, в код добавлена принудительная delay(25). Если ее убрать - курсор будет двигаться по экрану рывками.
Собственно, на этом - всё.
Далее по желанию можно добавить имитацию нажатий на кнопки или какую-нибудь логику. Прокрутку колеса, увы, добавить не получится - в те времена подобных мышей просто не существовало и протокол колесо не поддерживает. Я пробовал посылать четвертый байт с разными значениями - однако, никакой реакции на него от операционной системы не заметил.
Отрицательные приращения работают криво, движение на -1 выглядит примерно как на +30 (по амплитуде, с направлением все в порядке).В коде функции formPacket
- packet[1] = x & 0x1F; // ошибка, должно быть в обоих местах 0x3F
- packet[2] = y & 0x1F;
необходимо поменять 0x1F на 0x3F, так как передаются нижние 6 бит, а не 5.
В качестве Arduino я взял имевшийся в загашнике Arduino Nano v3. Свой код привожу ниже.
- uint8_t packet[3];
- static void formPacket(bool leftClick, bool rightClick, uint8_t x, uint8_t y)
- {
- packet[0] = (1<<6) | (leftClick<<5) | (rightClick<<4);
- packet[0] |= ((y>>6) & 0x3) << 2;
- packet[0] |= ((x>>6) & 0x3);
- packet[1] = x & 0x3F;
- packet[2] = y & 0x3F;
- }
- void setup() {
- Serial.begin(1200);
- for(int i=0; i<200; i++)
- Serial.write('M');
- }
- int count=256;
- int pos=0;
- int d[][2]={
- {1,0},
- {0,1},
- {-1,0},
- {0,-1},
- {0,0},
- };
- int Speed=8;
- void loop() {
- while(1)
- {
- formPacket(0, 0, d[pos][0]*Speed, d[pos][1]*Speed);
- Serial.write(packet,3);
- count-=Speed;
- if(count<0)
- {
- count=256;
- pos++;
- if(d[pos][0]==0 && d[pos][1]==0)
- pos=0;
- }
- Serial.flush();
- delay(25);
- }
- }
Согласно мышиному протоколу, общение с хостом идет на скорости последовательного порта 1200 бит/сек, 7 битов данных, 2 стоп бита. Пойдет и "классический" режим 8 битов данных и 1 стоп, как в моем коде.
Так как COM порт не является Plug and Play устройством, в диспетчере устройств Windows необходимо явно нажать на "Scan for Hardware Changes":
Хост в момент детекта устройства производит определенные манипуляции с линиями DTR и RTS, что в нашем случае приводит к резету Arduino Nano, и, соответственно, запуску функции setup(). Согласно мышиному протоколу, при этом необходимо отправить латинскую букву 'M' (я на всякий случай делаю это 200 раз), и в системе появляется "Microsoft Serial Mouse". На скриншоте также виден COM4 от Arduino, через который и идет "общение" с псевдо-мышью.
Далее - код функции loop() отправляет в цикле дельты перемещения курсора согласно массиву d[][2] - в данном случае это квадрат.
Так как "классические" Serial Mouse не работали со скоростью выше 200 перемещений в секунду, в код добавлена принудительная delay(25). Если ее убрать - курсор будет двигаться по экрану рывками.
Собственно, на этом - всё.
Далее по желанию можно добавить имитацию нажатий на кнопки или какую-нибудь логику. Прокрутку колеса, увы, добавить не получится - в те времена подобных мышей просто не существовало и протокол колесо не поддерживает. Я пробовал посылать четвертый байт с разными значениями - однако, никакой реакции на него от операционной системы не заметил.