Scruge wrote:Okay, here's my first trial balloon for KISMACK, KISmet Merge And Convert to Kml.
Due to an out of date installer I'll have to repost at a later time.
Sorry for the trouble.
Looking forward to test it out Scruge.
Are you checking for duplicate networks in the xml files, and are you updating or just overwriting data, if there are duplicate networks ?
As for merging the .gps files, no checking is necessary. I manually copy the first .gps file to a new file, edit it to remove the </gps-run> at the end, then run a cat/grep command to add the <gps-point> data to the new file :
I.E. three files to concatenate : Kismet-Feb-02-2006.1.gps, Kismet-Feb-03-2006.1.gps, Kismet-Feb-04-2006.1.gps
copy Kismet-Feb-02-2006.1.gps to new.gps, edit new.gps to remove the </gps-run> at the end, then execute
- Code: Select all
cat Kismet-Feb-03*.gps Kismet-Feb-04*.gps |grep gpspoint>>new.gps && echo "</gps-run>">>new.gps
Currently I'm using a revised version of revised original perl klc.pl script (search kismetwireless.net forums for it) for the .xml files. I made some bugfixes to it, as well as a couple of changes to the loop checking for duplicates, as it was quite slow.
Even with the changes to the loop it is still quite slow, taking about 12 hours to merge two files with 1200+ and 800+ networks (about 25 % duplicates) on the wardriving laptop (a 850Mhz PIII), so if your application can do it faster, I'm definitely going to use your application.
A short pseudocode outline of how the revised klc.pl file works :
- Code: Select all
Read the first xml logfile]
For those who want to use the revised revised klc.pl file, untill Scruge gets his app out, I'm including it here.
Perl, Linux and libXML required. Might work on Windows also, if perl and libXML is available, but not tested.
[code]
#!/usr/bin/perl
# copyright 2005 tud.thaunderdog
# minor bugfix and speedup attempt by Dutch 2006
use XML::LibXML;
unless ( @ARGV > 2 ) {
print "Usage: $0 <input-1st> <input-Nth> <output>\n";
exit;
}
$start_time = localtime(time);
$out_file_name = pop @ARGV;
@log_files = @ARGV;
$net_num = 0;
$firstlog = 0;
foreach $this_log (@log_files) {
$firstlog++;
print "KLV: Reading Logfile $this_log....\n";
$doc = XML::LibXML::Document->new();
$root = $doc->createElement('html');
$doc->setDocumentElement($root);
$body = $doc->createElement('body');
$root->appendChild($body);
if (!$xml_body) {
open(LOG_FILE,"<$this_log");
@log_file = <LOG_FILE>;
close(LOG_FILE);
foreach $line (@log_file) {
if ($line=~/<?xml/) { $xml_head .= $line; }
elsif ($line=~/<!DOCTYPE/) {$xml_head .= $line; }
elsif ($line=~/<detection-run/) { $xml_head .= $line; }
elsif ($line=~/<\/detection-run/) { $xml_foot .= $line; }
}
open(OUT_FILE,">$out_file_name");
print OUT_FILE ("$xml_head");
print OUT_FILE ("$xml_foot");
close(OUT_FILE);
$xml_body = 1;
}
$parser = XML::LibXML->new();
$parser->expand_entities(0);
$tree = $parser->parse_file($this_log);
$root = $tree->getDocumentElement;
@networks = $root->getElementsByTagName('wireless-network');
foreach $this_network (@networks) {
$net_bssid = $this_network->getElementsByTagName('BSSID')->[0]->getFirstChild->getData;
$out_parser = XML::LibXML->new();
$out_parser->expand_entities(0);
$out_tree = $out_parser->parse_file($out_file_name);
$out_root = $out_tree->getDocumentElement;
if ( $temp = $out_root->getElementsByTagName('wireless-network') ) { @out_networks = $out_root->getElementsByTagName('wireless-network'); }
$unique = 1;
if ("$firstlog" > "1") {
if (@out_networks) {
foreach $this_out_network (@out_networks) {
$out_net_bssid = $this_out_network->getElementsByTagName('BSSID')->[0]->getFirstChild->getData;
if ( "$net_bssid" eq "$out_net_bssid" ) {
undef $unique;
$out_net = $this_out_network;
last;
}
} # end foreach $this_out_network
} # end if there are networks in out file
}
if ($unique) {
print "KLV: Merging $net_bssid - $net_num - $firstlog\n";
## Is this faster?...
#$net_num = 0;
#foreach $this_out_network (@out_networks) {
#
# $this_network_xml = $this_out_network->toString;
# if ( $this_network_xml =~ /<wireless-network number="\d+"/ ) {
# $net_num++;
# $this_network_xml=~ s/<wireless-network number="\d+"/<wireless-network number="$net_num"/;
# } else {
# $networks .= "\n$this_network_xml";
# }
#}
#$this_network_xml = $this_network->toString;
#$networks .= "\n$this_network_xml";
#
## ...Or is this?
$net_num++;
$this_network_xml = $this_network->toString;
$this_network_xml=~ s/<wireless-network number="\d+"/ <wireless-network number="$net_num"/;
$networks .= "\n$this_network_xml";
} else {
print "KLV: Merging $net_bssid - Updated\n";
undef $networks;
undef $gps;
$net_packets_LLC = $this_network->getElementsByTagName('LLC')->[0]->getFirstChild->getData;
$out_net_packets_LLC = $out_net->getElementsByTagName('LLC')->[0]->getFirstChild->getData;
$net_packets_LLC += $out_net_packets_LLC;
$net_packets_data = $this_network->getElementsByTagName('data')->[0]->getFirstChild->getData;
$out_net_packets_data = $out_net->getElementsByTagName('data')->[0]->getFirstChild->getData;
$net_packets_data += $out_net_packets_data;
$net_packets_crypt = $this_network->getElementsByTagName('crypt')->[0]->getFirstChild->getData;
$out_net_packets_crypt = $out_net->getElementsByTagName('crypt')->[0]->getFirstChild->getData;
$net_packets_crypt += $out_net_packets_crypt;
$net_packets_weak = $this_network->getElementsByTagName('weak')->[0]->getFirstChild->getData;
$out_net_packets_weak = $out_net->getElementsByTagName('weak')->[0]->getFirstChild->getData;
$net_packets_weak += $out_net_packets_weak;
$net_packets_dupeiv = $this_network->getElementsByTagName('dupeiv')->[0]->getFirstChild->getData;
$out_net_packets_dupeiv = $out_net->getElementsByTagName('dupeiv')->[0]->getFirstChild->getData;
$net_packets_dupeiv += $out_net_packets_dupeiv;
$net_packets_total = $this_network->getElementsByTagName('total')->[0]->getFirstChild->getData;
$out_net_packets_total = $out_net->getElementsByTagName('total')->[0]->getFirstChild->getData;
$net_packets_total += $out_net_packets_total;
$net_packets_datasize = $this_network->getElementsByTagName('datasize')->[0]->getFirstChild->getData;
$out_net_packets_datasize = $out_net->getElementsByTagName('datasize')->[0]->getFirstChild->getData;
$net_packets_datasize += $out_net_packets_datasize;
if ( ( $temp = $this_network->getElementsByTagName('min-lat')->[0] ) && ( $temp = $out_net->getElementsByTagName('min-lat')->[0] ) ) {
$gps = 1;
$net_gps_min_lat = $this_network->getElementsByTagName('min-lat')->[0]->getFirstChild->getData;
$out_net_gps_min_lat = $out_net->getElementsByTagName('min-lat')->[0]->getFirstChild->getData;
if ( $net_gps_min_lat > $out_net_gps_min_lat ) { $net_gps_min_lat = $out_net_gps_min_lat; }
$net_gps_min_lon = $this_network->getElementsByTagName('min-lon')->[0]->getFirstChild->getData;
$out_net_gps_min_lon = $out_net->getElementsByTagName('min-lon')->[0]->getFirstChild->getData;
if ( $net_gps_min_lon > $out_net_gps_min_lon ) { $net_gps_min_lon = $out_net_gps_min_lon; }
$net_gps_min_alt = $this_network->getElementsByTagName('min-alt')->[0]->getFirstChild->getData;
$out_net_gps_min_alt = $out_net->getElementsByTagName('min-alt')->[0]->getFirstChild->getData;
if ( $net_gps_min_alt > $out_net_gps_min_alt ) { $net_gps_min_alt = $out_net_gps_min_alt; }
$net_gps_min_spd = $this_network->getElementsByTagName('min-spd')->[0]->getFirstChild->getData;
$out_net_gps_min_spd = $out_net->getElementsByTagName('min-spd')->[0]->getFirstChild->getData;
if ( $net_gps_min_spd > $out_net_gps_min_spd ) { $net_gps_min_spd = $out_net_gps_min_spd; }
$net_gps_max_lat = $this_network->getElementsByTagName('max-lat')->[0]->getFirstChild->getData;
$out_net_gps_max_lat = $out_net->getElementsByTagName('max-lat')->[0]->getFirstChild->getData;
if ( $net_gps_max_lat < $out_net_gps_max_lat ) { $net_gps_max_lat = $out_net_gps_max_lat; }
$net_gps_max_lon = $this_network->getElementsByTagName('max-lon')->[0]->getFirstChild->getData;
$out_net_gps_max_lon = $out_net->getElementsByTagName('max-lon')->[0]->getFirstChild->getData;
if ( $net_gps_max_lon < $out_net_gps_max_lon ) { $net_gps_max_lon = $out_net_gps_max_lon; }
$net_gps_max_alt = $this_network->getElementsByTagName('max-alt')->[0]->getFirstChild->getData;
$out_net_gps_max_alt = $out_net->getElementsByTagName('max-alt')->[0]->getFirstChild->getData;
if ( $net_gps_max_alt < $out_net_gps_max_alt ) { $net_gps_max_alt = $out_net_gps_max_alt; }
$net_gps_max_spd = $this_network->getElementsByTagName('max-spd')->[0]->getFirstChild->getData;
$out_net_gps_max_spd = $out_net->getElementsByTagName('max-spd')->[0]->getFirstChild->getData;
if ( $net_gps_max_spd < $out_net_gps_max_spd ) { $net_gps_max_spd = $out_net_gps_max_spd; }
}
foreach $this_out_network (@out_networks) {
$this_network_xml = $this_out_network->toString;
if ($this_out_network eq $out_net) {
$this_network_xml=~ s/<LLC>\d*<\/LLC>/<LLC>$net_packets_LLC<\/LLC>/;
$this_network_xml=~ s/<data>\d*<\/data>/<data>$net_packets_data<\/data>/;
$this_network_xml=~ s/<crypt>\d*<\/crypt>/<crypt>$net_packets_crypt<\/crypt>/;
$this_network_xml=~ s/<weak>\d*<\/weak>/<weak>$net_packets_weak<\/weak>/;
$this_network_xml=~ s/<dupeiv>\d*<\/dupeiv>/<dupeiv>$net_packets_dupeiv<\/dupeiv>/;
$this_network_xml=~ s/<total>\d*<\/total>/<total>$net_packets_total<\/total>/;
$this_network_xml=~ s/<datasize>\d*<\/datasize>/<datasize>$net_packets_datasize<\/datasize>/;
if ($gps) {
$this_network_xml=~ s/<min-lat>\d*\.\d*<\/min-lat>/<min-lat>$net_gps_min_lat<\/min-lat>/;
$this_network_xml=~ s/<min-lon>\d*\.\d*<\/min-lon>/<min-lon>$net_gps_min_lon<\/min-lon>/;
$this_network_xml=~ s/<min-alt>\d*\.\d*<\/min-alt>/<min-alt>$net_gps_min_alt<\/min-alt>/;
$this_network_xml=~ s/<min-spd>\d*\.\d*<\/min-spd>/<min-spd>$net_gps_min_spd<\/min-spd>/;
$this_network_xml=~ s/<max-lat>\d*\.\d*<\/max-lat>/<max-lat>$net_gps_max_lat<\/max-lat>/;
$this_network_xml=~ s/<max-lon>\d*\.\d*<\/max-lon>/<max-lon>$net_gps_max_lon<\/max-lon>/;
$this_network_xml=~ s/<max-alt>\d*\.\d*<\/max-alt>/<max-alt>$net_gps_max_alt<\/max-alt>/;
$this_network_xml=~ s/<max-spd>\d*\.\d*<\/max-spd>/<max-spd>$net_gps_max_spd<\/max-spd>/;
}
$client_num = @net_clients = $this_network->getElementsByTagName('wireless-client');
undef $client_num;
if (@net_clients) {
while ($this_network_xml=~ /.*client.*\n/) { $this_network_xml=~ s/.*client.*\n//; }
$this_network_xml=~ s/.*<\/wireless-network>.*//;
foreach $this_client (@net_clients) {
$unique = 1;
$client_mac = $this_client->getElementsByTagName('client-mac')->[0]->getFirstChild->getData;
$out_net_clients_total = @out_net_clients = $out_net->getElementsByTagName('wireless-client');
foreach $out_this_client (@out_net_clients) {
$out_client_mac = $out_this_client->getElementsByTagName('client-mac')->[0]->getFirstChild->getData;
if ( "$client_mac" eq "$out_client_mac" ) {
undef $unique;
$out_client = $this_out_client;
last;
}
}
if ($unique) {
print " Client $client_mac\n";
$this_client_xml = $this_client->toString;
$client_num++;
$this_client_xml=~ s/<wireless-client number="\d+"/<wireless-client number="$client_num"/;
} else {
print " Client $client_mac - Updated\n";
undef $gps;
$client_packets_data = $this_client->getElementsByTagName('client-data')->[0]->getFirstChild->getData;
$out_net_packets_data = $out_net->getElementsByTagName('client-data')->[0]->getFirstChild->getData;
$client_packets_data += $out_net_packets_data;
$client_packets_crypt = $this_client->getElementsByTagName('client-crypt')->[0]->getFirstChild->getData;
$out_net_packets_crypt = $out_net->getElementsByTagName('client-crypt')->[0]->getFirstChild->getData;
$client_packets_crypt += $out_net_packets_crypt;
$client_packets_weak = $this_client->getElementsByTagName('client-weak')->[0]->getFirstChild->getData;
$out_net_packets_weak = $out_net->getElementsByTagName('client-weak')->[0]->getFirstChild->getData;
$client_packets_weak += $out_net_packets_weak;
$client_packets_datasize = $this_client->getElementsByTagName('client-datasize')->[0]->getFirstChild->getData;
$out_client_packets_datasize = $out_net->getElementsByTagName('client-datasize')->[0]->getFirstChild->getData;
$client_packets_datasize += $out_cliet_packets_datasize;
if ( ( $temp = $this_client->getElementsByTagName('client-min-lat')->[0] ) && ( $temp = $out_net->getElementsByTagName('client-min-lat')->[0] ) ) {
$gps = 1;
$client_gps_min_lat = $this_client->getElementsByTagName('client-min-lat')->[0]->getFirstChild->getData;
$out_net_gps_min_lat = $out_net->getElementsByTagName('client-min-lat')->[0]->getFirstChild->getData;
if ( $client_gps_min_lat > $out_net_gps_min_lat ) { $client_gps_min_lat = $out_net_gps_min_lat; }
$client_gps_min_lon = $this_client->getElementsByTagName('client-min-lon')->[0]->getFirstChild->getData;
$out_net_gps_min_lon = $out_net->getElementsByTagName('client-min-lon')->[0]->getFirstChild->getData;
if ( $client_gps_min_lon > $out_net_gps_min_lon ) { $client_gps_min_lon = $out_net_gps_min_lon; }
$client_gps_min_alt = $this_client->getElementsByTagName('client-min-alt')->[0]->getFirstChild->getData;
$out_net_gps_min_alt = $out_net->getElementsByTagName('client-min-alt')->[0]->getFirstChild->getData;
if ( $client_gps_min_alt > $out_net_gps_min_alt ) { $client_gps_min_alt = $out_net_gps_min_alt; }
$client_gps_min_spd = $this_client->getElementsByTagName('client-min-spd')->[0]->getFirstChild->getData;
$out_net_gps_min_spd = $out_net->getElementsByTagName('client-min-spd')->[0]->getFirstChild->getData;
if ( $client_gps_min_spd > $out_net_gps_min_spd ) { $client_gps_min_spd = $out_net_gps_min_spd; }
$client_gps_max_lat = $this_client->getElementsByTagName('client-max-lat')->[0]->getFirstChild->getData;
$out_net_gps_max_lat = $out_net->getElementsByTagName('client-max-lat')->[0]->getFirstChild->getData;
if ( $client_gps_max_lat < $out_net_gps_max_lat ) { $client_gps_max_lat = $out_net_gps_max_lat; }
$client_gps_max_lon = $this_client->getElementsByTagName('client-max-lon')->[0]->getFirstChild->getData;
$out_net_gps_max_lon = $out_net->getElementsByTagName('client-max-lon')->[0]->getFirstChild->getData;
if ( $client_gps_max_lon < $out_net_gps_max_lon ) { $client_gps_max_lon = $out_net_gps_max_lon; }
$client_gps_max_alt = $this_client->getElementsByTagName('client-max-alt')->[0]->getFirstChild->getData;
$out_net_gps_max_alt = $out_net->getElementsByTagName('client-max-alt')->[0]->getFirstChild->getData;
if ( $client_gps_max_alt < $out_net_gps_max_alt ) { $client_gps_max_alt = $out_net_gps_max_alt; }
$client_gps_max_spd = $this_client->getElementsByTagName('client-max-spd')->[0]->getFirstChild->getData;
$out_net_gps_max_spd = $out_net->getElementsByTagName('client-max-spd')->[0]->getFirstChild->getData;
if ( $client_gps_max_spd < $out_net_gps_max_spd ) { $client_gps_max_spd = $out_net_gps_max_spd; }
} # enf client if gps
$this_client_xml = $this_client->toString;
$this_client_xml=~ s/<client-data>\d*<\/client-data>/<client-data>$client_packets_data<\/client-data>/;
$this_client_xml=~ s/<client-crypt>\d*<\/client-crypt>/<client-crypt>$client_packets_crypt<\/client-crypt>/;
$this_client_xml=~ s/<client-weak>\d*<\/client-weak>/<client-weak>$client_packets_weak<\/client-weak>/;
$this_client_xml=~ s/<client-datasize>\d*<\/client-datasize>/<client-datasize>$client_packets_datasize<\/client-datasize>/;
if ($gps) {
$this_client_xml=~ s/<client-min-lat>\d*\.\d*<\/client-min-lat>/<client-min-lat>$client_gps_min_lat<\/client-min-lat>/;
$this_client_xml=~ s/<client-min-lon>\d*\.\d*<\/client-min-lon>/<client-min-lon>$client_gps_min_lon<\/client-min-lon>/;
$this_client_xml=~ s/<client-min-alt>\d*\.\d*<\/client-min-alt>/<client-min-alt>$client_gps_min_alt<\/client-min-alt>/;
$this_client_xml=~ s/<client-min-spd>\d*\.\d*<\/client-min-spd>/<client-min-spd>$client_gps_min_spd<\/client-min-spd>/;
$this_client_xml=~ s/<client-max-lat>\d*\.\d*<\/client-max-lat>/<client-max-lat>$client_gps_max_lat<\/client-max-lat>/;
$this_client_xml=~ s/<client-max-lon>\d*\.\d*<\/client-max-lon>/<client-max-lon>$client_gps_max_lon<\/client-max-lon>/;
$this_client_xml=~ s/<client-max-alt>\d*\.\d*<\/client-max-alt>/<client-max-alt>$client_gps_max_alt<\/client-max-alt>/;
$this_client_xml=~ s/<client-max-spd>\d*\.\d*<\/client-max-spd>/<client-max-spd>$client_gps_max_spd<\/client-max-spd>/;
} # end gps
$client_num++;
$this_client_xml=~ s/<wireless-client number="\d+"/<wireless-client number="$client_num"/;
} # end if client unique
$this_network_xml .= "$this_client_xml\n";
} # end foreach client this net
$this_network_xml.= "</wireless-network>\n";
} # end if net has clients
$networks .= "\n$this_network_xml";
} else {
$networks .= "\n$this_network_xml";
} # end if found unique net
} # end foreach out network
} # end if net unique
open(OUT_FILE,">$out_file_name");
print OUT_FILE ("$xml_head");
print OUT_FILE ("$networks\n");
print OUT_FILE ("$xml_foot\n");
close(OUT_FILE);
} # end foreach $this_network
} # end foreach $this_log
$end_time = localtime(time);
print "KLV: Combined Logs to $out_file_name\n";
print "KLV: Operation Started: $start_time\n";
print "KLV: Operation Ended: $end_time\n";
print "KLV: Done\n";
# EOF
[/code]
To produce a KML or KMZ file from kismet xml and gps files, there are several solutions available. I'm using another self revised version of the php based converter made by P. Niquille, and posted on [url]www.niquille.com[/url].
I like this one because you can use it to visualize the coverage by any specific detected network, based on the data from the .gps file. I changed the visualization list to show the ESSID just like the AP list, iso BSSID, making it easier to select the AP to visualize, as well as some minor bugfixes.
Works under both windows and Linux. Requires PHP5 installed.
[code]
<?php
/*
Kismet to kml (Google Earth) log file converter alias "Kismet Earth"
Released by Philippe Niquille, philippe at niquille dot com, www.niquille.com
******************************
* version 0.1 beta3 - 28.9.2005
******************************
features
--------
parses Kismet log files (.xml and .gps) to generate a google earth kml file
- draws WarDrive Path as tesselated line
- adds discovered access points to specific location on the map, parses meta information (mac, channel, packets, clients, etc.)
- draws 3D polygons instead of simple AP images. The shape should represent the signal area as far as every corner has been
captured correctly. The height depends on the channel. The color is yellow (open), green (closed) or blue when open and cloaked.
- parses ap_manuf and client_manuf for vendor information
- saves .kml as .kmz (zipped) upon request
requirements
------------
PHP5 because of simple_xml, file_get_content functions
usage
-----
Use it as command line script as followed:
/usr/bin/php -f parse.php <Kismet-Sep-16-2005-5> <kmz>
The first argument is the kismet log file name without extension. The second one is optional.
changelog
---------
v0.1 beta3-ds - Small bugfixes and changed the Visualized list to show ESSID iso BSSID making it easier to select both
the AP icon and the corresponding visualized polygon.
v0.1 beta3 - added pack as kmz functionality (zip compression)
v0.1 beta2 - replaced real slow for loop with foreach and gps coordinates index array, huge speed boost
- added vendor information parser, added to description
- tweaked description section
v0.1 beta1 - initial release
todo/wishlist
-------------
- parse default password list
- give the WarSession a name
- merge multiple log files
- get better icons
- better polygons... (interpolation?)
- do dynamic (network connection) stuff
*/
/*******************
* set vars
********************/
$ap_manuf_file = "ap_manuf";
$client_manuf_file = "client_manuf";
//$argv[1] = "Kismet-20041223-10"; //debug
//$argv[2] = "kmz";
/*******************
* execution time
********************/
$mtime = explode(" ",microtime());
$mtime = $mtime[1] + $mtime[0];
$starttime = $mtime;
/*******************
* open files
********************/
if(isset($argv[1]))//get filenames
{
$xml_file = $argv[1].'.xml';
$gps_file = $argv[1].'.gps';
}else
exit("No argument specified\n");
if(file_exists($xml_file) && file_exists($gps_file))
{
$xml = simplexml_load_file($xml_file); //load kismet log
$gps = simplexml_load_file($gps_file); //load corresponding detailed gps log
}else
exit("Files couldn't be opened: ".$xml_file.", ".$gps_file."\n");
if(file_exists($ap_manuf_file) && file_exists($client_manuf_file))
{
$ap_manuf = parse_vendor($ap_manuf_file); //load access point vendor data
$client_manuf = parse_vendor($client_manuf_file); //load client vendor data
}else
exit("Files couldn't be opened: ".$ap_manuf_file.", ".$client_manuf_file."\n");
$array = object2array($xml); //convert simplexml object to php array, easier to work on..
/*******************
* do meta stuff
********************/
$meta['session-duration'] = strtotime($xml['end-time'])-strtotime($xml['start-time']); //get duration (unix timestamp, in seconds)
$meta['session-duration'] = floor($meta['session-duration']/3600).' h, '.floor($meta['session-duration']/60).' min'; //format
$meta['net-count'] = count($array['wireless-network']);
$meta['parsed'] = $meta['net-count'];
/*******************
* parse .gps file and build gps coordinates index
********************/
foreach($gps->{'gps-point'} as $value)
{
$coordinates[(string) $value['bssid']][] = array((string) $value['lon'], (string) $value['lat']);
}
/*******************
* loop trough kismet wireless nets - types: infrastructure, probe
********************/
foreach($array['wireless-network'] as $key => $network)
{
if(
($network['gps-info']['min-lat'] == '90.000000' && $network['gps-info']['min-lon'] == '180.000000') //remove nets with no gps coordinates, no sense to display them on a map
|| $network['BSSID'] == '00:00:00:00:00:00'
|| $xml->{'wireless-network'}[$key]['type'] != 'infrastructure') //remove zero bssid nets, just junk
{
if($xml->{'wireless-network'}[$key]['type'] == 'probe') //count probes
$meta['probe-count']++;
$meta['net-count']--; //remove non infrastructure from total net count, exit foreach
continue;
}elseif(!isset($lookatnet)) //get the first usable net to set LookAt coordinates
$lookatnet = $key;
$kml .= "<Placemark>\n<name>";
$kml .= "<![CDATA[";
if(empty($network['SSID'])) $kml .= "no ssid";
else $kml .= $network['SSID'];
$kml .= "]]></name>\n";
/*******************
* build description html
********************/
$seenfor = strtotime($xml->{'wireless-network'}[$key]['last-time'])-strtotime($xml->{'wireless-network'}[$key]['first-time']);
$kml .= "\t<description><![CDATA[SSID :";
if(empty($network['SSID'])) $kml .= "no ssid";
else $kml .= $network['SSID']."
\n";
$kml .= "seen for ".floor($seenfor/60)." min (".floor($seenfor)." sec)
"; //get duration
$kml .= "first seen: ".$xml->{'wireless-network'}[$key]['first-time']."
last seen: ".$xml->{'wireless-network'}[$key]['last-time']."
<hr>\n";
$kml .= "BSSID: ".$network['BSSID']."
\nchannel: ".$network['channel']."
\n";
if($xml->{'wireless-network'}[$key]['wep'] == 'true') //net encrypton on?
{
if($network['encryption'] == 'WEP')
$kml .= "<font color=\"green\">encryption: WEP</font>";
elseif(is_array($network['encryption']))
{
$kml .= "<font color=\"green\">encryption: ";
foreach($network['encryption'] as $enc)
{
$kml .= $enc." ";
}
$kml .= "</font>";
}
}else
$kml .= "<font color=\"red\">no encryption</font>";
$kml .= "
\ncloaked: ".$xml->{'wireless-network'}['cloaked'];
$kml .= "
\nmax rate: ".$xml->{'wireless-network'}['maxrate'];
if(isset($network['ip-address']))
$kml .= "
IP range: ".$network['ip-address']['ip-range'];
/*******************
* get vendor info
********************/
if(get_manuf((string) $network['BSSID'],$ap_manuf) != false)
{
$manuf = get_manuf((string) $network['BSSID'],$ap_manuf);
$kml .= "<hr>\n<b>Vendor Info</b>
Type: ".$manuf[0]." ".$manuf[1];
if(!empty($manuf[2]))
$kml .= "
default SSID: ".$manuf[2].", channel ".$manuf[3];
if(!empty($manuf[4]))
$kml .= "
default ip range: ".$manuf[4];
}
$kml .= "<hr>\n<b>GPS coordinates</b>
\nfirst-seen: ".$network['gps-info']['min-lat']." lat, ".$network['gps-info']['min-lon']." lon, ".round($network['gps-info']['min-alt'],1)." alt";
$kml .= "\n
last-seen: ".$network['gps-info']['max-lat']." lat, ".$network['gps-info']['max-lon']." lon, ".round($network['gps-info']['max-alt'],1)." alt";
$kml .= "<hr>\n<b>captured packets</b>
\n";
/*******************
* list the packets section (IV's, LLC, Data, etc.)
********************/
foreach($network['packets'] as $tag => $value)
{
$kml .= $tag.": ".$value."
\n";
}
$kml .= "total datasize captured: ".$network['datasize']."\n";
/*******************
* parse clients, if existant - types: fromds, tods
********************/
if(isset($network['wireless-client']))
{
$kml .="<hr>\n<b>captured ".count($network['wireless-client'])." attached clients</b>\n
\n<ul>\n";
foreach($network['wireless-client'] as $client) //list all attached and captured clients
{
$kml .= "<li>MAC: ".$client['client-mac'];
if(get_manuf((string) $client['client-mac'],$client_manuf) != false)
{
$manuf = get_manuf((string) $client['client-mac'],$client_manuf);
$kml .= " (".$manuf[0]." ".$manuf[1].")";
}
$kml .= "
IP: ";
if(isset($client['client-ip-address'])) //IP discovered?
$kml .= $client['client-ip-address'];
else
$kml .= "none discovered";
$kml .= "</li>\n";
}
}
$kml .= "</ul>]]>\n</description>\n\t<View>\n\t<longitude>".$network['gps-info']['min-lon']."</longitude>\n";
$kml .= "\t<latitude>".$network['gps-info']['min-lat']."</latitude>\n</View>\n";
$kml .= "\t<visibility>1</visibility>\n\t<styleUrl>root://styleMaps#default?iconId=0x307</styleUrl>\n";
if($xml->{'wireless-network'}[$key]['wep'] == 'true') //net encrypton on?
{
if($argv[2] == 'kmz') //if kmz requested point to local icons
$kml .= "\t<Style>\t<icon>node_closed.png</icon></Style>";
else
$kml .= "\t<Style>\t<icon>http://www.niquille.com/wp-content/node_closed.png</icon></Style>";
$meta['wep-count']++;
}else{
if($argv[2] == 'kmz')
$kml .= "\t<Style>\t<icon>node_open.png</icon></Style>";
else
$kml .= "\t<Style>\t<icon>http://www.niquille.com/wp-content/node_open.png</icon></Style>";
}
$kml .= "\t<Point>\n\t<coordinates>".$network['gps-info']['min-lon'].", ".$network['gps-info']['min-lat'].", ".$network['gps-info']['min-alt']."</coordinates>\n</Point>\n</Placemark>\n";
/*******************
* add gps coordinates to path source
********************/
$line .= $network['gps-info']['min-lon'].", ".$network['gps-info']['min-lat'].", ".$network['gps-info']['min-alt']." ";
/*******************
* assemble polygon placemark
********************/
if($network['channel'] != '0') //we don't display networks with no height
{
$poly .= "<Placemark>\n<name><![CDATA[";
if(empty($network['SSID'])) $poly .= "no ssid";
else $poly .= $network['SSID'];
echo "SSID:".$network['SSID']." BSSID:".$network['BSSID']."\n";
$poly .= "]]></name>\n<visibility>0</visibility>\n<open>0</open>\n";
$poly .= "<Style>\n\t<LineStyle>\n\t<width>1.5</width></LineStyle>\n\t<PolyStyle>";
if($xml->{'wireless-network'}[$key]['wep'] == 'true') //set color
$poly .= "<color>8f00ff00</color>\n"; //green, closed
elseif($meta[$key]['cloaked'] == 'true')
$poly .= "<color>7dff0000</color>\n"; //blue, cloaked
else
$poly .= "<color>7d00ff00</color>\n"; //red, open
$poly .= "</PolyStyle>\n</Style>\n<Polygon>\n<extrude>1</extrude>\n<tessellate>0</tessellate>\n";
$poly .= "<altitudeMode>relativeToGround</altitudeMode>\n<outerBoundaryIs>\n<LinearRing>\n<extrude>0</extrude>";
$poly .= "<tessellate>0</tessellate>\n<altitudeMode>clampToGround</altitudeMode>\n<coordinates>";
$poly_alt = $network['channel']*10;
foreach($coordinates[$network['BSSID']] as $index => $gpoints)
{
if($gpoints[0] != $coordinates[$network['BSSID']][$index-1][0]
&& $gpoints[1] != $coordinates[$network['BSSID']][$index-1][1]) //remove duplicates
$poly .= $gpoints[0].", ".$gpoints[1].", ".$poly_alt." ";
}
$poly .= $coordinates[$network['BSSID']][0][0].", ".$coordinates[$network['BSSID']][0][1].", ".$poly_alt." "; //finish polygon at first coordinate
$poly .= "</coordinates>\n</LinearRing>\n</outerBoundaryIs>\n</Polygon>\n</Placemark>";
}
} //end foreach
/*******************
* assemble final KML xml file
********************/
$meta['wep-count'] = ($meta['wep-count']/$meta['net-count'])*100; //encrypted percentage of total nets
$kml_final = "<?xml version='1.0' encoding='UTF-8'?>\n<kml xmlns='http://earth.google.com/kml/2.0'>\n<Folder>\n<name>";
$kml_final .= $meta['session-duration'].', '.$meta['net-count'].' nets, '.$meta['probe-count'].' probes ('.$meta['parsed'].' total parsed) - '.date('d.m.Y',strtotime($xml['start-time']));
$kml_final .= "</name>\n<visibility>1</visibility><description>encrypted: ".round($meta['wep-count'],2)."%</description>\n";
//fly to first network
//range: zoom level, tilt: view angle
$kml_final .= "<LookAt>\n\t<longitude>".$array['wireless-network'][$lookatnet]['gps-info']['min-lon']."</longitude>\n\t<latitude>".$array['wireless-network'][$lookatnet]['gps-info']['min-lat']."</latitude>";
$kml_final .= "<range>1000</range><tilt>54</tilt><heading>-35</heading></LookAt>";
// output the WarDrive Path in a separate placemark
$kml_final .= "\n<Placemark>\n<name>WarSession Path</name>\n<description></description>\n<visibility>0</visibility>\n";
$kml_final .= "\t<Style>\n\t<geomColor>BB0000FF</geomColor>\n<geomScale>3</geomScale>\n</Style>\n\t<LineString>";
$kml_final .= "\n\t<tessellate>1</tessellate>\n\t<coordinates>$line</coordinates>\n</LineString>\n</Placemark>\n"; //tesselate adjusts to terrain
//output 3D visualized polygons
$kml_final .= "<Folder>\n<name>3D visualized view</name><open>0</open>\n";
$kml_final .= $poly;
$kml_final .= "</Folder>\n";
$kml_final .= $kml;
$kml_final .= "</Folder>\n</kml>";
//$kml_final = simplexml_load_string($kml_final); //check kml syntax (xml), fails because of
, <li> in description tag
//$kml_final->asXML('new.kml');
writeXML($argv[1].".kml",$kml_final); //write final XML file as KML to disk
echo $argv[1].".kml saved.\n";
if($argv[2] == 'kmz') //output as kmz (zipped) if second command line argument supplied
{
$zip = new zipfile();
$zip->addFiles(array($argv[1].".kml","node_open.png","node_closed.png")); //also include icons
$zip->output($argv[1].".kmz");
echo $argv[1].".kmz saved.\n";
}
/*******************
* execution time
********************/
$mtime = explode(" ",microtime());
$mtime = $mtime[1] + $mtime[0];
$endtime = $mtime;
$totaltime = ($endtime - $starttime);
echo "Parsed in ".round($totaltime,2)." seconds\n";
/*******************
* functions
********************/
function parse_vendor($filename)
{
$array = explode("\n",file_get_contents($filename));
foreach($array as $row)
{
$tabs = explode("\t",$row);
$mac = explode("/",$tabs[0]);
array_shift($tabs); //pop off first element (mac)
if($mac[1] == "FF:FF:FF:FF:00:00")
$mac = rtrim($mac[0],":00:00");
elseif($mac[1] == "FF:FF:FF:00:00:00")
$mac = rtrim($mac[0],":00:00:00").":*";
$macarray[(string) $mac] = $tabs;
} //end foreach
return $macarray;
/*
get's array with all the different mac ranges and vendor/manufactor info:
Array ( [00:00:22:22] =>
Array ( [0] => Lucent
[1] => Orinoco Silver
[2] =>
[3] => 0
[4] => )
etc.
*/
}
function get_manuf($mac,$macarray)
{
$longmac = substr($mac,0,11); //format to array style
$shortmac = substr($mac,0,9)."*";
if(isset($macarray[$longmac]))
return $macarray[$longmac];
elseif(isset($macarray[$shortmac]))
return $macarray[$shortmac];
else
return false; //no info found
}
function writeXML($filename, $kml)
{
$handle = fopen($filename,'w+'); //open xml file for writing
// fwrite($handle, header("Content-type: text/xml")); //write header to xml file
fwrite($handle, $kml);
fclose($handle);
}
/*******************
* pulled from php.net
********************/
function object2array($object)
{
$return = NULL;
if(is_array($object))
{
foreach($object as $key => $value)
$return[$key] = object2array($value);
}
else
{
$var = get_object_vars($object);
if($var)
{
foreach($var as $key => $value)
$return[$key] = ($key && !$value) ? NULL : object2array($value);
}
else return $object;
}
return $return;
}
/*
* zipLib v1.1
*
* Last Modification and Extension By :
*
* Hasin Hayder
* HomePage : www.hasinme.info
* Email : countdraculla@gmail.com
* IDE : PHP Designer 2005
*
*
* Originally Based on :
*
* http://www.zend.com/codex.php?id=535&single=1
* By Eric Mueller <eric@themepark.com>
*
* http://www.zend.com/codex.php?id=470&single=1
* by Denis125 <webmaster@atlant.ru>
*
* a patch from Peter Listiak <mlady@users.sourceforge.net> for last modified
* date and time of the compressed file
*/
class zipfile
{
/**
* Array to store compressed data
*
* @var array $datasec
*/
var $datasec = array();
/**
* Central directory
*
* @var array $ctrl_dir
*/
var $ctrl_dir = array();
/**
* End of central directory record
*
* @var string $eof_ctrl_dir
*/
var $eof_ctrl_dir = "\x50\x4b\x05\x06\x00\x00\x00\x00";
/**
* Last offset position
*
* @var integer $old_offset
*/
var $old_offset = 0;
/**
* Converts an Unix timestamp to a four byte DOS date and time format (date
* in high two bytes, time in low two bytes allowing magnitude comparison).
*
* @param integer the current Unix timestamp
*
* @return integer the current date in a four byte DOS format
*
* @access private
*/
function unix2DosTime($unixtime = 0) {
$timearray = ($unixtime == 0) ? getdate() : getdate($unixtime);
if ($timearray['year'] < 1980) {
$timearray['year'] = 1980;
$timearray['mon'] = 1;
$timearray['mday'] = 1;
$timearray['hours'] = 0;
$timearray['minutes'] = 0;
$timearray['seconds'] = 0;
} // end if
return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) |
($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1);
} // end of the 'unix2DosTime()' method
/**
* Adds "file" to archive
*
* @param string file contents
* @param string name of the file in the archive (may contains the path)
* @param integer the current timestamp
*
* @access public
*/
function addFile($data, $name, $time = 0)
{
$name = str_replace('\\', '/', $name);
$dtime = dechex($this->unix2DosTime($time));
$hexdtime = '\x' . $dtime[6] . $dtime[7]
. '\x' . $dtime[4] . $dtime[5]
. '\x' . $dtime[2] . $dtime[3]
. '\x' . $dtime[0] . $dtime[1];
eval('$hexdtime = "' . $hexdtime . '";');
$fr = "\x50\x4b\x03\x04";
$fr .= "\x14\x00"; // ver needed to extract
$fr .= "\x00\x00"; // gen purpose bit flag
$fr .= "\x08\x00"; // compression method
$fr .= $hexdtime; // last mod time and date
// "local file header" segment
$unc_len = strlen($data);
$crc = crc32($data);
$zdata = gzcompress($data);
$zdata = substr(substr($zdata, 0, strlen($zdata) - 4), 2); // fix crc bug
$c_len = strlen($zdata);
$fr .= pack('V', $crc); // crc32
$fr .= pack('V', $c_len); // compressed filesize
$fr .= pack('V', $unc_len); // uncompressed filesize
$fr .= pack('v', strlen($name)); // length of filename
$fr .= pack('v', 0); // extra field length
$fr .= $name;
// "file data" segment
$fr .= $zdata;
// "data descriptor" segment (optional but necessary if archive is not
// served as file)
$fr .= pack('V', $crc); // crc32
$fr .= pack('V', $c_len); // compressed filesize
$fr .= pack('V', $unc_len); // uncompressed filesize
// add this entry to array
$this -> datasec[] = $fr;
// now add to central directory record
$cdrec = "\x50\x4b\x01\x02";
$cdrec .= "\x00\x00"; // version made by
$cdrec .= "\x14\x00"; // version needed to extract
$cdrec .= "\x00\x00"; // gen purpose bit flag
$cdrec .= "\x08\x00"; // compression method
$cdrec .= $hexdtime; // last mod time & date
$cdrec .= pack('V', $crc); // crc32
$cdrec .= pack('V', $c_len); // compressed filesize
$cdrec .= pack('V', $unc_len); // uncompressed filesize
$cdrec .= pack('v', strlen($name) ); // length of filename
$cdrec .= pack('v', 0 ); // extra field length
$cdrec .= pack('v', 0 ); // file comment length
$cdrec .= pack('v', 0 ); // disk number start
$cdrec .= pack('v', 0 ); // internal file attributes
$cdrec .= pack('V', 32 ); // external file attributes - 'archive' bit set
$cdrec .= pack('V', $this -> old_offset ); // relative offset of local header
$this -> old_offset += strlen($fr);
$cdrec .= $name;
// optional extra field, file comment goes here
// save to central directory
$this -> ctrl_dir[] = $cdrec;
} // end of the 'addFile()' method
/**
* Dumps out file
*
* @return string the zipped file
*
* @access public
*/
function file()
{
$data = implode('', $this -> datasec);
$ctrldir = implode('', $this -> ctrl_dir);
return
$data .
$ctrldir .
$this -> eof_ctrl_dir .
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries "on this disk"
pack('v', sizeof($this -> ctrl_dir)) . // total # of entries overall
pack('V', strlen($ctrldir)) . // size of central dir
pack('V', strlen($data)) . // offset to start of central dir
"\x00\x00"; // .zip file comment length
} // end of the 'file()' method
/**
* A Wrapper of original addFile Function
*
* Created By Hasin Hayder at 29th Jan, 1:29 AM
*
* @param array An Array of files with relative/absolute path to be added in Zip File
*
* @access public
*/
function addFiles($files /*Only Pass Array*/)
{
foreach($files as $file)
{
if (is_file($file)) //directory check
{
$data = implode("",file($file));
$this->addFile($data,$file);
}
}
}
/**
* A Wrapper of original file Function
*
* Created By Hasin Hayder at 29th Jan, 1:29 AM
*
* @param string Output file name
*
* @access public
*/
function output($file)
{
$fp=fopen($file,"w");
fwrite($fp,$this->file());
fclose($fp);
}
} // end of the 'zipfile' class
?>
Dutch
EDIT : New much faster optimized Kismet Log Combiner version available from this thread :
http://www.netstumbler.org/showthread.php?t=21021