Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

uart - fuzz

Send malformed and custom payloads to a UART interface and report anomalous responses.

Usage

iottack uart fuzz --port <PATH> [OPTIONS]

Description

Sends a sequence of payloads through a serial port and inspects each response for patterns that indicate crashes, errors, shell exposure, or any user-defined string. The built-in payload set covers common vulnerability classes (null bytes, long strings, format strings, shell metacharacters, boundary values, control characters). When --charset or --wordlist is supplied the built-in set is replaced so only the specified payloads are sent.

Status

ResultMeaning
passAt least one payload produced an interesting response (Medium severity)
failA High/Critical pattern matched (crash, shell prompt) or no response matched at all

Severity classification

SeverityMatched patterns
Criticalfault, panic, exception, stack, crash, abort, segfault, overflow
Highroot@, # , $ , login:, password:
MediumEverything else (error, invalid, user --pattern strings)

Options

FlagShortDefaultDescription
--port <PATH>-p(required)Serial port device, e.g. /dev/ttyUSB0
--baud-rate <BAUD>-b115200Baud rate
--timeout-ms <MS>-500Read timeout per payload in milliseconds
--iterations <N>-1Times to repeat the full payload set
--charset <CHARS>-c-Characters to fuzz — generates one payload per character per length step (replaces built-ins)
--length <N>-l16Maximum repeat length for charset payloads
--wordlist <PATH>-w-Wordlist file, one payload per line (replaces built-ins)
--suffix <BYTES>-s-Bytes appended to every payload, e.g. \r\n for line-oriented shells
--pattern <STRING>--Extra response pattern to flag as interesting
--delay-ms <MS>-d0Delay between payloads in milliseconds
--output <FILE>-o-Save result to a file
--format <FORMAT>-ftexttext or json
--verbose-v-Increase log verbosity (repeat for debug/trace)

Examples

Built-in payload set

iottack uart fuzz --port /dev/ttyUSB0

Charset fuzzing against a line-oriented shell

Generate every combination of the given characters up to length 8 (a, b, …, aa, ab, …, zz, aaa, …), append \r\n so the shell processes each entry, and flag any response containing Set command. Total payloads = |charset|¹ + |charset|² + … + |charset|^length — keep --length small for large charsets.

iottack uart fuzz --port /dev/ttyUSB0 \
  --charset "abcdefghijklmnopqrstuvwxyz0123456789" \
  --length 8 \
  --suffix '\r\n' \
  --pattern 'Set command '

Wordlist fuzzing

iottack uart fuzz --port /dev/ttyUSB0 \
  --wordlist /path/to/commands.txt \
  --suffix '\r\n' \
  --delay-ms 100

Wordlist format

Plain text, one payload per line. Blank lines and lines starting with # are skipped. The line is sent as-is (without a trailing newline unless --suffix adds one).

# commands.txt
help
version
debug
admin
reboot

Demo

The XIAO RP2040 target runs a CircuitPython shell that controls an onboard NeoPixel LED. The shell accepts a handful of commands (red, green, blue, off, abc, x) and echoes Hit - <command> for each recognized one. Unknown commands produce Unknown command: '...'.

The commands are not documented. The goal is to discover them via fuzzing.

Step 1: Discover single-character commands

--charset now generates every combination of the given characters up to the specified length: a, b, …, aa, ab, …, aaa, aab, abc, etc.

Start with --length 1 to find single-character commands quickly:

iottack uart fuzz --port /dev/ttyACM0 \
  --charset "abcdefghijklmnopqrstuvwxyz0123456789" \
  --length 1 \
  --suffix '\r\n' \
  --pattern 'Hit -' \
  --delay-ms 250

x triggers a Hit - response, so the plugin reports pass:

Plugin name:    uart/fuzz
Execution time: 9.25 s
Status:         pass
Date:           2026-10-17 12:15:34 UTC

Interesting response to 'x' payload
  /dev/ttyACM0 responded with patterns [Hit -] after receiving the 'x' payload.
  Evidence: "x\nHit - x\nxiao> "

Step 2: Discover multi-character commands

Extend to --length 3 to reach commands like abc (3 chars) and off (3 chars). For a 26-letter charset this generates 26 + 676 + 17 576 = 18 278 payloads — use a generous --delay-ms to avoid overwhelming the device:

iottack uart fuzz --port /dev/ttyACM0 \
  --charset "abcdefghijklmnopqrstuvwxyz" \
  --length 3 \
  --suffix '\r\n' \
  --pattern 'Hit -' \
  --delay-ms 50

abc, off, red and all other 1-3-letter commands are found. Commands longer than 3 characters (blue, green) require increasing --length to 5, or use a wordlist for targeted enumeration.

Step 3: Targeted wordlist

Once candidate commands are known, switch to a wordlist for exact matches:

iottack uart fuzz --port /dev/ttyACM0 \
  --wordlist commands.txt \
  --suffix '\r\n' \
  --pattern 'Hit -' \
  --delay-ms 100

commands.txt:

red
green
blue
abc
rainbow
off
reboot
factory-reset

Only red, green, blue, off, and abc produce Hit - responses; the others return Unknown command:.