Skip to content

Commit 2608358

Browse files
authored
fix(recon): consolidate chipset/OUI tables into core.ble_meta, drop dupes + bogus OUI (#56)
gatt_enum and ble_target_enum each carried a private copy of the CHIPSET_VENDORS, MFR_CHIPSET_HINTS, LMP_SUBVER_CHIPSET and OUI_CHIPSET tables. The gatt_enum copy contained a malformed 7-char OUI key ('D436390') that never matched. Both copies drifted from each other. Moved all four tables (plus convenience helpers chipset_for_address / _company_id / _manufacturer / _lmp_subversion) into core.ble_meta as public names. Both recon modules now import from one source of truth. adv_parser.COMPANY_IDS previously had 3 duplicate keys (0x0310, 0x038F, 0x0131) where silent override flipped vendor names. Trimmed to unique keys and added a fallback through core.utils.bt.decode_company_id on miss. Regenerated docs/recon.md and docs/exploits.md.
1 parent 680de6a commit 2608358

6 files changed

Lines changed: 244 additions & 211 deletions

File tree

core/ble_meta.py

Lines changed: 136 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
from __future__ import annotations
2525

26-
from typing import Iterable, List, Optional
26+
from typing import Dict, Iterable, List, Optional
2727

2828
# 16-bit GATT service UUIDs and their short names.
2929
# Pulled from the Bluetooth SIG Assigned Numbers (Services section).
@@ -353,15 +353,150 @@ def permissions_from_bitmap(bits: int) -> List[str]:
353353
return out
354354

355355

356+
# ── Chipset / vendor identification ──────────────────────────────────────────
357+
#
358+
# Shared truth used by recon modules that walk GATT (gatt_enum,
359+
# ble_target_enum) and any future module that needs to map a BD_ADDR,
360+
# PnP vendor id, or LMP subversion to a chipset label. Live in one place
361+
# to avoid drift; previous duplicate copies caused real bugs (e.g. a
362+
# malformed 7-char OUI key that never matched).
363+
364+
# Bluetooth SIG company identifiers -> chipset / brand vendor label.
365+
CHIPSET_VENDORS: Dict[int, str] = {
366+
0x0002: "Intel",
367+
0x0006: "Microsoft",
368+
0x000D: "Texas Instruments",
369+
0x000F: "Broadcom",
370+
0x001D: "Qualcomm Atheros",
371+
0x0059: "Nordic Semiconductor",
372+
0x0075: "Samsung",
373+
0x0087: "Garmin",
374+
0x004C: "Apple",
375+
0x00E0: "Google",
376+
0x012D: "GN Audio (Jabra)",
377+
0x012E: "MediaTek",
378+
0x0131: "Huawei Technologies",
379+
0x0157: "Xiaomi / LYWSD",
380+
0x0310: "Wyze Labs",
381+
0x038F: "Espressif Systems",
382+
0x03DA: "Bose",
383+
0x0499: "Ruuvi Innovations",
384+
0x054C: "Sony",
385+
0x0603: "Sonos",
386+
0x0822: "Espressif",
387+
}
388+
389+
# Manufacturer name substring -> probable chipset label. Used when the
390+
# Device Information Service exposes a manufacturer string but no PnP ID.
391+
MFR_CHIPSET_HINTS: Dict[str, str] = {
392+
"nordic": "Nordic Semiconductor nRF5x",
393+
"dialog": "Dialog Semiconductor DA14xxx",
394+
"texas": "Texas Instruments CC264x",
395+
"ti ": "Texas Instruments CC264x",
396+
"silicon labs": "Silicon Labs EFR32",
397+
"silabs": "Silicon Labs EFR32",
398+
"telink": "Telink TLSR",
399+
"realtek": "Realtek RTL8762",
400+
"beken": "Beken BK36xx",
401+
"mediatek": "MediaTek MT25xx",
402+
"qualcomm": "Qualcomm QCC",
403+
"cypress": "Infineon/Cypress CYW43xxx",
404+
"broadcom": "Broadcom BCM",
405+
"espressif": "Espressif ESP32",
406+
"esp": "Espressif ESP32",
407+
"nxp": "NXP KW4x",
408+
"kaha": "Realtek RTL8762 (KaHa platform)",
409+
"huawei": "HiSilicon BLE SoC",
410+
"xiaomi": "Beken / MediaTek platform",
411+
}
412+
413+
# LMP / LE-LL subversion value -> exact chipset model. Read off the
414+
# HCI_Read_Remote_Version response.
415+
LMP_SUBVER_CHIPSET: Dict[int, str] = {
416+
0x0001: "Nordic nRF52xxx",
417+
0x000D: "Nordic nRF52840",
418+
0x0048: "Texas Instruments CC2640",
419+
0x0051: "Texas Instruments CC2642",
420+
0x1000: "Nordic nRF51xxx",
421+
0x22BB: "Silicon Labs EFR32BG22",
422+
0x6109: "Qualcomm QCC512x",
423+
0x8761: "Realtek RTL8761",
424+
0x8762: "Realtek RTL8762",
425+
0x8763: "Realtek RTL8763",
426+
0x9908: "Dialog DA14531",
427+
}
428+
429+
# OUI prefix (6 uppercase hex chars, no colons) -> chipset / SoC vendor.
430+
# Smaller than the full IEEE OUI table; covers only the BLE-relevant
431+
# vendor blocks we want chipset attribution for.
432+
OUI_CHIPSET: Dict[str, str] = {
433+
"000F00": "Broadcom",
434+
"001A8A": "Samsung Electro-Mechanics",
435+
"001B10": "Nokia / MediaTek",
436+
"001E10": "Huawei Technologies",
437+
"240AC4": "Espressif ESP32",
438+
"246FAB": "Espressif ESP32",
439+
"30AEA4": "Espressif ESP32",
440+
"3C71BF": "Espressif ESP32",
441+
"5091F7": "Nordic Semiconductor",
442+
"5CCF7F": "Espressif ESP32",
443+
"84CCA8": "Espressif ESP32",
444+
"F4CE36": "Nordic Semiconductor",
445+
}
446+
447+
448+
def chipset_for_company_id(cid: int) -> Optional[str]:
449+
"""Map a Bluetooth SIG company id to a chipset / brand label."""
450+
return CHIPSET_VENDORS.get(cid)
451+
452+
453+
def chipset_for_manufacturer(name: str) -> Optional[str]:
454+
"""Best-effort chipset label from a manufacturer string (case-insensitive
455+
substring match against `MFR_CHIPSET_HINTS`)."""
456+
if not name:
457+
return None
458+
low = name.lower()
459+
for needle, label in MFR_CHIPSET_HINTS.items():
460+
if needle in low:
461+
return label
462+
return None
463+
464+
465+
def chipset_for_lmp_subversion(subver: int) -> Optional[str]:
466+
"""Map an LMP / LE-LL subversion value to a specific chipset model."""
467+
return LMP_SUBVER_CHIPSET.get(subver)
468+
469+
470+
def chipset_for_address(bd_addr: str) -> Optional[str]:
471+
"""Best-effort chipset / SoC vendor from a BD_ADDR's OUI prefix.
472+
473+
Accepts addresses with or without colons, in any case. Returns None
474+
if the OUI is not in `OUI_CHIPSET`."""
475+
if not bd_addr:
476+
return None
477+
oui = bd_addr.replace(":", "").upper()[:6]
478+
if len(oui) != 6:
479+
return None
480+
return OUI_CHIPSET.get(oui)
481+
482+
356483
__all__ = [
357484
"SERVICE_NAMES",
358485
"CHARACTERISTIC_NAMES",
359486
"DESCRIPTOR_NAMES",
360487
"PROP_BIT_NAMES",
488+
"CHIPSET_VENDORS",
489+
"MFR_CHIPSET_HINTS",
490+
"LMP_SUBVER_CHIPSET",
491+
"OUI_CHIPSET",
361492
"short_uuid",
362493
"name_for_service",
363494
"name_for_characteristic",
364495
"name_for_descriptor",
365496
"properties_to_permissions",
366497
"permissions_from_bitmap",
498+
"chipset_for_company_id",
499+
"chipset_for_manufacturer",
500+
"chipset_for_lmp_subversion",
501+
"chipset_for_address",
367502
]

docs/exploits.md

Lines changed: 19 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -401,7 +401,7 @@ Apple BT subsystem crash via malformed packets, iOS/macOS/watchOS/tvOS (CVE-2026
401401

402402
### `exploits/badchoice`
403403

404-
**exploits/classic/badchoice**
404+
**BadChoice (CVE-2020-12352 Linux BT info leak)**
405405

406406
BleedingTooth Linux A2MP Stack Info Leak (CVE-2020-12352)
407407

@@ -423,7 +423,7 @@ BleedingTooth Linux A2MP Stack Info Leak (CVE-2020-12352)
423423

424424
### `exploits/badkarma`
425425

426-
**exploits/classic/badkarma**
426+
**BadKarma (CVE-2020-12351 BleedingTooth L2CAP)**
427427

428428
BleedingTooth Linux L2CAP Type Confusion RCE (CVE-2020-12351)
429429

@@ -447,7 +447,7 @@ BleedingTooth Linux L2CAP Type Confusion RCE (CVE-2020-12351)
447447

448448
### `exploits/bias`
449449

450-
**exploits/classic/bias**
450+
**BIAS Authentication Bypass**
451451

452452
BIAS - Bluetooth Impersonation AttackS (CVE-2020-10135)
453453

@@ -775,7 +775,7 @@ Spoof BLE advertisements to impersonate AirTag, Fast Pair beacons, iBeacon, or T
775775

776776
### `exploits/bleedingtooth_native`
777777

778-
**exploits/classic/bleedingtooth_native**
778+
**BleedingTooth Native Exploit**
779779

780780
BleedingTooth full native RCE (CVE-2020-12351/52, EDB-49754)
781781

@@ -847,7 +847,7 @@ Spoof a previously paired BLE peripheral to hijack reconnection and serve forged
847847

848848
### `exploits/blueborne_bnep_overflow`
849849

850-
**exploits/classic/blueborne_bnep_overflow**
850+
**BlueBorne BNEP Buffer Overflow**
851851

852852
BlueBorne Android BNEP setup overflow (CVE-2017-0781, EDB-44554)
853853

@@ -869,7 +869,7 @@ BlueBorne Android BNEP setup overflow (CVE-2017-0781, EDB-44554)
869869

870870
### `exploits/blueborne_leak`
871871

872-
**exploits/classic/blueborne_leak**
872+
**BlueBorne Information Leak**
873873

874874
BlueBorne Android BNEP Information Leak (CVE-2017-0781)
875875

@@ -894,7 +894,7 @@ BlueBorne Android BNEP Information Leak (CVE-2017-0781)
894894

895895
### `exploits/blueborne_linux_rce`
896896

897-
**exploits/classic/blueborne_linux_rce**
897+
**BlueBorne Linux RCE**
898898

899899
BlueBorne Linux L2CAP Stack Buffer Overflow RCE (CVE-2017-1000251)
900900

@@ -916,7 +916,7 @@ BlueBorne Linux L2CAP Stack Buffer Overflow RCE (CVE-2017-1000251)
916916

917917
### `exploits/blueborne_sdp_leak`
918918

919-
**exploits/classic/blueborne_sdp_leak**
919+
**BlueBorne SDP Information Leak**
920920

921921
BlueBorne Android SDP heap info leak (CVE-2017-0785, EDB-44555)
922922

@@ -937,7 +937,7 @@ BlueBorne Android SDP heap info leak (CVE-2017-0785, EDB-44555)
937937

938938
### `exploits/bluebugging`
939939

940-
**exploits/classic/bluebugging**
940+
**Bluebugging (AT-command abuse)**
941941

942942
RFCOMM AT Command Injection via unauthenticated serial channel
943943

@@ -1008,7 +1008,7 @@ Run Rubber-Ducky-style payloads against unauthenticated HID Bluetooth peers via
10081008

10091009
### `exploits/bluefrag`
10101010

1011-
**exploits/classic/bluefrag**
1011+
**BlueFrag (CVE-2020-0022 Android RCE)**
10121012

10131013
BlueFrag Android A2DP Heap Overflow RCE (CVE-2020-0022)
10141014

@@ -1031,7 +1031,7 @@ BlueFrag Android A2DP Heap Overflow RCE (CVE-2020-0022)
10311031

10321032
### `exploits/bluesnarfing`
10331033

1034-
**exploits/classic/bluesnarfing**
1034+
**Bluesnarfing OBEX object exfil**
10351035

10361036
Unauthorized OBEX phonebook & object pull (Bluesnarfing)
10371037

@@ -1054,7 +1054,7 @@ Unauthorized OBEX phonebook & object pull (Bluesnarfing)
10541054

10551055
### `exploits/bluffs`
10561056

1057-
**exploits/classic/bluffs**
1057+
**BLUFFS Session Key Downgrade**
10581058

10591059
BLUFFS Bluetooth session key downgrade attack (CVE-2023-24023)
10601060

@@ -1080,7 +1080,7 @@ BLUFFS Bluetooth session key downgrade attack (CVE-2023-24023)
10801080

10811081
### `exploits/bluffs_mitm`
10821082

1083-
**exploits/classic/bluffs_mitm**
1083+
**BLUFFS MITM Variant**
10841084

10851085
Active MITM session key downgrade attack (BLUFFS/CVE-2023-24023)
10861086

@@ -1128,7 +1128,7 @@ Exploit Cross-Transport Key Derivation to overwrite an existing authenticated Bl
11281128

11291129
### `exploits/bnep_heap_disclosure`
11301130

1131-
**exploits/classic/bnep_heap_disclosure**
1131+
**BNEP Heap Disclosure**
11321132

11331133
BNEP bnep_data_ind() Remote Heap Disclosure (CVE-2017-13258)
11341134

@@ -1155,7 +1155,7 @@ BNEP bnep_data_ind() Remote Heap Disclosure (CVE-2017-13258)
11551155

11561156
### `exploits/braktooth_esp32`
11571157

1158-
**exploits/classic/braktooth_esp32**
1158+
**BrakTooth ESP32 LMP Exploits**
11591159

11601160
BrakTooth ESP32 Feature Page ACE (CVE-2021-28139)
11611161

@@ -1399,7 +1399,7 @@ Inject keystrokes into a Windows host by spoofing the BD_ADDR of a keyboard alre
13991399

14001400
### `exploits/knob`
14011401

1402-
**exploits/classic/knob**
1402+
**KNOB Key Negotiation Attack**
14031403

14041404
KNOB Attack - Encryption Key Entropy Downgrade (CVE-2019-9506)
14051405

@@ -1422,7 +1422,7 @@ KNOB Attack - Encryption Key Entropy Downgrade (CVE-2019-9506)
14221422

14231423
### `exploits/knob_active`
14241424

1425-
**exploits/classic/knob_active**
1425+
**KNOB Active Downgrade**
14261426

14271427
Actively force encryption key entropy downgrade (KNOB/CVE-2019-9506)
14281428

@@ -1991,7 +1991,7 @@ Force 7-byte (56-bit) LTK derivation by responding to LE pairing with max_key_si
19911991

19921992
### `exploits/sweyntooth`
19931993

1994-
**exploits/ble/sweyntooth**
1994+
**SweynTooth BLE Link-Layer Exploits**
19951995

19961996
SweynTooth BLE Link Layer stack overflow / deadlock family
19971997

@@ -2040,7 +2040,7 @@ Skip ECDH validation on TI SimpleLink CC2640R2 by setting up encryption before S
20402040

20412041
### `exploits/unauth_write`
20422042

2043-
**exploits/ble/unauth_write**
2043+
**Unauthenticated GATT Write**
20442044

20452045
Unauthenticated GATT characteristic write
20462046

0 commit comments

Comments
 (0)