Love is in the air: Reverse Engineering a shitty drone

El dia 9 de marzo del 2018 - Si hace un año atras, mas vale tarde que nunca :) -, tuvo lugar la Security Jam, una mini reunion amistosa de seguridad,  donde speakers presentan sus investigaciones en un ambiente relajado.
Ese año tuve la suerte de poder participar como Speaker dando la charla llamada:

Love is in the air: Reverse Engineering a shitty drone.


Ademas de la Security Jam, presente este Research en CharruaCon y 8.8 Chile, dos conferencias muy recomendadas para los que no hayan asistido!


La idea detras de este post es hablar sobre todo el Research que dio lugar a esta charla, y publicar el codigo creado.


TL;DR

Un research realizado a un Drone SYMA X5SW con 3 objetivos definidos.
  • Interceptar la telemetria del Drone y mostrarlo en una interfaz grafica en tiempo real.
  • Crear un transmisor, utilizando modulos de RF, Arduino y codigo C.
  • Interceptar el stream de video de la camara y buscar vulnerabilidades en ella.

Hablamos sobre algunos conceptos basicos de Radiofrecuencia, consejos para empezar un proyecto de este tipo y los problemas que hubo a lo largo de el.



El research empezo con SYMA X5SW, luego de jugar un poco con el, se me ocurrio si podria intentar reversearlo y entender su protocolo de comunicacion para hijackearlo.



Objetivo 1: Interceptar la telemetria del Drone.

    La idea detras de este objetivo es poder capturar los paquetes en pleno vuelo, asi como tambien entender el protocolo de comunicacion para poder obtener cuales son las acciones enviadas por el controlador y por ultimo mostrar toda la informacion en una interfaz grafica!

    Lo primero que nos interesa averiguar es que canal de comunicacion estan utilizando el transmisor y el drone para comunicarse y asi saber que hardware vamos a necesitar, las posibilidades son:

    1. Wi-Fi
    2. Radiofrecuencia
    3. Bluetooth

    Para averiguar esto tenemos varias formas...
    1. Abrir el transmisor y reconocer los chipsets utilizados, luego buscar en internet hasta encontrar el manual y su especificacion.
    2. Leer un poco el manual y la caja con la que viene el Drone, suele especificar esta informacion en la mayoria de casos.
    3. Buscar por el FCC-ID.

    Las primeras dos opciones son las mas conocidas y utilizadas, pero la ultima es un dato que no mucha gente conoce y puede acelerar un poco todo...


    La FCC (Federal Communications Commission) es una agencia gubernamental estadounidense la cual se encarga de analizar todos los dispositivos que trabajan con radiofrecuencia y realizan informes exhaustivos acerca de las capacidades de estos dispositivos.

    Manuales del fabricante, fotos internas y externas del dispositivo, especificaciones de los chipsets utilizados... una mina de oro.

    Toda esta informacion, por suerte, esta disponible publicamente en https://fccid.io/

    En nuestro caso particular, hallamos la informacion que estabamos buscando...
     

    Como podran observar, el modelo que encontramos en la base de datos es distinto al modelo que estabamos investigando, pero leyendo detenidamente el informe encontrado se menciona que la electronica incluida en ese modelo es la misma para el que estamos investigando.
    Por ultimo, si miramos la caja encontramos algo de informacion...



    Parece que el informe no mentia, 2.4 Ghz y al parecer trabaja con 4 canales (De los cuales solo nos interesa 1, mas adelante explicare esto en profundidad)


    Perfecto, tenemos la frecuencia!


    El problema es que necesitamos un hardware mas caro para poder hacer la investigacion, ya que la mayoria de dongles SDR del estilo RTL2832U, solo llegan hasta los 800 Mhz.


    Aca tenemos dos opciones:

    1. Usar un dongle RTL2832U, con un downconverter de 2.4 Ghz que baje la frecuencia hasta aproximadamente 400 Mhz la cual si es soportada por el Dongle.
    2. Usar la HackRF/BladeRF, que soporta esa frecuencia y tiene un ancho de banda mas amplio.
    En mi caso utilize la HackRF.

    El siguiente paso es empezar a trabajar en interceptar la señal y los paquetes de vuelo.
    Cuando empeze la investigacion no tenia conocimientos sobre radiofrecuencia o SDR, asi que lo primero que hice fue...

    Y tuve algo de suerte...



    Hay un conferencia que se realiza en Rusia, Moscu mas exactamente, llamada Positive Hack Days en donde hubo un reto que se basaba en hijackear un drone marca Syma, luego de terminado el reto crearon un blog post explicando todos los detalles tecnicos de como ellos lograron tener un receptor y transmisor funcionales. 

    Todo el codigo desarrollado esta en https://github.com/chopengauer/nrf_analyze

    El primer paso es probar el receptor y transmisor creado por ellos, ver si funciona con nuestro Drone.
    1. Clonar el proyecto: git clone https://github.com/chopengauer/nrf_analyze
    2. Instalar la HackRF y GNU Radio en nuestro Sistema Operativo: Un consejo sobre este punto, GNU Radio en los repositorios de Ubuntu no funciona correctamente por lo que es necesario compilar desde el source, si utilizan MacOS pueden usar brew.
    3. Conectamos la HackRF, abrimos el template de GNU Radio.
    4. Corremos el script python nrf_analyze.py: Hay que cambiar la siguiente linea para que obtenga los datos del pipe correcto https://github.com/chopengauer/nrf_analyze/blob/master/nrf24_analyzer.py#L65
    5. Si todo funciona correctamente, usamos el Drone y deberiamos ver los paquetes de vuelo.



    Por desgracia, no vemos ningun paquete, asi que nos toca analizar el codigo y buscar cuales son los problemas.
    Revisando el codigo, podemos encontrar algunos datos hardcodeados como direcciones, rutas a PIPEs, numeros de canales, etc. Debido a esto, es posible que no hayamos podido capturar ningun paquete de vuelo en nuestra prueba anterior.

    Revisemos cada uno de los puntos mencionados...

    • Frecuencia
    Gracias al informe de la FCC sabemos que la frecuencia de operacion del drone esta entre 2.41 - 2.474 GHz, comprobaremos esto en el paso siguiente cuando busquemos el ancho de banda y canales.


    • Canales
    Un canal en radiofrecuencia es una manera de separar e identificar un grupo de frecuencias, que seran utilizadas para la transmision o recepcion de datos.

    En nuestro caso, leyendo el manual del modulo de transmision que utiliza obtenemos una separación de 1 Mhz, lo que nos da 125 canales posibles (2.400 - 2.525 Ghz).

    Asi que ahora, utilizando nuevamente el proyecto nrf_analyze, cargamos en GNU Radio nrf.grc y conectamos nuestra HackRF para buscar los canales, segun indica la caja del Dron, estos son 4 supuestamente.

    Ahora iniciamos el nrf.grc template y vamos cambiando los canales, utilizamos el transmisor original del Dron para transmitir ordenes de movimiento y ver si encontramos la señal, y asi vamos cambiando de canales 1 por 1...

    Al final, encontramos que los canales son 22,26,30 y 34.




    • Direccion del drone
    Que es esto exactamente?

    Si pensamos en que la comunicacion de los datos se realiza a traves de radiofrecuencia que como vimos tienen un rango de espectro fijo y ademas canales fijos, esto significaria que si volamos dos dron del mismo modelo uno al lado del otro no seria posible.

    Esto es debido a que uno estaria transmitiendo y causando ruido para el otro dron.

    Para evitar esto, existen la address que se envia en la propia data transmitida y que permite identificar para que dispositivo esta dirigido ese paquete de datos.

    Con esto, es posible tener 2 drones volando en el mismo espacio fisico!

    Para encontrar la direccion mencionada, a
    brimos el template anterior de GNU Radio, configuramos uno de los canales que encontramos anteriormente. Creamos un pipe de linux y lo colocamos en el template de GNU Radio e iniciamos la tool nrf_analyze y comenzamos a ver los paquetes de vuelo.

    Al final, terminamos encontrando la direccion del dron mirando los primeros bytes de los paquetes: a1ca192dbc

    • Ancho de banda y bitrate
    Para obtener esta informacion, utilizamos el manual de la FCC que encontramos anteriormente.




    Bandwidth 800 kHz para 250 kbps rate

    Todo listo, recapitulando un poco las diferencias radican en los Canales y la Drone Address.
    Todo lo demas no necesita modificacion...



    El payload y su formato


      Leyendo el manual de transmision damos con el formato de datos transmitido, la imagen lo explica todo bastante bien.
      Se utiliza un byte como preambulo, que los receptores utilizan para identificar paquetes de datos entrando, luego la direccion que explicamos mas arriba su uso como identificador, un payload que es la data que nos interesa transmitir y al final, un CRC de 2 bytes para asegurarnos que recibimos el payload correctamente.
      A continuacion pueden ver un ejemplo del payload y el significado de cada byte importante:

      1. Acelerador motor.
      2. Inclinacion (Adelante o atras) (*)
      3. Timón (Giro sobre eje) (*)
      4. Alerones (Inclinación izquierda o derecha) (*)
      10. CRC (XOR de los primeros 9 bytes + 0x55)
      (*) (Bit mas alto = direccion, bits restantes = valor)

      Ahora tenemos todo lo necesario para crear el script de intercepcion!
      droneTelemetry.py

      • Class DecoderSymaX5SW: Parsea cada byte del paquete de vuelo, devolviendo una acción.
      • Class DisplayDrone: Usando urwid, muestra una interfaz gráfica con las acciones del drone.






      Telemetria en tiempo real :)

      Objetivo 2: Transmitir ordenes al Drone.

        Aca empieza la parte interesante, la idea es crear un transmisor que sea capaz de enviar ordenes al Drone, tal como lo hace el crontrolador original.
        Para esto vamos a necesitar un par de cosas:
        • Un modulo de transmision de Radiofrecuencia
        El modulo NRF24 es el que suele utilizarse en la mayoria de estos dispositivos, en el caso de nuestro controlador original el mismo utiliza una version clonada del modulo original.
        Lo bueno de este modulo es su precio (3 - 5 USD) y que funciona en Arduino, Raspberry Pi y BeagleBone.

          • Un dispositivo donde correr nuestro codigo y conectar nuestro transmisor
          Necesitamos tener especial cuidado sobre este punto  ya que en otros proyectos de electronica o IoT elegir entre un Arduino, Raspberry Pi o BeagleBone es a gusto personal. 

          Pero en este caso, el factor latencia y velocidad de transmision es critico, necesitamos que haya la minima latencia posible entre el codigo y el modulo de transmision para que en cuestion de milisegundos se transmitan nuestros paquetes, sino el drone literalmente caeria al suelo.

          Por este motivo la eleccion es Arduino, por la ausencia de un sistema operativo que castigue la performance a la hora de ejecutar el codigo.


          Ahora que tenemos todo el hardware necesario es hora de conectar todo, lo cual no es una tarea sencilla ya que hay poca informacion disponible en internet sobre esto.
          La siguiente tabla explica perfectamente como conectar el modulo, y fue obtenida a traves de prueba y error...


          Ahora, recuerdan el tema de los 4 canales de transmision que mencionaba la caja y el manual de la FCC
          Bueno resulta que no es asi, con transmitir en un solo canal podemos enviar ordenes al Drone, no es necesario ir cambiando y transmitiendo en los 4 canales.

          A continuacion, algunas partes del codigo tranmisor y una explicacion breve de lo mas importante


          sender.c esta desarrollado en C y permite enviar ordenes al Drone, como si del controlador original se tratase. Lo mas importante a mencionar del codigo es la definicion de los pines CE y CSN del modulo que en este caso son el 9 y 10, la definicion del address encontrado anteriormente y los canales a los cuales vamos a transmitir.


          Se definen los baudios para la conexion serial del Arduino y para poder obtener informacion de debug para nuestro codigo,ademas de algunas configuraciones propias del modulo como por ejemplo CRC de 16 bytes, potencia de transmision maxima y bit rate de 250 KBPS, incluyendo el canal de transmision y el size de payload.

          Si quieren ver el codigo completo, pueden verlo en https://github.com/infobyte/SymaX5SW-Rx-Tx.

          Con este transmisor y la falta de un protocolo de asociacion entre el Drone y el Controlador original, hijackear el dron es una cuestion de tener un transmisor con mayor potencia y alcance que el original!

          We did it!

          Objetivo 3: La camara

            Para conectarnos a la camara,es necesario una aplicacion que se conecta al Access Point WI-FI creado por la camara misma, y usando nuestro celular podemos ver el streaming de video, y hacer capturas.
            Ahora, si la idea es hijackear esa conexion de video, miremos un poco la aplicacion de Android a ver como se conecta a la camara...
            Decompilando el APK encontramos algunas cosas que nos llaman la atencion:
            • Conexiones a una IP harcodeada: 192.168.1.1 la IP de la camara.
            • Un escaneo de puertos a la camara nos muestra dos puertos abiertos: 80 y 2345.

            El fabricamente de la camara tiene documentacion publicada y en la misma encontramos una forma de habilitar el telnet, haciendo una peticion a la URL http://192.168.1.1/set_params.cgi?telnetd=1&save=1&reboot=1

            Y cuando lo hacemos...



            Root Shell, bastante simple...


            Continuamos leyendo la documentacion y encontramos que usando la url http://192.168.1.1/snapshot.cgi?user=admin&pwd= podemos sacar una foto usando la credenciales por defecto que encontramos en el APK.

            Y el stream de video?
            Tambien esta en la documentacion explicado!

            Primero solicitamos un ID de stream: http://192.168.1.1/request_av.cgi?user=admin&pwd=

            Luego, usamos ese ID obtenido anteriormente para solicitar el stream de video:  http://192.168.1.1/videostream.cgi?user=admin&pwd=&stream=714546261

            Y tenemos el stream de video!

            Conclusiones:
            Ahora es tiempo de otro Research...

            Ezequiel Tavella
            @EzequielTBH
            Security Researcher - Faraday Labs
            Post a Comment
            Thanks for your comment