Skip to content

Modular Framework Architecture

Choose a tag to compare

@Indspl0it Indspl0it released this 16 Apr 15:48
· 46 commits to main since this release

[2.6.0] - 2026-04-16

Summary

Blue-Tap 2.6.0 is the Modular Framework release — every module now implements the Module protocol, produces typed RunEnvelope output, and is auto-registered in a global ModuleRegistry. The CLI was redesigned around the assessment workflow (discover → recon → vulnscan → exploit → extract → fuzz → report). The hardware layer gained a unified resolve_active_hci() resolver. The report pipeline is fully adapter-driven with per-family outcome validation enforced at call time.

Added — Module Protocol (framework/module)

  • Module abstract base class — defines run(ctx: RunContext) → RunEnvelope; __init_subclass__ hook auto-registers every subclass in the global ModuleRegistry without a manual ModuleDescriptor block
  • RunContext dataclass — single typed argument to Module.run(): target, adapter, options, session_id, dry_run; replaces ad-hoc kwargs scattered across entry points
  • Typed option descriptorsOptAddress, OptPort, OptBool, OptInt, OptStr, OptChoice, OptFlag; each validates its value at resolution time and raises ValueError on invalid input
  • OptionsContainer — ordered dict of Option instances; resolves CLI args + env-var overrides at invocation time before Module.run() is called
  • ModuleInvoker — resolves module_id from the registry, builds RunContext from CLI params, calls Module.run(), and streams CliEvents to the operator console
  • ModuleLoader — imports Module classes from entry_point strings (package.module:Class); caches loaded classes to avoid repeated imports
  • autoload.py — imports all family __init__.py files so subclass auto-registration fires before the registry is queried for the first time

Added — Phase-Verb CLI Architecture (interfaces/cli)

  • discoverclassic / ble / all sub-verbs wrapping DiscoveryScanner via ModuleInvoker; replaces the flat scan command with an explicit workflow step
  • reconsdp / rfcomm / gatt / hci-capture / sniffer / lmp-sniff sub-verbs consolidating the former recon + capture families into one phase command
  • exploit — sub-commands: bias, bluffs, knob, ctkd, enc-downgrade, ssp-downgrade, hijack, pin-brute; grouped under Crypto/Key Attacks and Full Chain
  • extract — sub-commands: contacts, messages, audio, media, push, snarf, at; covers all post-exploitation data paths in one place
  • dosBLE / Classic / Raw-ACL sub-commands forwarded to the DoS runner with protocol grouping
  • fuzzcampaign + 9 protocol sub-commands (sdp-deep, l2cap-sig, rfcomm-raw, ble-att, ble-smp, bnep, obex, at-deep, lmp) plus crashes / minimize / replay / corpus analysis commands
  • doctor — hardware diagnostics: adapter list, DarkFirmware probe, USB dongle detection by VID:PID, HCI sanity check
  • auto — orchestrated discover → recon → vulnscan → exploit chain with --dry-run support and per-phase skip/abort handling
  • fleet — multi-target orchestration; per-target error isolation so one failure no longer aborts the full run
  • runner / plugins — generic blue-tap run <module_id> entry point; plugins lists registered modules and shows descriptor info
  • _module_runner.py — single shared helper for all family CLIs: resolves module, builds RunContext, streams events, writes session envelope

Added — Outcome Validation Taxonomy

  • VALID_OUTCOMES_BY_FAMILY (framework/contracts/result_schema.py) — per-family frozenset of allowed module_outcome values; make_execution() raises ValueError on any unlisted value so bugs surface in tests not in production envelopes
  • Family outcome sets — discovery (observed / merged / correlated / partial / not_applicable); assessment (confirmed / inconclusive / pairing_required / not_applicable / not_detected); exploitation (success / unresponsive / recovered / aborted / not_applicable); post_exploitation (extracted / connected / streamed / transferred / partial); fuzzing (crash_found / timeout / corpus_grown / no_findings / crash_detected / reproduced)
  • _infer_family_from_module_id() — extracts the family prefix from <family>.<name> module IDs; unknown families skip validation for backward compatibility with pre-2.6 modules

Added — Registry Extensions

  • ModuleDescriptor.category — optional sub-family grouping field (e.g. "pairing", "l2cap", "ble") for DoS and CVE check sub-classification within a family
  • ModuleDescriptor.referencestuple[str, ...] of external references (CVEs, RFCs, specs) associated with the module; surfaced in blue-tap plugins info <module> output
  • ModuleRegistry.try_get(module_id) — returns ModuleDescriptor | None; avoids KeyError when probing for optional or plugin-provided modules

Added — Hardware Adapter Resolution

  • resolve_active_hci(explicit=None) (hardware/adapter.py) — priority-ordered HCI resolution: explicit arg → BT_TAP_DARKFIRMWARE_HCI env var → RTL8761B USB VID:PID probe → first UP adapter from hciconfig"hci0" as last resort
  • Process-lifetime cache — result stored in _ACTIVE_HCI_CACHE after first hardware probe; reset_active_hci_cache() clears it on hot-plug or adapter-list refresh
  • RTL8761B identified by VID:PID (0bda:8771) not HCI slot position — fixes false "DarkFirmware unavailable" in multi-adapter setups where the scan adapter ≠ firmware dongle

Added — Native Module Classes

  • CveCheckModule (modules/assessment/base.py) — wraps legacy check functions into the Module protocol; subclasses declare check_fn and module_id without duplicating envelope construction
  • VulnScanModule (modules/assessment/vulnscan_module.py) — thin Module subclass delegating to vuln_scanner.run() and wrapping the result in a canonical RunEnvelope
  • DiscoveryScanner (modules/discovery/scanner.py) — Module class for Classic/BLE/combined scans; registered as "discovery.scanner" via auto-registration
  • _e0.py (modules/exploitation/) — E0 encryption-mode downgrade probe helper shared by knob.py and bias.py
  • DoSCheckModule (modules/exploitation/dos/base.py) — shared base for BLE / Classic / Raw-ACL DoS checks; handles timing evidence, recovery probe wiring, and envelope construction
  • FuzzCampaign (modules/fuzzing/campaign.py) — Module wrapping the full engine lifecycle: seed corpus, run, collect crashes, finalize RunEnvelope; supports campaign resume and crash export
  • ReconCampaign (modules/reconnaissance/campaign.py) — Module wrapping the multi-collector recon pipeline into a single RunEnvelope; registered as "reconnaissance.campaign"

Added — Documentation Site (MkDocs)

  • mkdocs.yml — Material theme configuration with structured nav tree, light/dark mode, code block highlights
  • docs/getting-started/ — installation, hardware setup (single/dual adapter), quick start, IVI simulator
  • docs/guide/ — per-phase operator guides: discovery, recon, vulnerability assessment, exploitation, DoS, fuzzing, post-exploitation, sessions and reporting, automation
  • docs/workflows/ — end-to-end scenario walkthroughs: full pentest, quick assessment, fuzzing campaign, encryption downgrade, audio eavesdropping, custom playbooks
  • docs/developer/ — architecture overview, module system, writing a module, report adapters, plugin entry-points
  • docs/reference/ — hardware compatibility matrix, platform notes, troubleshooting reference
  • docs/cve/ — CVE detection matrix, DoS CVE matrix, expansion roadmap; CVE specs moved from flat cve-detection-specs/cve/specs/

Added — Testing

  • conftest.py — shared fixtures: mock adapter, target MAC, tmp session directory, registry reset between tests
  • 13 test_userflow_*.py — end-to-end operator workflow coverage: discover→recon→report, vulnscan fleet, BIAS, KNOB, DoS runner, fuzzing campaign, PBAP/OPP, A2DP/AVRCP, report generation, session resume, console output, playbook execution
  • test_cli_facades.py — Click command registration smoke tests for every phase-verb subcommand; catches missing imports and mis-wired groups
  • test_outcome_validator.pyVALID_OUTCOMES_BY_FAMILY enforcement: valid outcomes pass, invalid ones raise ValueError
  • test_module_runtime_e2e.pyModule.run()RunEnvelope round-trip for one module per family; validates schema, run_id, and outcome fields
  • test_hci_vsc_concurrency.pyHciVscClient concurrent command safety under multi-thread access
  • test_dos_migration.py — DoS adapter post-migration regression: accepts() family-prefix matching, ingest(), section output shape

Changed

  • Report adapter accepts() — all adapters match both legacy module name strings and modern "family.name" prefixes; DiscoveryReportAdapter additionally accepts any "discovery.*" prefix
  • Envelope module label — renamed "attack""exploitation" across all envelope builders to align with module family taxonomy
  • Session store — atomic JSON writes via write-to-temp + os.replace(), correlation IDs on every operation, session-resume by name lookup, path configurable via BT_TAP_SESSIONS_DIR
  • Module __init__.py files — all family __init__.py dropped manual ModuleDescriptor blocks; __init_subclass__ auto-registration handles all modules
  • _check_darkfirmware_available() — identifies RTL8761B by USB VID:PID and reads BT_TAP_DARKFIRMWARE_HCI env var; scan adapter no longer assumed to be the firmware dongle
  • All recon collectors — call resolve_active_hci() instead of hardcoding "hci0"; structured WARNING-level logging on socket errors
  • All post-exploitation modulesresolve_active_hci() used in PBAP/MAP/OPP/A2DP/AVRCP/HFP paths
  • set_verbosity() — propagates to root logger so -v / -vv flags apply consistently across all modules
  • run_cmd() — explicit timeout= on all subprocess calls; stderr captured to avoid dangling file descriptors
  • parse_sdp_records() — handles malformed XML with a logged warning instead of raising ParseError
  • confirm_destructive() — accepts dry_run kwarg; logs the operator confirmation prompt to the audit log
  • Fleet scan — per-target errors captured in envelope without aborting the full run
  • vuln_scanner._run_hcitool_info() — calls resolve_active_hci() instead of defaulting to "hci0"
  • Report generator — accepts explicit session path; no module-specific logic remains in generator
  • output.py — added channel_table(), bare_table(), print_table() helpers; demo runner uses shared formatters
  • README — condensed to focused project summary with badge row and quick-start matching the phase-verb CLI

Fixed

  • clone_device_identity callersbias.py / hijack.py checked if not clone_device_identity(...) which evaluated False after bool→dict migration; fixed to result.get("success", False)
  • Recon capture-stopHCICapture.stop() returns a path string; two copy-paste blocks called .get("success") on it raising AttributeError
  • Recon lmp-sniff / nrf-sniffartifacts variable referenced in build_recon_result() but never initialized; NameError on every execution
  • L2CAP checks — two _check_ecred_* functions had unreachable return [] after finally blocks; removed dead code preventing results from being returned
  • btmgmt public-addr errors — handled safely instead of crashing the adapter command
  • DoS result/report normalization — aligned DoS result dict keys with report adapter field expectations
  • HFP reconnect socket leak — socket closed in finally block during reconnection
  • RAM BDADDR patching — corrected controller memory write sequence for RTL8761B

Removed

  • Deprecated top-level packagesblue_tap/attack/, blue_tap/cli.py, blue_tap/core/, blue_tap/fuzz/, blue_tap/recon/, blue_tap/report/ (all were deprecation-notice stubs with no active consumers)
  • Auto envelope builderframework/envelopes/auto.py; auto-pentest uses phase-verb CLI with per-phase family envelopes
  • Auto report adapterframework/reporting/adapters/auto.py removed alongside the auto envelope
  • AutoPentest modulemodules/exploitation/auto.py retired; superseded by blue-tap auto CLI command
  • Flat family CLI filesinterfaces/cli/assessment.py, discovery.py, exploitation.py, fuzzing.py, post_exploitation.py, reconnaissance.py replaced by phase-verb commands
  • Retired test filestest_auto_envelope.py, test_cli_events_coverage.py, test_cli_startup_bootstrap.py, test_discovery_regressions.py, test_media_data_regressions.py, test_recon_revamp.py; replaced by userflow tests