Streamable-HTTP MCP server on POST /mcp: device.state, attack.deploy/stop/ status/deauth/capture/export_hc22000, loot.handshakes/enterprise_creds, recon.aps/isearch/devices, pineap.kick_client/set_filter tools; recon DB + bundled opencode skills resources; attack playbook prompts. Cookie or Bearer auth. Harness page shows endpoint, token, curl snippet, capability explorer and a copy-paste pi.dev prompt. scripts/harness_stdio.py for stdio-only agents.
7.8 KiB
name, description
| name | description |
|---|---|
| pineapple-control | Use when operating a WiFi Pineapple (Pager / FENRIS / PineAP firmware) over SSH — accessing the device, understanding its radios/processes, controlling it via PINEAPPLE_* / _pineap / hostapd_cli, fixing pineapd crashes (SSID-pool SIGSEGV), or persistently configuring APs and evil twins via /etc/config/wireless. Pair with the wifi-deauth skill for deauth/handshake attack work. |
Pineapple Control (Pager / FENRIS)
Field-verified operating guide for the WiFi Pineapple Pager (FENRIS firmware, kernel 6.6, OpenWrt, BusyBox). Read this before touching the device; the wifi-deauth skill covers the attack methodology.
Hardware / radios
| Radio | Hardware | Interfaces | Notes |
|---|---|---|---|
| phy0 | internal mt76_wmac (2.4 GHz) |
wlan0wpa (AP), wlan0open (AP), wlan0mon (monitor), wlan0 (managed uplink) |
wlan0mon DOES see the Pineapple's own TX |
| phy1 | USB mt7921u (5 GHz) |
wlan1wpa (AP), wlan1mon (monitor) |
wlan1mon does NOT see own TX (beacon offload) — see Captures |
Naming: wlan0* = 2.4 GHz, wlan1* = 5 GHz. A phy's channel is held by its AP interface (iw dev); the monitor on that phy is pinned to it. The UI "Evil WPA AP" feature is hardwired to wlan0wpa (2.4 GHz); a 5 GHz evil twin must be made via /etc/config/wireless.
Access
sshpass -p '<pw>' ssh -o StrictHostKeyChecking=no root@<ip> # lab unit: 172.16.52.1
- Transient
Permission deniedafter bursts of sessions = SSH rate limiting — pause ~10 s and retry. - Keep sessions short; run each logical step in its own command. One combined session for multi-step attacks (see wifi-deauth).
- BusyBox:
pkill,nohup,sshpassare MISSING. Usekillall/kill $(pidof ...),setsid, and local sshpass.od/hexdump/cat -nabsent — usestrings/grep/head -c.
What runs on the box
| Process | Managed by | Purpose | Socket |
|---|---|---|---|
/pineapple/pineapple (ELF UI backend) |
procd (/etc/init.d/pineapplepager) |
Web UI; supervises/reconverges hostapd | — |
/usr/sbin/pineapd |
procd (auto-restarts on crash) | recon, deauth, SSID pool, handshake logging | /tmp/pineap_sock |
/usr/sbin/hostapd (single global instance) |
standalone (PPID 1) | all AP interfaces | /var/run/hostapd/global, per-iface under /var/run/hostapd/ |
wpa_supplicant |
procd | device's own client uplink (wlan0) |
— |
Command surface
PINEAPPLE_*(e.g.PINEAPPLE_DEAUTH_CLIENT) = symlinks tohak5cmd, which talks to pineapd over/tmp/pineap_sock. Do NOTcurl 127.0.0.1/api/...— the HTTP API is not on :80._pineap= pineapd control CLI (PING,RECON APS|DEVICES|ISEARCH format=json,INTERFACE LIST/SET,SSIDPOOL ...,DEAUTH,EXAMINE,PCAP START/STOP). Direct use can desync the UI — preferPINEAPPLE_*where one exists.hostapd_cli -i <iface> status|get_config|disable|enable(per-iface) and-p /var/run/hostapd -i global(global). This is a Karma-patched build.iw,sqlite3,tcpdump(full build:-G/-Wrotate supported),logread,dmesg.
Config & persistence (the hard-won rules)
/etc/config/wirelessis the SOURCE OF TRUTH for APs (config wifi-ifacesections).wifi reload(orwifi up radioN) applies it.- Editing
/var/run/hostapd-phy*.confis TRANSIENT.hostapd_cli ... reload_config/reloaddo NOT re-read the file.hostapd_cli raw ADD/REMOVEmisfires (treats the config path as the ctrl dir). Killing hostapd triggers the UI backend to restart it (-g /var/run/hostapd/global, no configs) and the ubus path reconverges from/etc/config/wireless— reverting your change. - To change an AP persistently: back up first, edit
/etc/config/wireless, thenwifi reload. Example — convert a 5 GHz AP to a WPA2-PSK evil twin:cp /etc/config/wireless /etc/config/wireless.bak # wifi-iface section: ssid 'TargetSSID', encryption 'psk2', key '<passphrase>' wifi reload hostapd_cli -i wlan1wpa get_config # verify ssid + key_mgmt=WPA-PSK
pineapd health & the crash-loop
- Symptom:
PINEAPPLE_*/ deauth returnscould not connect to pineap: dial unix /tmp/pineap_sock: connect: connection refused, andlogreadshowsdo_page_fault(): sending SIGSEGV to pineapd for invalid read access from 00000004. - Cause observed: the SSID-pool broadcast (68 SSIDs loaded from
/etc/config/pineapd) segfaults pineapd on a ~15 s-to-minutes cadence; procd respawns it. - Fix:
_pineap SSIDPOOL DISABLE && /etc/init.d/pineapd restart, verify with_pineap PING(PONG) and that the SIGSEGV count inlogreadstops climbing. The SSID pool is separate from hostapd evil twins — disabling it does not affect them. PINGto/tmp/pineap_sockfailing while the socket file exists = stale socket (pineapd down/restarting).
Recon DB
pineapd runs --recon --reconpath /root/recon/ --handshakepath /root/loot/handshakes. pineapd holds the DB — always read via the read-only URI with a timeout:
timeout 30 sqlite3 -header -column "file:/root/recon/recon.db?mode=ro" \
"SELECT bssid, CAST(ssid AS TEXT), channel, freq, signal, datetime(time,'unixepoch') FROM ssid ORDER BY time DESC LIMIT 40"
Tables: ssid (ssid is BLOB — CAST(ssid AS TEXT); has bssid/channel/freq/signal/encryption/hidden), wifi_device (mac/freq/signal/packets), scan, handshake (beacon/hs1..hs4 — captures for any nearby AP), hostap_handshake (mic/nonce/eapol — captures for the Pineapple's OWN evil-twin APs), plus hostap_basic/hostap_chalresp (PineAPE enterprise creds) and hostap_client. RECON CLIENTS does not exist — use RECON DEVICES.
Captures
- Raw monitor capture (802.11+radiotap; EAPOL is cleartext on the wire):
tcpdump -i wlan1mon -s 3000 -w /root/loot/pcap/mon_$(date +%s).cap - Own-TX visibility differs by radio. On phy0 (2.4 GHz)
wlan0moncaptures the Pineapple's own beacons/EAPOL; on phy1 (5 GHz)wlan1mondoes NOT see the Pineapple's own TX. A 5 GHz evil twin's M1/M3 will be invisible to the monitor — rely onhostap_handshake//root/loot/handshakesfor own-AP 4-ways. Client uplink frames (M2/M4, assoc) ARE visible on both. - PineAP's
PCAP STARTexport is management/control frames only — never rely on it for handshakes. - Standing capture that survives SSH disconnect (detaches via
setsid, rotates 5 min, keeps 48 files ≈ 4 h;/mmchad ~3.3 GB free):setsid tcpdump -i wlan1mon -s 3000 -G 300 -W 48 -w '/root/loot/pcap/nc_%Y%m%d_%H%M%S.cap' >/dev/null 2>&1 </dev/null & - Stop captures:
killall tcpdump(pkillmissing). - Pull evidence locally with
scp; analyze withtshark/capinfos/hcxpcapngtool(brewwireshark,hcxtools).
Verification & troubleshooting
- AP up but silent?
iw dev <iface> infofor ssid/type/channel;hostapd_cli -i <iface> status(state=ENABLED) andget_config. Statictx_packetson the netdev does NOT mean not-beaconing — beacons are driver-offloaded; checkdmesgfor driver errors instead. - Deauth channel targeting:
PINEAPPLE_DEAUTH_CLIENTinjects via the phy of the configured inject interface (herewlan1mon, 5 GHz) regardless of the channel argument — a "ch1" deauth goes out on 5 GHz. To reach 2.4 GHz clients the inject interface must be phy0. Verify on the wire with a monitor capture (SA=spoofed BSSID). hostapd_cli -p /var/run/hostapd -i global interfacelists managed interfaces.
Teardown & hygiene
- Stop captures:
killall tcpdump; kill only the standing capture's PID if you must keep others. - Leave
/root/loot/**pcap artifacts as evidence; scp them off before leaving. - If you disabled the SSID pool to fix a crash, tell the user it stays disabled (re-enabling re-crashes pineapd).
- Report persistent config changes you made (e.g. an AP converted in
/etc/config/wireless) so the user knows their device differs from the UI default.