2 pontos por GN⁺ 2023-12-16 | 1 comentários | Compartilhar no WhatsApp
  • Durante o processo de engenharia reversa para integrar um conjunto de luzes LED Bluetooth LE barato ao Home Assistant, ao testar valores de efeitos ocultos em uma string de LED endereçável de 10 m, o controlador acabou parando de funcionar
  • Com o Bluetooth HCI snoop do Android e Wireshark/tshark, foram capturados os pacotes BLE que o app gravava na iluminação, rastreando os bytes de controle nas requisições de escrita btatt.opcode.method==0x12
  • Os pacotes do app iDeal LED não pareciam simples valores de ligar/desligar, então, após descompilar o APK e consultar uma análise existente, eles foram descriptografados com uma chave AES fixa dentro de libAES.so
  • Os pacotes descriptografados de ligar/desligar se resumiam a um cabeçalho fixo e à diferença de 1/0 no 5º byte, e os padrões de bytes de cor, brilho e efeitos foram registrados executando repetidamente cada função
  • Ao enviar valores de 8 bits além do intervalo de 5 bits 0x1F usado pelo app para RGB, foi possível obter cores mais brilhantes, mas no momento em que o efeito número 12 foi enviado, as luzes apagaram e até o anúncio Bluetooth desapareceu

O ponto de partida para integrar luzes BLE baratas à automação residencial

  • Partindo da premissa de que dispositivos que se comunicam por Bluetooth LE e têm app dedicado podem ser integrados a sistemas de automação residencial, várias fitas de LED baratas foram alvo de engenharia reversa
  • Antes disso, uma fita de LED não endereçável de 5 m com controle por Bluetooth LE que custou £2,38 foi conectada ao Home Assistant em poucas horas, e o código relacionado está publicado em bj_led
  • Há também um trabalho de engenharia reversa do controlador LEDnetWF em lednetwf_ble
  • O alvo desta vez era uma string de LED endereçável de 10 m que estava sobre a mesa e era controlada pelo app “iDeal LED”
    • O app tem muitos recursos e funciona relativamente bem
    • Os LEDs provavelmente são WS2812 ou algo semelhante
    • O produto é uma iluminação comprada no AliExpress

Capturando os bytes BLE enviados pelo app

  • Para controlar o dispositivo com software próprio, primeiro era preciso ver a sequência de bytes que o app enviava ao dispositivo via Bluetooth
  • Um protocolo típico de iluminação pode ser composto por cabeçalho, bytes de comando para ações como ligar/desligar ou mudar a cor, e um rodapé que talvez seja um checksum
  • No Android, a captura foi feita na seguinte sequência
    • Ativar o modo de desenvolvedor
    • Instalar o app da iluminação
    • Ativar Bluetooth HCI snoop nas opções de desenvolvedor
    • Executar ações no app, como ligar e desligar as luzes
    • Copiar o log para o computador com adb pull sdcard/btsnoop_hci.log .
  • Ao abrir o log no Wireshark, é possível ver os bytes enviados para as luzes
    • Exemplo de filtro: bluetooth.dst == ff:ff:ff:ff:ff:ff && btatt.opcode.method==0x12
    • O endereço MAC deve ser trocado pelo MAC real das luzes
    • btatt.opcode.method==0x12 significa que houve uma operação de escrita do dispositivo Android para as luzes
  • Usando tshark, também dá para extrair os valores dos pacotes diretamente no terminal
    • tshark -r <filename> -T fields -e btatt.value imprime a carga útil gravada no controlador LED

O protocolo do iDeal LED não podia ser resolvido só com replay

  • Algumas luzes mostram padrões quase legíveis na operação de ligar/desligar
    • Um exemplo é a repetição de 69 96 02 01 01 e 69 96 02 01 00
    • O último byte alterna entre 1 e 0, indicando ligado/desligado
  • Nesta luz iDeal LED, a sequência de bytes repetida era muito mais longa, e embora fosse possível distinguir os dois tipos de pacote correspondentes a ligar/desligar, os valores pareciam ruído
  • Se o objetivo fosse apenas ligar e desligar, poderia bastar um replay retransmitindo exatamente a sequência de bytes capturada
    • É possível conectar-se a um dispositivo BLE com gatttool e enviar bytes
    • O handle a ser usado precisa ser identificado no Wireshark
  • Para obter mais controle, era necessário entender a estrutura dos pacotes, então a análise avançou para o próprio app Android

Descompilando o APK e encontrando a chave AES

  • O APK foi baixado e aberto com jadx para inspecionar o código do app
  • Referências a AES apareceram no código-fonte, levantando a possibilidade de que o protocolo estivesse criptografado
  • Para os dados criptografados, foram assumidas as seguintes condições
    • O texto cifrado da mesma ação não mudava a cada vez, então poderia haver uma chave consistente
    • Como a descriptografia precisava ser rápida em um MCU de baixo consumo, uma chave curta seria vantajosa
    • A chave poderia ser fixa, e não única por dispositivo
  • O app continha uma biblioteca AES compilada chamada libAES.so, que não podia ser analisada apenas com jadx
  • Foi encontrada uma análise em que outra pessoa descompilou a biblioteca AES com ida free e encontrou a chave embutida, e essa chave foi testada
  • Ao descriptografar com AES no modo ECB de Crypto.Cipher, os pacotes de ligar/desligar passaram a ter uma forma compreensível
    • Os valores descriptografados apareciam como 05 54 55 52 4E 01 ... e 05 54 55 52 4E 00 ...
    • Após um cabeçalho fixo, o 5º byte alternava entre 1 e 0, indicando ligado/desligado
    • O restante era preenchido com zeros
  • A partir daí, tornou-se possível descriptografar os pacotes enviados pelo app e reproduzir o mesmo controle em código próprio

Registrando padrões de bytes por função

  • O alcance do protocolo foi ampliado executando cada função do app uma a uma e registrando os bytes transmitidos
  • Cada ação foi repetida várias vezes, com padrões de desligar/ligar inseridos entre seções para facilitar a distinção
    • As cores eram alteradas várias vezes na ordem red, green, blue
    • O brilho era alterado para 100%, 50%, 10%, 50%, 100%
    • Off/on era inserido entre cada grupo para facilitar encontrar os limites no log capturado
  • Com esse método, foi possível ver quais bytes mudavam em cada ação e correlacionar as ações registradas com os pacotes capturados

O efeito número 12 que transformou o controlador em tijolo

  • Ao investigar a mudança de cor, foi confirmado que o app não enviava valores maiores que 0x1F para red, green e blue
    • 0x1F corresponde a um intervalo de 5 bits
    • Ao enviar diretamente valores de 8 bits, cores mais brilhantes funcionaram
  • Para verificar se havia efeitos adicionais além dos 10 usados pelo app, foi executado um loop range(20) enviando os números de efeito em sequência
    • De 1 a 10, tudo funcionou normalmente
    • Em 11, foi observado algo que parecia um modo oculto
    • Ao passar para 12, as luzes se apagaram
  • Depois disso, as luzes não voltaram a ligar
    • Elas deixaram de anunciar via Bluetooth
    • Também não foi mais possível conectar
    • Nem segurar o botão ao ligar a energia restaurou o funcionamento
    • Nem deixá-las desconectadas durante a noite fez com que voltassem
  • Suspeitou-se que um buffer overflow pudesse ter corrompido o firmware, mas a causa não foi confirmada
  • Como os próprios LEDs são LEDs endereçáveis padrão, a string pode ser reutilizada ligando-a a outro microcontrolador

O que sobrou e os cuidados necessários

  • Apesar da falha, a maior parte do protocolo foi documentada, e foi criado um projeto no GitHub com um componente customizado do Home Assistant incluído
  • O componente funciona, mas experimentos do mesmo tipo podem danificar o controlador das luzes, então devem ser feitos por conta e risco

1 comentários

 
GN⁺ 2023-12-16
Opiniões no Hacker News
  • Em vez de um “cabeçalho fixo” do FTA, parece mais ser um byte de comprimento (“o comando tem 5 bytes”), com o comando TURN, o argumento 0/1, e o restante preenchido com zeros até 16 bytes

    • 54 55 52 4E salta aos olhos imediatamente como as letras maiúsculas TURN
      Sabendo que números começam em 0x30, maiúsculas em 0x41 e minúsculas em 0x61, fica fácil encontrar padrões alfanuméricos em um dump hexadecimal
      Esse conhecimento é útil para strings curtas, mas, ao olhar pacotes ou dumps de memória, o formato hexdump padrão é o melhor
    • Bem observado. 0x54 55 52 4E é de fato T U R N
    • Boa descoberta. Vou verificar outros comandos para ver se a hipótese do byte de comprimento se confirma; parece plausível
    • É bem provável que não seja padding, e sim apenas um uint
    • Nesse caso, é como se o cabeçalho fosse fixo com base no comprimento e no ponto inicial
  • Pode ser um problema de alimentação elétrica. A família WS281x consegue acender com muito brilho e, quando vários são agrupados, consome uma corrente enorme
    Para uma fita de 100 LEDs com uma fonte de 12 V 3 A, mal dá para acender tudo em branco no brilho máximo, e fica extremamente ofuscante
    Então eu olharia primeiro para um fusível queimado. O fato de o firmware usar no máximo 31 de 255 no brilho também é uma pista

    • Quando vi que o brilho estava limitado a 0x1f, também pensei nisso de início. Com sorte, a fonte tem um fusível e talvez só ele tenha queimado
      Mesmo que não dê para recuperar, uma string de LEDs WS281x padrão pode ser conectada a um Raspberry Pi, e também dá para usar meu controlador open source de LEDs endereçáveis :) https://github.com/mbevand/ledthemfight
      Ele tem efeitos integrados e foi feito de forma bem modular para DIY, então com duas linhas de Python dá para criar um módulo simples de efeito LED personalizado. A demo está aqui: https://youtu.be/qpd2rILsnM4
    • Boa ideia. Vou pegar o multímetro
    • Isso não parece WS2812. Pelo link do Ali postado, a fita tem quatro fios: 12V, vermelho, verde e azul
      Parece uma fita RGB analógica, em que a fita inteira acende da mesma cor, não LEDs endereçáveis individualmente
      https://www.aliexpress.com/item/1005005485885067.html
      Quem quiser mexer com iluminação LED precisa ver o WLED. Ele tem muitos efeitos integrados, uma GUI web, usa um ESP32 ou ESP8266 bem barato como controlador e também pode reagir a som. Estou usando WLED nas luzes de Natal internas agora, e está ficando muito bom
    • Obrigado pela dica. Atualizei o código para deslocar 3 bits à direita e voltar a ser um número de 5 bits
      É uma forma elegante de limitar o consumo de energia
  • Ótimo texto. Lembro de ter tentado fazer engenharia reversa das luzes que tenho e descobrir que estavam criptografadas
    Uma era uma amaran 60d, e as outras eram algumas luzes LED SmallRig RM75 a bateria; eu queria ligar e desligar todas com um script só, sem ter que mexer em dois apps separados
    Passei bastante tempo fazendo engenharia reversa dos apps e dos protocolos, e parecia que as duas luzes usavam o mesmo procedimento de negociação, mas implementado com bibliotecas diferentes
    Tentei imitar a troca de chaves Diffie-Hellman feita na conexão, mas acabei desistindo. Pelo que lembro, havia mais uma ou duas etapas depois; após enviar a primeira chave, ele enviava outro número que parecia aleatório (outra chave?), e não consegui descobrir o que ele queria
    Este texto me fez pensar que eu deveria simplesmente tentar colocar uma chave hardcoded e ver se funciona

    • Seria muito bom se você tivesse sucesso com as luzes Amaran. Isso provavelmente poderia levar à engenharia reversa de toda a linha Aputure
      Uma integração open source para Elgato Stream Deck ou Home Assistant seria um grande caso de sucesso. Para o pessoal do YouTube que grava vídeos de talking head na mesa, seria muito melhor do que controlar as luzes pelo app do celular
  • Tentei automatizar luzes de Natal conectadas por BLE e criei lixo eletrônico. Agora você também pode

    • Não sei como você fez, mas já vi alguns desses SmartTrash fazerem hard reset com uma sequência mágica, tipo desligar e ligar rapidamente 5 vezes
    • Se quiser algo mais centrado em GUI para sniffar pacotes BLE, experimente o app nRF Connect
      Não sei no iPhone, mas no Android, se você deixá-lo em segundo plano, ele consegue capturar atividade BLE em uma GUI limpa no celular. Uso todos os dias
    • Se você contornar o controlador, ainda pode usar como luzes burras/clássicas
  • Isso me lembra MCUs de teclado que viravam tijolo ao receber certos comandos de iluminação
    O OpenRGB acabou tendo que desativar aquele módulo para que ele não fosse executado automaticamente nesse hardware. Às vezes, o software do fabricante também provocava o mesmo bug
    Infelizmente, em geral era preciso enviar um relatório USB HID para entrar no modo de programação no sistema, mas os dispositivos afetados nem sequer enumeravam mais
    Se de fato havia corrupção de firmware, ou se o hardware foi danificado por algum outro comportamento indefinido, é outra questão

  • “Enviar texto puro pelo ar não é inseguro?”
    “Não se preocupe, colocamos criptografia AES

    • A Tuya é realmente hilária nesse ponto. O protocolo é basicamente TLS sobre TCP, mas, toda vez que o app adiciona um novo dispositivo, ele espalha a senha do Wi-Fi para todas as STAs ao redor
      É assim que o pareamento funciona. O app sai transmitindo pacotes em broadcast para 255.255.255.255, e o dispositivo alvo (lâmpada, tomada etc.) fica aguardando em modo promíscuo
      O conteúdo dos pacotes é protegido por WPA2 etc., mas o comprimento dos pacotes não é protegido; então ele envia um monte de pacotes minúsculos, definindo o valor do byte ASCII do próximo caractere do handshake de configuração como o comprimento de cada pacote. Provavelmente envia isso repetidas vezes
      Por isso o pareamento leva 2 minutos e sempre para de repente antes de o contador chegar a 0
    • Parece criptografia contra o ar
  • Foi exatamente isso que me preocupou bastante no ano passado, quando fiz engenharia reversa do controlador BLE da minha lareira
    Especialmente porque o comando “Set password” aceita entrada em bytes brutos, enquanto o app do OEM só enviava dados numéricos com limite de tamanho
    Felizmente, parece que ele esquecia tudo o que tinha acontecido antes se ficasse sem energia por um instante
    Por isso, acho que a maioria dos controladores BLE da mesma marca continua com a senha padrão 0000. Se houver uma queda de energia, no fim eles voltam para esse estado. Se você estiver realmente entediado, isso pode ser um bom tema para BLE wardriving
    Eu também transformei o resultado da engenharia reversa em uma integração com o Home Assistant (https://github.com/kaechele/napoleon-efire) e escrevi a documentação do sistema e do protocolo (https://bonaparte.readthedocs.io/en/latest/index.html)

  • Estou procurando luzes flexíveis e resistentes para colocar no rack de teto do carro
    Precisam funcionar com bateria, ser adequadas para uso externo/em qualquer clima, e seria bom se a caixa de bateria pudesse ser presa facilmente à superfície com abraçadeiras
    Se possível, queria algo no formato “mini”, T5, e que fosse RGB e programável, para usar sazonalmente: vermelho/verde no Natal, roxo/laranja no Halloween etc.
    Queria saber se alguém conhece um produto que atenda a esses requisitos. Os três primeiros dá para encontrar no Walmart ou na Home Depot, mas foi difícil achar algo que satisfaça o último
    As buscas só retornam um monte de ruído
    [1] https://cdn.christmaslightsetc.com/images/CategoryDetail/788...

    • Acho que a direção vai depender de quanto você está disposto a fazer DIY
      Por exemplo, é fácil encontrar fitas de LED de 12 V com impermeabilização IP67 (do tipo que vem dentro de um tubo de silicone) [0], e elas têm muito mais LEDs do que cordões no estilo luzes de Natal, então o efeito também deve ser mais forte
      Mas você teria que comprar e programar um microcontrolador como Arduino, ESP32 ou ESP8266, e resolver por conta própria como puxar energia da bateria do carro [1]
      Talvez dê para deixar os componentes eletrônicos dentro do carro e passar só o fio para fora do porta-malas, contando com a vedação existente do porta-malas para a impermeabilização
      [0] https://www.aliexpress.com/item/1005004289391906.html
      [1] https://www.aliexpress.com/item/1005005977505151.html
    • Também vale olhar o WS2811 no estilo “bullet string”. Se você for ligar nos 12 V do carro, ele é nativo em 12 V, normalmente vem em produtos à prova d’água com pigtail xConnect, é fácil de prender e é flexível
      Também é fácil soldar novamente com extensões ou ligar em cadeia
      https://www.aliexpress.com/item/4000105913323.html
      Pelo que li, esses produtos, ou luzes semelhantes de 5 V, parecem ser usados quase como padrão em shows de iluminação natalina ao ar livre
    • Entre no Discord do WLED e veja os canais #projects e #showcase. Há muitos projetos com iluminação RGB LED instalada em veículos
      Mas cuidado, porque é fácil se deixar levar por esse assunto
      Link de convite: https://discord.gg/eVhhh2Wh
  • Dá para ver as luzes de Natal quebradas desmontadas?
    Saber que chip há dentro pode dar pistas sobre se existe memória flash e se é fácil fazer dump dela