Skip to content

Instantly share code, notes, and snippets.

@cr3ative
Last active July 11, 2024 08:38
Show Gist options
  • Save cr3ative/5dad5d425778db16463bb31f034cf67d to your computer and use it in GitHub Desktop.
Save cr3ative/5dad5d425778db16463bb31f034cf67d to your computer and use it in GitHub Desktop.
Making an inexpensive USB Mouse Jiggler, with slightly better USB Descriptor (PID, VID, Manufacturer)

Making a half-convincing USB Mouse Jiggler on the cheap

I object to USB Mouse Jigglers being £20-£30 on Amazon for something a microcontroller should be able to do with ease, in an unconfigurable/unknown state when it comes to how they describe themselves to the host machine.

We can do better, with a reprogrammable version for about £6.

There are existing guides to each part of this, and I've linked them inline. Here's a great one for people less familiar with Arduino, but this guide assumes basic knowledge of Arduino.

Hardware

Any 32u4-based Arduino or clone thereof. I used a generic Arduino Micro Pro clone. Be warned, the USB port falls off these, so take precautions to secure it properly to the board before to stress the port. I added some solder (which then leaked in to the port, and so the cable didn't fit - genius) and later some hot glue to hold the cable in and to the board which seems like a much better idea in retrospect.

A nice bit of heat shrink really sets off the whole product. So professional!

seems legit

Software

I chose the technique seen at https://github.com/TomasHubelbauer/arduino-mouse-jiggler#code - simple enough. Drop something like this in to the Arduino IDE and mess about with it to your hearts content.

As configured, this will move the mouse in a diamond shape 5 "units" in size over 150ms every 60 seconds. Simple enough.

#include "Mouse.h"

void setup() {
  Mouse.begin();
  // Give it a sec to initialise, or we miss the first jiggle when it's plugged in
  delay(1000);
}

int shift = 5;
int instdelay = 50;
int jiggledelay = 60000;

void loop() {
  Mouse.move(shift, -shift, 0);
  delay(instdelay);
  Mouse.move(shift, shift, 0);
  delay(instdelay);
  Mouse.move(-shift, shift, 0);
  delay(instdelay);
  Mouse.move(-shift, -shift, 0);
  delay(jiggledelay);
}

Going the extra mile - modifying the USB Descriptor

By default, this device will appear as an Arduino Leonardo (usually) with the USB Product ID, Vendor ID, Name and Description to match.

Let's make that slightly better. The device will still be an HID Gadget which isn't quite just a simple mouse, but it's better than it was - at least the vendor info and descriptions will be "correct".

image

Editing boards.txt

Loosely via https://gist.github.com/nebhead/c92da8f1a8b476f7c36c032a0ac2592a#linux-instructions - but we're not going to modify the default entry for the Leonardo board, we're going to create a "new" board to avoid overwriting a board you might want to keep standard.

Locate your Arduino IDE boards.txt file, make a backup, and find the entry for your board. We'll duplicate it and make a new entry based entirely off it.

My clone identifies as a Leonardo, so here's what I did:

Existing board - copy this section

We'll change the prefix to create a new Arduino board.

##############################################################

leonardo.name=Arduino Leonardo
leonardo.vid.0=0x2341
leonardo.pid.0=0x0036
leonardo.vid.1=0x2341
leonardo.pid.1=0x8036
leonardo.vid.2=0x2A03
leonardo.pid.2=0x0036
leonardo.vid.3=0x2A03
leonardo.pid.3=0x8036
leonardo.upload_port.0.vid=0x2341
leonardo.upload_port.0.pid=0x0036
leonardo.upload_port.1.vid=0x2341
leonardo.upload_port.1.pid=0x8036
leonardo.upload_port.2.vid=0x2A03
leonardo.upload_port.2.pid=0x0036
leonardo.upload_port.3.vid=0x2A03
leonardo.upload_port.3.pid=0x8036
leonardo.upload_port.4.board=leonardo

leonardo.upload.tool=avrdude
leonardo.upload.tool.default=avrdude
leonardo.upload.tool.network=arduino_ota
leonardo.upload.protocol=avr109
leonardo.upload.maximum_size=28672
leonardo.upload.maximum_data_size=2560
leonardo.upload.speed=57600
leonardo.upload.disable_flushing=true
leonardo.upload.use_1200bps_touch=true
leonardo.upload.wait_for_upload_port=true

leonardo.bootloader.tool=avrdude
leonardo.bootloader.tool.default=avrdude
leonardo.bootloader.low_fuses=0xff
leonardo.bootloader.high_fuses=0xd8
leonardo.bootloader.extended_fuses=0xcb
leonardo.bootloader.file=caterina/Caterina-Leonardo.hex
leonardo.bootloader.unlock_bits=0x3F
leonardo.bootloader.lock_bits=0x2F

leonardo.build.mcu=atmega32u4
leonardo.build.f_cpu=16000000L
leonardo.build.vid=0x2341
leonardo.build.pid=0x8036
leonardo.build.usb_product="Arduino Leonardo"
leonardo.build.board=AVR_LEONARDO
leonardo.build.core=arduino
leonardo.build.variant=leonardo
leonardo.build.extra_flags={build.usb_flags}

New board (including additions)

This is just a simple swap of prefix from leonardo. to jiggler. - paste it at the bottom of boards.txt

##############################################################

jiggler.name=Jiggler Project (Arduino Leonardo)
jiggler.vid.0=0x2341
jiggler.pid.0=0x0036
jiggler.vid.1=0x2341
jiggler.pid.1=0x8036
jiggler.vid.2=0x2A03
jiggler.pid.2=0x0036
jiggler.vid.3=0x2A03
jiggler.pid.3=0x8036
jiggler.upload_port.0.vid=0x2341
jiggler.upload_port.0.pid=0x0036
jiggler.upload_port.1.vid=0x2341
jiggler.upload_port.1.pid=0x8036
jiggler.upload_port.2.vid=0x2A03
jiggler.upload_port.2.pid=0x0036
jiggler.upload_port.3.vid=0x2A03
jiggler.upload_port.3.pid=0x8036
jiggler.upload_port.4.board=leonardo

jiggler.upload.tool=avrdude
jiggler.upload.tool.default=avrdude
jiggler.upload.tool.network=arduino_ota
jiggler.upload.protocol=avr109
jiggler.upload.maximum_size=28672
jiggler.upload.maximum_data_size=2560
jiggler.upload.speed=57600
jiggler.upload.disable_flushing=true
jiggler.upload.use_1200bps_touch=true
jiggler.upload.wait_for_upload_port=true

jiggler.bootloader.tool=avrdude
jiggler.bootloader.tool.default=avrdude
jiggler.bootloader.low_fuses=0xff
jiggler.bootloader.high_fuses=0xd8
jiggler.bootloader.extended_fuses=0xcb
jiggler.bootloader.file=caterina/Caterina-Leonardo.hex
jiggler.bootloader.unlock_bits=0x3F
jiggler.bootloader.lock_bits=0x2F

jiggler.build.mcu=atmega32u4
jiggler.build.f_cpu=16000000L
jiggler.build.vid=0x2341
jiggler.build.pid=0x8036
jiggler.build.board=AVR_LEONARDO
jiggler.build.core=arduino
jiggler.build.variant=leonardo

jiggler.build.usb_manufacturer="Microsoft Corporation"
jiggler.build.usb_product="Classic IntelliMouse"
jiggler.build.vid=0x045E
jiggler.build.pid=0x0823

jiggler.build.extra_flags={build.usb_flags}

Details of the changes and additions

Change the name to something you can recognise in the Arduino IDE menu:

jiggler.name=Jiggler Project (Arduino Leonardo)

Change the existing usb_product to something you wish to pretend to be

jiggler.build.usb_product="Classic IntelliMouse"

Add usb_manufacturer, vid and pid of your cloning target; you can find these values online

jiggler.build.usb_manufacturer="Microsoft Corporation"
jiggler.build.vid=0x045E
jiggler.build.pid=0x0823

Restart Arduino, and you can select this new board from the menu:

image

Changing USB Serial Number

Important note: this affects all Arduino boards. Change if 0 to if 1 to undo this behaviour once you're done creating your device.

Source: https://forum.arduino.cc/t/hacking-in-a-usb-serial-number-on-leonardo-lilypad-usb/481969

I didn't like that this still reported HIDGD as the USB Serial Number. So, let's change that.

Make a backup of, then open up USBCore.cpp, and find these lines:

else if (setup.wValueL == ISERIAL) {
#ifdef PLUGGABLE_USB_ENABLED
    char name[ISERIAL_MAX_LEN];
    PluggableUSB().getShortName(name);
    return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0);
#endif
}

I changed this over to:

else if (setup.wValueL == ISERIAL) {
    #ifdef PLUGGABLE_USB_ENABLED
        #if 0
            char name[ISERIAL_MAX_LEN];
            PluggableUSB().getShortName(name);
            return USB_SendStringDescriptor((uint8_t*)name, strlen(name), 0);
        #else
            // This is the custom serial number we wish to send
            return USB_SendStringDescriptor((uint8_t*)"0", 10, 0);
        #endif
    #endif
}

Which sends 0 as the serial number. That'll do. You can recompile your sketch without restarting the IDE in this case.

Security posture

Note: The device will still appear as a "USB HID Gadget" rather than "USB Mouse" in the "what are you?" class descriptors, which exposes a serial port to Arduino for reprogramming. This will only work around simple checks of the PID, VID, Vendor Name, Device Name, etc.

Footnote

Microsoft Teams should be ashamed of itself for implementing an activity indicator in such an insiduous manner.

@DeadInside-CZ
Copy link

DeadInside-CZ commented May 17, 2023

Hi and thank you.
Our company recently changed policy for VPN connections and if I am idle for more then 3 minutes, it automatically disconnects me.
I took inspiration and introduced some randomnes (i am a begginer in arduino), but i guess, there is some more elegent way to achive similar result.

#include "Mouse.h"

void setup() {
  Mouse.begin();
  delay(2000);
  randomSeed(analogRead(0));
}

void loop() {
  //random shift for each jiggle
  int rShift1 = random(15, 100);
  int rShift2 = random(15, 100);
  int rShift3 = random(15, 100);
  int rShift4 = random(15, 100);

  //random delay for jiggle 1-3 + random main delay on the end of the jiggle
  int rDelay1 = random(50, 250);
  int rDelay2 = random(50, 250);
  int rDelay3 = random(50, 250);
  int rMainDelay = random(30000, 60000);

  Mouse.move(rShift1, -rShift1, 0);
  delay(rDelay1);
  Mouse.move(rShift2, rShift2, 0);
  delay(rDelay2);
  Mouse.move(-rShift3, rShift3, 0);
  delay(rDelay3);
  Mouse.move(-rShift4, -rShift4, 0);
  delay(rMainDelay);
}`

Thank you for the inspiration.

@xf6jx5fq
Copy link

Hi @cr3ative

In the Security Posture section, can you show where I can find that "what are you?" class descriptors ?
Is this on Windows or Linux ? If on Linux, is this detectable on Windows ?
Also, is it better to hide this as a USB composite device instead of a mouse ? Having 2 mice (one to use for work and one to jiggle is suspicious don't you think ?

Thank you !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment