#!/usr/bin/perl

# pdump.pl v0.777b3 [http://pdump.LucidX.com] (tcpdump/ngrep/dsniff/macof/webspy/urlsnarf clone with neato stuff)
# started: 07/11/00 14:31:10.874351
# last updated: 08/14/00 21:40:39.547794
#
# watches for icmp, udp, and tcp packets
# also finds headers, ack sequences, window size, when (to the millisecond) the packet
# was sent or recieved, etc. and also output is very similar to tcpdump output
#
# includes over 10 of the same capabilities/options that tcpdump has
# includes over 5 of the same capabilities/options that ngrep has
#
# arguments:
# 
# ./pdump.pl [-ACfGhImnNpqStuvVXZ] [-c count] [-E "expression"] [-F file] [-g "regexp"] [-H "regexp"] [-i interface] [-P "regexp"] [-r file] [-s snaplen] [-w file] [-W "service, service"]
#
# this does not, yet, list all the options of pdump.  be sure to read the README file
# which has a very descriptive explanation of pdump.  it is the same thing as the man
# page, just in plain text.  there are also html and pod versions available in the
# docs directory.
#
# can use -E to use <X> as a bpf filter, e.g. -E "tcp port 21"
# can use -c to listen for <X> amount of packets then die (same in tcpdump/ngrep (-n in ngrep))
# can use -i to use <X> interface instead of looking for the interface itself (same in tcpdump/ngrep/macof/dsniff (-d in ngrep))
# N/A - can use -w to write output to <X> and readable with -r, even readable to tcpdump (same in tcpdump)
# N/A - can use -r to read input from <X> and will read tcpdump output, too (same in tcpdump)
# can use -P to not print any packets with the dest or source port/service name matching the regexp <X>
# can use -H to not print any packets with the ip/hostname matching the regxp <X>
# can use -C to go along with -H for -H's <X> to be case-insensitive
# can use -I to go along with -P for -P's <X> to be case-insensitive
# can use -g to 'grep' data and print it if <X> matches any packets (ngrep capability)
# can use -G to ignore case of the regexp used with -g (same in ngrep (-i in ngrep))
# can use -n to not lookup ips and only display port numbers [equivalent to -fS] (same in tcpdump)
# can use -N to only print first part of domains, e.g. LucidX.com would be 'LucidX' (same in tcpdump)
# can use -f to not lookup ips (same in tcpdump)
# can use -u to use ANSI color
# can use -A for arguments available
# can use -X to print any packets NOT matching -g's regexp
# can use -V to print version information (same in tcpdump/ngrep (part of -h in tcpdump))
# can use -S to display port numbers instead of services
# can use -s to capture, maximum, <X> bytes instead of 200 by default (same in tcpdump)
# can use -h to display help menu (same in tcpdump/ngrep)
# can use -R to invert -g's regexp to print anything that doesn't match it (same in ngrep (-v in ngrep))
# can use -q to go into quick/quiet mode to display less protocol information (same in tcpdump)
# N/A - can use -p to not go into promiscuous mode, although the interface may already be in it (same in tcpdump)
# can use -m to extract IPs with a different method, default method may extract incorrect/invalid IPs
# can use -t to not print a timestamp on each line
# can use -v to show an IP packet's time to live and type of service information
# can use -F to read <file> and use it as the input for the filter expression in -E
# can use -tt to print an unformatted timestamp on each line
# can use -Z to list all services you are able to sniff for passwords
# can use -W to sniff passwords from <services>
# can use -M to flood the local network with random MAC addresses just like macof (from dsniff and stand-alone program)
# can use -Y to use <port> as the source port for -M (from macof)
# can use -y to use <host> as the source host for -M (from macof)
# can use -D to use <port> as the destination port for -M (from macof)
# can use -d to use <host> as the destination host for -M (from macof)
# can use -Q to use <address> to set the destination MAC address (from macof)
# can use -R to random the destination MAC address (from macof)
# can use -O to use match all data that doesn't match the regular expression used with -g 
# can use -U to output all requested URLs sniffed from HTTP traffic (dsniff's urlsnarf)
# can use -b to output all requested URLs sniffed from HTTP traffic and also have you browser connect to the same pages (dsniff's webspy/urlsnarf)
# can use -B to do -b for only the pages that <hostname> is browsing (dsniff's webspy/urlsnarf)
#
# tested on (using Net::RawIP-0.9 and libpcap-0.4):
#	BSD:
#		FreeBSD 3.1-RELEASE, 3.4-(RELEASE|STABLE), 4.0-(RELEASE|STABLE), 4.1-(RC|RELEASE|STABLE)
#		OpenBSD ?
#	Linux:
#		Slackware 7.0, 2.2.17
#		Red Hat 5.2, 2.0.36
#		Mandrake 2.2.15-4mdksmp
#

BEGIN {
 my $filesep = '/';
 my $basedir = '.';
 my $libsdir = 'lib';
 my $fulpath = $basedir . $filesep . $libsdir;
# my $fulpath = '/usr/local/pdump/lib';
 opendir(DIR, $libsdir) or die "Unable to open $libsdir: $!\n";
 while ($file = readdir DIR) {
  next unless $file =~ /\.pl$/;
  require $fulpath . $filesep . $file;
 }
 closedir DIR;
}

###################################################################################
### Don't change anything below (unless you know what you're doing, of course)! ###
###################################################################################

use Socket;
use URI::Escape;
use Sys::Hostname;
use Term::ANSIColor;
use POSIX qw(strftime);
use Net::RawIP qw(:pcap);
&exits;
&ansi;
$SIG{'INT'} = \&die;
$tout = 10;
$dev = Net::RawIP::lookupdev($tout);
$snaplen = 200;
$xprc = " ";
$version = "0.777b3";
&get_args;
$| = 1;
$ip = ${ifaddrlist()}{$dev};
$top = 0;
if ($ntshst) {
# ($haddr) = (gethostbyname($ntshst))[4];
# $raddr = join(".", unpack("C4", $haddr));
 $raddr = &ip2dot($ntshst);
}
if ($ansi) {
 print STDERR colored("(", 'blue');
 print STDERR colored("pdump.pl", 'bold');
 print STDERR colored(")", 'blue');
 print " ";
 print STDERR colored($version, 'underline');
 print STDERR colored(":", 'green');
 print " ";
 print STDERR colored("by", 'white');
 print " ";
 print STDERR colored("CommPort5", 'bold green');
 print STDERR colored("(", 'bold blue');
 print STDERR colored("\@", 'bold red');
 print STDERR colored("LucidX.com", 'bold green');
 print STDERR colored(")", 'bold blue');
 print "\n";
 print STDERR colored("(", 'blue');
 print STDERR colored($0, 'underline');
 print STDERR colored(")", 'blue');
 print STDERR colored(":", 'green');
 print " ";
 print STDERR colored("listening", 'white');
 print " ";
 print colored("on", 'white');
 print " ";
 print STDERR colored($dev, 'green');
 print " ";
 print STDERR colored("::", 'bold');
 print " ";
 print STDERR colored($ip, 'green');
 print " ";
 print STDERR colored("[", 'bold red');
 print STDERR colored($host, 'bold cyan');
 print STDERR colored("]", 'bold red');
 print "\n";
 if ($ngrp and !$ngrq) {
  print colored("match", 'bold green');
  print colored(":", 'bold');
  print " ";
  print colored($ngrr, 'underline');
  print "\n";
 }
}
else {
 print STDERR "(pdump.pl) $version: by CommPort5(\@LucidX.com)\n";
 print STDERR "($0): listening on $dev :: $ip [$host]\n";
 if ($ngrp and !$ngrq) {
  print "match: $ngrr\n";
 }
}
if ($macof) {
 &macof;
}
else {
 if ($expr) {
  $packet_all  = new Net::RawIP;
  $filt_all    = $xprc;
  if ($ntsnf) {
   if ($lcls) {
    $filt_all  = "tcp and dst port 80 or dst port 8080 or dst port 3128";
   }
   else {
    $filt_all  = "tcp and dst port 80 or dst port 8080 or dst port 3128 and not host $ip";
   }
  }
  if ($snff) {
   $filt_all   = " ";
  }
  if ($nopr) {
   $pcap_all   = $packet_all->pcapinit($dev, $filt_all, $snaplen, 60, 0);
  }
  else {
   $pcap_all   = $packet_all->pcapinit($dev, $filt_all, $snaplen, 60);
  }
  $offset_all  = linkoffset($pcap_all);
  if ($wrt) {
   $awr        = dump_open($pcap_all, $write);
  }
 }
 else {
  $packet_udp  = new Net::RawIP({udp=>{}});
  $packet_tcp  = new Net::RawIP({tcp=>{}});
  $packet_icmp = new Net::RawIP({icmp=>{}});
  $filt_udp    = "ip proto \\udp";
  $filt_tcp    = "ip proto \\tcp";
  $filt_icmp   = "ip proto \\icmp";
  if ($nopr) {
   $pcap_tcp   = $packet_tcp->pcapinit($dev, $filt_tcp, $snaplen, 60, 0);
   $pcap_udp   = $packet_udp->pcapinit($dev, $filt_udp, $snaplen, 60, 0);
   $pcap_icmp  = $packet_icmp->pcapinit($dev, $filt_icmp, $snaplen, 60, 0);
  }
  else {
   $pcap_tcp   = $packet_tcp->pcapinit($dev, $filt_tcp, $snaplen, 60);
   $pcap_udp   = $packet_udp->pcapinit($dev, $filt_udp, $snaplen, 60);
   $pcap_icmp  = $packet_icmp->pcapinit($dev, $filt_icmp, $snaplen, 60);
  }
  $offset_tcp   = linkoffset($pcap_tcp);
  $offset_udp   = linkoffset($pcap_udp);
  $offset_icmp  = linkoffset($pcap_icmp);
  if ($wrt) {
   $twr         = dump_open($pcap_tcp, $write);
   $uwr         = dump_open($pcap_udp, $write);
   $iwr         = dump_open($pcap_icmp, $write);
  }
 }
}
unless ($macof) {
 if ($expr) {
  if ($wrt) {
   if ($ntsnf) {
    loop $pcap_all, -1, \&check_web, \$awr;
   }
   elsif ($snff) {
    @pws = split(/,\s*/, $snft);
    loop $pcap_all, -1, \&pwsniff, \$awr;
   }
   else {
    loop $pcap_all, -1, \&check_all, \$awr;
   }
  }
  else {
   if ($ntsnf) {
    loop $pcap_all, -1, \&check_web, \@packet_all;
   }
   elsif ($snff) {
    @pws = split(/,\s*/, $snft);
    loop $pcap_all, -1, \&pwsniff, \@packet_all;
   }
   else {
    loop $pcap_all, -1, \&check_all, \@packet_all;
   }
  }
 }
 else {
  if ($wrt) {
   if ($tf = fork) {
    loop $pcap_tcp, -1, \&check_tcp, \$twr;
   }
   if ($uf = fork) {
    loop $pcap_udp, -1, \&check_udp, \$uwr;
   }
   if ($if = fork) {
    loop $pcap_icmp, -1, \&check_icmp, \$iwr;
   }
  }
  else {
   if ($tf = fork) {
    loop $pcap_tcp, -1, \&check_tcp, \@packet_tcp;
   }
   if ($uf = fork) {
    loop $pcap_udp, -1, \&check_udp, \@packet_udp;
   }
   if ($if = fork) {
    loop $pcap_icmp, -1, \&check_icmp, \@packet_icmp;
   }
  }
 }
}


syntax highlighted by Code2HTML, v. 0.8.8b