Este documento descreve o processo pelo qual passei para engenharia reversa do protocolo Bluetooth do meu detector de radar Cobra Irad 900. Meu objetivo inicial era fazer com que minha interface Raspberry Pi 3 com o dispositivo via Bluetooth para lidar com alertas sem ter que usar o aplicativo iOS/Android, eventualmente para servir como uma boa interface com meu "Carputer" Raspberry Pi.
É importante observar que eu não tive experiência inicial com o protocolo Bluetooth, mas foi uma experiência de aprendizado bastante divertida em geral.
Quando iniciei esse projeto, não fazia ideia de onde começar, mas com o Google. Eu sabia como cheirar o tráfego regular da web, mas o Bluetooth era um pouco preto para mim. Com algumas pesquisas rápidas, encontrei a biblioteca Pybluez, bem como exemplos de comunicação através da RFCOMM. Também encontrei vários bons recursos, incluindo uma postagem interessante de blog de Travis Goodspeed.
No entanto, pouca orientação sobre o assunto, também gastei muito tempo em recursos como esse, pensando que Bluetooth Le era o que eu estava procurando.
Brincando com meu antigo iPhone 5 do Jailbroken, pude usar o BtServer para registrar o tráfego Bluetooth enviado e recebido pelo meu iPhone. Sendo cercado por vários dispositivos Bluetooth, os arquivos de log cresceram rapidamente, embora não fosse um problema. Felizmente, os logs foram produzidos como um arquivo .pklg, facilitando o filtro dos pacotes relevantes no Wireshark.
Usando o filtro de pacotes bluetooth.src == B8:92:1D:00:3F:61 , pude ver os pacotes brutos que o aplicativo iOS estava enviando para o detector de radar. Tomei algumas gravações de amostra da comunicação entre meu telefone e o detector de radar, algumas com alertas sendo gerados e outros sem.
Os dados Bluetooth são transferidos pelo protocolo RFComm. Quando os dispositivos se conectam primeiro, eles enviam algumas informações, provavelmente apenas sincronizando as configurações (mais sobre isso mais tarde). Depois, os dois dispositivos seguem um padrão previsível entre si. O detector de radar enviará um pacote RFComm através do Bluetooth em intervalos regulares de 1/2 segundo. Com algum tempo e paciência, pude decifrar a estrutura da carga útil enviada do detector de radar para o iPhone.
Estrutura da carga útil: Detector de radar → iPhone
| Item | Valor (hexadecimal) | Tamanho |
|---|---|---|
| Preâmbulo | 55 | 1 byte |
| Tamanho da carga útil | xx xx | 2 bytes |
| Ação | xx | 1 byte |
| Reservado | 00 | 1 byte |
| Seq | xx | 1 byte |
| Reservado | xx xx xx xx xx xx | 6 bytes |
| Alerta | xx | 1 byte |
| Tipo de alerta | xx | 1 byte |
| ... | ... | ... |
À medida que o detector de radar está em execução, ele estará enviando pacotes no formato acima. Embora a rede de computadores não seja minha área de especialização, tentarei explicar o melhor que pude.
O byte preâmbulo enviado é sempre enviado com o valor 0x55 . Isso especifica que é o começo de uma nova mensagem de carga útil do dispositivo, em vez de continuar a partir de um pacote anterior. Posteriormente, um valor de 2 bytes que contém o tamanho do restante da mensagem (tudo após os três primeiros bytes). O valor da ação especifica o tipo de informação que o pacote está enviando.
O número do SEQ é onde as coisas começam a ficar interessantes. Se você teve uma aula sobre redes ou souber um pouco sobre o TCP, provavelmente já sabe para que serve. O detector de radar enviará um valor de 1 byte para o iPhone e o aplicativo iOS deve responder com um número ACK do mesmo valor. Caso contrário, o detector de radar perceberá que algo é errado e se desconectará.
O byte Alert especifica se um alerta estiver sendo acionado. Nesse caso, é o conjunto de valor 0x41 e o seguinte byte é usado para especificar o tipo de alerta estar sendo enviado. Não consegui descobrir muito sobre os valores, pois não possuo uma pistola de radar real. No entanto, um cara da Instructables fez um simulador de armas LIDAR usando um Arduino. Isso ajudou muito a analisar os pacotes.
Para que o aplicativo iOS mantenha a conexão com o dispositivo, ele precisa enviar uma resposta no formato correto. Felizmente, a resposta ao detector de radar é muito mais simples e é de apenas 9 bytes.
Resposta: iPhone → Detector de radar
| Item | Valor (hexadecimal) | Tamanho |
|---|---|---|
| Preâmbulo | 55 | 1 byte |
| Tamanho da carga útil | xx xx | 2 bytes |
| Ação | 02 | 1 byte |
| Reservado | 00 | 1 byte |
| ACK | xx | 1 byte |
| Reservado | 00 42 | 2 bytes |
| Contador | xx | 1 byte |
Como mencionado anteriormente, o valor ACK deve ser o mesmo valor que o valor SEQ recebido anteriormente, caso contrário, a conexão será desconectada. Isso foi fácil o suficiente. Alguns outros protocolos podem ter métodos muito menos óbvios de verificação do cliente; Felizmente, esse não foi o caso. Curiosamente, há outra variável counter -usada. Eu realmente nunca descobri para que serve o byte, mas diminui em 1 para cada resposta ao dispositivo. Ambos os valores foram fáceis de codificar em um script python e não fizeram muito trabalho.
Como mencionei anteriormente, quando o aplicativo iOS se conecta primeiro ao detector de radar, algumas configurações e dados são sincronizados para frente e para trás. Não era realmente uma prioridade minha descobrir e quebrar esses pacotes, e eu não queria passar muito tempo com isso. Exportei todo o Logo de pacotes Wireshark como um arquivo XML (data.xml) e usei um script python (parsedata.py) para processar e armazenar as informações para uso posterior.
Quando carregado, o radar.py abrirá os dados pré-processados no arquivo packetdata.dat. Em seguida, ele digitaliza o detector de radar via Bluetooth e tenta se conectar a ele. Uma vez conectado, o detector de radar enviará alguns pacotes de dados para o dispositivo conectado. Felizmente, eles são os mesmos pacotes exatos na mesma sequência exata a cada vez. O script python analisará os dados do arquivo packetData.dat para o pacote que ele recebeu. Uma vez que o script Python principal encontre um pacote de máquinas, ele envia a resposta correspondente anteriormente gravada ao detector de radar.
Surpreendentemente, funcionou muito bem. No entanto, eu imagino que precisaria atualizar o arquivo de dados se alterasse alguma configuração no aplicativo iOS. Não foi um problema demais, já que eu precisaria apenas configurar o dispositivo uma vez e provavelmente nunca mais usar o aplicativo.
Dadas todas as informações que descobri, pude escrever um script python que emula a conexão do iPhone. Se um pacote não for encontrado no banco de dados de respostas gravadas, ele constrói um pacote de resposta com a estrutura que eu detalhei anteriormente acima.
Olhando para trás, foi um projeto muito divertido fazendo algo com o qual eu realmente nunca tive experiência. Como especialista em ciência da computação, foi interessante fazer algo com hardware pela primeira vez, isso é mais ou menos fora do ordens.
Brandon ASunion // [email protected]
Qualquer comentário/feedback é apreciado!