Changelog¶
All notable changes to Blue-Tap are documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
2.6.2 - 2026-04-17¶
Summary¶
Blue-Tap 2.6.2 is a small follow-up to 2.6.1 that fixes post-USB-reset verification on RTL8761B adapters and wires up automated GitHub Pages deployment for the docs site.
Fixed — Hardware¶
DarkFirmwareManager.usb_reset_and_wait()— new method that resets the RTL8761B, waits for teardown, then pollsfind_rtl8761b_hci()until the adapter re-enumerates and returns the newhciXname. The kernel can re-enumerate the adapter under a different index after reset (e.g.hci8 → hci0); callers that verified post-reset state (is_darkfirmware_loaded,get_current_bdaddr) were probing the pre-reset name and reporting "verification inconclusive" even when install/patch succeededfirmware-install(install + restore),patch_bdaddr, and the startup auto-install prompt now use the re-enumeratedhcifor verification and user-facing messages
Build¶
- Version bumped to
2.6.2 .github/workflows/docs.yml— new workflow auto-builds MkDocs site with--strictand deploys to GitHub Pages on every push tomainpyproject.toml— license metadata format fixed to satisfy PEP 639 (SPDX expression only, no classifier duplication)
2.6.1 - 2026-04-17¶
Summary¶
Blue-Tap 2.6.1 is a stability, ergonomics, and correctness release on top of 2.6.0. The CLI now supports interactive target selection across every target-taking command (omit the address to get a device picker); the hardware layer picks up a second RTL8761B dongle variant and hardens the DarkFirmware watchdog against concurrent HCI access; several modules that silently "succeeded" while producing wrong results now return honest envelopes; and the module loader can actually unregister + re-import plugin classes instead of leaking descriptors on reload.
Added — CLI Ergonomics¶
- Interactive target picker —
vulnscan,recon,exploit,extract,dos,fleet,adapter infonow acceptTARGETas optional. When omitted (or when the argument doesn't match a MAC), a device scan runs and presents a numbered picker invoke_or_exit()(interfaces/cli/_module_runner.py) — new helper used by all facade commands; failed module runs now exit with status1instead of0, soblue-tapworks correctly in shell pipelines and CI- Command-name-aware proxy usage hints —
dos-<check>,vuln-cve-*,vuln-<check>,recon-hci-capture,recon-snifferproxy commands now print the exact real-command invocation (e.g.blue-tap dos TARGET --checks bluefragorblue-tap vulnscan TARGET --cve CVE-2020-0022) instead of a generic "<group> <subcommand>" template fuzz cve— registered proxy command for replaying a known CVE fuzz patternrun-playbookadded to no-session command allow-list soblue-tap run-playbook --listworks without an active sessionauto— docstring rewritten to state explicitly that this is a 4-module shortcut (SDP recon → vuln_scanner → KNOB exploit → PBAP extract → report), not a "full pentest"; report generation now uses the active session's data correctly and writesreport.htmlinto the session directory
Added — Framework¶
ReportAdapter.priority— adapters now carry an integer priority (lower = runs first). Plugin adapters default to50; the built-invulnscanfallback adapter is pinned to200so third-party adapters are always tried firstget_report_adapters()— returns adapters sorted by priority, unifying built-in + plugin-registered adapters;interfaces/reporting/generator.pynow iterates through this function instead of the staticREPORT_ADAPTERStuple (plugin adapters were previously ignored during report generation)ModuleRegistry.unregister(module_id)— returnsTrueif the descriptor was present; used by the loader to clean up onreload=TrueModuleLoader.load_plugins(reload=True)— now unregisters previously-loaded descriptors and evicts cached modules fromsys.modulesbefore re-importing, so plugin upgrades no longer leak stale classesfunction_module()decorator — the generated_FunctionModuleclass is now injected into the calling module's namespace so itsentry_pointstring resolves at import time; this previously failed silently for any module defined via@function_module- Recon outcome taxonomy —
VALID_OUTCOMES_BY_FAMILY["reconnaissance"]extended withundetermined,partial_observation,auth_required,not_found,not_connectable,timeout,no_resultsto cover the actual envelopes recon modules were already emitting build_recon_execution(module_id=...)— new optional argument so recon executions can record their fully-qualified module ID (e.g.reconnaissance.campaign) instead of justreconnaissance- Session timestamps in UTC —
framework/sessions/store.pynow usesdatetime.now(timezone.utc).isoformat()via a single_now_iso_utc()helper; prevents naïve-local timestamps from drifting across hosts OptPath.validate()— returnsNonefor optional paths with no default instead of raisingOptionError, letting modules distinguish "path was given" from "path was not set"- Plugin discovery diagnostics —
ModuleRegistry.load_entry_points()now logs a warning with traceback when discovery fails instead of swallowing the exception silently
Added — Hardware¶
- Second RTL8761B dongle variant —
firmware.pynow detects both2357:0604(TP-Link UB500) and0bda:8771(generic Realtek) via a newRTL8761B_VID_PIDStuple;is_darkfirmware_loaded()and USB presence checks iterate both VID:PIDs - DarkFirmware watchdog thread safety —
DarkFirmwareWatchdognow uses athreading.Lockaround_reinit_count,_last_reinit, and a new_reinit_in_progressflag; prevents double-reinit races when a USB event fires during an in-flight reinit - HCIVSCSocket.recv_event() concurrency guard — raises
RuntimeErrorif called from an external thread while the LMP monitor loop is running on the same socket; two concurrent readers were causing event-frame corruption adapter_up,adapter_down,adapter_reset— now auto-resolvehci=Noneviaresolve_active_hci()and return a structured error dict if no adapter can be discovered, instead of NPE-ing downstream- L2CAP DoS socket binding —
_l2cap_raw_socket()now binds to the requested HCI's local address before connecting, so DoS traffic goes out the intended adapter in multi-dongle setups
Fixed — Hardware¶
- MAC spoofer fallback —
spoof_rtl8761b()now falls through from RAM patch to firmware-file patch when RAM patch reports success but the adapter still reports the wrong BDADDR (previously returnedverified=Falsewithsuccess=True, confusing the caller) - MAC spoofer file-write permission —
save_original_mac()now catchesPermissionErrorand emits a user-facing warning pointing at the root-owned state file, instead of raising into the caller - Firmware RAM-patch length check —
patch_bdaddr_ram()now requires exactly 4 bytes back fromvsc.read_memory()before attempting the file-patch fallback, instead of accepting any byte count ≥4 - Firmware file-read leak —
is_darkfirmware_loaded()now useswith open(...)for modalias probes (previously leaked file descriptors in the multi-adapter loop)
Fixed — Modules¶
assessment.fleet— UUID matching now canonicalizes short form,0xprefix, and full 128-bit Base UUID; previously only matched exact"0x111f"literal, so IVIs advertising"111f","0000111f-0000-1000-8000-00805f9b34fb", or uppercase variants were misclassified as generic headsetsassessment.vuln_scanner._check_blueborne— removed thebluetoothd --versionprobe (it reports the local stack version, not the target's); now relies on SDP-extractedBlueZ X.Ystrings only. Removes a class of false-positive BlueBorne findings on assessments run from a Kali attackerexploitation.encryption_downgrade—results["success"]now reflects whether at least one downgrade method actually worked; previously hardcodedTrueeven when the target rejected every methodexploitation.hijack— bails out of the attack chain when recon fails; was previously entering SSP/pairing with no target datareconnaissance.sdp.search_services_batch— UUID matching normalizes0x-prefixed hex and checks the fullclass_id_uuidslist against candidate service records; previously missed services whose class IDs used a different textual form than the filter UUIDreconnaissance.fingerprint—vendorderivation now usesmanufacturer(the actual output field) instead of a non-existentchipset.vendornested key, sohas_signalcorrectly flips on vendor-only fingerprintsreconnaissance.hci_capture— capture loop uses a clampedremainingtime slice and exits cleanly whenremaining <= 0, preventing a hang at the boundary ofdurationreconnaissance.campaign—_cleanup_tmp_artifact()unlinks the tempfile on all four capture-step failure paths (was leaking empty PCAPs into the session dir)reconnaissance.prerequisites— prerequisitemissinglist now filters by a newapplicableflag per check, so a BLE-only target no longer reports DarkFirmware/LMP prerequisites as "missing"post_exploitation.pbap—extract_allnow deduplicatesPBAP_PATH_ALIASESto 9 unique canonical paths instead of pulling the same phonebook 28 times (one for every alias key)post_exploitation.map_client— allself.sock.send()calls go through a_send()helper that raises if not connected; addsNoneguards on_setpath_root,_setpath_down,_recv_response; message bodyLENGTH:header now reflects byte length of the UTF-8 encoded body, not character countpost_exploitation.bluesnarfer— auto-discovers the AT RFCOMM channel via SDP (triesDial-up Networking,Serial Port,DUN,SPP) instead of raisingOptionErrorwhen CHANNEL was not supplied; also preserves original case on raw AT commands (was uppercasing vendor-specific payloads and breaking them)post_exploitation.a2dp—recordaction now usescapture_a2dp()(was calling an undefinedrecord_car_mic());bytesfield in result reflects actual on-disk size after capture;set_sink_volume()failure is now a warning instead of an uncaught exceptionpost_exploitation.hfp— codec-negotiation response now distinguishesERROR(rejected) from silent fallback;dial/answer/hangupsuccess flags reflect"ERROR" not in responserather than truthy-ness alone;silent_call()guards on socket being connected before issuing ATDfuzzing.engine— protocol names now run throughcanonical_protocol()which maps operator aliases (pbap,map,opp,att,smp,hfp,phonebook,sms) to canonical transport keys; mutator fallback generates fresh random bytes when the mutator returns an empty payload; strategy-unavailable path now updatesself.strategyso the envelope records what actually ran;CrashDBis closed in afinallyblock in_finalize()fuzzing.health_monitor— removed unused_check_zombie(protocol_responses)and replaced it with a per-protocol consecutive-failure tracker (_protocol_consecutive_fails); a target is declaredZOMBIEwhen ≥2 tracked protocols have ≥3 consecutive failures while L2CAP is still alive;update()now acceptsprotocol=to identify which protocol's response was observedfuzzing.campaign—CONTINUE=trueresumes an existingfuzz/campaign_state.json(falls back to a fresh campaign if the file is missing or corrupt); transport overrides are rebuilt from the resumed protocol list, not the CLIPROTOCOLSoptionfuzzing.cli_commands(replay) — delegates toCrashDB.reproduce_crash(transport)instead of duplicating the recv/timeout logic inline; multi-packet crashes now report packet count before replayfuzzing.state_inference— replaces non-deterministichash(indicator)withmd5(...)[:2]so AT state IDs are stable across Python interpreter runs (was breaking state-machine convergence on restart)fuzzing.lmp_state_tests— thekey_size_after_start_enctest now uses a fixed 16-byte hex seed instead ofos.urandom(16)so the test is reproduciblefuzzing.transport—LMPTransport._establish_acl()closes the probe socket in afinallyblock instead of relying on successful-path cleanuputils.bt_helpers.get_adapter_state— escapeshcibefore embedding it in thepgrepregex; previously vulnerable to weird adapter names injecting regex metacharacters
Fixed — CLI¶
blue-tap run <module>— missing / destructive / option-error conditions now exit with status1instead of falling through to status0; "see available modules" hint now points atblue-tap search(the real command) instead of the removedlist-modulesblue-tap run-playbook— no longer replaces the lowercase literaltargetinside command strings (broke any module that hadtargetas a legitimate substring in an argument); only the uppercaseTARGETsentinel and the explicit{target}placeholder are substitutedadapter up/down/reset/set-name— raiseClickExceptionon failure so exit status matches;inforaisesClickExceptioninstead of silently returning when the adapter doesn't exist_module_runner.resolve_target— validates theTARGETargument shape with a MAC regex; if the first positional token is a subcommand name (e.g.blue-tap recon sdp) the picker fires instead of treating the subcommand as an address
Fixed — Playbooks¶
full-assessment.yaml— updated to v2.6 CLI grammar:recon {target} rfcomminstead ofrecon rfcomm-scan {target},sniff -m lmpinstead oflmp-sniff,-ainstead of-iivi-attack.yaml— exploit commands now use theexploit {target} <sub>form;-ainstead of-ilmp-fuzzing.yaml— removed the deprecated standalonefuzz lmpstep; campaign uses the-p <proto>repeatable flag (matches current CLI) andcoverage_guided(underscore form)passive-recon.yaml,quick-recon.yaml—scan classic/blereplaced withdiscover classic/ble; recon subcommands reordered torecon {target} <sub>form
Fixed — Tests¶
test_cli_facades—vulnscan/dos"requires target" tests replaced with "interactive picker when no target" to reflect the new optional-target behaviortest_userflow_dos,test_userflow_exploitation_bias,test_userflow_exploitation_knob— expect exit code1for unknown modules and blocked destructive runs (previously accepted0due to the silent-failure bug)
Fixed — Docs¶
- CLI reference — rewritten to show
[TARGET]as optional acrossvulnscan,recon,exploit,extract,dos; options table updated (-a, --hcireplaces the old-a, --adapter/-i, --adapterforms); added interactive-picker callout - Navigation — mkdocs sidebar renames "Reference" to "Technical Reference"
- Guide pages —
reconnaissance,vulnerability-assessment,denial-of-service,fuzzing,post-exploitation,sessions-and-reporting,automation,exploitationupdated to match the v2.6 command grammar;docs/developer/architecture.mdexpanded with framework-layer details - README and target/README — all example invocations updated to
discover/recon {target} <sub>/-agrammar; fuzz examples use-prepeatable andfuzz crashes list
Build¶
- Version bumped to
2.6.1 pyproject.toml— removed strayasyncio_default_fixture_loop_scope(no async tests in the suite).gitignore— addssite/(mkdocs build),fuzz/(corpus + crashes.db),map_dump/,x/,hci_capture.pcap,tmp_dos_review.*to avoid committing operator artifacts
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)¶
Moduleabstract base class — definesrun(ctx: RunContext) → RunEnvelope;__init_subclass__hook auto-registers every subclass in the globalModuleRegistrywithout a manualModuleDescriptorblockRunContextdataclass — single typed argument toModule.run():target,adapter,options,session_id,dry_run; replaces ad-hoc kwargs scattered across entry points- Typed option descriptors —
OptAddress,OptPort,OptBool,OptInt,OptStr,OptChoice,OptFlag; each validates its value at resolution time and raisesValueErroron invalid input OptionsContainer— ordered dict ofOptioninstances; resolves CLI args + env-var overrides at invocation time beforeModule.run()is calledModuleInvoker— resolvesmodule_idfrom the registry, buildsRunContextfrom CLI params, callsModule.run(), and streamsCliEventsto the operator consoleModuleLoader— importsModuleclasses fromentry_pointstrings (package.module:Class); caches loaded classes to avoid repeated importsautoload.py— imports all family__init__.pyfiles so subclass auto-registration fires before the registry is queried for the first time
Added — Phase-Verb CLI Architecture (interfaces/cli)¶
discover—classic / ble / allsub-verbs wrappingDiscoveryScannerviaModuleInvoker; replaces the flatscancommand with an explicit workflow steprecon—sdp / rfcomm / gatt / hci-capture / sniffer / lmp-sniffsub-verbs consolidating the formerrecon+capturefamilies into one phase commandexploit— sub-commands:bias,bluffs,knob,ctkd,enc-downgrade,ssp-downgrade,hijack,pin-brute; grouped under Crypto/Key Attacks and Full Chainextract— sub-commands:contacts,messages,audio,media,push,snarf,at; covers all post-exploitation data paths in one placedos—BLE / Classic / Raw-ACLsub-commands forwarded to the DoS runner with protocol groupingfuzz—campaign+ 9 protocol sub-commands (sdp-deep,l2cap-sig,rfcomm-raw,ble-att,ble-smp,bnep,obex,at-deep,lmp) pluscrashes / minimize / replay / corpusanalysis commandsdoctor— hardware diagnostics: adapter list, DarkFirmware probe, USB dongle detection by VID:PID, HCI sanity checkauto— orchestrateddiscover → recon → vulnscan → exploitchain with--dry-runsupport and per-phase skip/abort handlingfleet— multi-target orchestration; per-target error isolation so one failure no longer aborts the full runrunner/plugins— genericblue-tap run <module_id>entry point;pluginslists registered modules and shows descriptor info_module_runner.py— single shared helper for all family CLIs: resolves module, buildsRunContext, streams events, writes session envelope
Added — Outcome Validation Taxonomy¶
VALID_OUTCOMES_BY_FAMILY(framework/contracts/result_schema.py) — per-familyfrozensetof allowedmodule_outcomevalues;make_execution()raisesValueErroron 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 familyModuleDescriptor.references—tuple[str, ...]of external references (CVEs, RFCs, specs) associated with the module; surfaced inblue-tap plugins info <module>outputModuleRegistry.try_get(module_id)— returnsModuleDescriptor | None; avoidsKeyErrorwhen 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_HCIenv var → RTL8761B USB VID:PID probe → first UP adapter fromhciconfig→"hci0"as last resort- Process-lifetime cache — result stored in
_ACTIVE_HCI_CACHEafter 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 theModuleprotocol; subclasses declarecheck_fnandmodule_idwithout duplicating envelope constructionVulnScanModule(modules/assessment/vulnscan_module.py) — thinModulesubclass delegating tovuln_scanner.run()and wrapping the result in a canonicalRunEnvelopeDiscoveryScanner(modules/discovery/scanner.py) —Moduleclass for Classic/BLE/combined scans; registered as"discovery.scanner"via auto-registration_e0.py(modules/exploitation/) — E0 encryption-mode downgrade probe helper shared byknob.pyandbias.pyDoSCheckModule(modules/exploitation/dos/base.py) — shared base for BLE / Classic / Raw-ACL DoS checks; handles timing evidence, recovery probe wiring, and envelope constructionFuzzCampaign(modules/fuzzing/campaign.py) —Modulewrapping the full engine lifecycle: seed corpus, run, collect crashes, finalizeRunEnvelope; supports campaign resume and crash exportReconCampaign(modules/reconnaissance/campaign.py) —Modulewrapping the multi-collector recon pipeline into a singleRunEnvelope; registered as"reconnaissance.campaign"
Added — Documentation Site (MkDocs)¶
mkdocs.yml— Material theme configuration with structured nav tree, light/dark mode, code block highlightsdocs/getting-started/— installation, hardware setup (single/dual adapter), quick start, IVI simulatordocs/guide/— per-phase operator guides: discovery, recon, vulnerability assessment, exploitation, DoS, fuzzing, post-exploitation, sessions and reporting, automationdocs/workflows/— end-to-end scenario walkthroughs: full pentest, quick assessment, fuzzing campaign, encryption downgrade, audio eavesdropping, custom playbooksdocs/developer/— architecture overview, module system, writing a module, report adapters, plugin entry-pointsdocs/reference/— hardware compatibility matrix, platform notes, troubleshooting referencedocs/cve/— CVE detection matrix, DoS CVE matrix, expansion roadmap; CVE specs moved from flatcve-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 groupstest_outcome_validator.py—VALID_OUTCOMES_BY_FAMILYenforcement: valid outcomes pass, invalid ones raiseValueErrortest_module_runtime_e2e.py—Module.run()→RunEnveloperound-trip for one module per family; validates schema, run_id, and outcome fieldstest_hci_vsc_concurrency.py—HciVscClientconcurrent command safety under multi-thread accesstest_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;DiscoveryReportAdapteradditionally 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 viaBT_TAP_SESSIONS_DIR - Module
__init__.pyfiles — all family__init__.pydropped manualModuleDescriptorblocks;__init_subclass__auto-registration handles all modules _check_darkfirmware_available()— identifies RTL8761B by USB VID:PID and readsBT_TAP_DARKFIRMWARE_HCIenv 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 modules —
resolve_active_hci()used in PBAP/MAP/OPP/A2DP/AVRCP/HFP paths set_verbosity()— propagates to root logger so-v/-vvflags apply consistently across all modulesrun_cmd()— explicittimeout=on all subprocess calls; stderr captured to avoid dangling file descriptorsparse_sdp_records()— handles malformed XML with a logged warning instead of raisingParseErrorconfirm_destructive()— acceptsdry_runkwarg; 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()— callsresolve_active_hci()instead of defaulting to"hci0"- Report generator — accepts explicit session path; no module-specific logic remains in generator
output.py— addedchannel_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_identitycallers —bias.py/hijack.pycheckedif not clone_device_identity(...)which evaluatedFalseafter bool→dict migration; fixed toresult.get("success", False)- Recon capture-stop —
HCICapture.stop()returns a path string; two copy-paste blocks called.get("success")on it raisingAttributeError - Recon lmp-sniff / nrf-sniff —
artifactsvariable referenced inbuild_recon_result()but never initialized;NameErroron every execution - L2CAP checks — two
_check_ecred_*functions had unreachablereturn []afterfinallyblocks; removed dead code preventing results from being returned btmgmt public-addrerrors — 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
finallyblock during reconnection - RAM BDADDR patching — corrected controller memory write sequence for RTL8761B
Removed¶
- Deprecated top-level packages —
blue_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 builder —
framework/envelopes/auto.py; auto-pentest uses phase-verb CLI with per-phase family envelopes - Auto report adapter —
framework/reporting/adapters/auto.pyremoved alongside the auto envelope AutoPentestmodule —modules/exploitation/auto.pyretired; superseded byblue-tap autoCLI command- Flat family CLI files —
interfaces/cli/assessment.py,discovery.py,exploitation.py,fuzzing.py,post_exploitation.py,reconnaissance.pyreplaced by phase-verb commands - Retired test files —
test_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
2.5.0 - 2026-04-11¶
Summary¶
Blue-Tap 2.5.0 is the Standardized Framework release. Every module now produces structured RunEnvelope output with typed ExecutionRecord entries, evidence blocks, and artifact references. The report pipeline has been rewritten around module-owned ReportAdapter classes. The CLI emits structured lifecycle events throughout all operations. Session logging validates envelope shape. This release lays the groundwork for the upcoming modular framework architecture (Metasploit-style module families, registry, and plugin system).
Added — Standardized Result Schema¶
Core Framework Contracts¶
RunEnvelopeschema (core/result_schema.py) — canonical output container for every module invocation with required fields:schema,schema_version,module,run_id,target,adapter,started_at/completed_at,operator_context,summary,executions,artifacts,module_dataExecutionRecordmodel — normalized unit of work within a run with two-layer status taxonomy:execution_status(lifecycle: completed/failed/error/skipped/timeout) andmodule_outcome(semantic: confirmed/inconclusive/recovered/observed/etc.)EvidenceRecordmodel — structured observation container withsummary,confidence,observations,packets,state_changes,module_evidence, andcapability_limitationsArtifactRefmodel — typed pointer to saved files (pcap, log, HTML, JSON) withartifact_id,kind,label,path,execution_idvalidate_run_envelope()— schema shape validator for envelope integritylooks_like_run_envelope()— fast heuristic check for session logging- Envelope helper functions —
build_run_envelope(),make_execution(),make_evidence(),make_artifact(),envelope_executions(),envelope_module_data()
Structured CLI Event System¶
emit_cli_event()(core/cli_events.py) — structured event emitter with required fields:event_type,module,run_id,target,adapter,timestamp,message,details- 13 defined event types —
run_started,phase_started,execution_started,execution_result,execution_skipped,pairing_required,recovery_wait_started,recovery_wait_progress,recovery_wait_finished,artifact_saved,run_completed,run_aborted,run_error - Every CLI command now emits lifecycle events — operators always know what started, what's running, and when it's done
Report Adapter Architecture¶
ReportAdapterABC (core/report_contract.py) — module-owned report interface withaccepts(),ingest(),build_sections(),build_json_section()SectionModel/SectionBlockdata models — typed report section containers replacing raw HTML string generation- 12 report adapters — one per module type:
DiscoveryReportAdapter— scan result tables with device properties, risk indicatorsVulnscanReportAdapter— CVE/non-CVE finding cards with evidence, execution logsAttackReportAdapter— attack outcome cards with phase tracking, evidenceAutoReportAdapter— 9-phase pentest summary with per-phase execution recordsDataReportAdapter— PBAP/MAP/OPP/AT extraction summaries with artifact linksAudioReportAdapter— HFP/A2DP/AVRCP session summaries with capture artifactsDosReportAdapter— DoS check results with recovery probe outcomesFirmwareReportAdapter— DarkFirmware operations with KNOB detection cardsFuzzReportAdapter— per-protocol campaign runs with crash details and corpus statsLmpCaptureReportAdapter— LMP sniff session summariesReconReportAdapter— reconnaissance campaign results with correlation analysisSpoofReportAdapter— spoof operations with before/after MAC evidence- Block renderer system (
report/renderers/) —BlockRendererRegistrywith typed block renderers for tables, paragraphs, text, and custom block types render_sections()— convertsSectionModellists into HTML via block renderers
Report Generator Refactor¶
- Adapter-driven report generation —
generator.pynow orchestrates viaREPORT_ADAPTERSregistry: dispatches envelopes to matching adapters, collectsSectionModeloutput, renders HTML/JSON through shared renderers - Generator no longer contains module-specific logic — all CVE interpretation, evidence formatting, and finding classification moved to adapters
- Unified ingestion pipeline — both HTML and JSON reports consume the same adapter output, preventing report format divergence
Added — Module Envelope Builders¶
Each module family has a dedicated envelope builder in core/:
attack_framework.py—build_attack_result()for exploitation modules (BIAS, KNOB, BLUFFS, hijack, SSP/encryption downgrade, CTKD)audio_framework.py—build_audio_result()for HFP/A2DP/AVRCP sessionsauto_framework.py—build_auto_result()withbuild_auto_phase_execution()for 9-phase auto pentestdata_framework.py—build_data_result()for PBAP/MAP/OPP/AT data extractionfirmware_framework.py—build_firmware_status_result(),build_firmware_dump_result(),build_connection_inspect_result(),build_firmware_operation_result()for DarkFirmware operationsfuzz_framework.py—build_fuzz_result()for fuzzing campaign runsrecon_framework.py—build_recon_result()for reconnaissance operationsscan_framework.py—build_scan_result()for discovery scansspoof_framework.py—build_spoof_result()with MAC before/after evidence, method verification
Added — Module Standardization¶
Discovery & Scan¶
- Scan commands produce
RunEnvelope—scan classic,scan ble,scan combined,scan all,scan inquiry,scan watchall log full envelopes to session - Campaign correlation output wrapped in scan envelopes with correlation evidence
- Fleet scan logs actual scan envelope instead of raw device list
Reconnaissance¶
- All 13 recon commands produce envelopes via
build_recon_result()— auto, sdp, gatt, fingerprint, ssp, rfcomm, l2cap, capture, capture-analyze, pairing-mode, ble-sniff, lmp-capture, lmp-intercept, combined-sniff, crackle, extract-keys, wireshark-keys - Recon CLI helpers —
_recon_cli_context(),_recon_emit(),_recon_start(),_recon_result(),_recon_skip()for consistent event emission - Capture analysis wrapped in recon correlation envelopes
- HCI capture — improved parser, stale PID detection, capture analysis integration
Vulnerability Assessment¶
- Vulnscan produces structured envelope (
blue_tap.vulnscan.result) with scanner metadata, per-check execution logs, finding summaries, and evidence - CVE check execution tracking — each check records execution_status + module_outcome + evidence
- Fleet assessment builds reports from standardized scan and vuln envelopes
Exploitation¶
- BIAS — per-phase
ExecutionRecordentries (spoof, connect, inject, verify) with structured evidence - KNOB — probe and brute-force phases produce typed execution records with key-size evidence
- BLUFFS — per-variant (A1 LSC downgrade, A3 SC→LSC) execution records with DarkFirmware capability reporting
- SSP downgrade — execution tracking across SSP probe, legacy force, PIN brute phases with lockout evidence
- Hijack — 4-phase tracking (spoof, connect, monitor, exploit) with per-phase success/failure evidence
- CTKD — probe result standardization with MAC normalization and cross-transport key evidence
- Encryption downgrade — 3 method variants (disable, toggle, SC-reject) produce execution records with LMP evidence
- DoS — all checks wrapped in
RunEnvelopewith recovery probe outcomes, timing evidence, and severity
Post-Exploitation¶
- PBAP/MAP — structured data envelopes with extraction counts, artifact refs, parsed entry metadata
- HFP — all 8 subcommands (call, answer, hangup, volume, dtmf, sco, codec, diagnostics) log audio envelopes
- A2DP — capture/record/eavesdrop/play/stream/loopback produce audio envelopes with duration, codec, sample rate evidence
- AVRCP — all 10 subcommands (play, pause, next, prev, volume, info, shuffle, repeat, monitor, flood) log structured envelopes
- AT commands — extraction responses parsed into structured device artifacts with field-level evidence
- OPP — transfer diagnostics across dbus and raw fallback paths with artifact tracking
- Bluesnarfer — extraction operations produce data envelopes
Fuzzing¶
- Per-protocol
RunEnvelope— each protocol fuzz run produces its own envelope with crash/corpus/timing evidence - Run IDs — every fuzz campaign gets a stable run_id carried through all events and artifacts
- Crash lifecycle events —
execution_resultemitted for each crash with severity and reproduction steps - Utility commands (list-crashes, replay, import-pcap) emit structured events
- Legacy fuzz commands removed — all fuzzing routes through the standardized engine
Adapter & Firmware¶
- Adapter commands (up, down, reset, set-name, set-class) log general envelopes to session
- Firmware status/install/init/dump emit lifecycle events and log envelopes
- Connection inspect builds envelope with per-slot KNOB detection findings
- Spoof commands produce spoof envelopes with before/after MAC proof and method verification
Auto Pentest¶
- 9-phase
RunEnvelopewith per-phaseExecutionRecordentries (discover, fingerprint, recon, vulnscan, pair, exploit, fuzz, dos, report) - Phase skip tracking — skipped phases produce execution records with skip reason evidence
- Summary counters — per-phase success/fail/skip counts in envelope summary
Playbook / Run Mode¶
- Playbook execution produces
RunEnvelopewith per-step execution records - Lifecycle events emitted per playbook step (run_started, execution_started, execution_result, run_completed)
Added — Shared OBEX Client¶
core/obex_client.py— unified dbus-fast OBEX client for PBAP, MAP, and OPP with shared session management, error handling, and transfer trackingPBAPSession— PBAP phonebook access with folder navigation, vCard pull, property filteringMAPSession— MAP message access with folder listing, message pull, notification registrationOPPSession— OPP file push with progress tracking and transfer validation- Shared OBEX error hierarchy —
ObexError, transport-level vs protocol-level error distinction
Added — DoS Expansion¶
- Modular CVE-backed DoS probes for BLE, AVRCP, and AVDTP paths
- Recovery probe validation — real ATT request validation instead of simple ping
- DoS guide (
docs/dos-guide.md) — workflow documentation - DoS CVE matrix (
docs/dos-cve-matrix.md) — coverage mapping - Structured DoS metadata in report generation
Added — Profile Environment Doctor¶
env-doctorcommand — prerequisite checker for BlueZ, OBEX, PulseAudio, and audio subsystem readiness- OBEX capability detection — validates dbus-fast OBEX transport availability
- Audio prerequisites — PulseAudio module availability, Bluetooth source/sink detection
Added — Framework Architecture Plan¶
- Modular framework architecture plan (
thoughts/plans/2026-04-11-blue-tap-framework-architecture-plan.md) — 13-phase migration plan to Metasploit-style module families with registry, contracts, and plugin system - Framework architecture rules (
.claude/rules/blue-tap-architecture.md) — enforced development rules for all agents: import paths, family classification, registry requirements, schema rules, migration protocol
Added — Testing¶
- 36 new envelope tests across 3 test files:
test_spoof_envelope.py(11 tests) — envelope shape, validation, success/failure/restore outcomes, MAC evidence, adapter round-triptest_firmware_envelope.py(17 tests) — status/dump/inspect/operation builders, KNOB detection, partial hooks, artifact refstest_auto_envelope.py(8 tests) — per-phase executions, skip/fail evidence, summary counters, validation- Fuzz envelope tests — l2cap-sig transport map, transport overrides, raw frame format, connect failure finalization
- Report adapter regression tests — standardized rendering validation
- Attack envelope regression tests — BIAS/KNOB/BLUFFS/hijack/SSP/CTKD/encryption downgrade envelope validation
- Discovery regression tests — scan envelope shape validation
- Media/data regression tests — HFP/A2DP/AVRCP/PBAP/MAP envelope validation
- PBAP/MAP/media regression fixtures — structured test data
Changed¶
- Report generator completely refactored — adapter-driven architecture replaces monolithic parsing; generator orchestrates layout and dispatch only
- Session logging now validates envelope shape — non-envelope data logged at debug level for audit traceability
clone_device_identity()return type changed frombooltodictwithsuccess,method,original_mac,target_mac,verified,errorfieldsspoof_address()/bdaddr()/spooftooph()/btmgmt()/rtl8761b()return types changed fromboolto structured dicts with per-operation evidencerestore_original_mac()return type changed fromboolto dict withrestored_macandmethod- Adapter input validation —
device_classhex format/range validation (0x000000-0xFFFFFF),device_namelength validation (max 248 bytes UTF-8) - DarkFirmware detection — failures logged instead of silenced; adapter power recovery when stuck DOWN after SSP toggle
- DarkFirmware CLI bootstrap — smart skip for non-hardware commands (scan/report/session); partial hook status downgraded from info to warning
- Fuzz engine —
transport_overridesparameter for per-protocol channel/hci_dev override; extracted_finalize_single_run()for consistent envelope construction on error paths - Crash replay — removed
_StubTransportfallback, addedRawACLTransportsupport - L2CAP-sig fuzzing — rewired to raw ACL via DarkFirmware instead of standard L2CAP socket
- AT deep fuzzing — context-aware injection corpus with RFCOMM surface autodiscovery, batch runner across hfp/phonebook/sms/injection channels
- Transport hardening — DarkFirmware presence check in LMP and RawACL
connect()returns False instead of crashing - DoS probe timeouts — hardened timeout handling for unresponsive targets
- Attack cleanup — improved cleanup paths in attack modules and recon transport retries
- Fleet reports — built from standardized scan and vuln envelopes instead of ad hoc data
- Demo report data — standardized around run envelopes
Fixed¶
clone_device_identitycallers —bias.pyandhijack.pyusedif not clone_device_identity(...)which always evaluated False after the bool→dict migration (non-empty dicts are truthy); fixed to checkresult.get("success", False)- Recon capture-stop —
HCICapture.stop()returns a string path, not a dict; two stray copy-paste blocks calledresult.get("success")on the string, raisingAttributeError - Recon lmp-sniff —
artifactsvariable referenced inbuild_recon_result()but never initialized, causingNameErroron every execution - Recon nrf-sniff — same
NameError—artifactsundefined beforebuild_recon_result() - RAM BDADDR patching — corrected controller spoofing memory write for RTL8761B
- HFP reconnect socket leak — fixed socket resource leak in HFP reconnection path
- DoS result/report normalization — aligned DoS result keys with report adapter expectations
- Report merge conflict marker — removed leftover
<<<<<<< HEADmarker fromgenerator.py - btmgmt public-addr errors —
btmgmt public-addrcall errors now handled safely instead of crashing
Removed¶
- Legacy fuzz commands — all standalone fuzz protocol commands removed; all fuzzing routes through the unified engine
_StubTransportfallback in crash replay — replaced with proper transport selection
2.3.2 - 2026-04-09¶
Added — Structured Vulnerability Scanner Framework¶
This release turns vulnscan into the single end-to-end vulnerability assessment entry point, adds modular OTA CVE detection coverage, and extends the report pipeline to preserve per-check execution evidence for both CVE and non-CVE checks.
CVE Detection Framework¶
- Shared CVE result framework (
attack/cve_framework.py) — centralized finding builder, status constants, per-check summary helpers, structuredCveCheck/CveSectionmetadata, and vulnscan result envelope generation - Structured vulnscan envelope —
blue_tap.vulnscan.resultnow carries scanner metadata, finding summaries, CVE execution logs, and non-CVE execution logs for report generation and downstream parsing - Per-check execution logging — scanner records primary status, finding count, status counts, and evidence samples for each check instead of only emitting a flat findings list
Modular OTA CVE Probe Coverage¶
- Airoha RACE checks (
attack/cve_checks_airoha.py) — OTA detection for: CVE-2025-20700unauthenticated RACE over GATTCVE-2025-20701unauthenticated RACE over BR/EDRCVE-2025-20702link-key disclosure over confirmed RACE transport- AVRCP checks (
attack/cve_checks_avrcp.py) — OTA behavioral probes for: CVE-2021-0507CVE-2022-39176- BNEP checks (
attack/cve_checks_bnep.py) — OTA probes for: CVE-2017-0783CVE-2017-13258CVE-2017-13260CVE-2017-13261CVE-2017-13262- BLE SMP checks (
attack/cve_checks_ble_smp.py) — pairing-aware OTA checks for: CVE-2024-34722CVE-2018-9365- GATT / ATT checks (
attack/cve_checks_gatt.py) — OTA differential checks for: CVE-2022-0204CVE-2023-35681- HID / HOGP checks (
attack/cve_checks_hid.py) — OTA checks for: CVE-2020-0556CVE-2023-45866- L2CAP checks (
attack/cve_checks_l2cap.py) — OTA differential checks for: CVE-2019-3459CVE-2018-9359CVE-2018-9360CVE-2018-9361CVE-2020-12352CVE-2022-42896CVE-2022-20345CVE-2022-42895CVE-2026-23395- BR/EDR pairing checks (
attack/cve_checks_pairing.py) — pairing-driven probes for: CVE-2020-26558CVE-2022-25837CVE-2019-2225- Raw ACL check (
attack/cve_checks_raw_acl.py) — DarkFirmware-backed BlueFrag boundary probe forCVE-2020-0022 - SDP continuation check (
attack/cve_checks_sdp.py) — OTA continuation-state replay probe forCVE-2017-0785
Non-CVE Modular Scanner Coverage¶
- RFCOMM / OBEX non-CVE module (
attack/non_cve_checks_rfcomm.py) with structured checks for: - sensitive RFCOMM profile reachability
- hidden RFCOMM channels
- low-security RFCOMM acceptance
- OBEX authorization posture
- automotive diagnostics and serial responder detection
- BLE non-CVE module (
attack/non_cve_checks_ble.py) with structured checks for: - writable GATT surface classification
- sensitive writable BLE control/DFU/debug surfaces
- EATT capability posture
- pairing-method posture with IO-capability context
- Security-posture module (
attack/non_cve_checks_posture.py) with structured checks for: - legacy PIN lockout / throttling behavior
- device-class posture and corroboration
- LMP feature posture and prerequisites
Reporting and Documentation¶
- Dedicated vulnscan matrix (
docs/vulnscan-cve-matrix.md) listing the CVEs actually checked byblue-tap vulnscanplus the modular non-CVE checks that are part of the same scan path - HTML report enhancement — report generator now renders Non-CVE and CVE check execution tables with richer finding metadata
- JSON report enhancement — exported vulnerability report data now preserves structured vulnscan runs
Changed¶
vulnscancommand model — runs the full scanner in one invocation;--activeno longer required- BIAS input handling —
--phoneremains available as optional paired-phone context - Non-CVE finding semantics — exposure and posture checks now distinguish reachable transport vs actual unauthenticated access
- Writable GATT analysis — separates generic writable characteristics from sensitive writable surfaces
- EATT reporting — treated as protocol capability / posture instead of implicit weakness
- PIN lockout analysis — stronger retry sampling and timing interpretation
- Device class and LMP feature reporting — serve as scanner posture/context signals
Fixed¶
- Airoha false positives — GATT RACE detection requires valid unauthenticated RACE response
- Airoha RFCOMM overclaim — BR/EDR RACE detection no longer guesses RFCOMM channel 1
- Airoha link-key confirmation — chains from confirmed RACE transport
- L2CAP patched-response handling —
CVE-2022-20345accepts documented patched reject outcomes - L2CAP duplicate-identifier logic —
CVE-2026-23395evaluates second duplicate response - LE credit-based response parsing — corrected in
CVE-2022-42896andCVE-2023-35681 - Off-by-one L2CAP response guard — requires full 12-byte buffer
- Pairing CVE overclaims —
CVE-2019-2225andCVE-2022-25837no longer overclaim from weak evidence - BlueFrag confirmation heuristic — stays conservative unless boundary probe produces defensible evidence
- Android GATT CVE overclaims — removed incomplete coverage for
CVE-2023-40129,CVE-2024-0039,CVE-2024-49748 - Parallel active-probe nondeterminism — transport-mutating checks executed in deterministic sequence
- Report/rendering mismatch — understands structured vulnscan envelope instead of assuming legacy flat findings
Removed¶
- Top-level
assesscommand —vulnscanis now the single CLI entry point vulnscan --activepublic workflow — no longer advertised- Stale assess-based playbooks and docs
2.3.1 - 2026-04-08¶
Added — Deep DarkFirmware Integration¶
This release completes the DarkFirmware integration with full bidirectional LMP traffic parsing, connection table inspection, in-flight packet modification, and new attack modules.
DarkFirmware HCI Infrastructure¶
- Bidirectional traffic parsing — TXXX (outgoing LMP), ACLX (outgoing ACL), RXLC (incoming LC) marker parsers added to HCI VSC socket alongside existing AAAA (incoming LMP)
- Complete LMP opcode tables — 61 standard + 22 extended opcodes per BT Core Spec v5.4 with human-readable decode helper
- In-flight LMP modification —
set_mod_mode()/clear_mod_mode()for Hook 2 modes: passthrough, modify, drop, opcode-drop, persistent-modify, auto-respond - Raw ACL injection —
send_raw_acl()bypasses BlueZ L2CAP stack for below-stack packet injection - Oversize LMP PDUs — TX max raised from 17 to 28 bytes for BrakTooth-style oversize packet testing
- read_memory quirk fix — RTL8761B returns 4 bytes only with size=0x20 (not size=4)
Hook Management & Connection Inspection¶
- Hook initialization —
init_hooks()writes Hook 3/4 backup pointers to RAM and verifies all 4 hooks active - ConnectionInspector — Read/write controller RAM for encryption state, key material, auth flags, Secure Connections flag across all 12 connection slots
- DarkFirmwareWatchdog — Dual detection (udevadm monitor + periodic health check) with 5s debounce and 3s settle for multi-day fuzzing
- Firmware-level detection — Replaced MAC-based DarkFirmware detection with hook backup probe + LMP TX echo verification
- CONNECTION_SLOT_SIZE fix — Corrected from 500 to 0x2B8 (696 bytes) per reverse engineering findings
Below-HCI Attack Modules¶
- CTKD attack (
attack/ctkd.py) — CVE-2020-15802 cross-transport key derivation probe: snapshots key material before/after Classic attack, detects shared keys across slots - KNOB RAM verification — ConnectionInspector confirms actual key_size in controller memory after KNOB negotiation injection
- 20 LMP state confusion tests — BrakTooth-style test cases as vulnerability scanner seeds
- Raw L2CAP builders (
fuzz/protocols/l2cap_raw.py) — Frame builders + 15 malformed fuzz tests for below-stack injection
Fuzzing Transports¶
- LMPTransport.send_and_collect() — Send packet, wait for responses from rx_queue and lmp_log_buffer
- LMPTransport.check_alive() — HCI Read BD Addr probe to detect dongle crash during fuzzing
- RawACLTransport — Full transport class routing send() through send_raw_acl(), ACL handle resolution, ACLX/RXLC event monitoring
CLI Integration¶
- Root privilege check on startup (allows --help/--version/demo without root)
- Startup hardware detection — Probe dongle, check DarkFirmware, init hooks, start watchdog (non-blocking)
adapter firmware-init— Manual hook initialization commandadapter connection-inspect— Dump connection table from controller RAMctkdcommand — Cross-transport key derivation attack with probe and monitor modes
Fixed¶
- OBEX PUT opcode —
OBEX_PUTwas 0x82 (PUT-Final) instead of 0x02 (PUT), breaking multi-part OPP file transfers - _read_bytes() alignment bug — Unaligned addresses truncated reads; rewrote to track actual bytes extracted per iteration
Changed¶
- README restructured — Split 1876-line README into focused docs: features, usage guide, troubleshooting, IVI simulator. README retains purpose, architecture, quick start with hyperlinks to detailed docs.
- Memory read/write logging — Changed from
info()tologger.debug()to reduce noise during fuzzing
2.3.0 - 2026-04-05¶
Added — DarkFirmware Below-HCI Attack Platform¶
This release extends Blue-Tap below the HCI boundary with a custom firmware platform for RTL8761B (TP-Link UB500). The DarkFirmware integration enables direct LMP packet injection and monitoring — capabilities that no standard BlueZ tool provides.
Key breakthrough: Live RAM patching of the RTL8761B controller — BDADDR spoofing and 17-byte LMP PDU injection/capture work without adapter reset, by writing directly to the running firmware's SRAM via HCI VSC 0xFC61/0xFC62. The original DarkFirmware research supported basic injection; Blue-Tap extends this with live RAM patching, full 17-byte LMP PDU support (not just 10-byte), and structured LMP log parsing.
DarkFirmware Core (4 new modules, 1,772 lines)¶
core/hci_vsc.py(584 lines) — Raw HCI socket interface for vendor-specific commands: LMP injection (VSC 0xFE22), controller memory read (0xFC61), memory write (0xFC62), background LMP monitor thread with structured 56-byte log parsingcore/firmware.py(788 lines) — DarkFirmware lifecycle management: RTL8761B detection, firmware install/restore with automatic backup, live RAM BDADDR patching (no reset), firmware status verification via memory read, controller memory dump, USB reset- Runtime detection — CLI auto-detects RTL8761B and DarkFirmware at startup, shows green "active" status or warning with install command
- Firmware CLI commands —
adapter firmware-status,firmware-install,firmware-spoof,firmware-set,firmware-dump,connections
Below-HCI Attacks (2 new modules, 771 lines)¶
- BLUFFS attack (
attack/bluffs.py, 408 lines) — CVE-2023-24023 session key derivation downgrade with probe/A1 (LSC key-downgrade)/A3 (SC→LSC downgrade) variants via DarkFirmware LMP injection - Encryption downgrade (
attack/encryption_downgrade.py, 363 lines) — 3 attack methods beyond KNOB:LMP_ENCRYPTION_MODE_REQ(mode=0)to disable encryption, stop/start toggle for weaker renegotiation, SC PDU rejection to force Legacy SC
LMP Protocol Support¶
- LMP protocol builder (
fuzz/protocols/lmp.py, 2,020 lines) — Full LMP PDU construction for 30+ opcodes - LMP fuzzing — 12th protocol added to campaign engine via HCI VSC injection
- LMP sniffing —
recon lmp-sniff,lmp-monitor,combined-sniff - LMP DoS —
dos lmpwith configurable method, count, and delay
Other New Features¶
- TargetedStrategy wired into engine —
--strategy targetednow works in fuzz campaigns - Session adapter tracking —
set_adapter()auto-records which HCI adapter is used - Protocol DoS expansion — LMP-level DoS attacks via DarkFirmware
- BIAS LMP injection mode — BIAS attack can now use DarkFirmware for LMP-level role-switch manipulation
- KNOB LMP negotiation — KNOB attack uses DarkFirmware for direct LMP key-size manipulation
- Sniffer rewrite — Replaced USRP B210 SDR integration with DarkFirmware LMP capture
- Playbooks module —
blue_tap/playbooks/for reusable assessment sequences - UI dashboard —
blue_tap/ui/dashboard.pyfor live attack monitoring
Improved¶
- README overhauled — BLUFFS, encryption downgrade, DarkFirmware sections; RTL8761B as primary adapter
- Hardware recommendations — RTL8761B (TP-Link UB500) promoted to primary adapter
- Fuzz engine — Baseline learning with explicit
recv_timeout=5.0; field weight tracker logs exceptions - SDP parser — PSM channel fallback returns
0(int) for type consistency - CLI command grouping — Added bluffs, encryption-downgrade to Rich-Click groups
Fixed¶
- fleet_assess NameError —
risk_colorundefined whenresultsis empty - _StubCorpus missing
get_all_seeds()— Baseline learning silently skipped - Silent field tracker exceptions —
except: passnow logs warnings - Baseline recv timeout — Passes explicit timeout instead of relying on transport default
Removed¶
- USRP B210 SDR integration — Replaced by DarkFirmware LMP capture
- CSR8510 from recommended hardware — Superseded by RTL8761B
- All mock-based test files (26 files, 21K lines) — Replaced with real hardware validation workflows
2.2.0 - 2026-04-04¶
Added¶
- Active BIAS vulnerability probe in vulnscan with
--active --phoneflags - Parallel vulnerability analysis — ThreadPoolExecutor cuts scan time ~60%
- KNOB real brute-force — XOR decryption against captured ACL data with L2CAP header validation
- ACL traffic capture for KNOB — 60-second capture windows via hcidump
- IVI confidence scoring in fingerprint — normalized 0.0-1.0 confidence float
- Codec auto-detection in HFP — detects CVSD (8kHz) vs mSBC (16kHz)
- Sample rate auto-detection in A2DP — queries PulseAudio source info
- PulseAudio loopback tracking — module ID stored for reliable cleanup
- Session logging added to all CLI commands
- 2,109 unit tests across 13 new test files (66% line coverage)
Improved¶
- Scanner, SDP, GATT, RFCOMM/L2CAP, HCI Capture, Fingerprint, Vuln Scanner, Hijack, SSP Downgrade, BIAS, HFP, A2DP, AVRCP, MAC Spoofing, Auto Pentest, Fleet, CLI (rich-click migration), README
Fixed¶
- 12 specific bug fixes across scanner, spoofer, hijack, BIAS, HFP, A2DP, RFCOMM, fleet, encryption enforcement
Removed¶
- Link Key Harvest feature
2.1.1 - 2026-03-31¶
Added¶
- 10 protocol-level DoS attacks targeting L2CAP, SDP, RFCOMM, OBEX, and HFP
- Link key harvest and persistent access
- SSP downgrade attack
- KNOB attack execution (CVE-2019-9506)
- Fleet-wide assessment
- Full 9-phase automated pentest (
autocommand) - Changelog file
Changed¶
- Report overhaul: modern UI, pentest narrative
- Auto command rewritten from 4-phase to 9-phase methodology
Fixed¶
- L2CAP DoS socket operations, DoS result dict key mismatch, KNOB probe missing fields, fleet assess crash, report collector namespaces, DoS grouping keywords
2.1.0 - 2026-03-31¶
Added¶
- Response-guided intelligent fuzzing engine with 6 layers of analysis (state inference, anomaly-guided mutation, structural validation, timing coverage, entropy leak detection, watchdog reboot detection)
- Full engine integration of all 6 phases into the campaign main loop
- Live dashboard intelligence panel
- Fuzzing intelligence section in reports
- Link key harvest and persistent access
- SSP downgrade attack
- KNOB attack execution
- Fleet-wide assessment
- GPL v3 license, SVG banner,
requirements.txt, 129 unit tests
Changed¶
- Fuzzing engine strategy dispatch, response fingerprinting, AVRCP rewritten to
dbus-fast, dependency overhaul, report generator complete rewrite
Fixed¶
- Campaign duration reset on resume, stub API mismatches, response_analyzer monitor bug, banner SVG spacing
2.0.1 - 2026-03-30¶
Fixed¶
- Duration limit reset on campaign resume
- Stub API mismatches
- Version display hardcoded in CLI
2.0.0 - 2026-03-29¶
Added¶
- Initial public release with full Bluetooth Classic and BLE penetration testing toolkit
- Device discovery, service enumeration, fingerprinting
- Vulnerability scanner with 20+ CVE checks
- PBAP, MAP, AT, OPP data extraction
- Connection hijacking, BIAS, HFP, A2DP, AVRCP
- DoS attacks, multi-protocol fuzzing engine
- 4 fuzzing strategies, crash database, minimization
- Session management, HTML/JSON reports, auto pentest, playbooks