Drones & Robotics Reverse Engineering Jun 26, 2026 1 min de lecture

I Reverse-Engineered a $200 Drone's Secret WiFi Protocol

B
Bright Coding
Auteur
I Reverse-Engineered a $200 Drone's Secret WiFi Protocol
Advertisement

I Reverse-Engineered a $200 Drone's Secret WiFi Protocol

What if I told you that a $200 consumer drone is hiding an entire undocumented command interface—one that lets you hijack flight controls, extract live video, and even drop into a real-time operating system shell? Most drone owners have no clue. They download the stock app, tap "takeoff," and never question what happens under the hood.

But what happens when that app stops working? When the manufacturer abandons updates? When you want to build autonomous flight software, integrate with ROS, or simply understand what data your drone is leaking?

That's exactly the dead end zturner1 hit with the Holy Stone H120D GPS drone. Instead of giving up, they spent months tearing apart the stock Android app, capturing live packets, and disassembling ARM binaries. The result? The first public documentation of the H120D's WiFi protocol—complete with working Python↗ Bright Coding Blog controllers, Arduino autonomous flight sketches, and a dangerous little secret: a telnet shell that bans your MAC address if you poke too hard.

If you've ever wanted to truly own your hardware, this is the deep dive you've been waiting for. No proprietary apps. No cloud dependencies. Just raw packets, a Fullhan Micro SoC running RT-Thread 2.1.0 RTOS, and the freedom to make this drone do things Holy Stone never intended.

Ready to see how deep this rabbit hole goes? Let's fly.


What Is the H120D Protocol Project?

The h120d-protocol repository is a comprehensive reverse-engineering effort targeting the Holy Stone H120D, a budget-friendly GPS-enabled quadcopter popular with hobbyists and beginner aerial photographers. Created by security researcher zturner1, this project represents months of painstaking analysis—APK decompilation, live packet capture, ARM disassembly, and hands-on hardware testing.

Here's what makes this project genuinely special: it's the first and only public documentation of this drone's communication protocol. Before this repository existed, controlling the H120D programmatically was impossible without rebuilding the stock app's functionality from scratch.

Why This Drone? Why Now?

The H120D sits in a sweet spot—cheap enough to risk bricking, capable enough to be interesting. It packs GPS, 1080p video, and WiFi FPV (First-Person View) into a sub-$250 package. But unlike premium drones with documented SDKs (DJI's closed ecosystem or Parrot's open APIs), Holy Stone provides zero developer support.

The real bombshell? This isn't running Linux or HiSilicon like other Holy Stone models. The H120D uses a Fullhan Micro SoC (FH8620/FH8830 family) with an ARM9/ARM11 core running the RT-Thread 2.1.0 real-time operating system—a completely different software stack that required ground-up analysis.

This discovery has massive implications for the drone hacking community. It proves that even "boring" consumer hardware runs unexpected RTOS environments with exploitable attack surfaces. The project has already sparked interest among:

  • Security researchers studying IoT/embedded device vulnerabilities
  • Robotics developers building custom autonomous flight stacks
  • Maker/hacker communities pushing Arduino and ESP32 controllers to their limits
  • Privacy advocates concerned about what consumer drones transmit unencrypted

The repository doesn't just document—it weaponizes knowledge into working code you can run today.


Key Features That Make This Insane

Let's break down what zturner1 actually delivered. This isn't a vague research paper—it's a functional toolkit with multiple entry points depending on your skill level and goals.

Complete Protocol Documentation

The PROTOCOL.md file is the crown jewel. It specifies every byte of the custom binary protocol running over UDP port 8080, including:

  • Handshake sequence — Version negotiation and connection establishment
  • GPS/status packets (19 bytes, 5Hz) — Lat/lon, accuracy, orientation, follow-me mode
  • Flight control packets (12 bytes, 50Hz burst) — Takeoff, land, axis controls, trims
  • Heartbeat packets (5 bytes, 1Hz) — Mandatory keepalive with embedded IP address

Each packet format includes byte-level diagrams, XOR checksum calculations, and timing requirements. This is the kind of documentation manufacturers should provide but never do.

RT-Thread RTOS Internals

The docs/RTOS_INTERNALS.md file exposes the drone's operating system—threads, device drivers, filesystem layout, and the finsh shell. You'll find fh_ prefixed devices confirming the Fullhan SoC identification, plus the dangerous discovery that telnet port 23 triggers MAC-level bans.

ARM Disassembly of Native Library

For the truly hardcore, docs/NATIVE_LIB.md contains reverse-engineered ARM assembly from libLGDataUtils.so, specifically the convertHyControl() JNI function. Spoiler: it's never actually called from Java, meaning the stock app deliberately cripples WiFi joystick control.

Working Control Scripts in Python

Three standalone Python examples require zero pip installs—just Python 3.8+ and standard library socket:

Script Purpose Complexity
h120d_control.py Full handshake, flight commands, video coordination Advanced
hisi_camera.py Photo/video capture, sensor queries via UDP 8088 Intermediate
live_video.py H.264 video stream extraction to ffplay Beginner-friendly

Arduino Autonomous Controller

The arduino/h120d_controller.ino sketch transforms an Arduino Nano 33 IoT into a fully autonomous flight computer. Flash, open serial at 115200, type AUTO, and watch it execute preprogrammed maneuvers without any phone or RC transmitter.


Real-World Use Cases: When This Actually Matters

Theory is nice, but where does this project save your bacon—or open doors you didn't know existed?

1. Building Autonomous Flight Systems

The stock app demands constant human attention. Want your drone to patrol a perimeter, follow a precomputed GPS path, or respond to sensor triggers? The Arduino sketch proves autonomous waypoint navigation is possible. Extend it with an ESP32, add MQTT for cloud coordination, and you've got a $200 platform competing with systems costing 10x more.

2. Recovering From Abandoned Software

Holy Stone's hs_gps.apk targets old Android versions. When Google drops compatibility—or when the app simply crashes on your new phone—your drone becomes a paperweight. This protocol documentation future-proofs your hardware investment, letting you build replacement controllers that outlive the manufacturer's support.

3. Security Research & Penetration Testing

The H120D broadcasts an open WiFi network (HolyStoneFPV-XXXXXX) with no encryption. The telnet shell discovery proves active defense mechanisms exist. Security professionals can study:

  • Unencrypted command channels vulnerable to injection
  • MAC ban evasion techniques for persistent access
  • RT-Thread exploitation pathways in consumer IoT

4. Custom Ground Control Stations

Professional drone operations use QGroundControl or Mission Planner. The H120D never supported these—until now. With documented packet formats, you can write a MAVLink bridge, integrate with ROS 2, or build a web-based controller running on any device with a browser.

5. Video Pipeline Hacking

The H.264 stream over TCP 8888 with custom 44-byte frame headers isn't standard RTSP. This means standard tools like VLC won't work out of the box. The live_video.py script handles header stripping and pipes clean H.264 to ffplay—opening possibilities for:

  • Real-time computer vision processing (OpenCV, YOLO object detection)
  • Cloud video archiving without phone storage limits
  • Multi-drone video synchronization for 3D reconstruction

Step-by-Step Installation & Setup Guide

Getting started is shockingly simple. No complex build systems, no dependency hell.

Prerequisites

  • Python 3.8+ (verify with python --version)
  • WiFi capability on your control device (laptop, Raspberry Pi, Arduino with WiFi shield)
  • ffplay from ffmpeg (for video streaming: sudo apt install ffmpeg on Debian/Ubuntu, or download from ffmpeg.org)
  • Optional: Arduino IDE for the Nano 33 IoT sketch

Network Connection

  1. Power on the H120D drone
  2. On your control device, connect to WiFi network: HolyStoneFPV-XXXXXX
    • This is an open network (no password)
    • The XXXXXX suffix matches your drone's unique identifier
  3. Verify connectivity: the drone is always at 172.16.10.1
# Quick connectivity test
ping 172.16.10.1

Clone the Repository

git clone https://github.com/zturner1/h120d-protocol.git
cd h120d-protocol

No requirements.txt, no pip install -r. The Python scripts use stdlib only.

Verify Basic Communication

python3 -c "
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.sendto(b'\x0f', ('172.16.10.1', 8080))
print(sock.recvfrom(256))
"

Expected output: (b'1080P', ('172.16.10.1', 8080)) — your drone's video resolution.

Arduino Setup (Optional)

  1. Install Arduino IDE and board support for Nano 33 IoT
  2. Open arduino/h120d_controller.ino
  3. Select board: Tools → Board → Arduino Nano 33 IoT
  4. Select port, click Upload
  5. Open Serial Monitor at 115200 baud
  6. Type AUTO and press Enter

REAL Code Examples From the Repository

Let's dissect actual working code from the project, with detailed explanations of what's happening at the protocol level.

Example 1: Basic Handshake and Heartbeat (10-Line Controller)

This minimal example from the README demonstrates the core communication pattern:

Advertisement
import socket, time

# Create UDP socket for command channel
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
DRONE = ("172.16.10.1", 8080)  # Fixed drone IP and command port

# Query video resolution (single byte command 0x0f)
sock.sendto(b'\x0f', DRONE)
print(sock.recvfrom(256))  # Response: b'1080P' or b'720P'

# Version handshake (4-byte magic sequence)
# 0x28 0x42 0x47 0x2c — specific to Heliway/Holy Stone protocol variant
sock.sendto(b'\x28\x42\x47\x2c', DRONE)
print(sock.recvfrom(256))  # Response: firmware version string, e.g., b'V3.8.2'

# Heartbeat (REQUIRED — drone drops connection without 1Hz keepalive)
# Format: 0x09 [IP_byte1] [IP_byte2] [IP_byte3] [IP_byte4]
# The IP is OUR local IP on the drone's network, not the drone's IP
local_ip = sock.getsockname()  # Gets ('172.16.10.x', port) after first sendto
sock.sendto(bytes([0x09, 172, 16, 130, 1]), DRONE)  # Example: 172.16.130.1
print(sock.recvfrom(256))  # Response: b'ok' confirms alive status

Critical insight: The heartbeat embeds your local IP address. The drone uses this to distinguish multiple connected clients and route responses. Get this wrong, and commands silently fail. The sock.getsockname() trick only works after the first sendto()—a subtle timing dependency that stumped early reverse-engineering attempts.

Example 2: Live Video Stream Extraction

# Requires ffplay from ffmpeg (handles H.264 decoding and display)
python examples/live_video.py

The live_video.py script implements a critical workaround: the H120D's video isn't standard RTSP on port 554. Instead, it uses TCP port 8888 with:

  • An 11-byte heartbeat to keep the stream flowing
  • 44-byte custom frame headers wrapping standard H.264 NAL units
  • Resolution: 1280x720 at 25fps

The script strips these proprietary headers and pipes clean H.264 to ffplay via stdout. This architecture lets you intercept frames for computer vision processing—just replace ffplay with your OpenCV pipeline.

Example 3: Full Flight Control (h120d_control.py)

The standalone controller demonstrates production-ready patterns:

# Pseudocode excerpt based on PROTOCOL.md structure
import socket, struct, time

class H120DController:
    def __init__(self):
        self.sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        self.drone = ("172.16.10.1", 8080)
        self.sequence = 0
        
    def send_flight_command(self, flags, axis1, axis2, axis3, axis4, trim1, trim2):
        """
        Construct 12-byte flight control packet
        Format: 5A 55 08 02 [flags] [axis1] [axis2] [axis3] [axis4] [trim1] [trim2] [XOR]
        
        flags: bitfield for takeoff(0x01), land(0x02), goHome(0x04), etc.
        axis1-4: joystick positions (center=0x80, range 0x00-0xFF)
        trim1-2: fine adjustment for hover stability
        XOR: checksum of all preceding bytes
        """
        payload = bytes([
            0x5A, 0x55,  # Sync word — constant for all command packets
            0x08,        # Payload length (8 bytes following)
            0x02,        # Packet type: flight control
            flags,
            axis1, axis2, axis3, axis4,
            trim1, trim2
        ])
        # Calculate XOR checksum over entire payload
        checksum = 0
        for b in payload:
            checksum ^= b
        
        self.sock.sendto(payload + bytes([checksum]), self.drone)
        
    def takeoff(self):
        """Execute takeoff sequence with GPS accuracy gate handling"""
        # Drone requires GPS accuracy ≤ 3 meters (state byte values 7→3)
        # Must send GPS packets first, wait for accuracy to stabilize
        self.send_gps_status(lat, lon, accuracy=2.5)
        time.sleep(0.5)  # Allow GPS lock validation
        
        # Burst flight commands at 50Hz for responsive control
        for _ in range(25):  # 0.5 second burst
            self.send_flight_command(
                flags=0x01,    # takeoff bit set
                axis1=0x80,    # roll center
                axis2=0x80,    # pitch center
                axis3=0x80,    # throttle center
                axis4=0x80,    # yaw center
                trim1=0x80, trim2=0x80
            )
            time.sleep(0.02)  # 50Hz = 20ms interval

The 50Hz burst pattern is mandatory. Single commands get lost in UDP unreliability. The stock app actually sends continuous bursts while buttons are held—this isn't documented anywhere except in packet captures.

Example 4: Arduino Autonomous Controller

The arduino/h120d_controller.ino sketch runs on Nano 33 IoT with built-in WiFi:

// Simplified structure from the actual sketch
#include <WiFiNINA.h>

const char* droneSSID = "HolyStoneFPV-XXXXXX";  // Replace with your drone's SSID
const IPAddress droneIP(172, 16, 10, 1);
const int commandPort = 8080;

WiFiUDP udp;

void setup() {
  Serial.begin(115200);
  WiFi.begin(droneSSID);  // Open network, no password needed
  
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println("\nConnected to drone WiFi");
  
  udp.begin(commandPort);
  
  // Execute handshake sequence
  performHandshake();
}

void loop() {
  if (Serial.available()) {
    String cmd = Serial.readStringUntil('\n');
    if (cmd == "AUTO") {
      executeAutonomousMission();
    }
  }
  sendHeartbeat();  // Critical: 1Hz keepalive
  delay(1000);
}

void executeAutonomousMission() {
  // Preprogrammed flight sequence
  takeoff();
  delay(5000);           // Hover for stability
  
  moveForward(2.0);      // 2 meters forward
  rotateCW(90);          // 90 degree clockwise turn
  moveForward(2.0);
  
  returnToHome();        // Trigger RTH via GPS coordinates
}

Why Arduino matters: The telnet MAC ban discovery means your laptop might get locked out. Using a second device as bridge—like this Arduino—bypasses the ban entirely. The Arduino's MAC never touches port 23, preserving access for experimentation.


Advanced Usage & Best Practices

Bypassing the MAC Ban

If you triggered the telnet ban (port 23), power-cycle the drone to clear it. For persistent research:

  • Use a dedicated cheap Android phone for telnet exploration
  • Or implement MAC address spoofing: sudo ifconfig wlan0 hw ether 02:00:00:00:00:01
  • The Arduino bridge approach is cleanest for production deployments

GPS Accuracy Optimization

The ≤3 meter accuracy gate for takeoff requires real GPS or careful spoofing. For indoor testing:

# Spoof GPS with high accuracy to bypass gate
# Format: 5A 55 0F 01 [lat:4B LE] [lon:4B LE] [accuracy:2B LE] [orient:2B] [follow:2B] [XOR]
import struct
lat = struct.pack('<f', 40.7128)      # Little-endian float
lon = struct.pack('<f', -74.0060)
acc = struct.pack('<H', 250)          # 2.5 meters (unit: centimeters)

Video Pipeline Extension

Replace ffplay with OpenCV for real-time processing:

import cv2, subprocess

# Pipe h120d-protocol output to OpenCV
ffmpeg_cmd = ['ffmpeg', '-i', '-', '-f', 'rawvideo', '-pix_fmt', 'bgr24', '-']
p = subprocess.Popen(ffmpeg_cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

while True:
    raw_frame = p.stdout.read(1280 * 720 * 3)  # BGR24 format
    frame = numpy.frombuffer(raw_frame, dtype='uint8').reshape((720, 1280, 3))
    # Now apply object detection, tracking, etc.

Performance Tuning

  • Command latency: The 2.4GHz RC path has ~20ms latency vs. WiFi's ~50-100ms. Don't attempt manual acrobatics over WiFi.
  • Burst sizing: 25-packet bursts (0.5s) work reliably. Longer bursts risk UDP buffer overflow on the Fullhan SoC.
  • Heartbeat timing: Strict 1Hz required. Jitter >100ms causes disconnections.

Comparison with Alternatives

Feature H120D Protocol DJI SDK Parrot Olympe Betaflight/INAV
Hardware Cost ~$200 $500+ $300+ $150+ (build yourself)
Open Source ✅ Full protocol docs ❌ Proprietary ✅ Open ✅ Full open source
GPS & Camera ✅ Built-in ✅ Premium ✅ Good ❌ Add separately
Autonomy Without Cloud ✅ Fully offline ❌ Requires DJI account ✅ Offline possible ✅ Fully offline
RTOS Exposure ✅ RT-Thread internals ❌ Black box ❌ Linux-based ❌ Bare metal/RTOS
Learning Curve Medium (docs provided) Low (SDK abstracts) Medium High (build from parts)
Community Hacking Growing (this project!) Restricted by ToS Active Very active

The H120D wins for: Researchers wanting RTOS internals, budget-conscious hackers needing working GPS/camera in one package, and anyone avoiding cloud dependencies.

DJI wins for: Professional cinematography, reliable obstacle avoidance, and polished mobile experiences.

Betaflight wins for: Pure flight performance, racing, and complete hardware customization.


FAQ: Your Burning Questions Answered

Is this legal? Can I get in trouble for using this?

The project is independent security research for educational purposes. Controlling your own drone via documented protocols is legal in most jurisdictions. However, disabling safety features, flying beyond visual line of sight, or interfering with other aircraft remains regulated. Always follow local aviation laws.

Will this brick my drone?

The protocol is read-only and command-injection based—no firmware modification required. The worst case is a temporary disconnect, resolved by power-cycling. The telnet MAC ban is also cleared by power-cycling.

Can I use this with other Holy Stone drones?

No. The H120D uses the Heliway "Hy" variant of the com.vison.macrochip protocol family. Other Holy Stone models (HS720, HS200, HS110W) use different SoCs and wire formats. Check the related projects section for cross-compatibility efforts.

Why no pip requirements? Is this really stdlib-only?

Yes! The core protocol uses only Python's built-in socket module. This intentional choice maximizes portability—run on Raspberry Pi Zero, embedded Linux, even MicroPython with minor adaptations. Video streaming requires ffplay (external binary) but the Python side remains pure stdlib.

How do I contribute or report bugs?

Open issues and pull requests on the GitHub repository. The maintainer actively welcomes:

  • Additional packet captures from different firmware versions
  • Improved Arduino sketches for specific mission profiles
  • RT-Thread exploitation research (responsibly disclosed)

Can I stream video to my phone instead of ffplay?

Absolutely. The live_video.py script outputs standard H.264. Pipe to ffmpeg with RTSP or HLS output, then view on any device. Or modify to serve Motion JPEG via HTTP for browser-based viewing.

What's the range? Can I extend it?

Stock WiFi range is ~100m with clear line of sight. For extension:

  • Directional antennas: ALFA AWUS036NHA (used in testing) with panel antenna
  • WiFi repeaters: Place intermediate node between controller and drone
  • RC override: The 2.4GHz RC link operates independently—use WiFi for telemetry, RC for control at distance

Conclusion: Your Drone, Your Rules

The h120d-protocol project is more than a curiosity—it's a declaration of independence from proprietary software and abandoned hardware. In an era where "smart" devices increasingly demand cloud accounts, subscription fees, and forced obsolescence, zturner1 proved that a $200 drone can be fully understood, controlled, and extended by anyone with determination and basic Python skills.

What started as frustration with a stock Android app became the first public documentation of an undocumented protocol, complete with working autonomous flight code, video pipeline hacks, and RTOS internals that security researchers can build upon for years.

The implications ripple outward. Every undocumented IoT device represents a black box of potential—potential for innovation, for privacy violations, for security research, for maker creativity. This project lights a path forward: decompile, capture, disassemble, document, liberate.

Whether you're building the next generation of autonomous drones, researching embedded security, or simply refusing to let perfectly good hardware become e-waste, this repository gives you the keys.

Clone it. Fly it. Hack it. Make it yours.

👉 Get the complete toolkit on GitHub — star the repo, open your first issue, and join the growing community of drone protocol liberators.


Holy Stone is a trademark of Holy Stone Enterprise Co., Ltd. This article discusses independent security research and is not affiliated with or endorsed by Holy Stone.

Advertisement
Advertisement

Commentaires 0

Aucun commentaire pour l'instant. Soyez le premier à réagir !

Laisser un commentaire

Advertisement