Thursday, January 7, 2010

Creating a sniffer using perl

Below is simple program i wrote to sniff live DNS requests so a network admin can have an idea of the websites that a user is requesting in real time.

#!/usr/local/bin/perl

#
#
#
use strict;
use Net::Pcap;
use NetPacket::Ethernet;
use NetPacket::IP;
use NetPacket::TCP;
##################################

# Variable Declarations

my $filter_t;
my ($tcp,$ip,$ethernet);
my ($net,$mask,$err);
my $dev = $ARGV[0]; //takes the network card interface as the first parameter
my $filter = "udp dst port 53"; //this is the filter we are going to use, in tcpdump notaion
my $optimize = 1;
############################################

# Determine network number and mask for use later on when we're compiling our filter
if (Net::Pcap::lookupnet($dev, \$net, \$mask, \$err) == -1){
die 'Cannot determine network number and subnet mask - ' , $err;
}

# create a live pcap capture object
my $pcap_object = Net::Pcap::open_live($dev, 1500, 0, 0, \$err);
if (defined $err){
die 'Failed to create live capture on - ' , $dev , ' - ', $err;
}

Net::Pcap::compile($pcap_object, \$filter_t, $filter, $optimize, $mask); //compile our filter ,$filter and return it in the $filter_t variable
Net::Pcap::setfilter($pcap_object, $filter_t); //set the compliled filter, of $filter_t
Net::Pcap::loop($pcap_object, -1, \&capture_packets, '') || die 'Unable to perform packet capture'; //loop or sniff packets on the network infinitly
Net::Pcap::close($pcap_object); //close the pcap object gracefully
#######################################

# subroutine to handle each packet that is sniffed
sub capture_packets {
my ($user_data, $hdr, $pkt) = @_; //this line should always be present to handle the incoming packets, You refer to the incoming packets from $pkt as you would see from the next lines of code
my $ethernet = NetPacket::Ethernet->decode($pkt); //decodes the ethernet frame
my $ip = NetPacket::IP->decode($ethernet->{data}); // decodes the IP headers
my $tcp = NetPacket::TCP->decode($ip->{data}); // decodes the TCP data
print "$ip->{src_ip} -> $ip->{dest_ip} : "; // prints source to destination IP's
print "$tcp->{data}\n"; //prints the data contained in this packet
}

The unfortunate thing about dns request is that there can be so many of them, even when you request one website. For instance, try going to www.google.com. You would notice that you capture the dns request for www.google.com in addition to a couple other request that the google page itself has made for you.

No comments:

Post a Comment