Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
jbl-wave-buds2-firmware-research — Reverse-engineering notes and Python tooling for JBL Wave Buds 2 (BES1306) firmware: OTA container format, flash layout, BLE/GATT protocol, and CRC-32 trust model. | Kitploit
Tools/GitHubGitHub/c8dhjp4tyv-bit/jbl-wave-buds2-firmware-research
Embedded Systems SecurityBluetooth SecurityIoT SecurityExploitationReverse EngineeringCryptographyHardware & IoT SecurityBinary AnalysisPapers & Research

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share
Firmware Analysis
GitHubc8dhjp4tyv-bit/jbl-wave-buds2-firmware-research

jbl-wave-buds2-firmware-research

Reverse-engineering notes and Python tooling for JBL Wave Buds 2 (BES1306) firmware: OTA container format, flash layout, BLE/GATT protocol, and CRC-32 trust model.

View Repository
1332 days agoNot yet reviewed

JBL Wave Buds 2 — firmware & OTA reverse engineering

Tests

Reverse-engineering notes and reproducible tooling for the JBL Wave Buds 2 (Bestechnic BES1306, PID 2100): the on-flash layout, the OTA container format down to the byte, the BLE/GATT command protocol and the BES "TOTA v2" encrypted transport, the device- and app-side trust boundaries, the factory console, and a reproducible method for loading a self-built image onto a unit you own.

The analysis spans two builds — the IDA-analyzed wavebuds.elf (Apr 2025) and the distribution package 2.9.0 (Sep 2026) — a fully specified 8-stream OTA container (verified by byte-identical repack), the CRC-32 integrity model confirmed on both the app and device sides, a 54/59-entry factory command table, 12 OTA RAM state variables, a 7,960-function enumeration, and a cross-build differential. Semantic recovery is deep for the OTA/flash/CRC/factory subsystems and enumeration-only elsewhere — see the completeness audit.

[!WARNING] This is owner-performed hardware research, not an official JBL update. Flashing a modified image is irreversible: the download phase is staged and brick-safe, but activation of a CRC-valid-but-broken image has no exposed recovery path. Read SAFETY.md before reproducing anything.

Türkçe sürüm: README.tr.md

The tested JBL Wave Buds 2 in the companion app: both earbuds connected at 100%, all controls live

Hardware result on the tested unit: after the app + user-CA MITM OTA pipeline was validated, both earbuds connect, report 100%, and every app control (ANC/Ambient, gestures, EQ) works. The one-byte-modified image was accepted the same way and the device stayed fully functional.

Confirmed findings

Addresses are from the analyzed build (wavebuds.elf); see the address ledger and provenance.

  • The OTA image is not cryptographically signed. Device-side integrity is CRC-32 only — the handler 0x2C0918BC checks config, each segment, and the whole image with the CRC-32 routine 0x2C0CE944 (table 0x2C0F5218) plus a "BEST" magic. A CRC-valid image with one modified byte was accepted and booted.
  • The app's RSA-2048 verifier (com.jbl.counterfeit.Rsa2048DynamicVerifier) is anti-counterfeit (device authenticity), not firmware signing.
  • The app does not pin its OTA endpoints; a user-installed CA is enough to intercept and rewrite the OTA config.
  • OTA is staged: the new image is copied to flash base 0x28120000 while the running application is untouched, so the download phase is brick-safe.
  • An external BLE central cannot drive OTA: the handlers are gated on an internal TWS/connection state (0x2C0905E4: MEMORY[0x20026BA0] ∈ {2,4}).
  • The BES TOTA v2 transport derives its AES-128 session key entirely client-side; there is no server/device secret.
  • A factory/engineering console (59 commands in the analyzed build, 54 in 2.9.0) can read/write device identity (MAC/BLE address), crystal trim, and the BT link key. Its over-the-air reachability is UNRESOLVED.
  • The two builds are separately compiled and relocated: same product, shifted addresses, 59 → 54 factory entries. See the differential.

Tested modification

The modification is intentionally minimal — one byte of the decompressed image. It changes the RTX kernel string RTX V5.5.1 → V5.5.2 at decompressed offset 64096, and the container CRC-32 is recomputed. It is cosmetic by design: the point is to prove the device accepts a modified-but-CRC-valid image, not to change behavior.

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)

The repository intentionally contains no JBL firmware. Supply your own legally obtained package and reproduce:

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

The repacked container's exact bytes depend on the LZMA encoder; the device verifies CRC-32, not a package hash (see docs/04), and the one-byte decompressed diff is deterministic. Delivery through the app is in docs/08.

Diagrams

Flash map2 MB NOR partitioning
OTA command flowthe sequence and its CRC-32 checkpoints
Trust boundarieswhat each stage verifies, and where image trust rests

Documentation

Download Tool