Ducky Script · Volume 6
Ducky Script Volume 6 — Exfiltration & ATTACKMODE
Using the device as more than a typist — ATTACKMODE, USB identity spoofing, Keystroke Reflection, and HIDE_PAYLOAD
Contents
1. About this volume
Vols 3-5 covered the device as a keyboard — typing, deciding, timing. This volume covers everything that makes a Ducky Script device more than a keyboard: presenting as a different kind of USB device entirely (ATTACKMODE), lying about its USB identity, and — the clever centrepiece — turning the three-bit lock-key back-channel from Vol 5 into a genuine exfiltration path (Keystroke Reflection).
These are 3.0 features on the USB Rubber Ducky. They are also where the USB Rubber Ducky starts to look like its bigger siblings — and §9 sets up the device volumes by showing how the Bash Bunny, Key Croc, and O.MG each take this further.
2. ATTACKMODE — what the device pretends to be
A USB device announces, at enumeration, what class of device it is. ATTACKMODE is the command that sets what a Ducky Script device announces:
ATTACKMODE HID REM a keyboard — the default, for keystroke injection
ATTACKMODE STORAGE REM a USB mass-storage device — a flash drive
ATTACKMODE HID STORAGE REM both at once — keyboard AND flash drive
ATTACKMODE OFF REM present as nothing — no HID, no storage
ATTACKMODE can be issued multiple times in one payload — the device can change what it presents as, mid-run. The operational uses:
| Mode | What it enables |
|---|---|
HID | the baseline — keystroke injection. Most payloads never need anything else. |
STORAGE | the device shows up as a flash drive — so a payload can type a command that reads a file off the device itself, or the device can carry tools/output |
HID STORAGE | type a command and have a drive present for that command to read from / write to — the basis of “type a loader that pulls the real payload off my own storage” |
OFF | present as nothing — used to hide (the device is connected but invisible as HID/storage), often paired with HIDE_PAYLOAD (§7) |
Why HID STORAGE is powerful
════════════════════════════════════════════════════════
Problem: typing a 500-line script keystroke-by-keystroke
is slow and fragile (Vol 3).
ATTACKMODE HID STORAGE solution:
1. device presents as keyboard + flash drive
2. the real payload/tool already sits on the drive
3. the HID side just TYPES a short loader:
"run the script on the drive that just appeared"
4. one short reliable type, instead of 500 fragile ones
The keyboard becomes a bootstrap; the storage carries
the weight.
3. USB identity spoofing — VID, PID, and friends
Every USB device has identity strings: a Vendor ID (VID), a Product ID (PID), and human-readable manufacturer / product / serial strings. By default a Ducky Script device enumerates with Hak5’s identity — which is exactly what a USB-device-control defense (Vol 15) is watching for.
ATTACKMODE takes optional parameters that override every identity field:
ATTACKMODE HID VID_413C PID_2107 MAN_Dell PROD_Dell_USB_Keyboard
| Parameter | Sets |
|---|---|
VID_xxxx | Vendor ID (hex) |
PID_xxxx | Product ID (hex) |
MAN_... | manufacturer string |
PROD_... | product string |
SERIAL_... | serial number string |
And the _RANDOM variants — VID_RANDOM, PID_RANDOM, MAN_RANDOM, PROD_RANDOM, SERIAL_RANDOM — randomise the field each run.
The operational point: a Ducky Script device can present as a specific real keyboard — a Dell keyboard, a Logitech keyboard, whatever the target environment uses. Against a USB allow-list keyed on VID/PID (Vol 15), spoofing a permitted keyboard’s identity is the direct counter. Against logging-based detection, _RANDOM makes each insertion look like a different device so they don’t correlate. The internal variables $_CURRENT_VID, $_CURRENT_PID, $_CURRENT_ATTACKMODE let the payload read back its own current identity.
This is a genuine arms-race feature, and Vol 15 covers the defensive response (allow-lists keyed on more than VID/PID, behavioural detection that spoofing doesn’t touch).
4. SAVE_ATTACKMODE / RESTORE_ATTACKMODE
Because ATTACKMODE can change mid-payload, 3.0 gives you a stack-of-one to snapshot and restore it:
SAVE_ATTACKMODE REM remember the current mode + identity
ATTACKMODE OFF REM go invisible to do something quietly
REM ... do the quiet thing ...
RESTORE_ATTACKMODE REM go back to exactly what we were
The use: a payload that needs to transiently change what the device presents as — drop to OFF to hide, flip to STORAGE to stage a file — without having to hard-code “what was I before.” It keeps multi-mode payloads clean.
5. Keystroke Reflection — the exfiltration channel
This is the centrepiece, and it is genuinely clever. The problem: a keyboard is (almost) one-way. It sends keystrokes. It cannot read the host. So how does a keystroke-injection device get data off the target?
The answer, from Vol 5 §4: the lock-key LED state is a host → device back-channel. The host broadcasts CAPS/NUM/SCROLL LED state to every keyboard. The device is a keyboard. So:
Keystroke Reflection — exfil over three LEDs
════════════════════════════════════════════════════════
1. The payload TYPES a script onto the host.
2. That script reads the data you want (a file, a token,
a result) and ENCODES it as a sequence of lock-key
toggles — turning CAPS/NUM/SCROLL on and off in a
pattern that represents the data.
3. The host, doing what hosts do, BROADCASTS each lock-key
change back to all keyboards — including the device.
4. The device READS that stream of lock-key changes and
DECODES it back into the original data.
data ──typed script──► host ──lock-key LED toggles──► device
The keyboard "read" the host. Through its own status LEDs.
The technique is called KEYSTROKE REFLECTION — the host's
data is reflected back through the keyboard-status channel.
It is slow — three bits per update, and you are limited by how fast lock-key state can be toggled and observed — so it is an exfil path for secrets, not bulk data: a credential, an API token, a config value, a short result. But it is real, it needs no network, no extra hardware, and no storage device to be mounted — it works through the keyboard interface alone, on a host where USB mass-storage is blocked. That is what makes it notable: it is exfiltration on a device class (HID) that defenders rarely think of as an exfiltration risk.
The enabling internal variable is $_EXFIL_MODE_ENABLED (TRUE/FALSE) — it turns on the device’s reading-and-decoding of the reflected lock-key stream.
6. EXFIL and loot.bin
Once Keystroke Reflection is decoding data, it has to go somewhere. The EXFIL command writes a variable’s data to loot.bin on the device’s storage:
$_EXFIL_MODE_ENABLED = TRUE
REM ... payload types a script that reflects data back ...
REM ... the reflected data is captured into a variable ...
EXFIL $captured_value
The model: the reflected data lands in the payload’s variables, and EXFIL persists it to loot.bin on the microSD card. After the engagement, the operator reads loot.bin off the card. It is the on-device counterpart to the host-side analysis the bigger devices do natively (§9).
loot.bin joins inject.bin (the encoded payload) and seed.bin (the randomization seed, Vol 5 §8) as the three meaningful files the SD-card workflow deals with — Vol 12 covers the file/SD-card workflow in full.
7. HIDE_PAYLOAD — concealing the device’s storage
When a Ducky Script device presents as STORAGE, an inquisitive target (or their endpoint software) can look at the drive — and find inject.bin, seed.bin, loot.bin sitting there, which is about as self-incriminating as it gets.
HIDE_PAYLOAD conceals those files; RESTORE_PAYLOAD brings them back:
HIDE_PAYLOAD REM inject.bin / seed.bin become invisible on the storage
REM ... the device can still present as STORAGE for cover —
REM a blank-looking flash drive — while the payload files hide
RESTORE_PAYLOAD REM bring them back (e.g. so YOU can read loot.bin later)
HIDE_PAYLOAD requires the device to be in ATTACKMODE OFF or ATTACKMODE HID (you cannot hide the files while actively presenting the storage that contains them in a way that would expose them). The operational picture: the device can look like an ordinary empty flash drive — useful cover for a “found USB stick” scenario — with the incriminating payload files hidden, then restore them so the operator can retrieve loot.bin.
It is concealment, not encryption — a forensic examination of the storage still finds the data. It defeats a casual look, not a deliberate investigation (Vol 15, Vol 16).
8. LED control and status
Small but operationally real: the device’s status LED is payload-controllable.
LED_OFF REM LED off
LED_R REM red
LED_G REM green
Plus internal variables governing whether the LED reflects system/storage/injecting activity ($_SYSTEM_LEDS_ENABLED, $_STORAGE_LEDS_ENABLED, $_INJECTING_LEDS_ENABLED) and lock-key state ($_LED_SHOW_CAPS, etc.).
Two uses: operator feedback — the LED tells you what phase the payload is in (red = working, green = done, so you know when to pull the device) — and, conversely, going dark — LED_OFF and disabling the activity LEDs so a payload runs without a blinking light drawing a bystander’s eye. Which one you want is a posture decision (Vol 16).
9. The exfiltration picture across the device family
Everything above is the USB Rubber Ducky’s answer to “be more than a typist” — and it is an ingenious answer precisely because the Rubber Ducky has so little to work with: a microcontroller, an HID interface, optional mass storage, and three lock-key LEDs. Keystroke Reflection is what you invent when that is all you have.
The other three devices have far more, and the device volumes cover it — but here is the family picture so the contrast is clear from the start:
| Device | ”More than a typist” capability | Volume |
|---|---|---|
| USB Rubber Ducky | ATTACKMODE STORAGE, VID/PID spoofing, Keystroke Reflection exfil over lock keys, loot.bin | Vol 8 |
| Bash Bunny | ATTACKMODE emulates storage, serial, and full USB-ethernet — it can be a network adapter; a whole Linux userland to process/stage/exfil; far richer than the Ducky | Vol 9 |
| Key Croc | it is a keylogger — exfiltration is its native mode; logs keystrokes to its 8 GB SSD, streams them, and has Wi-Fi and remote access | Vol 10 |
| O.MG | Wi-Fi — payloads, triggering, and results all flow over the device’s own Wi-Fi to a web UI; exfil is a network operation, not a lock-key trick | Vol 11 |
So: Keystroke Reflection is the clever-because-constrained technique; the bigger devices simply have a network (or are the keylogger). When you reach Vols 8-11, the throughline is “how does this device, given its actual hardware, solve the get-data-off-the-host problem” — and the Rubber Ducky’s answer in this volume is the baseline the others are measured against.
10. Resources
- Attack modes, constants & variables: https://docs.hak5.org/hak5-usb-rubber-ducky/attack-modes-constants-and-variables/
- Ducky Script quick reference (
ATTACKMODE,EXFIL,HIDE_PAYLOAD, internal variables): https://docs.hak5.org/hak5-usb-rubber-ducky/duckyscript-quick-reference/ - Hak5’s Keystroke Reflection technique writeup (docs.hak5.org)
- Vol 5 — the lock-key back-channel that Keystroke Reflection is built on
- Vols 8-11 — how each device family extends “more than a typist”
- Vol 15 — the defensive response to identity spoofing and HID exfiltration
This is Volume 6 of an 18-volume series. Next: Vol 7 closes Part I with keyboard layouts — the cross-locale problem that is the single most common cause of a payload that “ran but typed garbage,” and the discipline for writing payloads that survive being run on a keyboard layout you did not encode for.