{"id":13651947,"url":"https://github.com/RUB-SysSec/DroneSecurity","last_synced_at":"2025-04-23T02:31:47.208Z","repository":{"id":85012947,"uuid":"585634235","full_name":"RUB-SysSec/DroneSecurity","owner":"RUB-SysSec","description":"DroneSecurity (NDSS 2023)","archived":false,"fork":false,"pushed_at":"2023-03-10T12:58:04.000Z","size":6909,"stargazers_count":1013,"open_issues_count":13,"forks_count":180,"subscribers_count":53,"default_branch":"public_squash","last_synced_at":"2024-12-24T09:02:16.109Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/RUB-SysSec.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-01-05T17:11:55.000Z","updated_at":"2024-12-23T13:20:11.000Z","dependencies_parsed_at":"2024-11-10T03:30:47.219Z","dependency_job_id":"883eea4b-1a8f-45a9-a944-d68945faa443","html_url":"https://github.com/RUB-SysSec/DroneSecurity","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RUB-SysSec%2FDroneSecurity","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RUB-SysSec%2FDroneSecurity/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RUB-SysSec%2FDroneSecurity/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/RUB-SysSec%2FDroneSecurity/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/RUB-SysSec","download_url":"https://codeload.github.com/RUB-SysSec/DroneSecurity/tar.gz/refs/heads/public_squash","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250357669,"owners_count":21417325,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-02T02:00:53.669Z","updated_at":"2025-04-23T02:31:47.197Z","avatar_url":"https://github.com/RUB-SysSec.png","language":"Python","funding_links":[],"categories":["🏢 Vendor-Specific Research","Security \u0026 Safety 🪂"],"sub_categories":["DJI","Hacking \u0026 Hijacking 🔓"],"readme":"# Drone-ID Receiver for DJI OcuSync 2.0\n\n\u003cp\u003e\u003ca href=\"https://www.ndss-symposium.org/wp-content/uploads/2023/02/ndss2023_f217_paper.pdf\"\u003e\u003cimg alt=\"Paper thumbnail\" align=\"right\" width=\"250\" src=\"./img/paper_thumbnail.png\"\u003e\u003c/a\u003e\u003c/p\u003e\n\nThis project is a receiver for DJI's Drone-ID protocol. The receiver works either live with an SDR, or offline on pre-recorded captures.\n\nOur paper from NDSS'23 explains the protocol and receiver design: [Drone Security and the Mysterious Case of DJI's DroneID](https://www.ndss-symposium.org/wp-content/uploads/2023/02/ndss2023_f217_paper.pdf) [pdf]\n\n\u003e If you're looking for the fuzzer, we will upload that shortly :)\n\nThe live receiver was tested with:\n* Ettus USRP B205-mini\n* DJI mini 2, DJI Mavic Air 2\n\nOur software is a proof-of-concept receiver that we used to reverse-engineer an unknown protocol. Hence, it is not optimized for bad RF conditions, performance, or range.\n\n\u003cp\u003e\u003cimg alt=\"Decoded Payload\" width=500 src=\"./img/result.png\"\u003e\u003c/a\u003e\u003c/p\u003e\n\n## Sample Files\n\nWe provide sample files in the `samples/` folder.\n\nThe samples were directly dumped from the first stage of the live receiver that\n*detects* candidate frames and performs no other data processing; it usually hands\nthem directly to the rest of the code that you can test offline.\n\nYou can use `inspectrum` to visualize the raw sample file:\n\n```\nsudo apt install inspectrum\ninspectrum -r 50e6 samples/mini2_sm\n```\n\n\u003cimg alt=\"Inspectrum screenshot of Drone-ID bursts\" width=500 src=\"./img/inspectrum.png\"\u003e\u003c/a\u003e\u003c/p\u003e\n\n## Quick Start (Offline)\n\nCreate a virtual environment for Python and install the requirements:\n\n```\npython3 -m venv .venv\nsource .venv/bin/activate\npip3 install -r requirements.txt \n```\n\nYou can now run the decoder on the sample file:\n```\n./src/droneid_receiver_offline.py -i samples/mini2_sm\n```\n\n### Results\n\nThe script performs detection and decoding just as the live receiver would. It prints the decoded payload for each Drone-ID frame:\n\n```json\n## Drone-ID Payload ##\n{\n    \"pkt_len\": 88,\n    \"unk\": 16,\n    \"version\": 2,\n    \"sequence_number\": 878,\n    \"state_info\": 8179,\n    \"serial_number\": \"SecureStorage?\",\n    \"longitude\": 7.267960786785307,\n    \"latitude\": 51.446866781640146,\n    \"altitude\": 39.32,\n    \"height\": 5.49,\n    \"v_north\": 0,\n    \"v_east\": -7,\n    \"v_up\": 0,\n    \"d_1_angle\": 16900,\n    \"gps_time\": 1650894901980,\n    \"app_lat\": 43.26826445428658,\n    \"app_lon\": 6.640125363111847,\n    \"longitude_home\": 7.26794359805882,\n    \"latitude_home\": 51.446883970366635,\n    \"device_type\": \"Mini 2\",\n    \"uuid_len\": 0,\n    \"uuid\": \"\",\n    \"crc-packet\": \"c935\",\n    \"crc-calculated\": \"c935\"\n}\n```\n\nThe summary contains decoding stats and flight path. In the `mini2_sm` sample, the drone did not have GPS coordinates locked yet, and only the smartphone's location is transmitted:\n```\n$ ./src/droneid_receiver_offline.py -i samples/mini2_sm\n… … …\nFrame detection: 10 candidates\nDecoder: 9 total, CRC OK: 7 (2 CRC errors)\nDrone Coordinates:\nApp Coordinates:\n(51.447176178716916, 7.266528392911369)\n(51.447176178716916, 7.266528392911369)\n…\n(51.447176178716916, 7.266528392911369)\n```\n\nFor `samples/mavic_air_2` both locations are transmitted:\n```\n$ ./src/droneid_receiver_offline.py -i samples/mavic_air_2\n…\nDecoder: 1 total, CRC OK: 1 (0 CRC errors)\nDrone Coordinates:\n(51.44633393111904, 7.26721594197086, 12.8)\nApp Coordinates:\n(51.44620788045814, 7.267101350460944)\n```\n\n# Live Receiver\n\nThe live receiver additionally requires the UHD driver and **quite powerful machines** (for captures at 50 MHz bandwidth).\n\nEnvironment:\n* Ettus USRP B205-mini\n* DJI mini 2, DJI Mavic Air 2\n\nFirst, setup the Python environment. Due to the UHD driver, this does not work with a virtual environment. If you previously activated a virtual environment, exit that environment first. Install Python requirements:\n```\npip3 install -r requirements.txt\n```\n\nInstall UHD:\n```\nsudo apt install libuhd-dev uhd-host python3-uhd\n```\n\nRun the receiver:\n\n```\n./src/droneid_receiver_live.py \n```\n\nThe receiver will hop through a list of frequencies and, if a drone is detected, lock on that band.\n\n## Deeper Dive: Script output\n\n\u003cp\u003e\u003cimg alt=\"Processing Pipeline\" align=\"right\" width=500 src=\"./img/pipeline.png\"\u003e\u003c/a\u003e\u003c/p\u003e\n\n\u003e If you're looking for a deeper dive into the processing steps, we suggest calling the offline decoder with `--debug`. This will **enable a GUI** with step-by-step decoding.\n\n\u003e ```\n\u003e ./src/droneid_receiver_offline.py -i samples/mini2_sm --debug\n\u003e ```\n\n\nFirst, the `SpectrumCapture` class performs *packet detection* and splits the capture file into individual frames:\n```\nPacket #0, start 0.000076, end 0.000721, length 0.000644, cfo -12207.031250\nPacket #1, start 0.000811, end 0.001456, length 0.000644, cfo 0.000000\nPacket #2, start 0.001546, end 0.002191, length 0.000644, cfo 0.000000\n…\n```\n\nSome of these packets are false-positives and we do not expect successful decoding. Start and end are in seconds, so you can use inspectrum to take a look at individual frames.\n\nNext, the `Packet` class detects the Zadoff-Chu sequences and performs time and frequency offset corrections. It splits the frames into individual OFDM symbols.\n```\nFFO: -6546.528614\nFound ZC sequences: 600 147\nZC Offset: -2.867868\n```\n\nThe `Decoder` class gets the OFDM symbols and demodulates the subcarriers using QPSK. We do not know the QPSK orientation here, hence, we simply brute-force the orientation. `decoder.magic()` performs the descrambling and turbo-decode.\n\n`DroneIDPacket` unpacks the resulting bitstream into the Drone-ID struct. At this point the message could be decoded, but might be corrupted (CRC check needed).\n\nCRC check FAIL is easy to spot by looking at the Serial Number (should read 'SecureStorage?'):\n```\n    \"serial_number\": \"Sa#upeStore\u0026q?\\u0010\\b\",\n    …\n    \"crc-packet\": \"d985\",\n    \"crc-calculated\": \"9b01\"\n}\nCRC Check FAILED!\n```\n\nAt the very end, we print some statistics:\n```\nSuccessfully decoded 14 / 34 packets\n4 Packets with CRC error\n```\n\nSo in total we decoded 18 packets, 14 with correct CRC. Again, this is *expected* as the sample file includes Drone-ID Frames with greatly varying quality.\n\n# FAQ - Frequently Asked Questions\n\nIs DJI's Drone-ID the same as the standardized, Bluetooth or WiFi-based \"Remote ID\"?\n\u003e No. DJI uses a dedicated wireless protocol for its Drone-ID, hence the need to implement an receiver.\n\nCan I use *this software* to locate drones from other manufacturers?\n\u003e No. This software decodes DJI-specific protocols. It does not work with WiFi or Bluetooth-based \"Remote ID\".\n\nCan I locate drones without this software?\n\u003e Maybe. Since late 2022, the US or EU started requiring drone manufacturers to implement \"Drone Remote ID\" - an international standard that works on top of WiFi or Bluetooth. You can use a smartphone app to locate drones that support the standard. New drones already feature WiFi/Bluetooth-based \"Remote ID\", and existing drones are gradually retrofitted (e.g., through firmware updates).\n\nWhere can I find more information on the WiFi/Bluetooth-based Remote ID?\n\u003e Standard documents in EU: EN 4709, US: ASTM F3411.\n\u003e For practical information, check out [this page](https://www.faa.gov/uas/getting_started/remote_id/drone_pilots) by the FAA. If you're looking for an open-source implementation (e.g., Android apps), we suggest [opendroneid.org](https://www.opendroneid.org) and their [Github repositories](https://github.com/opendroneid).\n\nAre you going to improve the receiver, introduce new features, or port to another SDR?\n\u003e We're not planning to include new features at this point. The tool is provided as artifact along our academic paper and enables researchers to reproduce our results, and to help study the privacy implications. It is not meant for productive, reliable localization of drones.\n\nIs your receiver the only receiver available?\n\u003e No. The code in [proto17/dji_droneid](https://github.com/proto17/dji_droneid) was developed in parallel. We think it's great and if you're interested in details, you should take a look at both implementations.\n\n# Citing the Paper\n\nIf you would like to cite our work, use the following BibTex entry:\n```\n@inproceedings{schiller2023drone,\n  title={Drone Security and the Mysterious Case of DJI's DroneID},\n  author={Schiller, Nico and Chlosta, Merlin and Schloegel, Moritz and Bars, Nils and Eisenhofer, Thorsten and Scharnowski, Tobias and Domke, Felix and Sch{\\\"o}nherr, Lea and Holz, Thorsten},\n  booktitle={Network and Distributed System Security Symposium (NDSS)},\n  year={2023}\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRUB-SysSec%2FDroneSecurity","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FRUB-SysSec%2FDroneSecurity","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FRUB-SysSec%2FDroneSecurity/lists"}