commit 894dd9ea680cc0576fc3223d3069f28324e651f8 Author: Seppe De Loore Date: Tue Mar 17 21:39:58 2026 +0100 Initial commit. diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..03f4a3c --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +.pio diff --git a/README.md b/README.md new file mode 100644 index 0000000..81a80be --- /dev/null +++ b/README.md @@ -0,0 +1,151 @@ +# Digispark USB Rubber Ducky PoC + +A proof-of-concept USB HID keystroke injection tool using a Digispark ATtiny85 development board and PlatformIO. + +When plugged into a host machine the device emulates a USB keyboard and automatically types a predefined payload. + +## Prerequisites + +- [PlatformIO CLI](https://docs.platformio.org/en/latest/core/installation/index.html) (or the PlatformIO IDE extension for VS Code) +- A Digispark ATtiny85 board with the micronucleus bootloader + +On Linux you may also need udev rules so the micronucleus uploader can access the USB device without root: + +```bash +# /etc/udev/rules.d/49-micronucleus.rules +SUBSYSTEMS=="usb", ATTRS{idVendor}=="16d0", ATTRS{idProduct}=="0753", MODE="0660", GROUP="plugdev" +``` + +Reload rules after creating the file: + +```bash +sudo udevadm control --reload-rules && sudo udevadm trigger +``` + +## Project structure + +``` +. +├── platformio.ini # Board & framework configuration +├── src/ +│ └── main.cpp # Payload source code +├── include/ # Project header files +├── lib/ # Private libraries +└── test/ # Unit tests +``` + +## Building + +Compile the firmware: + +```bash +pio run +``` + +PlatformIO will automatically download the required toolchain and Digistump framework on the first run. + +## Uploading to the device + +```bash +pio run -t upload +``` + +The console will print `Plug in device now...`. You then have **60 seconds** to connect the Digispark to a USB port. The micronucleus bootloader on the board will receive the firmware and reboot into the payload automatically. + +> **Tip:** If the upload times out, unplug the board, run the command again and re-plug when prompted. + +## Adapting the payload + +All payload logic lives in the `setup()` function inside `src/main.cpp`, between the `--- payload start ---` and `--- payload end ---` comments. + +### Keyboard layout + +The layout is selected with a `#define` **before** the `DigiKeyboard.h` include: + +```cpp +#define LAYOUT_FRENCH // AZERTY +#include +``` + +Available layouts (define exactly one): + +| Define | Layout | +|---|---| +| `LAYOUT_US_ENGLISH` | US QWERTY (default if none specified) | +| `LAYOUT_FRENCH` | French AZERTY | +| `LAYOUT_FRENCH_BELGIAN` | Belgian AZERTY | +| `LAYOUT_FRENCH_SWISS` | Swiss French | +| `LAYOUT_CANADIAN_FRENCH` | Canadian French | +| `LAYOUT_CANADIAN_MULTILINGUAL` | Canadian Multilingual | +| `LAYOUT_GERMAN` | German QWERTZ | +| `LAYOUT_GERMAN_SWISS` | Swiss German | +| `LAYOUT_SPANISH` | Spanish | +| `LAYOUT_SPANISH_LATIN_AMERICA` | Latin American Spanish | +| `LAYOUT_ITALIAN` | Italian | +| `LAYOUT_PORTUGUESE` | Portuguese | +| `LAYOUT_PORTUGUESE_BRAZILIAN` | Brazilian Portuguese | +| `LAYOUT_DANISH` | Danish | +| `LAYOUT_FINNISH` | Finnish | +| `LAYOUT_NORWEGIAN` | Norwegian | +| `LAYOUT_SWEDISH` | Swedish | +| `LAYOUT_TURKISH` | Turkish | +| `LAYOUT_UNITED_KINGDOM` | UK | +| `LAYOUT_ICELANDIC` | Icelandic | +| `LAYOUT_IRISH` | Irish | + +### Useful API + +| Function | Description | +|---|---| +| `DigiKeyboard.print("text")` | Type a string | +| `DigiKeyboard.println("text")` | Type a string followed by Enter | +| `DigiKeyboard.sendKeyStroke(key)` | Send a single key press | +| `DigiKeyboard.sendKeyStroke(key, modifier)` | Send a key press with a modifier | +| `DigiKeyboard.delay(ms)` | Wait (also keeps USB alive) | + +Common modifier constants: `MOD_SHIFT_LEFT`, `MOD_CONTROL_LEFT`, `MOD_ALT_LEFT`, `MOD_GUI_LEFT` (Windows/Super key). + +Common key codes (USB HID usage IDs): + +| Code | Key | +|---|---| +| `0x04`..`0x1D` | a..z | +| `0x1E`..`0x27` | 1..0 | +| `40` | Enter | +| `41` | Escape | +| `43` | Tab | +| `44` | Space | + +The full list is in the [USB HID usage tables](https://usb.org/document-library/hid-usage-tables-15) specification (section 10, Keyboard/Keypad Page). + +### Example: open a terminal on Linux and run a command + +```cpp +void setup() { + DigiKeyboard.delay(2000); + + // Ctrl+Alt+T opens a terminal on most Linux desktops + DigiKeyboard.sendKeyStroke(0x17, MOD_CONTROL_LEFT | MOD_ALT_LEFT); // 't' + DigiKeyboard.delay(1000); + + DigiKeyboard.println("echo 'Hello from Digispark!'"); +} +``` + +## Hardware constraints + +| Resource | Total | Used by current payload | +|---|---|---| +| Flash | 6 012 bytes | ~2 860 bytes (48%) | +| RAM | 512 bytes | ~104 bytes (20%) | + +The micronucleus bootloader occupies roughly 2 KB of the 8 KB total flash, leaving ~6 KB for application code. Keep payloads concise, especially long strings. + +## Troubleshooting + +| Problem | Solution | +|---|---| +| `Upload failed: cannot access USB device` | Add udev rules (see Prerequisites) or run with `sudo` | +| Upload times out | Unplug the board, run `pio run -t upload` again, plug in when prompted | +| Wrong characters appear on the host | Change the `LAYOUT_*` define to match the host OS keyboard layout | +| Payload runs too fast / host misses keystrokes | Increase `DigiKeyboard.delay()` values between actions | diff --git a/include/README b/include/README new file mode 100644 index 0000000..49819c0 --- /dev/null +++ b/include/README @@ -0,0 +1,37 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the convention is to give header files names that end with `.h'. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..9379397 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into the executable file. + +The source code of each library should be placed in a separate directory +("lib/your_library_name/[Code]"). + +For example, see the structure of the following example libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +Example contents of `src/main.c` using Foo and Bar: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +The PlatformIO Library Dependency Finder will find automatically dependent +libraries by scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..562d0ed --- /dev/null +++ b/platformio.ini @@ -0,0 +1,17 @@ +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:digispark-tiny] +platform = atmelavr +board = digispark-tiny +framework = arduino + +; DigiKeyboard is bundled with the Digistump framework +; Upload: plug in the Digispark when prompted (uses micronucleus bootloader) diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..0a1b8dc --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,33 @@ +#include + +// Select AZERTY (French) keyboard layout before including DigiKeyboard +#define LAYOUT_FRENCH +#include + +// Proof of concept: types "Hello world!" on an AZERTY host. + +void setup() { + // Wait for the host to recognise the USB device. + DigiKeyboard.delay(2000); + + // --- payload start --- + + // Open the Run dialog on Windows (Win+R) + DigiKeyboard.sendKeyStroke(0x15, MOD_GUI_LEFT); // 'r' + DigiKeyboard.delay(500); + + // Launch Notepad + DigiKeyboard.print("notepad"); + DigiKeyboard.sendKeyStroke(40); // Enter + DigiKeyboard.delay(1000); + + // Type the message + DigiKeyboard.print("Hello world!"); + + // --- payload end --- +} + +void loop() { + // Nothing to repeat. Keep the USB connection alive. + DigiKeyboard.delay(5000); +} diff --git a/test/README b/test/README new file mode 100644 index 0000000..9b1e87b --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Test Runner and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html