Ajustando o volume dos meus earbuds Bluetooth
(blog.ornx.net)- Os sons do sistema de pareamento, conexão e desconexão dos earbuds Tozo T6 eram altos demais, então isso foi resolvido reduzindo diretamente o ganho dos arquivos de áudio dentro do firmware
- O chipset foi estimado como sendo da família Airoha AB1562, e foi confirmado que o app AirReps156X podia fornecer informações de diagnóstico e talvez enviar firmware modificado
- O tráfego de verificação de atualização do app Tozo foi interceptado com mitmproxy, e o link do binário de firmware dos earbuds foi obtido na resposta de
/api/v1/getOtaVersionV3 - O firmware era composto por 2 FotaPackages para os earbuds esquerdo e direito e 2 FileSystemImages, e dentro da imagem de sistema de arquivos alvo da modificação havia arquivos mp3 originais intactos
- Depois de reduzir apenas -19.5dB com
mp3gain, sem recodificar os mp3 nem alterar seu tamanho, os bytes dentro da imagem foram substituídos e o firmware foi gravado; o dispositivo continuou funcionando normalmente e o som ficou bem mais baixo
Sons do sistema altos demais e hipóteses iniciais
- Os earbuds Tozo T6 reproduziam sons ao parear, conectar e desconectar, e esse volume era muito mais alto do que o usuário considerava confortável
- Reduzir alguns dB em toda a faixa no equalizador não resolveu, e após contato por e-mail com a Tozo, a empresa respondeu que não havia nada que pudesse fazer
- O objetivo era modificar o firmware executado no dispositivo para baixar o volume desses arquivos de som
- No começo, a abordagem foi baseada em algumas suposições
- Seria possível obter online o binário de firmware do dispositivo
- O firmware poderia ter uma estrutura binária mais fácil de entender, como ELF
- Os arquivos de áudio estariam incluídos no firmware e, sabendo o offset e o tamanho, seria possível modificá-los
- O áudio poderia estar em um formato simples, como PCM
- O firmware modificado poderia ser gravado com uma ferramenta para o dispositivo ou para o chipset
- Na prática, várias dessas suposições estavam erradas, e mais tempo foi gasto configurando infraestrutura de análise como proxies e procurando caminhos alternativos do que propriamente fazendo engenharia reversa
Identificando o dispositivo e o chipset
- Em eletrônicos baratos, normalmente há várias camadas e agentes envolvidos
- O fornecedor que vende o produto com sua marca, neste caso a Tozo
- O chipset, que é o hardware central que executa o firmware
- O chipset pode usar uma ISA derivada de tecnologias-base como ARM ou MIPS
- Funções para coprocessadores adicionais ou interfaces de hardware também podem estar integradas
- Ao desmontar o app Android da Tozo, foram encontrados o Airoha SDK, referências a modelos específicos de chipset e funções básicas de comunicação com o dispositivo
- A direção da investigação também foi influenciada por informações encontradas na comunidade do Reddit
/r/airreps, voltada a réplicas de AirPods, onde o app AirReps156X também apareceu - O app AirReps156X usa o Airoha SDK e conseguia mostrar informações de diagnóstico de dispositivos Airoha
- Ao conectar o dispositivo a esse app, apareceu a string de diagnóstico
QW_1562U_SDK1.5.1, o que levou à conclusão de que o chipset do dispositivo era da série Airoha AB1562 - O AirReps156X também tinha função para gravar novo firmware, atendendo um requisito essencial para enviar o firmware modificado ao dispositivo
Encontrando a URL do firmware no tráfego do app Tozo
- O app Tozo mostrava a versão atual do firmware e se ela era a mais recente quando conectava aos earbuds
- Como o app claramente consultava o servidor para verificar firmware novo, a ideia foi localizar a URL real do arquivo de firmware durante essa checagem
- Em vez de seguir apenas com análise estática lendo todo o código decompilado, foi escolhida uma análise dinâmica, observando diretamente as requisições de rede
- Foi montado um proxy de interceptação com NIC sem fio,
hostapdemitmproxy - O APK da Tozo foi modificado com
apktooleuber apk signerpara confiar no certificado TLS do mitmproxy presente no repositório de CAs do usuário- Muitos apps Android, por padrão, consultam apenas o repositório de CAs do sistema
- O patch no APK permitiu usar também o repositório de CAs do usuário, e o app foi assinado novamente para rodar no Android
- A configuração do proxy também incluiu AP, redirecionamento de tráfego 80/443 para a porta do mitmproxy com
iptablese configuração de NAT - Quando o app mostrava “current” ao lado da versão do firmware, ele fazia uma requisição para o endpoint
/api/v1/getOtaVersionV3, e a resposta continha os links dos bins de firmware necessários
Estrutura dos arquivos de firmware e análise
- O firmware obtido era composto por 4 arquivos ao todo
- Um
FotaPackagepara cada earbud, esquerdo e direito - Um
FileSystemImagepara cada earbud, esquerdo e direito
- Um
- As duas imagens de sistema de arquivos eram idênticas, então os arquivos únicos eram 2 FotaPackages para esquerdo e direito e 1 imagem de sistema de arquivos, totalizando 3 arquivos
- Foram usados
file,strings,hexdumpebinwalkpara tentar identificar o formato e arquivos embutidos - Na imagem de sistema de arquivos, algumas strings com nomes de arquivo eram visíveis, mas o
binwalknão encontrou os mp3 esperados - Como mp3 não tem um magic number claro nem footer, era difícil determinar com segurança seu offset e tamanho dentro de um binário arbitrário
- O início poderia ser
0xFFFFou0xFFFE - Mas nenhum dos dois era distintivo o bastante para identificar um arquivo com segurança
- O início poderia ser
- A partir da ideia de que entender a estrutura da imagem de sistema de arquivos revelaria o começo e o fim de cada arquivo, o foco passou a ser entender esse formato de imagem
Análise de entropia e ROFS
- A análise de entropia é útil para visualizar quais partes de um arquivo se parecem mais com constantes, ruído aleatório, texto ASCII e onde ocorrem transições
- A imagem de sistema de arquivos parecia estruturada, mas os arquivos FotaPackage aparentavam estar compactados ou criptografados
- Os FotaPackages do lado esquerdo e direito diferiam apenas em partes esparsas do cabeçalho, com o corpo quase idêntico, até divergirem completamente em cerca de 7KB no final
- Não foi possível determinar exatamente o que essa diferença significava, mas como havia uma transformação opaca envolvida, concluiu-se que seria difícil extrair algo útil sem grande esforço
- A imagem de sistema de arquivos começava com a string ASCII
ROFS - Não foi encontrada documentação pública nem descrição de formato correspondente para
ROFS, e mais tarde foi descoberto que o Airoha SDK continha a implementação da interface que lia essa imagem - Em certo momento foi tentado um caminho para decifrar o FotaPackage, mas isso serviu apenas para confirmar que o SDK não transformava o firmware antes do envio, sem resultados práticos
Reduzindo o mp3 sem recodificar
- O fato de os arquivos serem mp3 foi visto no início como um risco
- Codificadores mp3 têm muitas opções, e um decodificador desconhecido pode falhar ao processar certos arquivos válidos
- Se o áudio reproduzido logo após a conexão causasse algum problema, o dispositivo poderia travar antes de se reconectar, tornando a recuperação impossível
- Recodificar o mp3 poderia alterar o tamanho do arquivo, exigindo talvez ajustar também com precisão as informações de tamanho dentro da imagem de sistema de arquivos
- Felizmente, era possível ajustar o ganho do mp3 sem recodificação, sem mudar o tamanho e sem mexer nos metadados
- Isso é semelhante a girar um JPEG sem recodificá-lo: a mudança afeta apenas parte da estrutura interna dos dados
A pista decisiva vinda do SDK
- Pesquisando pelo nome do chipset, foi encontrada uma cópia do Airoha SDK, e dentro dela havia arquivos
.mp3iguais aos sons ouvidos no dispositivo - Foi criado um pequeno programa Python,
bincontains.py, para verificar quais arquivos estavam incluídos literalmente dentro de outro binário - Isso confirmou que os mp3 do SDK estavam presentes na imagem de sistema de arquivos exatamente como os originais
- Não estavam compactados
- Não estavam divididos em blocos
- Portanto, era possível calcular o offset e o tamanho deles dentro da imagem
- Também foi feita uma leitura rápida do código do SDK relacionado ao ROFS, e não apareceram símbolos que sugerissem fortemente a existência de checksum
- Nesse ponto, as condições necessárias para a modificação estavam reunidas sem necessidade de mais engenharia reversa
- Havia os arquivos de firmware e uma forma de gravá-los
- Era possível localizar e medir os arquivos mp3 dentro da imagem
- O ganho do mp3 podia ser ajustado sem alterar o tamanho
- Assumiu-se que trocar apenas o intervalo de bytes do arquivo não quebraria os metadados do sistema de arquivos
Modificando a imagem de sistema de arquivos e gravando o firmware
- Um script em Bash percorria os arquivos mp3 do SDK para localizar quais estavam incluídos na imagem de sistema de arquivos
- Os mp3 encontrados eram copiados para arquivos temporários e tinham o ganho reduzido com
mp3gain - O valor aplicado foi de -19.5dB
- Depois de confirmar que o tamanho dos mp3 modificados era igual ao original, os bytes eram sobrescritos no offset correspondente da imagem com
dd - A imagem final do firmware mostrava, no diff binário, apenas as poucas alterações esperadas
- O firmware modificado foi então gravado no dispositivo, que continuou funcionando normalmente, com os sons do sistema muito mais baixos do que antes
Resultado e limitações
- Não foi necessário decifrar a criptografia do firmware nem entender completamente o formato do sistema de arquivos
ROFS - Na prática, grande parte do tempo de engenharia reversa foi gasta em desvios que não eram diretamente necessários para a solução final
- Se o ajuste de volume dos sons do sistema fosse um recurso nativo do dispositivo, essa modificação não teria sido necessária
- Em qualquer aparelho que reproduza áudio, faria mais sentido haver no UI um controle de volume aplicado a todos os sons emitidos pelo dispositivo
- Neste caso, porém, reduzir apenas o ganho dos mp3 dentro da imagem de firmware foi um desvio suficiente e eficaz
1 comentários
Opiniões do Hacker News
Queria que alguém consertasse assim também a minha máscara de dormir Bluetooth
No geral ela é bem boa, mas, quando a bateria está baixa ou está na hora de desligar, ela avisa isso no volume máximo
Numa máscara de dormir
Já usei um despertador com um defeito parecido, que tinha um recurso de sincronização de horário por rádio MSF
Só que, toda vez que ele resincronizava com o sinal horário MSF, fazia o mesmo som do alarme por 2–3 segundos, e não dava para desligar
Sempre tocava em um horário horrível, tipo 3 da manhã, então no fim eu abri o aparelho, cortei a antena MSF, e passei a dormir melhor sabendo que o relógio sempre ficava um pouco errado
Nesse intervalo, tento recuperar o que a pessoa do outro lado da chamada falou por alguns segundos, mas não dá muito certo
Esse aviso é muito pior do que não fazer nada. Sem aviso, o pior caso é o som cortar e eu perder a fala da outra pessoa; o ear clip cria exatamente esse efeito de propósito, só que em um cronograma mais antecipado
Não há motivo para não misturar isso ao fluxo de áudio existente como algum padrão discreto de bipes. Levaria menos de 1 segundo e não criaria por si só o problema que está tentando evitar
Entre comportamentos ruins de Bluetooth difíceis de imaginar, também há o caso em que, ao usar chat de voz, todo o áudio normal do computador desaparece. Quando o chat de voz usa a entrada do microfone, o dispositivo Bluetooth muda para o modo “headset”, e esse modo transforma estéreo em mono e passa a ser a única saída permitida enquanto uma entrada de áudio estiver sendo fornecida, ou puder vir a ser fornecida
Apps que não usam entrada de áudio continuam tentando tocar no dispositivo de fone Bluetooth que não existe mais, então todos ficam sem som
Não sei por que o dispositivo precisa ter vários modos. Não vejo motivo para querer perder funcionalidade como efeito colateral de falar com a família. Não sei o que há de tão difícil em tocar sinais de áudio diferentes nos dois ouvidos ao mesmo tempo só porque existe a possibilidade de o microfone estar ligado. Dispositivos não Bluetooth lidam com isso, e isso nem é tratado como um recurso digno de destaque. Por que “os fones não desligam enquanto uso o microfone” deveria ser algo especial?
Legal! Parabéns ao autor original por ir até o fim
Já que o assunto são earbuds altos, talvez eu tenha o problema oposto. Uso earbuds esportivos da Bose na esteira em um volume que considero confortável e conservador, mas o iPhone me mostra notificações dizendo que o volume está alto demais e que estou prejudicando minha audição
Será que o celular está certo? Se estiver, estou disposto a sacrificar um pouco de prazer pela saúde dos meus ouvidos. Mas também há outra hipótese plausível. Esses earbuds têm um volume físico real nitidamente menor do que outros produtos que já usei no mesmo ajuste de volume, então uma modelagem preguiçosa da Apple poderia gerar avisos falsos como os que recebo
Se a Apple criou um banco de dados que mapeia modelo de produto e ajuste de volume para volume físico real, eu elogiaria. Mas as notificações e a descrição do recurso não trazem detalhe nenhum, então não me passam confiança, e eu não quero tornar meu treino pior só porque a Apple colocou em um produto real um modelo de nível de trabalho de faculdade
Alguém sabe se a ciência de dados por trás dessas notificações é boa mesmo?
Primeiro, no iOS, o volume mínimo dos meus earbuds Bluetooth é alto demais. Isso aconteceu com todos os fones de terceiros que já testei, e há reclamações online sobre isso há 10 anos. A UE até aprovou uma lei mandando corrigir, mas spoiler: não adiantou
Por favor, o volume mínimo da UI deveria mapear para o inteiro 1 do volume de hardware
Segundo, apps de terceiros não conseguem expor músicas ou podcasts no menu de navegação de mídia Bluetooth do carro. No Android, conseguem
Então, no Android, consigo ouvir podcasts e fazer streaming do Tidal usando o botão giratório do carro, mas no iOS não
Também tenho outras reclamações sobre Bluetooth. Por que meu Apple Watch coloca o som estéreo do carro em blacklist? O Bluetooth das versões N e N-1 do iOS é realmente cheio de bugs
É simplesmente um recurso obviamente idiota. Se eu conseguisse fazer root, poderia desligar aquela chave em algum arquivo de configuração, mas nunca consegui em um Samsung Galaxy J1 (2016)
Meu Bose também se comporta de maneiras diferentes dependendo do chipset Bluetooth. No Linux, preciso colocar o volume em 150% para ouvir qualquer coisa direito
Mas não há motivo para acreditar que eles fizeram isso. Seria interessante se o fabricante do fone informasse a faixa de dB ao conectar por Bluetooth, possibilitando esse tipo de recurso, mas nunca ouvi falar disso. Ao contrário do conector de 3,5 mm, Bluetooth está dentro de uma área em que esse recurso poderia ser possível
Com cancelamento de ruído, dá para manter o volume abaixo de 20% e ainda assim ter uma audição confortável sem forçar os ouvidos
No meu caso, alguns anos atrás comecei a sentir dor nos ouvidos depois de treinos longos, então acho que os avisos da Apple provavelmente estavam certos. Depois que passei a usar cancelamento de ruído, isso desapareceu completamente
Esse tipo de trabalho é muito legal. De repente esse modelo de fone ficou bem interessante para mim
Além disso, os sons de sistema emitidos por dispositivos Bluetooth são um dos fatores que mais diferenciam um produto de outro. Alguns são absolutamente horríveis: https://youtu.be/J2wPsH64JEM
Mas nunca vi reviews ou páginas de produto informarem que sons o produto emite. Mesmo sendo algo que você precisa ouvir várias vezes por dia e que nem dá para desligar
Só permitir alterar esses sons já seria uma diferenciação bem fácil
Ele é perfeito quando estou em um ambiente de trabalho barulhento usando protetores auriculares, mas, quando coloco música baixinho para me concentrar em um escritório silencioso, ele incomoda e dá susto
Não entendo por que os sons de sistema não seguem a configuração de volume
Seria bom se o celular pudesse saber se o headset conectado é um conjunto de caixas de som, monitores intra-auriculares, condução óssea etc.
A notificação de “volume alto demais” é irritante quando estou usando um conjunto de caixas comum e quero deixar alto de propósito para ouvir de qualquer lugar da casa
Com fones de condução óssea, é duplamente irritante, porque eles precisam de um volume bem alto para serem ouvidos direito
Ainda bem que isso é para um alvo Airoha sem criptografia de firmware
Para quem tiver curiosidade, também há um template do 010 Editor para o formato do firmware
https://github.com/ramikg/airoha-firmware-parser
Reconheço a habilidade, mas é triste que seja necessário tanto esforço para fazer algo tão básico quanto mudar um pouco o volume da reprodução de um arquivo
Não deveria ser preciso tanto trabalho para fazer uma ferramenta se comportar do jeito que você quer
Não é “compreensível”. Você pagou pelo produto, e isso é um problema do produto que precisa ser corrigido
Depois de ler este texto, comprei um Tozo T6 usado e, embora por fora parecesse ter sido fabricado bem recentemente, não consegui reproduzir o resultado
O app oficial da Tozo nem reconheceu o headset, e também não consegui confirmar se ele usava um chipset Airoha identificado pelo suporte a AAC. O meu só oferece suporte a SBC
Acho que comprei uma falsificação, ou houve uma mudança interna depois que o autor comprou o dele
Alguns arquivos de áudio soam iguais aos incluídos no SDK parcial da Airoha que existe na internet, mas ele também reproduz outros arquivos de voz novos
Se você quiser verificar esse resultado de forma independente ou brincar com isso, AirPods falsos podem ser um caminho melhor
Queria que mais gente reclamasse de sons de sistema altos e ruins
Meu Sony WH-1000XM4 tem exatamente o mesmo problema, mas parece que a Sony criptografa o payload do firmware e o descriptografa no dispositivo
Quase desmontei o fone para fazer dump de tudo e explorar, mas minhas mãos tremem e a chance de estragar é grande demais
Eu pagaria uma boa quantia por um headset com cancelamento de ruído que fosse hackeável