Skip to content

Add DuckyScript DEFINE constant support to BadUSB parser - #2818

Open
sergarsilla wants to merge 1 commit into
BruceDevices:devfrom
sergarsilla:feature/duckyscript-define
Open

Add DuckyScript DEFINE constant support to BadUSB parser#2818
sergarsilla wants to merge 1 commit into
BruceDevices:devfrom
sergarsilla:feature/duckyscript-define

Conversation

@sergarsilla

Copy link
Copy Markdown

Proposed Changes

Adds support for the DuckyScript 3.0 DEFINE command to the BadUSB / BadBLE parser (ducky_typer.cpp).

DEFINE declares a constant. Every subsequent line has each defined name replaced with its value before the line is parsed and dispatched, matching Hak5 DuckyScript 3.0. Names are conventionally #-prefixed but any name works.

  • DEFINE lines are directives: they store the constant and type nothing.
  • Substitution uses whole-token / word-boundary matching, so a name never partially replaces a larger token (#PORT is not matched inside #PORTAL). It works inside STRING / STRINGLN arguments as well as command arguments (e.g. DELAY #PAUSE).
  • Undefined names are left untouched — no error spam that blocks the run.
  • Constants live in a small std::map<String, String> local to key_input, freed when the script ends. Payloads that do not use DEFINE are completely unaffected.

Scope is intentionally limited to DEFINE only. VAR, IF/ELSE, WHILE, FUNCTION, expressions and ATTACKMODE are out of scope: Bruce already ships a full JavaScript interpreter for advanced logic, so re-implementing a scripting runtime inside the Ducky parser would add significant memory cost and complexity for little benefit. DEFINE is the one DuckyScript 3.0 feature broadly useful for plain HID payloads without needing a language runtime.

Context: discussion #1796 (DuckyScript version support).

Types of Changes

New Feature (additive, non-breaking).

Verification

  • Builds/compiles cleanly for lilygo-t-embed-cc1101 with no new warnings (board-agnostic parser logic, safe across all envs).
  • Example payload added at sd_files/BadUSB and BlueDucky/DuckyScript_DEFINE_demo.txt.
  • Substitution rules verified:
    • DEFINE #DUCKY_LOVE Mischief + STRING I <3 #DUCKY_LOVE -> types "I <3 Mischief"
    • DEFINE #PORT 8080 + STRING #PORT and #PORTAL -> "8080 and #PORTAL"
    • DEFINE #N 3 + REPEAT #N -> repeats 3 times
    • Undefined #FOO -> left as "#FOO"

Testing

The substitution logic was exercised against the exact algorithm with checks covering basic substitution, whole-token boundaries, values with spaces, multiple occurrences per line, undefined names, empty values and the "value contains its own name" case (verifying the scan cannot loop). The repo has no on-device unit-test harness for the Ducky parser, so validation was off-device plus the example payload.

Linked Issues

Discussion #1796 (DuckyScript version support).

User-Facing Change

Add DuckyScript 3.0 DEFINE constant support to the BadUSB/BadBLE parser. Use `DEFINE #NAME value` to declare a constant that is substituted throughout the payload before it runs.

Further Comments

The in-app DuckyScript reference (Ducky-en.html / Ducky-br.html) was updated to document DEFINE alongside the other misc commands.

Ninja-jr pushed a commit to Ninja-jr/Bruce_firmware that referenced this pull request Aug 22, 2026
Ninja-jr pushed a commit to Ninja-jr/Bruce_firmware that referenced this pull request Aug 22, 2026
Ninja-jr pushed a commit to Ninja-jr/Bruce_firmware that referenced this pull request Aug 22, 2026
Ninja-jr pushed a commit to Ninja-jr/Bruce_firmware that referenced this pull request Aug 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant