1
+ #!/usr/bin/env python
2
+ '''
3
+ pykismetstats parse .netxml file generated by kismet
4
+ and write statistics to CSV file.
5
+
6
+ XML parsing based on pykismetkml
7
+ http://code.google.com/p/pykismetkml
8
+
9
+ Following stats are implemented:
10
+ - channel usage ( how many networks works on each channel )
11
+ - manufacturer ( how many AP by each vendor )
12
+ - encryption ( none/wep/wpa+wpa2, do not distinguish between wpa/wpa2 )
13
+
14
+
15
+ @author: ziherung.pl
16
+ '''
17
+ import optparse
18
+ import xml .dom .minidom
19
+ import csv
20
+
21
+ class OptionParser (optparse .OptionParser ):
22
+ def check_required (self , opt , stop ):
23
+ option = self .get_option (opt )
24
+ if getattr (self .values , option .dest ) is None :
25
+ if stop :
26
+ return False
27
+ else :
28
+ self .error ("%s option not supplied" % option )
29
+ else :
30
+ return True
31
+
32
+ def parse (filename ,networks ):
33
+
34
+ document = xml .dom .minidom .parse (filename )
35
+ items = document .getElementsByTagName ("wireless-network" )
36
+
37
+ for item in items :
38
+ network = dict ()
39
+ # work only on 'infrastructure' networks
40
+ if item .getAttribute ('type' ) == 'infrastructure' :
41
+
42
+ # get ssid / cloaked
43
+ if ( item .getElementsByTagName ('essid' ).item (0 ).getAttribute ('cloaked' ) ) == 'false' :
44
+ network ['cloaked' ] = 'false'
45
+ network ['ssid' ] = item .getElementsByTagName ('essid' ).item (0 ).firstChild .data
46
+ else :
47
+ network ['cloaked' ] = 'true'
48
+ network ['ssid' ] = ' '
49
+
50
+ network ['manuf' ] = item .getElementsByTagName ('manuf' ).item (0 ).firstChild .data
51
+ network ['channel' ] = item .getElementsByTagName ('channel' ).item (0 ).firstChild .data
52
+ network ['encryption' ] = item .getElementsByTagName ('encryption' ).item (0 ).firstChild .data
53
+ network ['bssid' ] = item .getElementsByTagName ('BSSID' ).item (0 ).firstChild .data
54
+
55
+ networks .append (network )
56
+
57
+ def save_output (outputfile ,networks ,stats ):
58
+ '''Save parsed data to .csv'''
59
+ with open (outputfile ,'wb' ) as csvoutput :
60
+ csvwriter = csv .writer (csvoutput ,delimiter = ';' ,quotechar = '"' )
61
+
62
+ for el in stats :
63
+ csvwriter .writerow (el )
64
+
65
+ csvwriter .writerow (['ssid' ,'cloaked' ,'encryption' ,'manufacturer' ,'channel' ,'bssid' ])
66
+ for net in networks :
67
+ csvwriter .writerow ([net ['ssid' ],net ['cloaked' ],net ['encryption' ],net ['manuf' ],
68
+ net ['channel' ],net ['bssid' ]])
69
+
70
+
71
+
72
+ def make_stats (networks ,stats ):
73
+ '''Function get statistics about channel usage, encryption and AP manufacturers'''
74
+
75
+ channels_desc = range (1 ,15 ,1 )
76
+ channels_amount = [0 ]* 14
77
+
78
+ manuf = dict ()
79
+ enc = {'wpa/wpa2' :0 ,'wep' :0 ,'none' :0 }
80
+
81
+ for net in networks :
82
+ channels_amount [int (net ['channel' ])- 1 ]+= 1
83
+ if manuf .has_key (net ['manuf' ]):
84
+ manuf [net ['manuf' ]]+= 1
85
+ else :
86
+ manuf [net ['manuf' ]]= 1
87
+ if net ['encryption' ].find ('WPA' ) != - 1 :
88
+ enc ['wpa/wpa2' ]+= 1
89
+ elif net ['encryption' ].find ('WEP' ) != - 1 :
90
+ enc ['wep' ]+= 1
91
+ else :
92
+ enc ['none' ]+= 1
93
+
94
+
95
+
96
+
97
+ stats .append (['channel usage:' ])
98
+ stats .append (channels_desc )
99
+ stats .append (channels_amount )
100
+
101
+ stats .append (['----------' ])
102
+ stats .append (['manufacturer' ,'amount' ])
103
+ for k ,v in manuf .iteritems ():
104
+ stats .append ([k ,v ])
105
+
106
+ stats .append (['----------' ])
107
+ stats .append (['encryption' ,'amount' ])
108
+ for k ,v in enc .iteritems ():
109
+ stats .append ([k ,v ])
110
+
111
+ stats .append (['----------' ])
112
+
113
+
114
+
115
+
116
+
117
+ if __name__ == '__main__' :
118
+ usage = "%prog -i <kismet_netxml_file> [ optional -o <csv_output> ]"
119
+ parser = OptionParser (usage = usage )
120
+ parser .add_option ("-i" ,"--input" , dest = "netxml" ,help = "NetXML input file generated by kismet" )
121
+ parser .add_option ("-o" , "--output" , dest = "csvoutput" , help = "( Optional ) Path to CSV output file, out.csv if not specified." )
122
+
123
+ (options , args ) = parser .parse_args ()
124
+ parser .check_required ("-i" , False )
125
+ filename = options .netxml
126
+
127
+ if parser .check_required ("-o" , True ):
128
+ outputfile = options .csvoutput
129
+ else :
130
+ outputfile = "out.csv"
131
+
132
+ networks = []
133
+ stats = []
134
+
135
+ parse (filename ,networks )
136
+ make_stats (networks , stats )
137
+ save_output (outputfile ,networks ,stats )
138
+
0 commit comments