I reverse engineered a toy drone to make it programmable
I continued the project on my personal blog.
If you want to program your own drone based on a video feed for a cheap price head there and get the python scripts:
As you can see airodump-ng picked up the WiFi of the drone and also that it is running on channel 2. Next I recorded some packages.
sudo airodump-ng -w JJRC_out -c 2 -bssid 10:A4:BE:2E:77:B5 wlan0mon
While recording I simply used all the functions the drone had and flew around so I could get a full picture of what packages would be sent. After I was done I opened the file in WireShark.
After some inspection I concluded that the videostream is being sent via a TCP stream on port 8888 and that controls are being sent via UDP to port 8080 on the drone. I also noticed that a simple data string of hex numbers was used to control every part of the drone. With the help of live package inspection by using
tcpdump -i 2 udp dst port 8080 -x -vv
I was able to decipher most of it. For better understanding here is a link to explain the vocabulary that is being used in the explanaiton.
"Arm" means the start of the blades, "disarm" the initiation of the landing sequence and "stop" the momentary stop of the blades.
These were my notes:
App sends every 50ms a package -> If no control is used the IDLE package is sent Maximum of most pairs are their IDLE value times 2. Data: ff08 7e3f 403f 9010 1000 0b (Standard-Calibration IDLE) Names: abcd efgh ijkl mnop qrst uv Controls: ef -> THROTTLE: Counts up for higher, counts down for lower ij -> PITCH: Counts down for forward, counts up for backward kl -> ROLL: Counts up for right, counts down for left gh -> YAW: Counts up for right, counts down for left Calibration: mn: Counts up for right yaw calibration, down for left yaw calibration op: Counts up for forward calibration, down for backward calibration qr: Counts up for right roll calibration, down for left roll calibration Commands: s: sends arm:4 disarm:8 stop:a gravity sensor:1 t: 30%:0 60%:1 100%:2 Extra bits that simply count and make my life harder: uv: Counts(?) Example: If "ef" counts up to fly the drone higher, "uv" counts down by the same value-1. THROTTLE: Counts down for higher, counts up for lower YAW: Counts up for left counts down for right turn PITCH: Counts up for forward, counts down for backwards ROLL: Counts down for right, counts up for left CALIBRATION: Counts up for left yaw, left roll and downwards throttle calibration Some examples after I stopped testing: THROTTLE: HIGHER: (ef:7e -> +7e -> ef:fc | uv:07 -> -(7e-1) -> +82 -> uv:89) LOWER: (ef:7e -> -7e -> ef:00 | uv:07 -> +(7e+0) -> +7e -> uv:85) YAW: LEFT: (gh:3f -> -3f -> gh:00 | uv:07 -> +(3f+2) -> +41 -> uv:48) RIGHT: (gh:3f -> +3f -> gh:7e | uv:07 -> -(3f+2) -> +c3 -> uv:ca) PITCH: FORWD: (ij:40 -> -3f -> ij:01 | uv:07 -> +(3f+0) -> +3f -> uv:46) BACKW: (ij:40 -> +3f -> ij:7f | uv:07 -> -(3f+1) -> -40 -> uv:c8) uv in addition with s-Commands: DISARM: -> -80(hex) ARM: -> +B0(hex) STOP: -> -A0(hex
I couldn't figure out the controls exactly so for the rest of the project I simply used prerecorded data packets for each direction.
On to the testing!
So I knew the drone was creating a WiFi called JJRC-Something. So in order to capture the traffic the app was sending to the drone I fired up Kali Linux and used aircrack-ng to start a scan.
First stop the network driver in order to use monitor mode.
sudo airmong-ng check kill sudo airmong-ng start wlan0 sudo airodump-ng wlan0mon