Ducky Script · Volume 3
Ducky Script Volume 3 — The Language Core
Ducky Script 1.0 — the foundation every device and every payload is built on: syntax, STRING, DELAY, REM, key names, and modifiers
Contents
1. About this volume
This volume is the language core — Ducky Script 1.0, the 2010 macro language. Everything in Vol 4 (the 3.0 language) is built on top of this, and 1.0 is a clean subset of 3.0, so a 1.0 payload runs unmodified on every device in the family. If you learn one volume of language syntax, learn this one — it is the part you will use in 90% of payloads regardless of device.
The 1.0 language is small enough to cover completely. By the end of this volume you will have seen every command 1.0 has.
2. The shape of a payload
A Ducky Script payload is a plain text file, one command per line, processed top to bottom, exactly once, with no branching. A line is a command word (uppercase by convention and, for most, by requirement) optionally followed by an argument.
Anatomy of a payload line
════════════════════════════════════════════════
STRING Hello, World!
▲ ▲
│ └── argument (everything after the first space)
└──────────── command word (uppercase)
DELAY 500
▲ ▲
│ └── argument (here: milliseconds)
└──────────── command word
ENTER
▲
└──────────── command word with no argument
Rules that trip people up:
- One command per line. There is no statement separator; the newline is the separator.
- Command words are uppercase.
STRINGworks;stringdoes not. - The argument is literal. After
STRING, everything to the end of the line is typed verbatim — including spaces, including what looks like it could be another command.STRING ENTERtypes the five charactersE-N-T-E-R; it does not press Return. - Blank lines are ignored. Use them to group a payload visually.
- There is no “run” concept beyond connection. On a USB Rubber Ducky, the payload runs when the device is plugged in (or the button is pressed — Vol 8). The payload is the program; there is no
main().
3. REM — comments
REM (from “remark”) is a comment. The line is ignored by the encoder; it injects nothing.
REM ── Payload: open Notepad on Windows ──
REM Author: tjscientist Target: Win10/11, US layout
REM Authorization: <engagement ref> ← put this on EVERY payload
DELAY 1000
GUI r
Two disciplines this manual insists on:
- Header every payload with
REMlines stating what it does, the target OS and keyboard layout, and the authorization context (Vol 16). A payload with no authorization line is a payload you should not run. REMyourDELAYs. A bareDELAY 2000is a mystery in six months;REM wait for the Run dialog to focus/DELAY 2000is maintainable.
Ducky Script 3.0 adds REM_BLOCK … END_REM for multi-line comments — covered in Vol 4, but mentioned here so you recognise it in modern payloads.
4. STRING and STRINGLN — typing text
STRING is the workhorse. It types its argument as keystrokes, automatically handling shift for uppercase letters and shifted symbols — you write STRING Hello! and the device presses SHIFT+H, e, l, l, o, SHIFT+1.
STRING powershell -NoProfile -ExecutionPolicy Bypass
STRINGLN is STRING followed by an automatic ENTER — type the text and submit it. It is the natural command for “type a command and run it”:
STRINGLN whoami REM types 'whoami' and presses Enter
Ducky Script 3.0 adds the multi-line block forms — STRING … END_STRING and STRINGLN … END_STRINGLN — for typing whole blocks of text (a script, a config file) without one STRING per line. Those are a 3.0 feature; Vol 4 covers them. In pure 1.0, every typed line is its own STRING/STRINGLN.
The layout caveat, stated once and expanded in Vol 7: STRING types scan codes, and what character a scan code produces depends on the target’s keyboard layout, not yours. STRING ] on a payload encoded for US-QWERTY will produce a different character on an AZERTY target. This is the single biggest cause of “my payload typed garbage” — Vol 7 is the whole volume on it.
5. DELAY — the most important command
DELAY pauses execution for a number of milliseconds. It is, in a blind language, the most important command there is — because a 1.0 payload cannot see the screen, DELAY is the only tool it has to stay synchronised with the target.
DELAY 1000 REM wait one second
DELAY 200 REM wait 200 ms
The minimum effective delay is around 20 ms (Ducky Script 3.0 documents 20 ms as the floor; below that the host may not register the timing). Practical DELAY discipline:
| Situation | Typical DELAY | Why |
|---|---|---|
| After the device is plugged in, before anything | 500–3000 ms | the OS needs time to enumerate the “keyboard” and load its driver |
| After opening the Run dialog / a launcher | 200–800 ms | the window needs focus before it will accept text |
| After launching an application | 1000–5000 ms | the app must be up and focused |
| Between keystrokes in a fragile sequence | 50–100 ms (or jitter — Vol 5) | some targets drop keystrokes typed faster than they can process |
| Waiting on the network (a download) | seconds, generously | you are guessing; a 1.0 payload cannot confirm |
The DELAY tax — a 1.0 payload's reliability cost
════════════════════════════════════════════════════════
too short ──► payload races ahead of the target:
keystrokes land in the wrong window,
commands run before the shell is ready,
the payload "doesn't work" intermittently
too long ──► payload is slow; the operator's window of
physical access is wasted; on a shoulder-
surf-risk target, every extra second is risk
just right ─► you guessed correctly for THIS machine.
the next machine may be slower. this is the
fundamental fragility of blind injection.
The 3.0 language’s OS/host-state detection (Vol 5) exists precisely to replace guessed DELAYs with confirmed waits — but on 1.0, and in 1.0-style payloads, DELAY discipline is payload reliability.
6. Named keys — the key catalogue
Keys that are not printable characters get named commands. Pressing a named key is one line. The full 1.0/3.0 catalogue:
Cursor and navigation
UP / DOWN / LEFT / RIGHT (also UPARROW / DOWNARROW / LEFTARROW / RIGHTARROW)
PAGEUP / PAGEDOWN
HOME / END
INSERT
DELETE / DEL
BACKSPACE
TAB
SPACE
System and editing keys
ENTER
ESCAPE
PAUSE / BREAK
PRINTSCREEN
MENU / APP (the context-menu key)
F1 … F12
Lock keys
CAPSLOCK
NUMLOCK
SCROLLLOCK
A named key can be combined with a STRING argument on some — but the clean mental model is: named keys are their own lines. ENTER on its own line presses Return. TAB on its own line presses Tab.
REM Fill a two-field form: username <tab> password <enter>
STRING tjscientist
TAB
STRING hunter2
ENTER
7. Modifier keys and combinations
Modifier keys — the ones you hold while pressing something else — are named, and Ducky Script’s syntax for “modifier + key” is simply putting them on the same line.
The modifiers
SHIFT
ALT
CONTROL (or CTRL)
COMMAND (the Mac ⌘ key)
WINDOWS (or GUI — the Windows/Super key)
Modifier + key — same line:
GUI r REM Windows: open the Run dialog
CTRL c REM copy
ALT F4 REM close the active window
GUI d REM Windows: show desktop
CONTROL ALT DELETE REM the secure attention sequence
Documented multi-modifier combinations (the quick reference enumerates these as first-class):
CTRL SHIFT
ALT SHIFT
COMMAND CTRL
COMMAND CTRL SHIFT
COMMAND OPTION
COMMAND OPTION SHIFT
CONTROL ALT DELETE
So CTRL SHIFT ESCAPE opens Task Manager on Windows; COMMAND SPACE opens Spotlight on macOS.
INJECT_MOD (a 3.0 refinement, noted here for completeness) presses a modifier key by itself — e.g. INJECT_MOD WINDOWS taps the Windows key alone to open the Start menu, which a bare WINDOWS line followed by nothing does not reliably do across all hosts.
The cross-platform reality
════════════════════════════════════════════════════════
The SAME payload line means different things per OS:
GUI r Windows: Run dialog macOS: nothing useful
GUI SPACE Windows: nothing useful macOS: Spotlight
GUI l Windows: lock screen macOS: (varies)
A 1.0 payload that hard-codes GUI r only works on Windows.
A robust payload either targets ONE OS deliberately, or —
in 3.0 — detects $_OS first and branches (Vol 5).
8. The classic payload patterns
Everything above, assembled into the patterns you will write constantly. These are 1.0 — they run on every device.
The launcher (Windows Run dialog → command):
REM Open an elevated-or-not command prompt and run a command
DELAY 2000
GUI r
DELAY 500
STRINGLN cmd
DELAY 750
STRINGLN whoami
The PowerShell one-liner (the offensive workhorse shape):
DELAY 2000
GUI r
DELAY 500
STRINGLN powershell -NoProfile -WindowStyle Hidden -Command "<command here>"
The “type a whole script via clipboard” trick — faster and more reliable than typing a long script keystroke-by-keystroke, because the long part is one paste:
REM (1.0 style — set the clipboard, then paste)
GUI r
DELAY 500
STRINGLN powershell
DELAY 1000
STRINGLN Set-Clipboard -Value 'Get-Process | Out-File C:\Users\Public\p.txt'
STRINGLN powershell -Command "iex (Get-Clipboard)"
The macOS launcher (Spotlight → Terminal):
DELAY 2000
GUI SPACE
DELAY 500
STRINGLN terminal
DELAY 1500
STRINGLN whoami
Vol 13 is the full payload catalogue with worked, device-specific examples; this section is just to show the 1.0 core doing something.
9. Why 1.0 payloads break — typing blind
The defining limitation, stated plainly so every later volume can reference it: a 1.0 payload has no feedback. It cannot tell:
- whether the OS has finished enumerating the device,
- whether the window it is typing into has focus,
- whether the last command succeeded or threw an error,
- whether a UAC prompt, a dialog, or a notification stole focus,
- what OS or keyboard layout it is even on.
Everything that makes a 1.0 payload robust is a workaround for this blindness:
| Technique | What it works around |
|---|---|
Generous opening DELAY | enumeration timing varies by host |
DELAY after every focus-changing action | window focus is not instantaneous |
ESCAPE / ESCAPE / ESCAPE at the start | clears any stray dialog/menu state |
| Targeting one OS deliberately | a payload that branches needs 3.0 |
| Keeping payloads short | every line is another chance to desynchronise |
| Clipboard-paste for long content | one paste can’t desynchronise mid-way like 200 keystrokes can |
This is the entire motivation for Ducky Script 3.0’s “smart payload” features (Vol 5) — $_OS detection and the WAIT_FOR_* lock-key waits exist to replace guesswork with confirmation. But the 1.0 core is still where most payloads live, because most payloads are short and most of the time a well-tuned DELAY is enough. Know the blindness; respect it; reach for 3.0 when the payload is long, branchy, or has to work across machines you can’t test on.
10. Resources
- Ducky Script quick reference: https://docs.hak5.org/hak5-usb-rubber-ducky/duckyscript-quick-reference/
- “Hello, World!” — the canonical first payload: https://docs.hak5.org/hak5-usb-rubber-ducky/ducky-script-basics/hello-world/
- Vol 2 — where the 1.0 language came from
- Vol 4 — Ducky Script 3.0: everything 1.0 cannot do
- Vol 7 — keyboard layouts: why
STRINGbetrays you across locales - Vol 13 — the full payload catalogue
This is Volume 3 of an 18-volume series. Next: Vol 4 covers Ducky Script 3.0 — the structured language: VAR and the operator set, IF/ELSE conditionals, WHILE loops, FUNCTIONs, and the DEFINE preprocessor.