Love is in the air: Reverse Engineering a shitty drone

El dia 9 de marzo del 2018 - Si hace un año atrás, mas vale tarde que nunca :) -, tuvo lugar la
Security Jam, una reunión/conferencia 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.

Además de la Security Jam, presente este charla en CharruaCon y 8.8 Chile,
dos conferencias muy recomendadas para los que no hayan asistido!

A continuación conocerán los detalles de la investigación y, por supuesto,
tendrán acceso al código creado ;)

TL;DR

Un research realizado a un Drone SYMA X5SW con 3 objetivos definidos.
  1. Interceptar la telemetría del Drone y mostrarlo en una interfaz gráfica en tiempo real.
  2. Crear un transmisor (Control de mando), utilizando módulos de RF, Arduino y código C.
  3. Interceptar el stream de video de la cámara y buscar vulnerabilidades en ella.

Hablamos sobre algunos conceptos básicos de Radiofrecuencia, consejos para empezar un
proyecto de este tipo y los problemas que hubo a lo largo de él.

El research empezó con SYMA X5SW, luego de jugar un poco con él, se me ocurrió si podría intentar
hacer ingeniería inversa y entender su protocolo de comunicación para “hijackearlo”.

Objetivo 1: Interceptar la telemetría del Drone.

La idea detrás de este objetivo es poder capturar los paquetes en pleno vuelo, así como también
entender el protocolo de comunicación para poder obtener cuales son las acciones enviadas
por el controlador y por último mostrar toda la información en una interfaz gráfica!

Lo primero que nos interesa averiguar es que canal de comunicación están utilizando el transmisor
y el drone para comunicarse y así 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 especificación.
2. Leer un poco el manual y la caja con la que viene el Drone, suele especificar esta información
en la mayoría de casos.
3. Buscar por el FCC-ID.
Las primeras dos opciones son las más 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 información que estábamos buscando...

Como podrán observar, el modelo que encontramos en la base de datos es distinto al modelo
que estábamos investigando, pero leyendo detenidamente el informe encontrado se menciona que
la electrónica incluida en ese modelo es la misma para el que estamos investigando.
Por último, si miramos la caja encontramos algo de información...


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

Perfecto, tenemos la frecuencia!

El problema es que necesitamos un hardware más caro para poder hacer la investigación,
ya que la mayoría de dongles SDR del estilo RTL2832U, solo llegan hasta los 800 Mhz.

Acá 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 más amplio.
En mi caso utilice la HackRF.

El siguiente paso es empezar a trabajar en interceptar la señal y los paquetes de vuelo.
Debido a mi poco conocimiento en este campo, decidi investigar un poco en Internet acerca de esto...
Y tuve suerte...

Hay un conferencia que se realiza en Rusia, Moscú más 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 técnicos de cómo 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
Si todo funciona correctamente, usamos el Drone y deberíamos ver los paquetes de vuelo.



Por desgracia, no vemos ningún paquete, así que nos toca analizar el código y
buscar cuales son los problemas.
Revisando el código, podemos encontrar algunos datos hardcodeados como direcciones,
rutas a PIPEs, números de canales, etc. Debido a esto, es posible que no hayamos podido
capturar ningún 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 operación del drone está 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 serán utilizadas para la transmision o recepcion de datos.
    En nuestro caso, leyendo el manual del modulo de transmisión que utiliza obtenemos una separación
    de 1 Mhz, lo que nos da 125 canales posibles (2.400 - 2.525 Ghz).
    Así que ahora, utilizando nuevamente el proyecto nrf_analyze, cargamos en GNU Radio nrf.grc
    y conectamos nuestra HackRF para buscar los canales, según 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 órdenes de movimiento y ver si encontramos la señal, y así vamos cambiando
    de canales 1 por 1...
    Al final, encontramos que los canales son 22,26,30 y 34.



    • Dirección del drone
      Qué es esto exactamente?

      Si pensamos en que la comunicación de los datos se realiza a través de radiofrecuencia que como
      vimos tienen un rango de espectro fijo y además canales fijos, esto significa que si volamos dos dron
      del mismo modelo uno al lado del otro no sería posible.
      Esto es debido a que uno estaría transmitiendo y causando ruido para el otro dron.

      Para evitar esto, existen la address que se envía en la propia data transmitida y que permite identificar
      para qué dispositivo está dirigido ese paquete de datos.
      Con esto, es posible tener 2 drones volando en el mismo espacio físico!

      Para encontrar la dirección mencionada, abrimos 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 dirección del dron mirando los primeros bytes de los paquetes:
      a1ca192dbc

      • Ancho de banda y bitrate
        Para obtener esta información, 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 demás no necesita modificación...

        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 preámbulo, que los receptores utilizan para identificar paquetes de datos
        entrando, luego la dirección que explicamos más 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 continuación pueden ver un ejemplo del payload y el significado de cada byte importante:

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

        Ahora tenemos todo lo necesario para crear el script de intercepción!
        • 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.

        Telemetría 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 órdenes
        al Drone, tal como lo hace el controlador original.
        Para esto vamos a necesitar un par de cosas:

        • Un módulo de transmisión de Radiofrecuencia
        El módulo NRF24 es el que suele utilizarse en la mayoría de estos dispositivos, en el caso de
        nuestro controlador original el mismo utiliza una versión clonada del módulo original.
        Lo bueno de este módulo es su precio (3 - 5 USD) y que funciona en Arduino, Raspberry Pi
        y BeagleBone.



        • Un dispositivo donde correr nuestro código 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 transmisión es crítico, necesitamos que haya
          la mínima latencia posible entre el código y el modulo de transmision para que en cuestión de
          milisegundos se transmitan nuestros paquetes, sino el drone literalmente caería al suelo.
          Por este motivo la elección es Arduino, por la ausencia de un sistema operativo que castigue la
          performance a la hora de ejecutar el código.


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


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

          A continuación, algunas partes del código transmisor y una explicación breve de lo más importante


          sender.c está desarrollado en C y permite enviar órdenes al Drone, como si del controlador original
          se tratase. Lo más importante a mencionar del código es la definición de los pines CE y CSN del
          módulo que en este caso son el 9 y 10, la definición del address encontrado anteriormente y los
          canales a los cuales vamos a transmitir.

          Se definen los baudios para la conexión serial del Arduino y para poder obtener información de debug
          para nuestro código,además de algunas configuraciones propias del módulo como por ejemplo CRC
          de 16 bytes, potencia de transmisión máxima y “Bitrate” de 250 KBPS, incluyendo el canal de
          transmisión 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 asociación entre el Drone y el Controlador original,
          “hijackear” el dron es una cuestión de tener un transmisor con mayor potencia
          y alcance que el original!
          We did it!

          Objetivo 3: La cámara

          Para conectarnos a la cámara, es necesario una aplicación que se conecta al Access Point WI-FI
          creado por la cámara misma, y usando nuestro celular podemos ver el streaming de video, y hacer
          capturas.
          Ahora, si la idea es “hijackear” esa conexión de video, miremos un poco la aplicación de Android
          a ver como se conecta a la cámara...
          Descompilando el APK encontramos algunas cosas que nos llaman la atención:
          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 documentación 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 documentación 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:
          • Interceptamos la telemetría del Drone, logramos “hijackearlo” junto con su stream de video.
          • Tuvimos varios problemas con la transmisión, lo resolvimos utilizando un power bank para suministrar el pico de energía requerido por el modulo de transmision, Arduino y C, para mejorar la performance de transmisión.
          • No hay seguridad en la comunicación: Ni cifrado, ni protocolo de asociación seguro. El que tiene el transmisor de mayor potencia ganar el control del Drone.

          ¡Pudimos interceptar la telemetría del dron y logramos hijackearlo junto con el stream de video!


          Cabe aclarar que cuando comencé con este proyecto no tenía conocimientos sobre Radiofrecuencia y tampoco sobre SDR. Con curiosidad y perseverancia, y conexión a internet, se pueden lograr algunas cosas :)

          Ahora es tiempo de otro Research...

          Todo el codigo desarrollado disponible en:
          Ezequiel Tavella
          @EzequielTBH
          Security Researcher - Faraday Labs
          Post a Comment
          Thanks for your comment