
Notas de ingeniería inversa y herramientas en Python para el firmware de los JBL Wave Buds 2 (BES1306): formato de contenedor OTA, diseño de la memoria flash, protocolo BLE/GATT y modelo de confianza CRC-32.
Notas de ingeniería inversa y herramientas reproducibles para los JBL Wave Buds 2
(Bestechnic BES1306, PID 2100): el diseño en flash, el formato del contenedor
OTA hasta el byte, el protocolo de comandos BLE/GATT y el transporte cifrado
"TOTA v2" de BES, los límites de confianza del lado del dispositivo y de la app, la
consola de fábrica, y un método reproducible para cargar una imagen compilada por
uno mismo en una unidad de su propiedad.
El análisis abarca dos compilaciones — el wavebuds.elf analizado con IDA (abr 2025) y
el paquete de distribución 2.9.0 (sep 2026) — un contenedor OTA de 8 flujos
completamente especificado (verificado mediante un reempaquetado byte a byte idéntico), el modelo de integridad CRC-32
confirmado tanto en el lado de la app como en el del dispositivo, una tabla de comandos de fábrica de 54/59 entradas,
12 variables de estado de la RAM de OTA, una enumeración de 7.960 funciones, y un
diferencial entre compilaciones. La recuperación semántica es profunda para los subsistemas
de OTA/flash/CRC/fábrica y solo de enumeración en el resto — véase la auditoría de completitud.
[!WARNING] Esta es una investigación de hardware realizada por el propietario, no una actualización oficial de JBL. Flashear una imagen modificada es irreversible: la fase de descarga está por etapas y es segura contra el brick, pero la activación de una imagen válida en CRC pero defectuosa no tiene una ruta de recuperación expuesta. Lea SAFETY.md antes de reproducir cualquier cosa.
Versión en turco: README.tr.md

Resultado en hardware sobre la unidad probada: tras validar el pipeline OTA mediante MITM con la app + CA de usuario, ambos auriculares se conectan, reportan el 100%, y cada control de la app (ANC/Ambient, gestos, EQ) funciona. La imagen modificada en un byte fue aceptada de la misma manera y el dispositivo permaneció totalmente funcional.
Las direcciones provienen de la compilación analizada (wavebuds.elf); véanse el
registro de direcciones y la procedencia.
0x2C0918BC verifica la configuración, cada segmento y la
imagen completa con la rutina CRC-32 0x2C0CE944 (tabla 0x2C0F5218) más un
magic "BEST". Una imagen válida en CRC con un byte modificado fue aceptada y
arrancó.com.jbl.counterfeit.Rsa2048DynamicVerifier) es
anticounterfeit (autenticidad del dispositivo), no firma de firmware.0x28120000 mientras la
aplicación en ejecución permanece intacta, por lo que la fase de descarga es segura contra el brick.0x2C0905E4: MEMORY[0x20026BA0] ∈ {2,4}).UNRESOLVED.La modificación es intencionalmente mínima — un byte de la imagen descomprimida.
Cambia la cadena del kernel RTX RTX V5.5.1 → V5.5.2 en el desplazamiento descomprimido
64096, y se recalcula el CRC-32 del contenedor. Es cosmética por diseño: el
objetivo es demostrar que el dispositivo acepta una imagen modificada pero válida en CRC, no
cambiar el comportamiento.
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)
El repositorio intencionalmente no contiene firmware de JBL. Proporciona tu propio paquete obtenido legalmente y 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
Los bytes exactos del contenedor reempaquetado dependen del codificador LZMA; el dispositivo verifica CRC-32, no un hash del paquete (véase docs/04), y el diff descomprimido de un byte es determinista. La entrega a través de la app se describe en docs/08.
| Mapa de flash | Particionado de NOR de 2 MB |
| Flujo de comandos OTA | la secuencia y sus puntos de control CRC-32 |
| Límites de confianza | qué verifica cada etapa y dónde reside la confianza en la imagen |