1 puntos por GN⁺ 2023-10-30 | 1 comentarios | Compartir por WhatsApp
  • Los sonidos del sistema de emparejamiento, conexión y desconexión de los earbuds Tozo T6 eran demasiado fuertes, así que se resolvió bajando directamente la ganancia de los archivos de audio dentro del firmware
  • Se estimó que el chipset era de la familia Airoha AB1562, y mediante la app AirReps156X se confirmó la posibilidad de subir información de diagnóstico y firmware modificado
  • Se interceptó con mitmproxy el tráfico de verificación de actualizaciones de la app de Tozo y se obtuvo, desde la respuesta de /api/v1/getOtaVersionV3, el enlace al binario de firmware de los earbuds
  • El firmware estaba compuesto por 2 FotaPackage para el earbud izquierdo y derecho, y 2 FileSystemImage; dentro de la imagen del sistema de archivos que se iba a modificar, los archivos mp3 estaban incluidos intactos
  • Tras bajar solo -19.5dB con mp3gain, sin recodificar los mp3 ni cambiar su longitud, se reemplazaron los bytes dentro de la imagen y se flasheó; el dispositivo siguió funcionando normalmente y el sonido quedó mucho más bajo

Sonidos del sistema demasiado fuertes y supuestos iniciales

  • Los earbuds Tozo T6 reproducían un sonido cada vez que se emparejaban, se conectaban o se desconectaban, y ese sonido era mucho más fuerte de lo que el usuario prefería
  • Bajar unos dB en todo el rango desde el ecualizador no resolvía el problema, y aunque se contactó a Tozo por correo, la empresa respondió que no podían hacer nada
  • El objetivo era modificar el firmware que corre en el dispositivo para bajar el volumen de esos archivos de sonido
  • Al principio se abordó el problema con varios supuestos
    • Que sería posible conseguir en línea el binario de firmware del dispositivo
    • Que el firmware podría tener una estructura binaria fácil de entender, como ELF
    • Que los archivos de audio estarían incluidos dentro del firmware y podrían modificarse si se conocían su offset y longitud
    • Que el audio podría estar en un formato simple, como PCM
    • Que el firmware modificado podría flashearse con herramientas para el dispositivo o el chipset
  • En la práctica, varios supuestos fallaron, y se invirtió más tiempo en configurar infraestructura de análisis como proxys y en buscar rutas alternas que en la ingeniería inversa en sí

Identificación del dispositivo y del chipset

  • En los electrónicos de bajo costo suele haber varios actores y capas involucrados
    • El vendor que vende el producto con marca propia, en este caso Tozo
    • El chipset, que es el hardware principal que ejecuta el firmware
    • El chipset puede usar una ISA derivada de tecnologías base como ARM o MIPS
    • También puede integrar coprocesadores adicionales o funciones para interfaces de hardware
  • Al desensamblar la app de Tozo para Android, se encontraron referencias al Airoha SDK, a modelos concretos de chips y a funciones básicas para comunicarse con el dispositivo
  • Se obtuvo orientación adicional en la comunidad de Reddit sobre réplicas de AirPods, /r/airreps, y también se identificó la app AirReps156X
  • La app AirReps156X usa el Airoha SDK y podía mostrar información de diagnóstico de dispositivos Airoha
  • Al conectar el dispositivo a esa app, apareció la cadena de diagnóstico QW_1562U_SDK1.5.1, y con base en eso se concluyó que el chipset del dispositivo pertenecía a la serie Airoha AB1562
  • La app AirReps156X también tenía función para flashear firmware nuevo, así que se cumplía una condición clave para cargar firmware modificado en el dispositivo

Búsqueda de la URL del firmware en el tráfico de la app de Tozo

  • La app de Tozo mostraba, al conectarse a los earbuds, la versión actual del firmware y si era la más reciente
  • Como la app consultaba al servidor para verificar esa información, se decidió buscar la URL real del firmware durante el proceso de revisión de actualizaciones
  • En vez de depender de análisis estático leyendo todo el código decompilado, se eligió análisis dinámico observando directamente las solicitudes de red
  • Se armó un proxy de intercepción con una NIC inalámbrica, hostapd y mitmproxy
  • El APK de Tozo se parchó con apktool y uber apk signer para que confiara en el certificado TLS de mitmproxy dentro del almacén de CA del usuario
    • Muchas apps de Android consultan solo el almacén de CA del sistema por defecto
    • El parche del APK hizo que también usara el almacén de CA del usuario, y luego se volvió a firmar para que Android lo ejecutara
  • La configuración del proxy incluyó ajustar el AP, redirigir con iptables el tráfico 80/443 al puerto de mitmproxy y configurar NAT
  • Cuando la app mostraba “current” junto a la versión del firmware, enviaba una solicitud al endpoint /api/v1/getOtaVersionV3, y en la respuesta venían los enlaces binarios del firmware necesarios

Estructura y análisis de los archivos de firmware

  • El firmware obtenido estaba compuesto por 4 archivos en total
    • Un FotaPackage para cada earbud, izquierdo y derecho
    • Un FileSystemImage para cada earbud, izquierdo y derecho
  • Las dos imágenes del sistema de archivos eran idénticas, así que en la práctica había 3 archivos únicos: 2 FotaPackage para izquierda y derecha, y 1 imagen del sistema de archivos
  • Se intentó identificar el formato y los archivos embebidos con file, strings, hexdump y binwalk
  • En la imagen del sistema de archivos se veían algunas cadenas con nombres de archivos, pero binwalk no lograba encontrar los mp3 esperados
  • Los mp3 no tienen un magic number o footer claros, así que era difícil fijar con certeza su offset y longitud dentro de un binario arbitrario
    • El inicio podía ser 0xFFFF o 0xFFFE
    • Ninguno de los dos era suficientemente distintivo como identificador de archivo
  • Como conocer la estructura de la imagen del sistema de archivos permitiría ubicar el inicio y fin de cada archivo, la investigación se orientó a entender ese formato

Análisis de entropía y ROFS

  • El análisis de entropía sirve para visualizar qué partes de un archivo se parecen más a constantes, ruido aleatorio o texto ASCII, y dónde están los puntos de transición
  • La imagen del sistema de archivos mostraba una estructura visible, pero los archivos FotaPackage parecían comprimidos o cifrados
  • Los FotaPackage izquierdo y derecho solo diferían esporádicamente en parte del header; el cuerpo era casi idéntico hasta que, en los últimos ~7KB, pasaba a ser completamente distinto
  • No se logró determinar exactamente qué significaba esa diferencia, pero parecía haber una transformación opaca aplicada, así que sin mucho más esfuerzo no se podía extraer información útil
  • La imagen del sistema de archivos empezaba con la cadena ASCII ROFS
  • No se encontró documentación pública ni información de formato que coincidiera con ROFS, aunque más adelante apareció en el Airoha SDK una implementación de la interfaz para leer esa imagen
  • En algún momento se intentó seguir la ruta de descifrar FotaPackage, pero solo se pudo confirmar que el SDK no transformaba el firmware antes de enviarlo, sin resultados útiles

Bajar el volumen del mp3 sin recodificarlo

  • Que los archivos fueran mp3 al principio se consideró un riesgo
    • Los codificadores mp3 tienen muchas opciones, y un decodificador desconocido podría no manejar correctamente ciertos archivos válidos
    • Si el audio que se reproduce justo después de conectar causaba problemas, el dispositivo podía fallar antes de reconectarse y quedar sin recuperación
  • Si se recodificaba el mp3, la longitud del archivo podía cambiar, y entonces quizá habría que corregir también la información de longitud dentro de la imagen del sistema de archivos
  • Por suerte, era posible ajustar la ganancia del mp3 sin recodificarlo, sin cambiar su longitud y sin modificar metadatos
  • Era algo más parecido a rotar un JPEG sin recodificarlo: se modificaba solo una parte de la estructura interna de datos

La pista decisiva obtenida del SDK

  • Buscando por el nombre del chipset se encontró una copia del Airoha SDK, y dentro venían archivos .mp3 iguales a los que se escuchaban en el dispositivo
  • Se escribió un programa sencillo en Python, bincontains.py, para comprobar qué archivos estaban incluidos intactos dentro de otro binario
  • Se verificó que los mp3 del SDK estaban incluidos sin cambios dentro de la imagen del sistema de archivos
    • No estaban comprimidos
    • No estaban divididos en bloques
    • Por lo tanto, era posible calcular su offset y longitud dentro de la imagen
  • También se revisó por encima el código del SDK relacionado con ROFS, y no aparecieron símbolos que sugirieran claramente la existencia de checksums
  • En ese punto ya estaban dadas las condiciones necesarias para modificar el firmware sin más ingeniería inversa
    • Se tenían los archivos de firmware y la forma de flashearlos
    • Se conocían la posición y longitud de los mp3 dentro de la imagen
    • La ganancia del mp3 podía ajustarse sin cambiar su longitud
    • Se asumió que cambiar solo el rango de bytes interno del archivo no rompería los metadatos del sistema de archivos

Modificación y flasheo de la imagen del sistema de archivos

  • Un script de Bash recorría los archivos mp3 del SDK y buscaba cuáles estaban incluidos dentro de la imagen del sistema de archivos
  • Luego copiaba el mp3 incluido a un archivo temporal y le bajaba la ganancia con mp3gain
  • El valor de ajuste usado fue -19.5dB
  • Después de comprobar que el tamaño del mp3 modificado era igual al original, se sobrescribían los bytes en ese offset de la imagen del sistema de archivos con dd
  • En el diff binario de la imagen final, como se esperaba, solo cambiaban unos pocos bytes
  • El firmware modificado se flasheó en el dispositivo; el equipo siguió funcionando normalmente y los sonidos del sistema quedaron mucho más silenciosos que antes

Resultado y limitaciones

  • No hizo falta descifrar el cifrado del firmware ni entender por completo el formato del sistema de archivos ROFS
  • De hecho, buena parte del tiempo invertido en ingeniería inversa se fue en rutas alternas que al final no fueron necesarias para la solución
  • Si ajustar el volumen de los sonidos del sistema hubiera sido una función nativa del dispositivo, este cambio no habría sido necesario
  • En cualquier dispositivo que reproduce audio, sería más apropiado ofrecer a nivel de UI un control de volumen que afecte todos los sonidos emitidos por el equipo
  • En este caso bastó con un workaround: bajar solo la ganancia de los mp3 dentro de la imagen del firmware

1 comentarios

 
GN⁺ 2023-10-30
Comentarios de Hacker News
  • Ojalá alguien arreglara así también mi máscara para dormir con Bluetooth
    En general está bastante bien, pero cuando se está quedando sin batería o está por apagarse, te lo avisa a volumen máximo
    En una máscara para dormir, imagínate

    • La verdad eso es bastante gracioso. Me imagino lo furioso que te habrás puesto la primera vez que lo descubriste
      Una vez usé un despertador con una falla parecida, que tenía sincronización horaria por radio MSF
      Pero cada vez que volvía a sincronizarse con la señal horaria MSF, hacía el mismo sonido que la alarma durante 2 o 3 segundos, y no se podía desactivar
      Siempre sonaba como a las 3 de la madrugada, una hora horrible, así que al final lo abrí, corté la antena MSF y dormí mejor aun sabiendo que el reloj siempre iba a estar un poco desajustado
    • Mis clips Bluetooth para la oreja hacen esto cuando avisan batería baja: silencian el audio que se está reproduciendo, dejan un silencio dramático, dicen “BATTERY LOW. PLEASE CHARGE NOW.”, dejan otro silencio dramático y luego vuelven a funcionar con normalidad
      Mientras tanto, yo intento volver a captar lo que dijo la otra persona durante esos segundos en la llamada, pero no lo logro muy bien
      Este aviso es mucho peor que no hacer nada. Sin advertencia, lo peor que puede pasar es que se corte el sonido y me pierda lo que dice la otra persona; el clip para la oreja justamente provoca ese efecto a propósito y con un horario más temprano
      No hay ninguna razón por la que no puedan mezclar algo como un patrón discreto de pitidos dentro del flujo de audio existente. Tomaría menos de 1 segundo y no causaría por sí mismo el problema que supuestamente intenta evitar
      Otro comportamiento Bluetooth absurdamente malo es que, si usas chat de voz, desaparece todo el audio normal de la computadora. Si el chat de voz usa la entrada del micrófono, el dispositivo Bluetooth cambia al modo “headset”, y ese modo convierte el estéreo en mono y se vuelve la única salida permitida mientras esté proporcionando o pueda proporcionar entrada de audio
      Las apps que no usan entrada de audio siguen intentando reproducir por un dispositivo de audífonos Bluetooth que ya no existe, así que todas se quedan sin poder sacar sonido
      No entiendo por qué tiene que haber varios modos de dispositivo. No hay razón para querer perder funciones como efecto secundario de hablar con tu familia. No entiendo qué tiene de tan difícil reproducir señales de audio distintas en ambos oídos solo porque existe la posibilidad de que el micrófono se active. Los dispositivos que no son Bluetooth resuelven esto, y ni siquiera se considera una función destacable. ¿Por qué tendría que ser especial que “los audífonos no se apaguen mientras usas el micrófono”?
    • Al final terminé usando un altavoz de almohada con cable y jack de 3.5 mm. Así evito estos problemas que tenía con Bluetooth
    • ¿Qué hace ese dispositivo? Me da curiosidad por qué necesitarías conexión Bluetooth a la hora de dormir
    • Me recuerda al reloj urbano NNY de Futurama. En una escena grita a todo volumen “THE TIME IS FOUR AM”
  • ¡Buenísimo! Mis respetos al autor original por llevarlo hasta el final
    Ya que salió el tema de los earbuds demasiado ruidosos, creo que yo podría tener el problema opuesto. En la caminadora uso unos Bose deportivos a un volumen que considero cómodo y conservador, pero el iPhone me muestra avisos de que el volumen está demasiado alto y me estoy dañando el oído
    ¿Tendrá razón el teléfono? Si es así, estoy dispuesto a sacrificar un poco de disfrute por la salud de mis oídos. Pero también hay otra hipótesis bastante plausible. Estos earbuds tienen un volumen físico real claramente más bajo, con la misma configuración de volumen, que otros productos que he usado, así que el modelado flojo de Apple podría estar generando alertas erróneas como la que me sale a mí
    Si Apple realmente construyó una base de datos que mapea modelo de producto y nivel de volumen al volumen físico real, los felicitaría. Pero como en la alerta y en la descripción de la función no hay ningún detalle, no me inspira confianza, y no quisiera arruinarme más el ejercicio solo porque Apple metió en un producto real un modelo a nivel tarea universitaria
    ¿Alguien sabe si la ciencia de datos detrás de esta alerta está bien hecha?

    • Hay exactamente dos cosas de Android que extraño en iOS, y ambas tienen que ver con que Bluetooth funciona menos mal
      Primero, en iOS el volumen mínimo de mis earbuds Bluetooth sigue siendo demasiado alto. Me ha pasado con todos los audífonos de terceros que he probado, y en internet llevan 10 años quejándose de eso. La UE hasta aprobó una ley para obligarlos a arreglarlo, pero spoiler: no sirvió de nada
      Por favor, el volumen mínimo de la UI debería mapearse al entero 1 del volumen de hardware
      Segundo, las apps de terceros no pueden exponer música o podcasts en el menú de navegación multimedia Bluetooth del auto. En Android sí se puede
      Así que en Android puedo escuchar podcasts y hacer streaming de Tidal con la perilla del auto, pero en iOS no
      También tengo otras quejas sobre Bluetooth. ¿Por qué mi Apple Watch pone el estéreo del auto en lista negra? El Bluetooth de iOS versión N y N-1 de verdad tiene muchísimos bugs
    • Mi teléfono también, es Android 5 y la verdad casi no lo uso, así que no necesito uno nuevo hasta que se rompa, hace exactamente lo mismo cada vez que se conecta por Bluetooth al auto por primera vez después de reiniciarse
      Es simplemente una función evidentemente estúpida. Si al menos pudiera rootearlo, podría desactivar ese interruptor que debe estar en algún archivo de configuración, pero nunca lo he logrado en un Samsung Galaxy J1 (2016)
    • No creo que el sistema operativo sepa cuántos dB salen del otro lado
      Mis Bose también se comportan distinto según el chipset Bluetooth. En Linux tengo que subir el volumen al 150% para escuchar cualquier cosa decentemente
    • Aunque Apple hubiera hecho ese mapeo, sería datos obsoletos desde el momento en que sale al mercado
      Pero tampoco hay motivo para creer que hayan hecho algo así. Sería interesante si el fabricante de audífonos informara el rango de dB al conectarse por Bluetooth para hacer posible una función así, pero nunca he oído de algo así. A diferencia del jack de 3.5 mm, Bluetooth sí es un ámbito donde eso podría hacerse posible
    • Los audífonos/earbuds con cancelación de ruido resuelven este problema
      Si usas cancelación de ruido, puedes mantener el volumen por debajo del 20% y aun así escuchar cómodamente sin maltratarte los oídos
      En mi caso, hace unos años empecé a tener dolor de oídos después de entrenamientos largos, así que creo que la alerta de Apple probablemente tenía razón. Desde que uso cancelación de ruido, desapareció por completo
  • Qué bueno este tipo de trabajo. De repente este modelo de audífonos se siente bastante interesante.
    Como añadido, los sonidos del sistema que emite un dispositivo Bluetooth son uno de los factores que más marcan la diferencia entre productos. Algunos son completamente horribles: https://youtu.be/J2wPsH64JEM
    Pero nunca he visto una reseña o página de producto que te diga qué sonidos hace ese producto. Y eso que tienes que oírlos varias veces al día y ni siquiera hay forma de apagarlos.
    Solo permitir cambiar esos sonidos ya me parece una forma bastante fácil de diferenciarse.

    • Ojalá pudiera bajar el volumen del pitido de reproducir/pausar de mis AfterShokz.
      Son perfectos cuando traigo tapones para los oídos y estoy en un lugar de trabajo ruidoso, pero si en una oficina silenciosa pongo música bajita para concentrarme, resulta molesto y hasta me pega un susto.
      No entiendo por qué los sonidos del sistema no siguen la configuración de volumen.
  • Estaría bien que el teléfono supiera si el headset conectado es un juego de bocinas, monitores intraaurales, de conducción ósea, etc.
    Cuando uso un juego de bocinas normal y a propósito quiero subirle para que se escuche en cualquier parte de la casa, la alerta de “volumen demasiado alto” es desesperante.
    Con audífonos de conducción ósea necesitas un volumen bastante alto para oír bien, así que molesta el doble.

  • Qué bueno que esto sea para un Airoha sin cifrado de firmware.
    Si les da curiosidad, también hay una plantilla de 010 Editor para el formato del firmware.
    https://github.com/ramikg/airoha-firmware-parser

  • Le reconozco el mérito, pero da pena que haga falta tanto esfuerzo para hacer algo tan básico como cambiar un poco el volumen de reproducción de un archivo.
    No debería requerirse tanto trabajo para hacer que una herramienta funcione como uno quiere.

  • No es “entendible”. Uno pagó por el producto, y esto es un problema del producto que deberían arreglar.

  • Leí esto y compré unos Tozo T6 usados, pero aunque por fuera parecían fabricados hace relativamente poco, no pude reproducirlo.
    La app oficial de Tozo ni siquiera reconoció el headset, y tampoco pude confirmar si usaba un chipset Airoha, que se identificaría por soporte AAC. Los míos solo soportan SBC.
    O compré una falsificación, o hubo un cambio interno después de que el autor compró los suyos.
    Algunos archivos de audio suenan igual que los incluidos en el SDK parcial de Airoha que anda en internet, pero también reproducen otros archivos de voz nuevos.
    Si quieren verificar este resultado de forma independiente o ponerse a experimentar, puede que los AirPods falsos sean una mejor ruta.

  • Ojalá más gente se quejara de los sonidos del sistema grandes y horribles.

  • Mis Sony WH-1000XM4 tienen exactamente el mismo problema, pero parece que Sony cifra el payload del firmware y lo descifra en el dispositivo.
    Estuve a punto de desarmarlos casi por completo para volcar todo y explorar, pero me tiemblan demasiado las manos y hay demasiada probabilidad de que los rompa.
    Pagaría bastante dinero por unos audífonos con cancelación de ruido que se pudieran hackear.