Skip to content

Firmware Probing

The console-probe tool is a generic embedded console scanner built for reverse-engineering firmware command interfaces. It auto-detects the prompt format, parses help output, enters submenus, and optionally brute-forces candidate command names. It was developed for the Winegard firmware but works with any prompt-based serial console.

The discovery process follows a structured sequence:

  1. Prompt detection. The tool sends empty lines (carriage returns) and analyzes the response to identify the prompt string. On the Carryout G2, this detects TRK> as the root prompt.

  2. Error string detection. A known-bad command is sent to capture the error response pattern. This lets the tool distinguish between “command recognized” and “command unknown” for subsequent probing.

  3. Help parsing. The tool sends the help command (default: ?) and parses the response to extract known commands, their parameters, and descriptions. It identifies which commands are submenus (they change the prompt when entered).

  4. Submenu discovery. For each discovered submenu, the tool enters it, queries help, and records the available commands. The prompt changes (e.g., TRK> to MOT>) confirming successful submenu entry.

  5. Brute-force probing (optional). With --deep, the tool sends candidate command names from a wordlist and checks whether each one produces a valid response (as opposed to the error string). This catches commands not listed in help output.

The fastest mode — queries ? at each menu level, no brute-force:

Terminal window
console-probe --port /dev/ttyUSB2 --baud 115200 --discover-only

This enters every discovered submenu, queries help, and prints the command inventory. Add --json to save a structured report:

Terminal window
console-probe --port /dev/ttyUSB2 --baud 115200 --discover-only --json /tmp/discover.json

Full discovery plus brute-force probing of all submenus:

Terminal window
console-probe --port /dev/ttyUSB2 --baud 115200 --deep --wordlist scripts/wordlists/winegard.txt

The wordlist file contains one candidate command per line. The bundled winegard.txt includes terms extracted from firmware strings and documentation.

Target a specific submenu without scanning all of them:

Terminal window
console-probe --port /dev/ttyUSB2 --baud 115200 --submenu dvb
OptionDefaultDescription
--port/dev/ttyUSB0Serial port
--baud115200Baud rate
--line-endingcrLine ending to send (cr, lf, crlf)
OptionDefaultDescription
--promptauto-detectOverride the root prompt string
--errorauto-detectOverride the error response string
--help-cmd?Command to request help
--exit-cmdqCommand to exit submenus
OptionDefaultDescription
--discover-onlyoffHelp-only mode, no brute-force
--deepoffProbe all discovered submenus
--submenu NAMEnoneProbe a single named submenu
--timeout0.5Per-command timeout in seconds
--blocklistreboot,stow,def,q,QCommands to never send
--wordlist FILEnoneExtra candidate words file (repeatable)
OptionDefaultDescription
--json FILEnoneWrite results as JSON to file

When --json is specified, the tool writes a structured report with format version 2. The report contains:

{
"format_version": 2,
"device": {
"port": "/dev/ttyUSB2",
"baud": 115200,
"root_prompt": "TRK>",
"error_string": "type '?' for help"
},
"menus": {
"TRK": {
"help": [
{"name": "mot", "params": "", "description": "enter motor control submenu"},
{"name": "dvb", "params": "", "description": "enter DVB tuner submenu"}
],
"probe_hits": [],
"undiscovered": []
},
"MOT": {
"help": [...],
"probe_hits": [["a", "Angle[0] = 180.00 Angle[1] = 45.00"]],
"undiscovered": [["xyz", "some unexpected response"]]
}
}
}

Key sections in each menu:

  • help — Commands discovered via the ? command, with parameter syntax and descriptions.
  • probe_hits — Commands that produced a valid (non-error) response during brute-force probing.
  • undiscovered — Commands found by probing that were not in the help output. These are the interesting findings — hidden or undocumented commands.

The default blocklist (reboot,stow,def,q,Q) prevents the probe from sending commands that would disrupt the session. The reboot command restarts the firmware. The stow command folds the dish flat (dangerous if you’ve modified the feed). The def command restores factory defaults. And q exits the shell entirely on the G2 root menu (kills UART, requires power cycle).

Add more commands to the blocklist if needed:

Terminal window
console-probe --port /dev/ttyUSB2 --baud 115200 --deep \
--blocklist "reboot,stow,def,q,Q,scan,kill"

The NVS submenu treats any unrecognized input as a sequential index read (no error string). This means every candidate command “succeeds” during brute-force probing, producing false positives. The results are harmless (read-only) but noisy. The --discover-only mode avoids this issue since it only queries help.

The tool is not Winegard-specific. It works with any serial console that has:

  • A recognizable prompt string (auto-detected or specified with --prompt)
  • A consistent error response for unknown commands (auto-detected or --error)
  • A help command that lists available commands (configurable with --help-cmd)
Terminal window
# U-Boot bootloader example
console-probe --port /dev/ttyUSB0 --baud 115200 \
--prompt "U-Boot>" --error "Unknown command" --help-cmd "help"

The console-probe package is organized as:

profile.py -- DeviceProfile + HelpEntry dataclasses
serial_io.py -- Prompt-aware serial I/O
discovery.py -- Auto-discovery, help parsing, submenu probing, candidate generation
report.py -- JSON report writer (format_version 2)
cli.py -- argparse CLI entry point

Install and run:

Terminal window
uv sync
uv run console-probe --help