Falamable/drone-protocol-analyzer
GitHub: Falamable/drone-protocol-analyzer
通过Wireshark抓包逆向分析DMH0002HW无人机的UDP控制协议,并用Python实现脱离官方App的编程控制。
Stars: 1 | Forks: 0
# 逆向工程我的无人机:物理项目 🚁
对于我的物理项目,我决定做点不一样的事情:我对我的 DMH002HW 无人机的通信协议进行了逆向工程,这样我就可以编写自己的 Python 脚本来控制它飞行!
这个项目帮助我将课堂上学到的关于**网络(UDP/IP)、十六进制、二进制数据和编程**的理论应用到了实际场景中。以下是我的具体操作步骤。
## 1. 目标:破解无人机
通常,我使用手机上的官方 App 来控制无人机。该 App 通过 Wi-Fi 发送不可见的信号来控制无人机。
我想用我自己编写的 Python 代码来替换这个 App。但要做到这一点,我需要拦截这些信号,并理解 App 与无人机“对话”时使用的“语言”(即协议)。
## 2. 方法:使用 Wireshark 进行抓包
为了弄清楚这个 App 是如何工作的,我在 PC 上安装了一个 Android 模拟器,安装了无人机的官方 App,并连接到了无人机的 Wi-Fi。然后,我使用了一个名为 **Wireshark** 的工具来记录模拟器和无人机之间的所有网络流量。Wireshark 就像一个窃听器,会记录连接上发送的每一个数据包。
我将这次记录保存为 `.pcapng` 文件。通过分析这个文件,我需要回答三个主要问题:
1. **数据发往哪里?**(IP 地址和端口)
2. **数据是如何发送的?**(协议)
3. **数据包含了什么内容?**(Payload)
## 3. 发现:破解代码
在盯着查看了大量的网络日志之后,我开始注意到一些规律,并成功破译了该协议!
### A. 地址簿(IP 和端口)
- **协议:** 该 App 使用 **UDP**(用户数据报协议)。在我的 AS Level 课程大纲中,我了解到 UDP 速度很快,并且与 TCP 不同,它不需要等待确认。这对于控制无人机来说非常合理,因为你需要实时的控制并且做到零延迟。
- **目标 IP:** 无人机充当自己的 Wi-Fi 路由器。它的 IP 地址是 `192.168.169.1`。
- **端口:** 无人机在端口 `8800` 上监听控制命令。
### B. 语言(十六进制 Payload)
计算机以二进制形式发送数据,但 Wireshark 以 **十六进制**(基数为 16)的形式显示,以便于阅读。我注意到主要发送了两种类型的数据包:
#### 1. “启动 / 飞行”数据包(88 字节长)
在飞行过程中,该 App 大约每 30 毫秒发送一个巨大的数据包。如果我停止发送这些数据包,无人机就会假定连接已丢失并安全地悬停。
以下是其中一个数据包内部的原始十六进制数据:
```
ef 02 58 00 02 02 00 01 00 00 00 00 [a6 07 00 00] 08 00 66 80 [80 80 81 40] 41 ...
```
以下是我的破译过程:
- **`ef 02`**:这是一个“魔数”。它基本上是在告诉无人机:“嘿,这是一个控制数据包!”
- **`58 00`**:数据包的长度(十六进制的 `0x58` 等于十进制的 88)。
- **`[a6 07 00 00]`**:这是**序列号**。每发送一个数据包,它就会增加 1。它帮助无人机忽略旧的、延迟的数据包。
- **`[80 80 81 40]`**:这些是实际的**摇杆数值**!
- `0x80` 在十进制中是 128。由于一个字节的范围是 0-255,所以 128 正好处于中间位置。这意味着俯仰、横滚和偏航的摇杆正处于完美的居中状态。
- `0x40` 在十进制中是 64。这代表油门(高度控制)处于零位/怠速状态。
#### 2. “停止”数据包(4 字节长)
当我关闭 App 或按下停止键时,它会发送一个微小的 4 字节数据包,立即终止连接:
```
ef 00 04 00
```
## 4. 解决方案:编写 Python 脚本
既然我已经知道了 IP、端口和确切的十六进制代码,我就可以使用 Python 构建完全相同的数据包,并通过 Wi-Fi 将它们发送出去。
这是我编写的 Python 脚本。它使用 `socket` 库连接到无人机,发送“怠速”控制命令 5 秒钟以保持其存活,然后干净地将其关闭。
```
import socket
import time
import struct
DRONE_IP = "192.168.169.1"
DRONE_PORT = 8800
def create_control_packet(seq_num):
# This is the 88-byte hex payload I copied from Wireshark.
# The joysticks are centered, and throttle is zero.
base_hex = (
"ef025800020200010000000000000000" # First 16 bytes
"08006680808081404199000000000000" # Next 16 bytes (Joysticks are here!)
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"00000000000000000000000000000000"
"324b142d0000" # Last 6 bytes
)
# Convert the long string of hex into actual raw bytes
packet = bytearray.fromhex(base_hex)
# I used the 'struct' library to easily inject my increasing
# Sequence Number into bytes 12, 13, 14, and 15 in Little-Endian format.
packet[12:16] = struct.pack("
标签:Android 模拟器, DMH0002HW, Python 控制脚本, UDP 协议, Wi-Fi FPV 无人机, Wireshark, 二进制解析, 十六进制数据分析, 句柄查看, 无人机逆向工程, 无线通信, 物理学项目, 物联网黑客, 硬件黑客, 移动应用逆向, 网络数据包分析, 自定义飞行控制, 计算机网络实践, 逆向工具, 通信协议分析, 防御绕过, 飞行控制指令 (油门/偏航/俯仰/翻滚)