Este documento describe el proceso que pasé para ingeniería inversa del protocolo Bluetooth de mi detector de radar Cobra IRAD 900. Mi objetivo inicial era tener mi interfaz Raspberry Pi 3 con el dispositivo a través de Bluetooth para manejar alertas sin tener que usar la aplicación iOS/Android, eventualmente para servir como una buena interfaz con mi "Carputer" de Raspberry Pi.
Es importante tener en cuenta que no tenía experiencia inicial con el protocolo Bluetooth, pero fue una experiencia de aprendizaje bastante divertida en general.
Cuando comencé este proyecto, no tenía idea de por dónde comenzar sino con Google. Sabía cómo oler el tráfico web regular, pero Bluetooth era un poco una caja negra para mí. Con un poco de búsqueda rápida, encontré la Biblioteca Pybluez, así como ejemplos para comunicarse a través de RFCOMM. También encontré varios buenos recursos, incluida una interesante publicación de blog de Travis Goodspeed.
Sin embargo, poca orientación sobre el tema, también pasé una buena cantidad de tiempo en recursos como este, pensando que Bluetooth LE era lo que estaba buscando.
Jugando con mi antiguo iPhone 5 de jailbreak, pude usar BTServer para registrar el tráfico Bluetooth enviado y recibido por mi iPhone. Al estar rodeado de múltiples dispositivos Bluetooth, los archivos de registro crecieron rápidamente, aunque no fue un gran problema. Afortunadamente, los registros se emitieron como un archivo .pklg, lo que facilita el filtro de los paquetes relevantes en Wireshark.
Usando el filtro de paquetes bluetooth.src == B8:92:1D:00:3F:61 , pude ver los paquetes sin procesar que la aplicación iOS estaba enviando al detector de radar. Tomé algunas grabaciones de muestra de la comunicación entre mi teléfono y el detector de radar, algunas con alertas generadas y otras sin.
Los datos de Bluetooth se transfieren a través del protocolo RFCOMM. Cuando los dispositivos se conectan por primera vez, envían información de ida y vuelta, probablemente solo sincronizar la configuración (más sobre esto más adelante). Posteriormente, los dos dispositivos siguen un patrón predecible entre sí. El detector de radar enviará un paquete RFCOMM a través de Bluetooth a intervalos regulares de 1/2 segundos. Con algo de tiempo y paciencia, pude descifrar la estructura de carga útil enviada desde el detector de radar al iPhone.
Estructura de carga útil: detector de radar → iPhone
| Artículo | Valor (hex) | Tamaño |
|---|---|---|
| Preámbulo | 55 | 1 byte |
| Tamaño de carga útil | xx xx | 2 bytes |
| Acción | xx | 1 byte |
| Reservado | 00 | 1 byte |
| Sesco | xx | 1 byte |
| Reservado | xx xx xx xx xx xx | 6 bytes |
| Alerta | xx | 1 byte |
| Tipo de alerta | xx | 1 byte |
| ... | ... | ... |
A medida que se ejecuta el detector de radar, enviará paquetes en el formato anterior. Aunque las redes de computadora no son mi área de especialización, intentaré explicar lo mejor que pueda.
El byte de preámbulo enviado siempre se envía con el valor 0x55 . Esto especifica que es el comienzo de un nuevo mensaje de carga útil desde el dispositivo, en lugar de continuar desde un paquete anterior. Posteriormente es un valor de 2 bytes que contiene el tamaño del resto del mensaje (todo después de los primeros 3 bytes). El valor de acción especifica el tipo de información que envía el paquete.
El número de SEQ es donde las cosas comienzan a ponerse interesantes. Si tomó una clase en las redes, o sabe un poco sobre TCP, probablemente ya sepa para qué sirve. El detector de radar enviará un valor de 1 byte al iPhone, y la aplicación iOS debe responder con un número ACK del mismo valor. De lo contrario, el detector de radar se dará cuenta de que algo está mal y se desconectará.
El byte Alert especifica si se activa una alerta. Si es así, se establece el valor 0x41 , y el siguiente byte se usa para especificar el tipo de alerta se está enviando. No pude averiguar demasiado sobre los valores, ya que no tengo una pistola de radar real. Sin embargo, un tipo en instructables hizo un simulador de pistola LiDAR usando un Arduino. Eso ayudó mucho a analizar los paquetes.
Para que la aplicación iOS mantenga la conexión con el dispositivo, debe enviar una respuesta en el formato correcto. Afortunadamente, la respuesta al detector de radar es mucho más simple y es solo 9 bytes.
Respuesta: iPhone → Detector de radar
| Artículo | Valor (hex) | Tamaño |
|---|---|---|
| Preámbulo | 55 | 1 byte |
| Tamaño de carga útil | xx xx | 2 bytes |
| Acción | 02 | 1 byte |
| Reservado | 00 | 1 byte |
| Ack | xx | 1 byte |
| Reservado | 00 42 | 2 bytes |
| Encimera | xx | 1 byte |
Como se mencionó anteriormente, el valor ACK debe ser el mismo valor que el valor SEQ recibido anteriormente, de lo contrario, la conexión se desconectará. Eso fue bastante fácil. Algunos otros protocolos pueden tener métodos mucho menos obvios de verificación de clientes; Afortunadamente, este no era el caso. Curiosamente, hay otra variable counter que se usa. Realmente nunca descubrí para qué sirve el byte, pero disminuye en 1 para cada respuesta al dispositivo. Ambos valores fueron bastante fáciles de codificar en un script de Python y no tomaron demasiado trabajo en absoluto.
Como mencioné anteriormente, cuando la aplicación iOS se conecta por primera vez al detector de radar, algunas configuraciones y datos se sincronizan de ida y vuelta. Realmente no era una prioridad mía descubrir y desglosar esos paquetes, y no quería pasar demasiado tiempo en esto. Exporté todo el registro de paquetes en Wireshark como un archivo XML (data.xml), luego utilicé un script de Python (parsedata.py) para procesar y almacenar la información para su uso posterior.
Cuando se carga, Radar.py abrirá los datos preprocesados dentro del archivo PacketData.dat. Luego escanea el detector de radar a través de Bluetooth e intenta conectarse a él. Una vez conectado, el detector de radar enviará algunos paquetes de datos al dispositivo conectado. Afortunadamente, son los mismos paquetes exactos en la misma secuencia exacta cada vez. El script de Python revisará los datos del archivo PacketData.dat para el paquete que recibió. Una vez que el script de Python principal encuentra un paquete de maching, envía la respuesta previamente grabada correspondiente al detector de radar.
Sorprendentemente, funcionó bien. Sin embargo, me imagino que necesitaría actualizar el archivo de datos si cambié alguna configuración dentro de la aplicación iOS. No fue un gran problema, ya que solo necesitaría configurar el dispositivo una vez, y probablemente nunca volver a usar la aplicación.
Dada toda la información que descubrí, pude escribir un script de Python que emule la conexión del iPhone. Si no se encuentra un paquete dentro de la base de datos de respuestas registradas, construye un paquete de respuesta con la estructura que detallé anteriormente.
Mirando hacia atrás, fue un proyecto realmente divertido haciendo algo con el que realmente nunca tuve experiencia. Como estudiante de informática, fue interesante hacer algo con hardware por una vez que sea más o menos fuera de lo común.
Brandon Asunción // [email protected]
¡Se agradece cualquier comentario/comentario!