1 | #!/usr/bin/env python
|
---|
2 | #
|
---|
3 | # Reading NS1 files - http://www.stumbler.net/ns1files.html
|
---|
4 | #
|
---|
5 | # Rick van der Zwet <info@rickvanderzwet.nl>
|
---|
6 | #
|
---|
7 | import datetime
|
---|
8 | from struct import unpack
|
---|
9 |
|
---|
10 | def parse_netstumbler(fh):
|
---|
11 | def get_int32(size=1):
|
---|
12 | v = unpack('<' + 'i'*size,fh.read(4*size))
|
---|
13 | return v[0] if size == 1 else v
|
---|
14 |
|
---|
15 | def get_uint32(size=1):
|
---|
16 | v = unpack('<' + 'I'*size,fh.read(4*size))
|
---|
17 | return v[0] if size == 1 else v
|
---|
18 |
|
---|
19 | def get_uint64(size=1):
|
---|
20 | v = unpack('<' + 'Q'*size,fh.read(8*size))
|
---|
21 | return v[0] if size == 1 else v
|
---|
22 |
|
---|
23 | def get_uint8(size=1):
|
---|
24 | v = unpack('<' + 'B'*size,fh.read(1*size))
|
---|
25 | return v[0] if size == 1 else v
|
---|
26 |
|
---|
27 | def get_filetime():
|
---|
28 | _FILETIME_null_date = datetime.datetime(1601, 1, 1, 0, 0, 0)
|
---|
29 | ns = unpack('<Q',fh.read(8))[0] * 10
|
---|
30 | sec = ns / 10**8
|
---|
31 | d = datetime.timedelta(seconds=sec)
|
---|
32 | return _FILETIME_null_date + d
|
---|
33 |
|
---|
34 | def get_char(size):
|
---|
35 | return fh.read(size)
|
---|
36 |
|
---|
37 | def get_double(size=1):
|
---|
38 | v = unpack('<' + 'd'*size,fh.read(8*size))
|
---|
39 | return v[0] if size == 1 else v
|
---|
40 |
|
---|
41 | def get_mac():
|
---|
42 | return ':'.join(["%02X" % x for x in unpack('BBBBBB',fh.read(6))])
|
---|
43 |
|
---|
44 | data = {}
|
---|
45 |
|
---|
46 | data["dwSignature"] = get_char(4)
|
---|
47 | data["dwFileVerunpack"] = get_uint32()
|
---|
48 | ApCount = get_uint32()
|
---|
49 | data["ApCount"] = ApCount
|
---|
50 |
|
---|
51 | data["aps"] = []
|
---|
52 | for a in range(0,ApCount):
|
---|
53 | ap = {}
|
---|
54 | SSIDLength = get_uint8()
|
---|
55 | ap["SSIDLength"] = SSIDLength
|
---|
56 | ap["SSID"] = get_char(SSIDLength)
|
---|
57 | ap["BSSID"] = get_mac()
|
---|
58 | ap["MaxSignal"] = get_int32()
|
---|
59 | ap["MinNoise"] = get_int32()
|
---|
60 | ap["MaxSNR"] = get_int32()
|
---|
61 | ap["Flags"] = get_uint32()
|
---|
62 | ap["BeaconInterval"] = get_uint32()
|
---|
63 | ap["FirstSeen"] = get_filetime()
|
---|
64 | ap["LastSeen"] = get_filetime()
|
---|
65 | ap["BestLat"] = get_double()
|
---|
66 | ap["BestLong"] = get_double()
|
---|
67 | DataCount = get_uint32()
|
---|
68 | ap["DataCount"] = DataCount
|
---|
69 | ap["measurements"] = []
|
---|
70 | for c in range(0,DataCount):
|
---|
71 | ms = {}
|
---|
72 | ms["Time"] = get_filetime()
|
---|
73 | ms["Signal"] = get_int32()
|
---|
74 | ms["Noice"] = get_int32()
|
---|
75 | LocationSource = get_int32()
|
---|
76 | ms["LocationSource"] = LocationSource
|
---|
77 | if LocationSource == 1:
|
---|
78 | ms["Latitude"] = get_double()
|
---|
79 | ms["Longitude"] = get_double()
|
---|
80 | ms["Altitude"] = get_double()
|
---|
81 | ms["NumStats"] = get_uint32()
|
---|
82 | ms["Speed"] = get_double()
|
---|
83 | ms["Track"] = get_double()
|
---|
84 | ms["MagVariation"] = get_double()
|
---|
85 | ms["Hdop"] = get_double()
|
---|
86 | ap["measurements"].append(ms)
|
---|
87 | NameLength = get_uint8()
|
---|
88 | ap["NameLength"] = NameLength
|
---|
89 | ap["Name"] = get_char(NameLength)
|
---|
90 | ap["Channels"] = get_uint64()
|
---|
91 | ap["LastChannel"] = get_uint32()
|
---|
92 | ap["IPAddress"] = get_uint32()
|
---|
93 | ap["MinSignal"] = get_int32()
|
---|
94 | ap["MaxSignal"] = get_int32()
|
---|
95 | ap["DataRate"] = get_uint32()
|
---|
96 | ap["IPSubnet"] = get_uint32()
|
---|
97 | ap["IPMask"] = get_uint32()
|
---|
98 | ap["ApFlags"] = get_uint32()
|
---|
99 | IELength = get_uint32()
|
---|
100 | ap["IELength"] = IELength
|
---|
101 | ap["InformationElements"] = get_uint8(IELength)
|
---|
102 | data["aps"].append(ap)
|
---|
103 | return data
|
---|
104 |
|
---|
105 | if __name__ == '__main__':
|
---|
106 | import sys
|
---|
107 | import pprint
|
---|
108 | pp = pprint.PrettyPrinter(indent=2)
|
---|
109 | pp.pprint(parse_netstumbler(open(sys.argv[1],'r')))
|
---|