Initial commit.
This commit is contained in:
@@ -0,0 +1 @@
|
|||||||
|
.pio
|
||||||
@@ -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 <DigiKeyboard.h>
|
||||||
|
```
|
||||||
|
|
||||||
|
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 |
|
||||||
@@ -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
|
||||||
+46
@@ -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 <Foo.h>
|
||||||
|
#include <Bar.h>
|
||||||
|
|
||||||
|
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
|
||||||
@@ -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)
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
// Select AZERTY (French) keyboard layout before including DigiKeyboard
|
||||||
|
#define LAYOUT_FRENCH
|
||||||
|
#include <DigiKeyboard.h>
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
+11
@@ -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
|
||||||
Reference in New Issue
Block a user