DJI Protocol – Day 6 – Progress Report

After some flights and live investigations with our custom network monitoring tool we did generate a lot of data, ready for further offline analysis. However, one strength of the live investigation tool is its capability to sort and filter network traffic, which isn’t available anymore after the application has been closed, resulting in the need of other analysis tools. (E.g.: Wireshark) A far better solution would be to “save” and “load” previous live sessions to simulate the exact same scenario without even starting the drone.

Without further ado we extended the application with a simulation functionality, whereas a *.pcap file can be fetched from the local drive and played back into the network monitoring tool. Worth mentioning, for the application, there is no difference between a live session and a simulation, as both follow the exact same workflow. A simulation feeds the network capture process, resulting in the exact same behavior as a live-monitoring scenario. Moreover, a Simulation doesn’t only support real-time playback, but also step-by-step debugging.

Step-by-step or real-time analysis

Next to the simulation, following features did find its way into the application

  • Automatic Drone and Operator detection; No more static IP’s within the code
  • Automatic network-interface detection and monitoring; Based on the obtained IP-Addresses the tool will stop listening on all other ‘irrelevant’ interfaces
  • Additional filter options
Filter options

The last worth mentioning update deserves more than just a bullet point. Imagine browsing and filtering through the network traffic. How do we examine the packet’s content? Up until now we only knew what has when arrived, but we weren’t able to inspect the packet’s payload; as only a copy function had been provided. The last feature does exactly offer this functionality. One can select an arbitrary packet, and print the payload’s hex value (including base 2 and base 10 representations) onto the screen. On top of that, these prints can be compared to other packets, offering the possibility to quickly detect payload differences visually.

Adding payload to the binary inspector
Binary comparison between packets

Connection Handshake

With those new features we were able to extend our findings on the packet 0x38. As our findings are limited to our current knowledge, we do require to inspect other packets to obtain more hints and clues. Our current plan is an in-depth analysis of the takeoff and landing procedure, as those two operations represent the most basic operator to drone interaction. Thus, we started to obtain different live-monitoring sessions from several takeoff and landing procedures, just to obtain our very first breakthrough. The connection handshake. As promised, detailed information about both packets (operator to drone and drone to operator) have been documented and added to the packet-types enumeration. In short: we were able to detect two important values within the handshake

  • Session identifier
  • Start values of several variables

Time will tell what those variables represent, but we were able to link the values of 0x08 and 0x09 to our first inspected packet-type 0x38, as those variables will be used for the 0x38 packet’s payload assembly.

Handshake: Operator -> Drone (Two separate scenarios compared)
Handshake: Drone -> Operator (Two separate scenarios compared)

We were quite curious about the drone’s response last byte. (See Fig. Handshake: Drone -> Operator) it seems like a checksum, but all CRC-8 checksums didn’t return a congruent result. As the only difference between both scenarios is the session identifier, all we required to do is to solve following equation:

0x6C XOR 0x21 XOR value = 0xC5
0xE6 XOR 0x37 XOR value = 0x59

And vola, the final XOR value equals 0x88

Same has been applied to the operator’s 0x07 byte, as it also seems to be a CRC-8 checksum value. (See Fig. Handshake: Operator -> Drone)

0x6C XOR 0x21 XNOR value = 0xFD
0xE6 XOR 0x37 XNOR value = 0x61

And vola, the final XNOR value equals 0x4F

0x21 Investigation

After the connection handshake the operator sends 14 packets of type 0x21. Before we print out our findings, we would like to discuss the bytes at position 0x1F – 0x20, as they seem to be arbitrary but fixed. We recorded the takeoff and landing procedure 4 times with following setup within 48 hours:

  1. Turn on the drone and connect to the access point
  2. Join the network with the operator
  3. Takeoff
  4. Land
  5. Disconnect the operator from the network
  6. Turn off the drone

It turned out, that the bytes at 0x1F – 0x20 were equal on day 1, but different to day 2. However, both values follow a pattern which we can’t explain yet. We will record yet another takeoff and landing procedure tomorrow, in order to ensure that the byte sequence is indeed time related. ADDON from the future: Two days later and the mystery has been solved. It is, again, a CRC checksum. The byte sequence for the CRC covering-range did equal on day one, hence the same CRC checksums had been generated.

0x001Packet Identifier / Packet Length – All packets with an ethernet frame-length of 75 bytes start with the static byte sequence of: 0x21
0x011Protocol Version
0x02 – 0x032Session Identifier – Value retrieved by Handshake at position 0x02 0x03
0x041Counter* – Shared counter accross different packets. Increments by 0x08 followed by 0x02.
Initial value retrieved by Handshake at position 0x08 with + 8.
E.g.: Start value: 0x60 leads to 0x68
Pattern: 0x68 -> 0x70 -> 0x78 -> 0x80 -> 0x88 -> 0x90
0x051???* – Shared value across different packets. Can be set externally.
Initial value retrieved by Handshake at position 0x09.
0x061Constant – 0x05
0x071CRC – 0x04 XOR val = 0x07
val: origin unknown
0x081 ???* – Shared value across different packets. Can be set externally.
Initial value retrieved by Handshake at position 0x08.
0x091Mirror – See 0x05
0x0A1Mirror – See 0x04
0x0B1Mirror – See 0x05
0x0C – 0x0F4Padding – Zero bits
0x101Counter* – Shared counter accross different packets.
Initial value 0x01, increments by 1
0x11 – 0x188Constants – { 0x01, 0x00, 0x00, 0x55, 0x0D, 0x04, 0x33, 0x02 }
0x1A – 0x1B2Exclusive Counter – Little Endian
Initial value { 0x0A, 0x00 } or { 0x0B, 0x00 }
0x1C1Constant – 0x40
0x1D – 0x1E2??? – Initialization?
May be related to the initialization. First packets do have a ‘initialization’ pattern:
1. { 0x00, 0x01 } 2. { 0x00, 0xFF } 3. { 0x00, 0x01 } 4. { 0x00, 0xFF } 5. { 0x00, 0xFF } 6. { 0x00, 0x01 }
Then arbitrary but fixed values follow. They did equal across all of our samples.
0x1F – 0x202CRC-16 KERMIT from 0x18 to incl. 0x1E. Little Endian byte order
Special: Final XOR value: 0x75
Packet structure of the 0x21 packet payload

We came across some familiar values from the packet 0x38. Especially the bytes at position 0x05, 0x08, 0x09, 0x0B were similar to the bytes at the position 0x08 – 0x0B within the 0x38 packet type. We assume that some values are not only used by one, but several packets at once. Those values change, sometimes; but changes pull through both packets. (It is safe to assume at this point that also other packets will contain those bytes) Moreover, we still need to investigate whether the Counter* overflow will trigger such a change event.

0x21 from two different takeoff recordings

Next up: DJI Protocol – Day 7 – Progress Report

0 0 votes
Article Rating
Notify of
Most Voted
Newest Oldest
Inline Feedbacks
View all comments

[…] we were capable of reconstructing the CRC target and XOR parameters last time for the connection handshake, we will re-review the 0x21 packet and try to apply the same strategy. […]


[…] Day 6 […]