satanklawz has asked for the wisdom of the Perl Monks concerning the following question:

Hello all, I'm setting up a Kismet IDS, and am currently just playing around with the whole thing. I've got a drone on one machine sending the data to a server which kicks out raw data to /tmp/kismet_dump. My end goal is to have a script that takes in the event logs of kismet live, and dump them into a MySQL table. I've googled around on how to conduct this with Snort, and I've gotten snort to read in the packet captures, but it ignores events like someone starting NetStumbler (which kismet is picking up). The question is that I am getting data kicked out like this:
¥¥¥¥¥¥¥¥DEME2cBNV Rÿÿÿÿÿÿ &ûo6]/Úo6]/ ÿ ¥¥¥¥¥¥¥¥DEME2cBqY Rÿÿÿÿÿÿ &ûo6]B Úo6]B ¥¥¥¥¥¥¥¥DEME2cBS_ Rÿÿÿÿÿÿ &û #A0Úªª #A Qÿ VT102¥¥¥¥¥¥¥¥DEME2cBb Rÿÿÿÿÿÿ &ûo6]9@Úo6]9 ÿ ¥¥¥¥¥¥¥¥DEME2cBRf Rÿÿÿÿÿÿ &ûo5:ëPÚo5:ë # VT102VT102VT102VT102¥¥¥¥¥¥¥¥DEME2cB_j Rÿÿÿÿÿÿ &ûo59`Úo59 ÿ ¥¥¥¥¥¥¥¥DEME2cBÙm Rÿÿÿÿÿÿ &û #5pÚªª #5 %ÿ
From the following simple file open
#!/usr/bin/perl -w use strict; open(KISMET,"/tmp/kismet_dump") or die "$!"; while (<KISMET>) { print $_; }
Thanks all! BTW- when watching this stream, I do see SSID's of neighboring networks popping up.

Replies are listed 'Best First'.
Re: Kismet Drone
by bart (Canon) on Apr 18, 2005 at 03:49 UTC
    Your first task will be to figure out the file format this dump is taking. It looks like complete jibberish to me. A quick Google search didn't reveal much to me, except that its dump format is related to that of other products, such as Etherreal; but that's still not much to go on.

    When you know more, and you still want to tackle this yourself in Perl, first thing to do is enable binmode on your file handle (on Unix-alikes, it won't appear to do much).

    Next step is probably to read fixed length chunks (just a guess), for which you can either use read/sysread (which are identical on the outside, but differently implemented on the inside, so I'm not sure which one will work best), or pseudo-line-like with the syntax you used, but with $/ set to a reference to an integer holding the byte count, or a scalar holding the byte count.

    And third step will likely be to turn the binary chunk into Perl data, for which you can use unpack with a format string matching the structure of your records. The module Data::FixedFormat may be helpful in that task, unpacking the data into a hash.

    Currently this is the program structure I envision:

    open(KISMET,"/tmp/kismet_dump") or die "$!"; binmode KISMET; $/ = \64; # example: IF the record length is 64 bytes while (<KISMET>) { my @raw = unpack $packformat, $_; ... }

    If the Kismet dump data format doesn't use fixed length records, but instead uses a delimiter, you can set $/ to it as a string — default is newline.

    You have a long journey ahead of you. I hope this at least starts you off in the right direction.

Re: Kismet Drone
by satanklawz (Beadle) on Apr 18, 2005 at 02:49 UTC
    After researching this more, and never having worked with binary files, I'm about to get edumacated about perl and binary files. Help would still be appreciated, but I think I'm on the right path now.
      I hate to keep posting to my own origional post, but it'll help other people who are interested in perl and Kismet. Turns out there's a module, called Net::Kismet. After looking at the documentation, and seeing other demo code, I still want to parse the binary data; hehe.
Re: Kismet Drone
by cazz (Pilgrim) on Apr 18, 2005 at 12:07 UTC
    kismet is logging to pcap format. Snort's wireless support is lacking currently. Frames snort doesn't know how to decode get marked as such and don't get logged to the database. The structures being logged are not too painful, and there are plenty of perl modules to start from to get an idea as to how to decode packets in perl.

    Check out Net::Pcap and NetPacket to get started.

    Brian (bmc@snort.org)

      Here it is; sloppy but works great! It's written so that perl beginners can understand it.
      #!/usr/bin/perl -w use Net::Pcap; my $err; my $dev = $ARGV[0]; my $object; $object = Net::Pcap::open_offline($dev, \$err); unless (defined $object) { die 'Unable to create packet capture on device ', $dev, ' - ', $er +r; } Net::Pcap::loop($object, -1, \&callback_function, ''); Net::Pcap::close($object); sub callback_function { my ($user_data,$header,$packet) =@_; if (length($packet)>36) { 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 packet +s 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 basestati +on mac $ssid=unpack ('A*',substr($packet,38,$len)); #get the ssid if ($len==0) { #if the ssid isnt broadcasted $ssid=">no ssid<"; } 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 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"; } } }
      Thanks Brian, Excellent suggestion! This is where I am so far:
      #!/usr/bin/perl -w use strict; use Net::Pcap; use NetPacket::Ethernet; use NetPacket::IP; use NetPacket::TCP; my $err; my $dev = $ARGV[0]; my $object; $object = Net::Pcap::open_offline($dev, \$err); unless (defined $object) { die 'Unable to create packet capture on device ', $dev, ' - ', $er +r; } Net::Pcap::loop($object, -1, \&callback_function, ''); Net::Pcap::close($object); sub callback_function { my ($user_data,$header,$packet) =@_; my $ether_data = NetPacket::Ethernet::strip($packet); my $ip = NetPacket::IP->decode($ether_data); my $tcp = NetPacket::TCP->decode($ip->{'data'}); print $ip->{'src_ip'}, ":", $tcp->{'src_port'}, " -> ", $ip->{'dest_ip'}, ":", $tcp->{'dest_port'}, "\n"; }
      With errors as
      Use of uninitialized value in unpack at /usr/lib/perl5/site_perl/5.8.0 +/NetPacket/TCP.pm line 138. 57.24.4.3:260 -> 0.0.100.0:33412 178.163.14.0:29300 -> 0.0.100.0:29295 3.0.0.0:0 -> 8.0.69.0:16401 252.87.141.0:4356 -> 0.0.100.0:12 Use of uninitialized value in unpack at /usr/lib/perl5/site_perl/5.8.0 +/NetPacket/TCP.pm line 138. 157.24.4.3:260 -> 0.0.100.0:33412 253.87.141.0:4356 -> 0.0.100.0:12 Use of uninitialized value in unpack at /usr/lib/perl5/site_perl/5.8.0 +/NetPacket/TCP.pm line 138. 159.24.4.3:260 -> 0.0.100.0:33412 239.36.90.0:0 -> 0.0.100.0:5 240.36.90.0:0 -> 0.0.100.0:5 3.37.90.0:0 -> 0.0.100.0:5 5.37.90.0:0 -> 0.0.100.0:5 3.0.0.0:1 -> 8.6.0.1:2560
      I bet all I need to do now is either find or write an appropriate NetPacket module. Almost there!
      Just to keep everyone up to date, and so that I have a backup of this; here's some sloppy code.
      #!/usr/bin/perl -w use Net::Pcap; my $err; my $dev = $ARGV[0]; my $object; $object = Net::Pcap::open_offline($dev, \$err); unless (defined $object) { die 'Unable to create packet capture on device ', $dev, ' - ', $er +r; } 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 $sourcemac = unpack ('H12',substr($packet,10,6)); my $bs = unpack ('H12',substr($packet,16,6)); my $o = unpack ('H2*',substr($packet,0,1)); my $len = sprintf("%x",unpack ('H1',substr($packet,38,1))); my $ssid=0; if ($o eq "80") { $ssid=unpack ('A*',substr($packet,38,$len)); if ($ssid eq " ") { #doesnt work yet $ssid=">no ssid<"; } print "Beacon Frame: source mac:",$sourcemac," basestation id: $ +bs other: ",$o," ssid: $ssid len: $len\n"; } } }