Sunday, January 29, 2017

Monitoring Telemetry for the DJI Phantom 3

I picked up a DJI Phantom 3 Standard drone about 6 months ago, and since the first time I flew it around my yard using the controller and DJI Go Android app, I've wondered about the possibility of using some kind of PC-based ground station software to control it.

If the DJI Go app uses WiFi to communicate with the drone, then in theory so could an application running on a laptop, right?

I did a little searching and found out that, at least for this model, DJI doesn't offer any official ground station software. That's when my gears started turning; Could I write some software to control the Phantom 3? We'll see, but the first step is trying to understand how the DJI Go app and the drone communicate, which is the subject of this post.

Recon


The first thing I needed to do is understand what systems are present on the Phantom 3 WLAN.

Note: Remove the propellers before turning on the system indoors!

I powered up the Phantom 3 and remote controller, then I connected my laptop to the PHANNTOM_240536 network. This network uses WPA pre-shared key authentication with a default password of 12341234 (which I should probably change). Once connected, I noticed that my laptop was given the IP Address 192.168.1.21 with a netmask of 255.255.255.0. Knowing the subnet in use on the Phantom 3 WLAN, I used an nmap ping sweep to find active hosts.

[user@eb8570p dji_re]$ nmap -sP 192.168.1.0/24

Starting Nmap 7.40 ( https://nmap.org ) at 2017-01-29 16:40 EST
Nmap scan report for 192.168.1.1
Host is up (0.0016s latency).
Nmap scan report for 192.168.1.2
Host is up (0.011s latency).
Nmap scan report for 192.168.1.3
Host is up (0.020s latency).
Nmap scan report for 192.168.1.20
Host is up (0.042s latency).
Nmap scan report for 192.168.1.21
Host is up (0.00020s latency).

My laptop is .21, the tablet is .20, so the .1-.3 addresses must be parts of the DJI system. Next I tried to see if there was anything else nmap could tell me. To do that I used an nnap port scan for each of the Phantom 3 system hosts.

[user@eb8570p dji_re]$ sudo nmap -p 1-65535 -sS 192.168.1.1

Starting Nmap 7.40 ( https://nmap.org ) at 2017-01-29 17:09 EST
Nmap scan report for 192.168.1.1
Host is up (0.0051s latency).
Not shown: 65533 closed ports
PORT     STATE SERVICE
21/tcp   open  ftp
2345/tcp open  dbm
MAC Address: 60:60:1F:24:05:36 (SZ DJI Technology)

Nmap done: 1 IP address (1 host up) scanned in 22.29 seconds

The numerical part of the Phantom 3 WLAN SSID seems to be three of the octets from the MAC address of this host.

[user@eb8570p dji_re]$ sudo nmap -p 1-65535 -sS 192.168.1.2

Starting Nmap 7.40 ( https://nmap.org ) at 2017-01-29 17:09 EST
Nmap scan report for 192.168.1.2
Host is up (0.066s latency).
Not shown: 65533 closed ports
PORT     STATE SERVICE
21/tcp   open  ftp
5678/tcp open  rrac
MAC Address: 60:60:1F:10:1B:E3 (SZ DJI Technology)

Nmap done: 1 IP address (1 host up) scanned in 35.70 seconds

[user@eb8570p dji_re]$ sudo nmap -p 1-65535 -sS 192.168.1.3

Starting Nmap 7.40 ( https://nmap.org ) at 2017-01-29 17:10 EST
Nmap scan report for 192.168.1.3
Host is up (0.074s latency).
Not shown: 65532 closed ports
PORT   STATE SERVICE
21/tcp open  ftp
22/tcp open  ssh
23/tcp open  telnet
MAC Address: 4E:EC:D3:3F:BB:B3 (Unknown)

Nmap done: 1 IP address (1 host up) scanned in 33.35 seconds

Well, nothing earth shattering there. I'll just keep this info for reference.

Passive Monitoring


Now that I had some understanding of the network, the next step was to monitor the WLAN and see who's talking to who. For this part I used my trusty Alfa USB WLAN adapter and Wireshark. Something I didn't realize right away is that WPA-PSK uses information other than just the pre-shared key to encrypt communications between hosts. This means that simply authenticating to the access point doesn't grant me access to all the traffic on the WLAN. In order to do that, I'll have to monitor the WPA client authentication sequence to grab all of the crypto material necessary to decrypt communications between the Phantom 3 and the DJI Go app running on the Android tablet. That all sounds super complicated, but luckily Wireshark and aircrack-ng can do most of the work.

I needed to put the Alfa card into Monitoring mode, and as a prerequisite step I had to disable some conflicting services.

[user@eb8570p dji_re]$ sudo airmon-ng check kill
[user@eb8570p dji_re]$ sudo airmon-ng start wlp0s20u2 6

The 6 here is the channel we want to monitor. My Phantom 3 seems to be configured to use channel 6.

With the WLAN adapter in Monitor mode, it's time to get Wireshark set up. First we need to tell wireshark about the WPA pre-shared key for the PHANTOM_240536 SSID. To do that, the Key can be entered in the IEEE-802.11 preferences dialog. This dialog can be accessed by navigating to Edit -> Preferences-> Protocols -> IEEE-802.11. Then click the Edit button to edit decryption keys. In the WEP and WPA Decryption Keys dialog, click the New button, then select wpa-psk, and enter your key in the form: psk:ssid. For me this looked like: 12341234:PHANTOM_240536.

Now that the interface is in Monitor mode and Wireshark is ready to listen, we need to make sure Wireshark is able to capture the client authentication handshake from the tablet. The easiest way to do this is to kick the tablet off the WLAN to force it to re-authenticate. This is done with aireplay-ng.

sudo aireplay-ng -0 1 -a 60:60:1f:24:05:36 -c bc:76:5e:6a:d4:b3 wlp0s20u2mon
The -a argument specifies the MAC address of the access point, and the -c argument specifies the MAC address of the client.

With airmon-ng and Wireshark ready to monitor the WLAN, I powered on the drone and controller, then started the DJI Go app on the tablet.


Right away the app connects to 192.168.1.1 on port 2345, and shortly thereafter also connects to 192.168.1.2 on port 5678. At a glance, both of these conversations seem to be mostly the Phantom 3 talking to the tablet, with a packets going the other direction every once in a while. My guess is that once the app connects, .1 and .2 stream status information to the app, while the app occasionally sends commands.


Finally, there's a UDP (UDT) handshake with 192.168.1.3, followed by a constant stream of data from 192.168.1.3 to the tablet, which I'm guessing is the encoded video.

Protocol Analysis


Assuming the UDP traffic is video, I focused my attention on the two TCP connections. Furthermore, I focused on the packets going from the Phantom 3 to the tablet. I figured if I can write a program to connect to these TCP servers and report telemetry for the drone, that would be pretty cool. I can always add command and control capabilities later... I've included the first 8 bytes of some received payloads below (I stripped out beyond that because some of the packets probably include location data).

55 1A 04 B1 0E 02 4C 2D
55 1A 04 B1 0E 02 4D 2D
55 1A 04 B1 0E 02 4E 2D
55 19 04 E4 1B 02 7D 0A
55 1A 04 B1 0E 02 4F 2D
55 1A 04 B1 0E 02 50 2D
55 1A 04 B1 0E 02 51 2D
55 12 04 C7 0E 02 52 2D
55 1A 04 B1 0E 02 53 2D
55 0D 04 33 1B 02 7E 0A
55 1A 04 B1 0E 02 54 2D
55 0E 04 66 1B 02 7F 0A
55 0E 04 66 1B 02 80 0A
55 1A 04 B1 0E 02 55 2D
55 1A 04 B1 0E 02 56 2D
55 1A 04 B1 0E 02 57 2D
55 1A 04 B1 0E 02 58 2D
55 1A 04 B1 0E 02 59 2D
55 19 04 E4 1B 02 84 0A
55 1A 04 B1 0E 02 5A 2D

After exporting the payloads and staring at them for a while, a couple patterns emerge. First, there's some kind of preamble or magic byte (0x55) at the beginning of each payload. Next, the second byte always matches the length of the payload in bytes. Also, the last two bytes of the payloads seem to vary randomly for each packet. I'm guessing there's a 16 bit checksum or CRC at the end of the messages, but I've been unable to figure out exactly how that's calculated. So there are preamble, length, and integrity check fields in the PDU; pretty normal stuff, and that's a good start.

I can see that the 3rd and 6th bytes never change. I've disconnected the app and reconnected several times, and these are always the same. I'm guessing these bytes include some flag bits. After looking at lots of data, I've concluded that byte 4 is probably some kind of message type indicator. In my collected data, I only see about 10 different values here, and they always correspond to the same payload lengths. Byte 5 is interesting because it changes, but only between a couple observed values. It could be flags, or it could be part of a multi-byte field that I don't understand yet.

Interestingly, byte 7 seems to increment two distinct counters.

Next Steps


The remainder of the payloads are going to be tough to decode. I think my best bet is to go for the low-hanging fruit, and try to find the position and attitude data. With the drone sitting on the table, that data should be relatively static, and if I were designing this protocol I'd probably use either 16 or 32 bits to represent angles. If I hold the drone steady and rotate just one axis, the data might give the fields away.

More to come in follow up posts...

References


I found the following useful sources of information while researching the Phantom 3 protocol:
[1] http://dronesec.xyz/2017/01/25/hacking-the-dji-phantom-3/ This blog post includes a lot of the same information as my research, except that it's written from an information security perspective.
[2] https://github.com/noahwilliamsson/dji-phantom-vision GitHub project for the Phantom 2 protocol, which has some similarities to what I've observed, but seems to be a different protocol.
[3] http://forum.dji.com/thread-55122-1-1.html Forum post about discovery of the Phantom 3 WLAN hosts and their roles in the system.
[4] https://github.com/hardening/Cave/blob/master/phantom3-video.cpp GitHub - C++ program to grab Phantom 3 UDT video.
[5] https://wiki.wireshark.org/HowToDecrypt802.11 How to decrypt 802.11 packets in Wireshark.
[6] https://www.aircrack-ng.org/doku.php?id=deauthentication How to disassociate wireless clients.

1 comment:

  1. Hello,

    you may be interested with my findings here =>
    http://www.hardening-consulting.com/en/posts/20170305-phantom-3-protocol.html

    Enjoy

    ReplyDelete