Practical drone attack via PWM: Reverse engineering and signal injection at the physical layer

Home » Hawktesters Cybersecurity Research » Practical drone attack via PWM: Reverse engineering and signal injection at the physical layer

In this research we performed a physical control attack on a drone by injecting PWM signals directly to the receiver, replicating the commands that would normally be sent by the remote control.

First, we captured the original PWM signals using a logic analyzer while pressing specific buttons on the control (such as lowering camera, turning on propellers, etc.).

Then, we analyzed the pulse sequences (duration, frequency, pattern) and reconstructed them from a Raspberry Pi Pico, which was programmed to exactly reproduce those pulse trains through one of its GPIO pins.

This approach demonstrated that it is possible to emulate valid remote control commands without sending RF data or interacting with the network layer, attacking directly at the physical level.

The experiment confirms that many drones lack authentication or command validation at the signal level, leaving them exposed to physical PWM injections, even without access to the original control or its wireless protocol.

Recognition

One of the challenges we decided to take on was the idea of tackling something we didn’t know, no context, chip brands or datasheet, so we approached this process completely from scratch, let’s see a little bit, the victim Drone RG600Pro

the inside of its control is as follows.

Since I had no idea what this chip was, our first steps were to measure voltages and perform a recognition with the logic analyzer of what we would be seeing on each of the pins of the main control chip.

Several of the pins were identified through the logic analyzer, we had two types of protocols and signals, SPI and PWM.

The identification of these signals was performed by pressing each of the buttons on the drone control, and capturing the signals in the logic analyzer, once this objective was achieved we were able to successfully decode the SPI and PWM signals.

After several captures, we decided to perform a functionality injection through the PWM signal that the controller sent to the drone.

The idea was to faithfully emulate the PWM signal from the original remote control, allowing the drone to respond to the command as if it had been sent by the real control. This injection technique is effective because the drone’s receiver does not validate authenticity, it only interprets pulses.

PWM signal injection

To achieve this process we only had to use a pico raspberri that has PWM outputs on its pin configurations, and emulate one of the signals that we captured through the logic analyzer.

So we connected the pins from the rapsberry pico to the drone control chip and were able to faithfully replicate one of the functionalities.


from machine import Pin
import time

# Output pin
pwm_pin = Pin(19, Pin.OUT)

# Pulse train captured
pulse_durations_us = [
    517, 1551, 517, 1034, 1551, 1550, 1034, 516, 517, 517,
    1034, 1034, 516, 1034, 2585, 1034, 2585, 1034, 3619, 516,
    1034, 517, 516, 2585, 1034, 1034, 517, 1550, 517, 516,
    517, 2067, 1034, 1034, 1034, 516, 3102, 517, 517, 1551,
    1551, 3102, 516, 1034, 1551, 517, 1551, 1551, 517, 1034,
    518, 1551, 517, 518, 516, 517, 2068, 1552, 1034, 2068,
    517, 516, 1034, 517, 1034, 1035
]

def send_pulses():
    for _ in range(6):  # Repeat only 3 times
        for duration in pulse_durations_us:
            pwm_pin.high()
            time.sleep_us(duration)
            pwm_pin.low()
            time.sleep_us(200)  # Between pulses
        time.sleep_ms(10)  # Short break between trains

    # Final resting state
    pwm_pin.high()
    time.sleep_ms(100)

# Execute
send_pulses()

Aspects that we had to consider in the Raspberry Pi Pico for PWM injection

  • Suitable output GPIO pin
    • We selected a pin (GPIO19 in your case) that supports digital output with good timing stability.
    • This pin was configured as Pin.OUT to generate the PWM signal manually (bit banging).
  • Timing accuracy
    • The signal captured from the drone control was very sensitive to microsecond pulse widths.
    • We used time.sleep_us() to ensure accurate times in microseconds.
    • A small spacing between pulses (sleep_us(200)) and between trains (sleep_ms(10)) was also respected.
  • Signal frequency
    • Although a “continuous” PWM signal was not generated, the effective pulse frequency was crucial.
    • The pulse_durations_us values reflect an accurately captured pulse train that was to be replicated without distortion or jitter.
  • Format of the pulse train
    • The signal was composed of a precise sequence of variable pulse widths (between 500 µs and >3 ms).
    • It is essential to reproduce the entire complete pattern, as the drone interprets that as a valid command (such as “turn on” or “activate camera”).
  • Pulse train repetition
    • Some devices require the pulse train to be repeated several times to be recognized.
    • Therefore the loop repeats the train 6 times (for _ in range(6)).
  • Appropriate logic level
    • The Raspberry Pi Pico operates at 3.3V, and is compatible with many PWM devices, but:
      • If the drone expected 5V, a level shifter would be needed.
      • In this case, apparently 3.3V was enough to activate the drone’s receiver pin.
  • Idle condition of the pin
    • After finishing the send, the pin was left in the high state (pwm_pin.high()) for 100ms.
    • This simulates the behavior of the real controller, avoiding false commands after injection.

Conclusion

PWM pulse injection from a Raspberry Pi Pico proved to be an effective technique to emulate control commands on a drone, accurately replicating the pulse train of the original control. This test confirms that, with proper timing and without the need for wireless communication, it is possible to manipulate physical devices at a low level, opening the way to new forms of analysis and attack in embedded environments.

Samir Sánchez Garnica

Hi, Samir Sanchez Garnica is a seasoned Purple Team professional with over 12 years of expertise in ethical hacking, specializing in security testing across web environments, cloud platforms (Azure, AWS, Google Cloud), and on-premise infrastructures—with a primary focus on the banking sector. His extensive experience encompasses mobile application security, reverse engineering, network team exercises, and social engineering initiatives. A passionate programmer, Samir continually enhances his work through the automation of pentesting processes, leveraging his proficiency in SHELLSCRIPT, Python3, PHP, C, JavaScript, PowerShell, Objective-C, Node.js, Dart, and Assembly Language. Samir’s current endeavors are centered on reverse engineering, where he excels as both a reverser and shellcode writer across Windows, macOS, and GNU/Linux environments, spanning user land and kernel land. His latest research efforts delve into debugging within iOS mobile environments, IoT technologies, and the intricacies of reversing on MIPS and ARM architectures, with a specialized focus on radio frequency-based hardware exploitation.

Post navigation

Leave a Comment

Leave a Reply

Your email address will not be published. Required fields are marked *