
Notes de rétro-ingénierie et outils Python pour le firmware des JBL Wave Buds 2 (BES1306) : format de conteneur OTA, disposition de la mémoire flash, protocole BLE/GATT et modèle de confiance CRC-32.
Notes de rétro-ingénierie et outillage reproductible pour les JBL Wave Buds 2
(Bestechnic BES1306, PID 2100) : la disposition en flash, le format du conteneur
OTA jusqu'à l'octet près, le protocole de commandes BLE/GATT et le transport chiffré
« TOTA v2 » de BES, les frontières de confiance côté appareil et côté application, la
console d'usine, et une méthode reproductible pour charger une image auto-construite sur un appareil que vous
possédez.
L'analyse couvre deux builds — le wavebuds.elf analysé dans IDA (avr. 2025) et
le paquet de distribution 2.9.0 (sept. 2026) — un conteneur OTA à 8 flux entièrement spécifié
(vérifié par un repackage octet pour octet identique), le modèle d'intégrité CRC-32
confirmé à la fois côté application et côté appareil, une table de commandes d'usine de 54/59 entrées,
12 variables d'état OTA en RAM, une énumération de 7 960 fonctions, et un
différentiel entre builds. La récupération sémantique est approfondie pour les sous-systèmes OTA/flash/CRC/usine
et limitée à l'énumération ailleurs — voir l'audit de complétude.
[!WARNING] Il s'agit de recherche matérielle réalisée par le propriétaire, et non d'une mise à jour officielle JBL. Flasher une image modifiée est irréversible : la phase de téléchargement est étagée et sans risque de brique, mais l'activation d'une image valide au CRC mais défectueuse n'a aucun chemin de récupération exposé. Lisez SAFETY.md avant de reproduire quoi que ce soit.
Version turque : README.tr.md

Résultat matériel sur l'appareil testé : après validation du pipeline OTA application + MITM avec CA utilisateur, les deux écouteurs se connectent, rapportent 100 %, et toutes les commandes de l'application (ANC/Ambient, gestes, EQ) fonctionnent. L'image modifiée d'un octet a été acceptée de la même manière et l'appareil est resté pleinement fonctionnel.
Les adresses proviennent du build analysé (wavebuds.elf) ; voir le
registre d'adresses et la provenance.
0x2C0918BC vérifie la configuration, chaque segment, et
l'image entière avec la routine CRC-32 0x2C0CE944 (table 0x2C0F5218) plus un
magic "BEST". Une image valide au CRC avec un octet modifié a été acceptée et
démarrée.com.jbl.counterfeit.Rsa2048DynamicVerifier) est
anti-contrefaçon (authenticité de l'appareil), et non une signature de firmware.0x28120000 tandis que
l'application en cours d'exécution reste intacte, de sorte que la phase de téléchargement est sans risque de brique.0x2C0905E4 : MEMORY[0x20026BA0] ∈ {2,4}).UNRESOLVED.La modification est volontairement minimale — un octet de l'image décompressée.
Elle change la chaîne du noyau RTX RTX V5.5.1 → V5.5.2 à l'offset décompressé
64096, et le CRC-32 du conteneur est recalculé. Elle est cosmétique par conception : le
but est de prouver que l'appareil accepte une image modifiée mais valide au CRC, et non de
changer le comportement.
Base (owner-supplied; not redistributed)
official 2.9.0 package 549,558 bytes SHA-256 836cb251f9fb2261dde14f39ba18d358c48018817f3c3d1b527e1ac5f3ab7ba2
decompressed image 955,596 bytes SHA-256 489663e80b76f20f4c94671064908569fac5f4e3df10ab6d7369baffe094f67d
container CRC-32 A0C7CCEC (valid), input range [0x0, 0x862AD)
Le dépôt ne contient intentionnellement aucun firmware JBL. Fournissez votre propre paquet obtenu légalement et reproduisez :
python3 tools/ota_unpack.py <official_2.9.0_package.bin> --extract image.bin
python3 tools/ota_repack.py make-test <official_2.9.0_package.bin> test.bin
python3 tools/ota_unpack.py test.bin # exactly one decompressed byte differs; CRC valid
Les octets exacts du conteneur repacké dépendent de l'encodeur LZMA ; l'appareil vérifie le CRC-32, et non un hash du paquet (voir docs/04), et le diff décompressé d'un octet est déterministe. La livraison via l'application est décrite dans docs/08.
| Carte flash | partitionnement NOR de 2 Mo |
| Flux de commandes OTA | la séquence et ses points de contrôle CRC-32 |
| Frontières de confiance | ce que vérifie chaque étape, et où repose la confiance dans l'image |