Scriptable ESP32 attack platform. Wi-Fi attacks, BLE offensive assessment (NimBLE), Bluetooth Classic, and nRF24L01+ RF capabilities from a single DevKitC-32. DRAM-optimised build fits ESP32 classic (34% RAM, 59% Flash).
For authorised penetration testing, red-team labs, and blue-team validation only. Misuse against networks or devices you do not own or have written authorisation to test is illegal under the Computer Misuse Act 1990 (UK) and equivalent legislation globally.
Midas Wraith is a modular, scriptable firmware for the ESP32 DevKitC-32 built on ESP-IDF v5.5. It combines offensive Wi-Fi, LAN, BLE, Bluetooth Classic, and nRF24L01+ 2.4 GHz RF capabilities into a single platform with a web UI, UART CLI, and an attack-chaining scripting engine.
It is designed for:
- Red-team operators validating wireless and LAN exposure
- Blue-team engineers testing detection and hardening
- Security researchers studying wireless protocols (including MouseJack/ESB)
- Educators demonstrating real-world attack chains in lab environments
Note: As of the ESP-IDF 5.5 migration, several CLI commands have been removed to optimise memory footprint. The underlying modules remain in the codebase but are not currently accessible via the CLI. See Changelog for details.
- Deauth flood (broadcast and targeted)
- Beacon spam (random, clone, rickroll)
- Probe flood
- CSA attack, SAE attack, sleep attack
- KARMA: open / spear / adaptive mode — glob SSID pattern + vendor OUI spear rules
- Evil Twin: automated clone + deauth + portal, optional WPA phishing; effectiveness tracking (assoc count, creds, handshake/PMKID linkage)
- Known beacons (UK SSID dictionary + custom list)
- PMKID sniff, EAPOL handshake capture (passive and active)
- AP scoring — per-AP score 0–100 derived from encryption weakness, RSSI proximity, probe history, client density, and PMF/WPA3 penalty
- Tag classification —
HIGH_VALUE_OPEN,LIKELY_ENTERPRISE,IOT_CLUSTER,HIDDEN_SSID,WPS_ENABLED,WEAK_CRYPTO,PMF_PROTECTED,HIGH_TRAFFIC - OUI vendor lookup — 30-entry static table; random MAC detection via locally-administered bit
- Client classification — sticky (single BSSID) vs roamer (multi-BSSID), per-client vendor tag
- Target selection strategies —
highest_score,open_only,score>N - Smart handshake harvester — AP-centric: passive PMKID listen → targeted deauth loop → poll; three rate presets (stealth / medium / burst)
- Per-STA eviction (
wifi_hs_evict_sta) — bidirectional deauth (AP→STA + STA→AP) with result tracking
- PMF / WPA3 inference from
authmodefield (required / optional / none) - Deauth susceptibility score — injects 10 broadcast deauths, measures client drop rate over 3 s (capped at 10 for WPA3 APs)
- Rogue AP preference test — clones target SSID as open AP, counts associations over 30 s versus legitimate AP
- DHCP starvation (with full DORA handshake option)
- Rogue DHCP server
- DNS spoofing
- ARP scan, port scan
- SSDP poisoning
- Captive portal with DNS hijack
- Built-in templates: Google, Microsoft, WPA phish, Hotel, Corporate SSO
- SD card template loading (custom HTML)
- Live credential feed in web UI
A 10-module NimBLE host-stack subsystem for offensive BLE evaluation. 9 of 10 modules are active in the DRAM-optimised build; ble_gatt_client (full GATT enumeration + BLESA auth-boundary testing) is stubbed to save ~30 KB and deferred to the ESP32-S3 sibling project.
Active Scanning & Device Classification
- Active scan with 50 ms / 30 ms interval/window
- ADV + scan-response parsing: name, appearance, TX power, manufacturer-specific data
- Automatic device classification: keyboard, mouse, BLE lock, HID generic, health sensor, wearable, audio, iBeacon (Apple 0x004C + 0x02/0x15), Eddystone (service UUID 0xFEAA)
- Per-device tracking: RSSI, ADV count, first/last seen timestamps, connectable flag
Connection Management
- Connection pool: 1 active connection in DRAM-optimised build (
WRAITH_MAX_CONNS=4available, NimBLE tuned to 1 concurrent) - Full GAP event lifecycle: CONNECT, DISCONNECT, ENC_CHANGE, MTU negotiation
- Connection parameter update (interval / supervision timeout)
GATT Enumeration (stubbed in DRAM-optimised build — full impl deferred to ESP32-S3)
- Full discovery pipeline: MTU exchange → services → characteristics → descriptors
- Blocking async pattern: FreeRTOS binary semaphore bridges NimBLE callbacks to synchronous caller
- Cached per-connection
gatt_profile_t(6 svcs × 8 chrs × 3 dscs) - Tree-format profile print: service / characteristic / descriptor hierarchy with property flags
BLESA Auth-Boundary Testing (stubbed in DRAM-optimised build — full impl deferred to ESP32-S3)
- Tests every characteristic for read/write access across 3 phases:
- Pre-pair — probe access before any pairing or encryption
- Post-pair — probe access after successful pairing (encrypted link)
- Reconnect — probe access on reconnect without re-pairing (BLESA-class vulnerability)
- Per-characteristic
chr_access_map_twithNOT_TESTED / DENIED / GRANTEDresults - Formatted auth-boundary report table
Pairing Engine
- Security Manager: Just Works, Passkey Entry, Numeric Comparison, OOB
- Configurable IO capability per pairing attempt
- Passkey injection (
ble_pairing_engine_inject_passkey) and NumComp confirm/reject - Downgrade-attack sequence: iterates Just Works Legacy → Just Works SC → SC+MITM, records lowest accepted security level
Device Fingerprinting
- djb2 structure hash over the GATT UUID / properties sequence (changes when access model changes)
- Privacy risk score 0–100 (static address +20, name in ADV +15, TX power present +10, manufacturer data +10, connectable +10, unauthenticated readable characteristics +15, …)
- Flags:
trackable(score ≥ 40),exposes_name,static_addr,pii_readable_unauth
Notification Auditor
- Writes CCCDs (0x0001 notify / 0x0002 indicate) on all eligible characteristics
- Flags unauthenticated subscriptions (CCCD write granted on unencrypted link)
- Waits 2 s for incoming notifications to confirm the subscription is live
- Persistence test: after reconnect, probes whether CCCD state survived without re-subscribing (CVE-class: unauthenticated notify persistence)
GATT Server (configurable profiles)
DECOY— Generic Access + Battery service with plausible valuesVULN_DEMO— custom service with one unauthenticated readable + writable + notify characteristic (noREAD_ENC/WRITE_ENCflags)LOCK_EMU— BLE lock emulation with writable lock-state characteristic- Runtime attribute value store;
ble_gatts_chr_updated()triggers notify to all subscribers
Advertising Engine
- Modes: iBeacon (Apple company ID + 25-byte manufacturer data), Eddystone-URL (service UUID 0xFEAA + encoded URL), clone (mirror scanned peer's ADV fields verbatim), decoy
- NRPA rotation via FreeRTOS software timer (configurable interval in seconds)
- Connectable undirected ADV (100–150 ms interval)
GATT Stress / ATT Edge-Case Tester
MTU_SWEEP— negotiate every MTU from 23 to 517 in 32-byte stepsHANDLE_WALK— probe-read known handles (or blind sample every 16th handle 0x0001–0x0200)WRITE_OVERFLOW— write 64-byte payloads to every writable characteristic; logs if acceptedPDU_FLOOD— 50 rapid-fire reads with no inter-op delayLONG_READ—ble_gattc_read_longon every readable characteristic- Per-phase report: ops sent / OK / ATT error / timeout / peer-disconnected flag
- BLE spam: Apple, Samsung, Google, Microsoft, Flipper Zero, Sour Apple, random cycle
- BLE recon: AirTag detection, Flipper detection, skimmer detection, Pwnagotchi detection
- Bluetooth Classic: MAC spoofing, memory read/write, device impersonation, address randomisation via HCI vendor commands
Stack selection: NimBLE (
CONFIG_BT_NIMBLE_ENABLED=y,CONFIG_BT_BLUEDROID_ENABLED=n) saves ~50 KB RAM and enables the fullble_assesscommand group. Bluedroid enables the legacyblespam/recon/HCI commands. Both cannot be active simultaneously.
- AP scan with hidden SSID reveal
- Probe request sniffing
- Deauth detection
- Client-AP mapping
- Signal strength tracking
Note: Wi-Fi recon and wardrive are stubbed (no-op) in the DRAM-optimised build to free ~48 KB. The
wifi_attackscan (wraith> scan) remains fully functional. Full recon/wardrive will be restored on the ESP32-S3 sibling project.
A full 7-layer nRF24 subsystem built on HSPI (SPI2), independent of the VSPI SD bus.
SIGINT / Passive
- 128-channel carrier-detect sweep (RPD register polling)
- Promiscuous ESB sniffing at 1 Mbps and 250 kbps (MouseJack technique: SETUP_AW=0x00, addr=0xAAAA, CRC disabled)
- Automatic address extraction from raw ESB frames with PC-field plausibility checks and frequency-based candidate promotion
- Target discovery table: address, channel bitmap, data rate, device classification, confidence score, inter-packet timing EMA
- Focused capture session: timestamped packet log, stored to RAM with SD export
Classification & Intelligence
- Heuristic device fingerprinting: HID keyboard, HID mouse, HID combo, game controller, IoT sensor, bursty proprietary
- Per-target analytics: packet rate, inter-packet jitter, packet error rate estimate (per-mille)
- Channel occupancy tracking (128 counters, saturating at 255)
- Multi-node cooperative scanning: remote node reports merged into the local target table
Active Attacks
- Replay engine: re-transmit captured sessions with timing preservation or fixed interval; optional
stop_on_ackto halt on first acknowledged transmission - HID keystroke injection: ASCII string typing, single key press, raw 8-byte HID report (MouseJack)
- Packet flood: sustained high-rate targeted TX (rate_hz configurable, duty-cycle guarded)
- Mutation fuzzer: bit-flip, length, field-increment, full-random modes with ACK-hit logging
Packet Lab & DSL
- Single-shot manual send (channel, address, payload, repeat count, inter-packet delay)
- Attack DSL: scriptable sequences with
SET_VAR/$namevariable substitution, SCAN, SAVE, REPLAY, INJECT, FLOOD, FUZZ, DELAY, LOOP, LABEL, GOTO, STOP opcodes
Safeguards
- PA/LNA duty-cycle guard: software ceiling on sustained PA_MAX TX time (default 75% of any 1 s window)
- Sweep limited to channels 0–83 (2.400–2.483 GHz ISM band) by default
Export
- Profiles →
/sdcard/rf24/profiles_<ts>.json - Sessions →
/sdcard/rf24/sessions_<ts>.json - Raw capture →
/sdcard/rf24/<session_id>.rf24cap(binary: 16-byte ID +[len][payload][ts_ms]frames)
- Text-based attack-chain DSL (sequencing, delay, loop, conditionals)
- Wi-Fi DSL opcodes (v3.2):
WIFI_SCAN,WIFI_TARGET_SELECT,WIFI_ATTACK,WIFI_HS_HARVEST,WAIT_FOR_WIFI,IF_WIFI,IF_AP_TAG,GOTOlabels $TARGETvariable — written byWIFI_TARGET_SELECT, consumed by subsequent Wi-Fi opcodes- Built-in chains:
harvest_hashes,wifi_hardening_check,lan_exposure_check,smart_harvest,open_ap_harvest - Custom chains loadable from SD card
- nRF24 DSL with per-script variable scoping (
SET_VAR channel $ch,SCAN $ch 100, etc.)
- Web UI dashboard: 9 tabs — Dashboard, WiFi, BLE, Network, Portal, Advanced, Tools, OTA, NRF24
- NRF24 tab: live radio status, sweep mode selector, target table, session capture, HID inject, flood, SD export
- REST API:
/api/nrf/{status,targets,sweep/*,session/*,inject,flood,stop,export/*} - UART CLI (
wraith>prompt, full command set includingnrfsubcommands) - SD card storage (PCAPs, creds, scripts, chain files, RF captures)
- OTA firmware update with rollback
- Stealth: MAC randomisation, deep-sleep persistence, timed scheduling
- PCAPng capture with radiotap metadata
| Component | Role |
|---|---|
| ESP32 DevKitC-32 (30-pin) | Main processor, Wi-Fi, BLE, BT |
| SD card module | Storage for logs, PCAPs, and chain scripts |
| nRF24L01+ PA/LNA module | 2.4 GHz ESB radio — promiscuous sniff, HID injection, replay, fuzz |
The nRF24L01+ PA/LNA variant (green PCB, onboard LNA + power amplifier) draws up to 130 mA at PA_MAX. Use a dedicated 3.3 V LDO (≥ 300 mA, 100 µF decoupling) — do not power directly from the ESP32 3V3 pin.
| Function | Default GPIO |
|---|---|
| SD MOSI | 23 |
| SD MISO | 19 |
| SD CLK | 18 |
| SD CS | 5 |
| Function | Default GPIO | Notes |
|---|---|---|
| NRF MOSI | 13 | HSPI, no conflict with SD |
| NRF MISO | 12 | |
| NRF CLK | 14 | |
| NRF CSN | 27 | |
| NRF CE | 33 | |
| NRF IRQ | 32 | Optional — not polled in current firmware |
All pins are configurable via idf.py menuconfig → Board Pin Configuration.
git clone https://github.com/<your-org>/midas-wraith-fw
cd midas-wraith-fw
idf.py set-target esp32
idf.py menuconfig # set Wi-Fi creds, pins if needed
idf.py build flash monitorConnect over serial at 115200 baud. You will see the Wraith banner and a wraith> prompt.
The NimBLE subsystem requires Bluedroid to be disabled. In menuconfig:
Component config → Bluetooth → Bluetooth Host → NimBLE (select)
Component config → Bluetooth → Bluedroid (deselect)
Or set directly in sdkconfig:
CONFIG_BT_NIMBLE_ENABLED=y
CONFIG_BT_BLUEDROID_ENABLED=n
CONFIG_BT_NIMBLE_MAX_CONNECTIONS=1
CONFIG_BT_NIMBLE_MAX_BONDS=1
CONFIG_BT_NIMBLE_MSYS_1_BLOCK_COUNT=6
CONFIG_BT_NIMBLE_HOST_TASK_STACK_SIZE=3072
CONFIG_BT_NIMBLE_ATT_PREFERRED_MTU=128
CONFIG_BTDM_CTRL_MODE_BLE_ONLY=y
The DRAM-optimised build tunes NimBLE for 1 concurrent connection with reduced mbuf pools and transport buffers. This is sufficient for targeted BLE assessment (scan → connect → attack → disconnect → next target). Raise MAX_CONNECTIONS on ESP32-S3 with PSRAM.
wraith> scan
wraith> deauth 0
wraith> karma start
wraith> karma spear AA:BB:CC:DD:EE:FF
wraith> eviltwin 2 wpa
wraith> chain run harvest_hashes
wraith> portal FreeWifi google
wraith> sd ls /
# Scan and score all visible APs (0-100), show ranked list
wraith> intel refresh
wraith> intel list
# Show intel for a specific AP by index
wraith> intel show 3
# Auto-select highest-scoring target, then harvest handshake (medium rate)
wraith> harvest run 3 medium 60000
# Evict a specific client from an AP to force re-authentication
wraith> harvest evict AA:BB:CC:DD:EE:FF 00:11:22:33:44:55 6 burst
# Adaptive KARMA — add a spear rule (SSID glob + OUI filter)
wraith> karma adaptive
wraith> karma rule "Corp*" AA:BB:CC
wraith> karma rules
# Run built-in smart harvest chain (auto-scores, selects, harvests)
wraith> chain run smart_harvest
# Check a single AP — infer PMF, run deauth susceptibility test
wraith> hardening check 2 deauth
# Full scan — test all APs, include rogue AP preference test
wraith> hardening full deauth rogue
# View last hardening report
wraith> hardening report
# Passive sweep — discover devices on all 128 channels
wraith> nrf sigint start 100
# View discovered targets
wraith> nrf targets
# Save target 0 with a label, start a focused capture session
wraith> nrf save 0 logitech_kb
wraith> nrf capture start 0
# Inject keystrokes into discovered HID target
wraith> nrf inject 0 "calc.exe"
# Run a MouseJack replay attack, stop on first ACK
wraith> nrf replay <session_id> 3
# Export targets and sessions to SD card
wraith> nrf export profiles
wraith> nrf export sessions
# Run an nRF24 DSL script from SD card
wraith> nrf dsl run /sd/scripts/mousejack.rf24
# Scan for HID targets on common channels
SET_VAR ch 8
SCAN $ch 200
SAVE 0 target_kb
# Inject a payload — open Run dialog then launch calc
INJECT 0 "WIN+R"
DELAY 800
INJECT 0 "calc.exe\n"
# Fuzz the target to probe for additional ACK responses
FUZZ 0 50 20
Create a .chain file on SD card:
scan
delay 3000
eviltwin 0
wait_for_creds 300000
Load and run:
wraith> chain run /sd/myscript.chain
# Active scan — discover and classify nearby devices
wraith> ble_assess scan start
wraith> ble_assess scan list
# Connect, enumerate GATT profile, run BLESA auth-boundary test
wraith> ble_assess connect AA:BB:CC:DD:EE:FF 1
wraith> ble_assess enumerate 0x0001
wraith> ble_assess auth-test 0x0001
# Privacy risk fingerprint from scan table entry
wraith> ble_assess fingerprint 3
# Audit unauthenticated notifications (no pairing required)
wraith> ble_assess notif-audit 0x0001
# Pairing downgrade: finds lowest security level peer accepts
wraith> ble_assess downgrade 0x0001
# GATT stress — MTU sweep + handle walk + write overflow + PDU flood
wraith> ble_assess stress 0x0001 0x0F
# Advertising: NRPA-rotating decoy (rotates every 60 s)
wraith> ble_assess adv decoy
# Spawn a vulnerable GATT server (unauthenticated read/write/notify)
wraith> ble_assess server vuln
# Rotate to a new NRPA immediately
wraith> ble_assess rotate
# Set TX power to +9 dBm, switch coex to BLE-heavy during an attack
wraith> ble_assess txpower 9
wraith> ble_assess coex ble
Ten ESP-IDF components with a strict unidirectional dependency hierarchy:
ble_core NimBLE stack init, NRPA, TX power, coex, shared types
├── ble_scanner Active scan, ADV parsing, device classification
├── ble_conn_manager 4-slot connection pool, GAP event handling
│ ├── ble_gatt_client GATT enumeration, BLESA auth-boundary test
│ ├── ble_pairing_engine SM: Just Works/Passkey/NumComp, downgrade
│ ├── ble_notification_auditor CCCD audit, persistence test
│ └── ble_gatt_stress ATT edge-case tester (MTU/walk/overflow/flood)
├── ble_fingerprint Structure hash, privacy risk score 0-100
├── ble_gatt_server Configurable GATT server (decoy/vuln/lock)
└── ble_adv_engine ADV engine: iBeacon, Eddystone, clone, decoy
All GATT and GAP operations are asynchronous (NimBLE callback model). Blocking is achieved via FreeRTOS binary semaphores passed as callback arguments — callers block on xSemaphoreTake while the NimBLE host task fires the callback from Core 0.
FreeRTOS task layout:
- Core 0 — NimBLE host task (
nimble_port_freertos_init) - Core 1 — All application tasks (scanner, CLI REPL, stress, audit)
Three ESP-IDF components layered above the existing wifi_attack and recon modules:
wifi_intel AP scoring, OUI lookup, tag classification, target selection
wifi_hs_harvester Handshake/PMKID harvester, STA eviction, rate control
wifi_hardening PMF inference, deauth susceptibility, rogue AP preference test
Dependency chain (no circular imports):
wifi_intel→wifi_attack,reconwifi_hs_harvester→pmkid_capture,recon,wifi_attack,frame_injectwifi_hardening→wifi_attack,recon,frame_inject,esp_eventattack_chain→wifi_intel,wifi_hs_harvester(new opcodes)
Six ESP-IDF components with a strict dependency hierarchy — no circular imports:
rf24_radio SPI2 HAL, register R/W, PA/LNA duty-cycle guard
└── rf24_profiles Shared types, NVS persistence, SD export, template registry
└── rf24_capture SIGINT sweep, promiscuous sniff, target table, sessions
└── rf24_attacks Replay, HID inject, flood, fuzz, packet lab
└── rf24_analytics Classification, timing EMA, channel occupancy
└── rf24_dsl DSL compiler + executor, variable scoping
All long-running operations run in dedicated FreeRTOS tasks. Only one attack engine runs at a time (shared radio resource). The capture and analytics layers can run concurrently with each other.
Current release: v3.3-dev. The Capability Overview reflects what is available on main.
| Version | Status | Notes |
|---|---|---|
| v1.0 | Legacy | Core Wi-Fi, BLE, BT HCI, network attacks, BadUSB, covert channels |
| v2.0 | Legacy | KARMA, evil twin, attack chaining, SD, OTA, web UI dashboard |
| v2.1 | Legacy | ESP-IDF 5.5 migration and memory optimisation; removed CLI commands: nethijack, cookie, osfp, mesh, revtcp, wardrive, ir, badusb |
| v3.0 | Legacy | nRF24L01+ PA/LNA subsystem: 128-ch sweep, promiscuous ESB sniff (MouseJack), HID injection, replay, fuzz, packet lab, attack DSL with variables, multi-node cooperative scanning, SD export, web UI Tab 8 |
| v3.1 | Legacy | NimBLE BLE assessment subsystem (10 modules): active scan + classification, GATT enumeration, BLESA auth-boundary testing, pairing engine with downgrade attacks, device fingerprinting, notification auditor, GATT server, ADV engine with NRPA rotation, GATT stress/ATT edge-case tester |
| v3.2 | Legacy | Wi-Fi intelligence subsystem: AP scoring (0–100), tag classification, OUI vendor lookup, sticky/roamer client tracking; smart handshake/PMKID harvester (3 rate presets + STA eviction); adaptive KARMA with glob+OUI spear rules; evil twin effectiveness tracking; hardening checks (PMF inference, deauth susceptibility, rogue AP preference); 8 new Wi-Fi DSL opcodes + $TARGET variable + 2 built-in scripts |
| v3.3-dev | Current | DRAM-optimised build — firmware links and fits on ESP32 classic (34% RAM, 59% Flash). NimBLE BLE split: 9 of 10 assessment modules active (gatt_client stubbed for DRAM). Bluedroid ble_spam/ble_recon replaced with no-op stubs. Recon/wardrive stubbed. BadUSB removed (no CYD hardware). Buffer trims across cookie_siphon, rf24_capture, wifi_attack. NimBLE tuned to 1 connection with reduced mbuf/transport pools. |
v2.0 legacy features:
git checkout v2.0to access BadUSB, covert channels, and wardrive CLI commands removed in v2.1.
Midas Wraith is a security research and education tool. It is intended for use on networks and devices you own or have explicit written authorisation to test.
Unauthorised use is illegal under the Computer Misuse Act 1990 (UK), the Computer Fraud and Abuse Act (US), and equivalent laws in other jurisdictions. The authors accept no liability for misuse.