Skip to content

Instantly share code, notes, and snippets.

@bAndie91
Created October 4, 2016 10:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bAndie91/dca26e544a1b75fcb06c8594c007e1c1 to your computer and use it in GitHub Desktop.
Save bAndie91/dca26e544a1b75fcb06c8594c007e1c1 to your computer and use it in GitHub Desktop.
#!/usr/bin/perl
#
# Rouge DHCP traffic detection.
#
$0 = "RougeDetect";
# Wait for dhcp offer:
$WAIT = 10;
# Only legal dhcp server and gateway:
$Router = "192.168.1.254";
$iface = "eth0";
use IO::Select;
use IO::Socket::INET;
use Net::DHCP::Packet;
use Net::DHCP::Constants;
use Data::Dumper;
use Net::RawIP;
use Net::Pcap qw/pcap_open_live lookupnet compile setfilter pcap_loop/;
use NetPacket::Ethernet qw/eth_strip/;
use NetPacket::IP;
use NetPacket::UDP;
use POSIX qw/:sys_wait_h/;
if(-t 2) {
open DEBUG, ">&STDERR";
}
else {
open DEBUG, ">", "/dev/null";
}
# generate fake mac address
@HWaddr = ( int(rand(2**24)) & 0xFCFFFF, int(rand(2**24)) );
$HWaddr = sprintf "%06X%06X", @HWaddr;
#$HWaddr = "000802d9b325";
#$HWaddr = "0026181beffe";
$MAC = mac2coloned($HWaddr);
$xid = int(rand(0xFFFFFFFF));
$discover = Net::DHCP::Packet->new(
Xid => $xid,
#Flags => 0x0000, # Unicast
Flags => 0x8000, # Broadcast
DHO_DHCP_MESSAGE_TYPE() => DHCPDISCOVER(),
Chaddr => $HWaddr,
Ciaddr => '0.0.0.0',
Siaddr => '0.0.0.0',
Giaddr => '0.0.0.0',
Hops => 0,
DHO_DHCP_PARAMETER_REQUEST_LIST() => join(' ', 1..254),
DHO_VENDOR_CLASS_IDENTIFIER() => "MSFT",
);
#print $discover->toString();
$dhcp = $discover->serialize();
$kid[0] = fork;
if($kid[0]==0) {
$0 = "RougeDetect-Listen";
exit fake_listen_sniff();
}
$kid[1] = fork;
if($kid[1]==0) {
$0 = "RougeDetect-Discover";
exit discover();
}
print DEBUG "Waiting $WAIT sec\n", ;
$start = time;
WAIT:
$kid = waitpid -1, WNOHANG;
$rouge = ($? >> 8);
if($kid == $kid[0]) {
kill 'TERM', $kid[1];
exit $rouge;
}
if($start + $WAIT > time) {
goto WAIT;
}
else {
kill 'TERM', @kid;
exit 0;
}
sub discover {
$packet = new Net::RawIP({
ip => {
saddr => '0.0.0.0',
daddr => '255.255.255.255',
frag_off => 0,
},
udp => {
source => 68,
dest => 67,
data => $dhcp,
},
});
#$packet->send;
$packet->ethnew($iface);
$packet->ethset(dest => "FF:FF:FF:FF:FF:FF");
$packet->ethset(source => $MAC);
for(1..5) {
print DEBUG "DHCP Discover $MAC\n", ;
$packet->ethsend;
sleep 1;
}
}
sub fake_listen_socket {
# listens for DHCP reply on dgram socket
my $start = time;
$socket = IO::Socket::INET->new(
Proto => 'udp',
LocalPort => '68',
LocalAddr => '0.0.0.0',
) or die "socket: $@\n";
while(1) {
@ready = IO::Select->new($socket)->can_read($WAIT);
if(not @ready or $start + $WAIT < time) {
return 0;
}
$socket->recv($newmsg, 1024);
my $rouge = display_dhcp_reply($newmsg);
return 1 if $rouge;
}
}
sub fake_listen_sniff {
# listens for DHCP reply on raw interface
$filter_str = "udp and dst port 68";
$pcap = pcap_open_live($iface, 1500, 1, $WAIT*1000, \$errstr)
or die "Can't open device $iface: $errstr\n";
lookupnet($iface, \$net, \$mask, \$errstr) == 0
or die "Can't get device properties $iface: $errstr\n";
compile($pcap, \$bpf_prog, $filter_str, 0, $mask) == 0
or die "Can't compile filter '$filter_str'\n";
setfilter($pcap, $bpf_prog) == 0
or die "Can't apply filter '$filter_str'\n";
my $rouge;
pcap_loop($pcap, -1, sub {
my ($rouge, $header, $packet) = @_;
$eth = NetPacket::Ethernet->decode($packet);
$ip = NetPacket::IP->decode(eth_strip($packet));
$udp = NetPacket::UDP->decode($ip->{'data'});
#print DEBUG Dumper $eth, $ip, $udp;
$rouge = display_dhcp_reply($udp->{'data'}, mac2coloned($eth->{'src_mac'}));
exit $rouge; # drasztikus
}, \$rouge);
return $rouge;
}
sub display_dhcp_reply {
my $packet = Net::DHCP::Packet->new($_[0]);
if($packet->xid eq $xid) {
if($packet->siaddr ne $Router or $packet->getOptionValue(DHO_ROUTERS()) ne $Router)
{
printf "src_mac = %s\n", $_[1] || "n/a";
print $packet->toString();
return 1;
}
}
return 0;
}
sub mac2coloned {
return join ':', grep {$_} split/(..)/, $_[0];
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment