-
Notifications
You must be signed in to change notification settings - Fork 0
Device and Platform
Qwavey edited this page Aug 23, 2026
·
1 revision
Hardware controls, device state, and the payload launcher itself.
Every command block below is that script's own --help output on the real device, pulled straight from its header comment - not retyped.
-
battery.sh- Show battery level and charge state. -
led.sh- Control the Pager's LEDs. -
ringtone.sh- Play a ringtone and/or vibrate. -
screen.sh- Turn the physical display on/off. -
config.sh- Device configuration helper. -
reset.sh- Put the device back to a known-good state (bridges, radios, orphaned background jobs). -
crash_logger.sh- Continuously mirror dmesg/logread to persistent storage, so a crash-reboot doesn't erase its own evidence. -
alert.sh- Push a message to the Pager's screen from SSH. -
webui.sh- Start/stop the Pager Control Panel. -
PayloadRunner.sh- Launcher for the Pager's real payload system.
Show battery level and charge state.
battery.sh - Show the Pager's battery level. Wraps the official
BATTERY_PERCENT and BATTERY_CHARGING DuckyScript commands.
Usage:
battery.sh print "72% (charging)" style summary
battery.sh --percent print just the number, e.g. "72"
battery.sh --watch refresh every 5s until Ctrl+C
Options:
--percent Print only the raw percentage number
--watch Keep printing, refreshing every --interval seconds
--interval SECS Refresh interval for --watch (default: 5)
--alert-below PCT With --watch: fire an on-screen ALERT the moment the
battery first drops below PCT (not charging), once
per dip - not every cycle. Useful for an unattended
field engagement where nobody's watching the SSH
output but the physical screen is still visible.
-h, --help This help
Control the Pager's LEDs.
led.sh - Control the Pager's LEDs. Wraps LED and DPADLED_CONFIG.
Syntax confirmed live via LED --help / DPADLED_CONFIG --help.
LED [color] [pattern] e.g. LED R SLOW, LED W SOLID
colors: R G B Y C M W (or off via the OFF state)
patterns: SOLID SLOW FAST VERYFAST SINGLE DOUBLE TRIPLE QUAD QUIN
ISINGLE IDOUBLE ITRIPLE IQUAD IQUIN SUCCESS
LED [state] e.g. LED ATTACK, LED FAIL, LED OFF
states: SETUP FAIL FAIL1 FAIL2 FAIL3 ATTACK STAGE1..5 SPECIAL SPECIAL1..5
CLEANUP FINISH OFF
DPADLED_CONFIG [color] one of: red green blue cyan yellow magenta white off
Usage:
led.sh --set COLOR [PATTERN] e.g. led.sh --set R SLOW
led.sh --state STATE e.g. led.sh --state ATTACK
led.sh --off
led.sh --dpad COLOR red/green/blue/cyan/yellow/magenta/white/off
led.sh interactive mode
Play a ringtone and/or vibrate.
ringtone.sh - Play a ringtone (with optional vibration) or vibrate alone.
Wraps the RINGTONE and VIBRATE DuckyScript commands.
Confirmed syntax from the Hak5 docs:
RINGTONE {--vibrate} [rtttl-or-filename]
VIBRATE [rtttl-or-filename]
Ringtone files are looked up in /root/ringtones/.
Usage:
ringtone.sh --play NAME_OR_FILE [--vibrate]
ringtone.sh --vibrate-only NAME_OR_FILE
ringtone.sh --list list ringtone files available under /root/ringtones/
ringtone.sh interactive mode
Turn the physical display on/off.
screen.sh - Turn the Pager's physical display on/off. Wraps
ENABLE_DISPLAY / DISABLE_DISPLAY (documented as simple no-argument
toggles in the Hak5 DuckyScript command table).
Usage:
screen.sh --on
screen.sh --off
screen.sh interactive mode
Device configuration helper.
config.sh - Device configuration helper for the WiFi Pineapple Pager.
Wraps OFFICIAL Hak5 commands only:
WIFI_MGMT_AP / _DISABLE / _HIDE / _CLEAR Management AP identity
PINEAPPLE_MIMIC_ENABLE / _DISABLE Open AP mimic mode
PINEAPPLE_SSID_POOL_START [random] Randomized BSSID for the SSID pool
PINEAPPLE_DEVICE_FILTER_MODE / NETWORK_FILTER_MODE allow/deny scoping
PAYLOAD_SET/GET/DEL_CONFIG Persistent settings store
(shared with EvilTwin.sh / LanScan.sh / PayloadRunner.sh)
NOTE ON HOSTNAME / SYSTEM IDENTITY:
There is no documented Hak5 command to change the underlying OpenWRT
hostname or the client-mode (wlan0cli) MAC address. Those aren't
Pineapple-specific features - they're generic OpenWRT/Linux config
(uci system, or the wireless macaddr option). This script keeps that
OFF by default and only touches it with --system-hostname, clearly
labelled as "generic OpenWRT, not an official Pineapple command."
Usage:
config.sh interactive menu
config.sh --show show current config
config.sh [options]
Options:
--mgmt-ssid SSID Set the Management AP SSID
--mgmt-pw PASS Set the Management AP password (WPA2/WPA3-SAE-mixed)
--mgmt-hide Hide the Management AP
--mgmt-disable Disable the Management AP
--mimic on|off Toggle PineAP Open-AP mimic mode
--ssid-pool-random on|off Randomize BSSID per SSID when advertising the pool
--device-filter allow|deny Set PineAP client (MAC) filter mode
--network-filter allow|deny Set PineAP network (SSID) filter mode
--set KEY VALUE Store an arbitrary named setting (shared store)
--get KEY Print a stored setting
--del KEY Delete a stored setting
--system-hostname NAME Generic OpenWRT hostname change (NOT a Hak5 command, off by default)
--show Print current PineAP / config state
-y, --yes Don't prompt for confirmation
-h, --help This help
Put the device back to a known-good state (bridges, radios, orphaned background jobs).
reset.sh - Put the device back to a known-good, standard state: no
leftover bridges, no locked WiFi channel, no Bluetooth radio stuck in
test/adv-spam mode, and no orphaned background captures/attacks from
this toolkit. Also (optionally) reloads the network subsystem from its
own saved config - the standard, safe OpenWRT way to undo any RUNTIME-
ONLY interface changes (bridges, interface masters) without touching
any actual configuration file.
WHY THIS EXISTS: built after SSH connectivity to the device was lost
mid-session while testing sniff.sh's --bridge tap mode, which enslaves
eth0 - the SAME interface USB-C/SSH management normally rides on - into
a separate ad-hoc bridge (br-sniff). If that bridge (or any other
runtime interface change from this toolkit) is left up when something
goes wrong, this is the one command that puts everything back without
needing a full device reboot or factory reset.
Deliberately does NOT touch: system-wide library/linker config (the
ld-musl incident that bricked this device once already, documented in
README.md, is exactly the kind of change this script stays away from),
UCI config files, firmware settings, or anything persistent - only
runtime state (bridges, radio modes, background processes) and a
config RELOAD (which re-applies what's already saved on disk, it
doesn't change what's saved).
BUG FOUND AND FIXED (live-caught): 'reset' is a real busybox/system
command (terminal reset - ESC codes, termios) already on $PATH ahead of
/root/scripts, so an alias literally named 'reset' would always be
shadowed - confirmed live: `reset --help` silently ran the terminal
reset instead of this script, three times in a row, before this was
caught. The CLI alias for this script is 'devreset', not 'reset' (see
setup.py's COLLISION_NAMES, same fix already applied to 'wifi'/
'autossh' for the same reason) - always run it as `devreset ...` or the
full path, never bare `reset`.
Usage:
reset.sh interactive: confirm once, do everything below (recommended, no reboot)
reset.sh --all -y do everything below, no prompts
reset.sh --network [-y] tear down br-sniff, reload network config
reset.sh --wifi [-y] reset WiFi channel lock / recon hopping
reset.sh --bluetooth [-y] reset BT radio (test mode / adv-spam)
reset.sh --processes [-y] stop any running toolkit captures/attacks
reset.sh --fast-restart [-y] restart just the pineapple app (fast)
reset.sh --reboot [-y] full system reboot (slow)
reset.sh --dry-run preview what --all would do, change nothing
Options:
--network Tear down the br-sniff bridge if present, then reload
the network subsystem from its saved config (via
`ubus call network reload`, falling back to
`/etc/init.d/network reload` if ubus isn't
available) - fixes eth0/br-lan/SSH connectivity
if a bridge or other runtime interface change
was left in a bad state.
--wifi Reset the WiFi channel lock (PINEAPPLE_EXAMINE_RESET)
so recon resumes its normal channel-hopping instead
of staying parked wherever a stopped/crashed
deauth attack last locked it.
--bluetooth Send LE Test End (in case the radio is stuck
transmitting from --disrupt) and clear any
registered adv-spam advertising instances.
--processes Stop any currently-running deauth/bluetooth/
sniff/tracer/EvilTwin/deadnet/wigle capture
or attack this toolkit's scripts track, plus
a defense-in-depth kill-by-name for the
underlying tcpdump/l2ping processes in case
something wasn't tracked (same reasoning as
deauth.sh's own stray-process fix).
--all All of the above (same as running with no
flags at all, just without the interactive
confirmation prompt listing).
--fast-restart Restart just the pineapple app process -
the SAME mechanism setup.py itself uses
after deploying changed payloads (kill
the real /pineapple/pineapple PID,
procd respawns it cleanly). Brief UI
interruption, no full reboot, no drop
of your SSH session.
--reboot Full system reboot - slower, drops SSH
and the physical UI until the device
fully comes back up. Use when more
than just the pineapple app needs a
clean slate (e.g. after something
deeper than this script's other
options can reach).
--dry-run Print exactly what the selected flags
would do and exit - no confirmation
prompt, no commands actually run,
nothing on the device touched.
Combine with --network/--wifi/etc.
to preview a specific subset, or use
alone to preview the full --all run.
-y, --yes Skip the confirmation prompt.
-h, --help This help.
Continuously mirror dmesg/logread to persistent storage, so a crash-reboot doesn't erase its own evidence.
crash_logger.sh - continuously appends dmesg/logread output to PERSISTENT
storage (/mmc, a real ext4 partition), so a crash that forces a reboot
doesn't destroy its own evidence the way it has three times running now
during dual-radio deauth testing.
WHY THIS EXISTS: dmesg and logread both live entirely in RAM on this
device (confirmed live: `mount` shows / is an overlayfs over a 31.6MB
jffs2 partition, /tmp is tmpfs, and the kernel ring buffer itself is
obviously RAM-only) - every one of the three real crashes hit while
testing raw_deauth.py's dual-radio feature left ZERO forensic trace,
because dmesg/logread both reset on boot and nothing was capturing them
to disk in real time. /mmc is a genuinely separate, persistent ext4
partition (3.3GB free, confirmed live) - the one piece of storage on
this device that actually survives a crash/reboot.
This polls dmesg with a bounded diff (wc -l + tail -n +N, the same
pattern used throughout this codebase instead of `dmesg -w`/`tail -f` -
not because -w is known broken here, just consistency with the
established orphan-process-safe pattern) every 1s, appends new lines to
/mmc/crash_dmesg.log, and calls `sync` after every write so whatever
made it to the file is actually on flash, not just buffered - cheap
insurance against a hard crash that doesn't get a clean unmount.
Usage: crash_logger.sh --background (start, logs to /mmc/crash_dmesg.log)
crash_logger.sh --stop
crash_logger.sh --status
crash_logger.sh --tail [N] (print the last N lines - default
50 - of the persistent log and
exit; doesn't start/need the
background logger)
After a crash, read /mmc/crash_dmesg.log (survives the reboot) instead
of dmesg (which won't - it resets on every boot). --tail is the quick way
to do that without having to remember the path or reach for `tail`/`cat`
separately over SSH.
Push a message to the Pager's screen from SSH.
alert.sh - Send a message to the Pager's physical screen from SSH.
Wraps ALERT / PROMPT / CONFIRMATION_DIALOG / ERROR_DIALOG (confirmed
syntax from the Hak5 docs - each just takes a message string). These
take over the screen and (for PROMPT/CONFIRMATION_DIALOG) block until
the user responds on the device.
NOTE: CONFIRMATION_DIALOG returns its yes/no answer via EXIT CODE (0 =
yes, non-zero = no), not via printed output - the docs' own example is
`CONFIRMATION_DIALOG "..." || { ... }`, checking $?, not $(...). This
script checks the exit code accordingly.
Usage:
alert.sh --alert "message" full-screen alert + ringtone
alert.sh --prompt "message" modal, waits for dismissal
alert.sh --confirm "question" yes/no on-screen, prints the answer
alert.sh --error "message" error dialog
alert.sh interactive mode
Start/stop the Pager Control Panel.
webui.sh - Start/stop the Pager Control Panel (a local web dashboard for
the scripts in this toolkit). Binds ONLY to br-lan (Management WiFi /
USB-C) - never the internet-facing uplink - same access model the Hak5
Virtual Pager itself uses.
Usage:
webui.sh --start [--port PORT] start the server (default port 8081)
webui.sh --stop stop it
webui.sh --status is it running?
webui.sh --set-token [TOKEN] set/rotate the access token
(required before first use -
blank = generate a random one)
webui.sh interactive mode
Launcher for the Pager's real payload system.
PayloadRunner.sh - Dynamic launcher for the WiFi Pineapple Pager's real
payload system (bash + Hak5 DuckyScript commands).
IMPORTANT: The Pager has NO keyboard-injection / HID capability - Hak5's
own docs are explicit: "The WiFi Pineapple Pager is not a keyboard
injection device... inject commands from the USB Rubber Ducky will not
work." Its DuckyScript is a Pager-specific command set for the screen,
WiFi, and PineAP - not for typing into a target computer. This script
runs THAT system (the one that actually exists on this hardware):
payload.sh scripts under /root/payloads/{user,alerts,recon}/.
Payloads run standalone fine over SSH (confirmed by testing) - any
on-screen commands they use (ALERT, PROMPT, LOG, etc.) will drive the
physical Pager screen exactly as if launched from the dashboard.
Usage:
PayloadRunner.sh interactive picker
PayloadRunner.sh --list [--category CAT]
PayloadRunner.sh --run CATEGORY/NAME [options]
Options:
--list List available payloads (with descriptions)
--category user|alerts|recon Restrict listing/picking to one category
--run CATEGORY/NAME Run a specific payload non-interactively
--timeout SECONDS Kill the payload if it runs longer than this
(useful for headless runs - some payloads use
WAIT_FOR_BUTTON_PRESS and need a person present)
--background Launch and detach, logging to /root/loot/payload-runs/
--status Is a backgrounded payload still running, and which one
--stop Stop the currently backgrounded payload
-y, --yes Don't prompt for confirmation
-h, --help This help