#!/usr/bin/perl -w

#ids.pl <pcap source>
#Where pcap source is any libpcap source file or socket.
#Copyright 2005 Russell Handorf, ClosedNetworks, Inc.
#This script is for educational purposes only. I am not
#responsible for any damage this script might cause.

use Net::Pcap;
use DBI;

my $err;
my $dev = $ARGV[0];
my $object;
my $dbh = DBI->connect('DBI:mysql:wifiabuse', 'root', '');

if (!$dev) {
  print "useage ids.pl <pcap source>\n";
  print "ids.pl written by Russell Handorf\n";
  print "rhandorf\@closednetworks.com for questions.\n";
  exit(0);
}

$object = Net::Pcap::open_offline($dev, \$err);
unless (defined $object) {
    die 'Unable to create packet capture on device ', $dev, ' - ', $err;
}

Net::Pcap::loop($object, -1, \&callback_function, '');
Net::Pcap::close($object);

sub callback_function {
  my ($user_data,$header,$packet) =@_;
  #the beacons have to be atleast 37 bytes
  if (length($packet)>36) {
    my $query="NULL";
    my $time = time();
    my $o = unpack ('H2*',substr($packet,0,1)); #find out what kind of packet it is
    if ($o eq "80") { #if it is a broadcast
      my $sourcemac = unpack ('H12',substr($packet,10,6)); #the packets source mac address
      my $len = hex unpack ('H2',substr($packet,37)); #get the size of the ssid
      my $bs = unpack ('H12',substr($packet,16,6)); #get the basestation mac
      my $ssid=unpack ('A*',substr($packet,38,$len)); #get the ssid
      if ($len==0) { #if the ssid isnt broadcasted
	$ssid=">no-ssid<";
      }
      my $tmplen=$len+38+1;
      my $rateslen=hex unpack ('H2',substr($packet,$tmplen));
      $tmplen=$tmplen+1;
      my $rates=unpack ('H*',substr($packet,$tmplen,$rateslen));
      $tmplen=$tmplen+$rateslen+2;
      my $channel=hex unpack ('H2',substr($packet,$tmplen));
      my $sth = $dbh->prepare("select id from detecteddevices where devbsmac='$bs' and devssid='$ssid'");
      $sth->execute();
      if ($sth->rows >1) {
        $query = "update detecteddevices set time='$time',channel='$channel',rates='$rates',devmac='$sourcemac' where devbsmac='$bs' and devssid='$ssid'";
      } else {
        $query = "insert into detecteddevices set time='$time',devbsmac='$bs',devssid='$ssid',channel='$channel',rates='$rates',devmac='$sourcemac'";
      }
      #print "Beacon Frame: source mac:",$sourcemac," basestation id: $bs other: ",$o," ssid: $ssid len: $len\n";
    }
    if ($o eq "40") { #if it's a probe for ssid's
      my $offmac=unpack ('H12',substr($packet,10,6)); #get the source mac
      $query = "insert into events set time='$time',offmac='$offmac',offtype='PROBE'";
      print "PROBE! source mac: $offmac\n";
    }
    #if ($o eq "50") { #if it's a probe response
    #  my $offmac=unpack ('H12',substr($packet,5,6));
    #  my $sourcemac = unpack ('H12',substr($packet,10,6));
    #  my $bs = unpack ('H12',substr($packet,16,6));
    #  my $len = hex unpack ('H2',substr($packet,37));
    #  my $ssid=unpack ('A*',substr($packet,38,$len));
    #  if ($len==0) {
    #    $ssid=">no ssid<";
    #  }
    #  #print "PROBE RESPONSES! source mac: $offmac $len $ssid\n";
    #}
    if ($query ne "NULL") {
      my $sth3 = $dbh->prepare($query);
      $sth3->execute() or die "Couldn't execute statement: " . $sth3->errstr;;
    }
  }
}

