trackerjacker 2.1.0__tar.gz → 2.2.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {trackerjacker-2.1.0/trackerjacker.egg-info → trackerjacker-2.2.0}/PKG-INFO +1 -1
- trackerjacker-2.2.0/tests/test_dot11map.py +119 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/dot11_frame.py +16 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/dot11_mapper.py +7 -4
- trackerjacker-2.2.0/trackerjacker/version.py +1 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0/trackerjacker.egg-info}/PKG-INFO +1 -1
- trackerjacker-2.1.0/tests/test_dot11map.py +0 -25
- trackerjacker-2.1.0/trackerjacker/version.py +0 -1
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/LICENSE +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/MANIFEST.in +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/README.md +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/requirements.txt +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/setup.cfg +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/setup.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/tests/test_config_management.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/tests/test_macvendordb.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/__init__.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/__main__.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/common.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/config_management.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/dot11_tracker.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/ieee_mac_vendor_db.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/linux_device_management.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/macos_device_management.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/oui.txt +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/plugin_parser.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/plugins/__init__.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/plugins/foxhunt.py +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker.egg-info/SOURCES.txt +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker.egg-info/dependency_links.txt +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker.egg-info/entry_points.txt +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker.egg-info/requires.txt +0 -0
- {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker.egg-info/top_level.txt +0 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
# pylint: disable=C0111, C0413, C0103, E0401, R0903
|
|
2
|
+
import os
|
|
3
|
+
import sys
|
|
4
|
+
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
|
5
|
+
|
|
6
|
+
import unittest
|
|
7
|
+
import trackerjacker.dot11_mapper as dot11_mapper
|
|
8
|
+
import trackerjacker.dot11_frame as dot11_frame
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class FakePayload:
|
|
12
|
+
def __init__(self):
|
|
13
|
+
self.payload = None
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class FakeDot11Elt:
|
|
17
|
+
def __init__(self, element_id, info, payload=None):
|
|
18
|
+
self.ID = element_id
|
|
19
|
+
self.info = info
|
|
20
|
+
self.payload = payload if payload is not None else FakePayload()
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class FakeRadioTap:
|
|
24
|
+
dBm_AntSignal = -42
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class FakeFrame:
|
|
28
|
+
def __init__(self, addr1, addr2, addr3, frame_type, fcfield=0, elements=None,
|
|
29
|
+
has_beacon=False, has_probe_resp=False):
|
|
30
|
+
self.addr1 = addr1
|
|
31
|
+
self.addr2 = addr2
|
|
32
|
+
self.addr3 = addr3
|
|
33
|
+
self.type = frame_type
|
|
34
|
+
self.FCfield = fcfield
|
|
35
|
+
self._elements = elements
|
|
36
|
+
self._has_beacon = has_beacon
|
|
37
|
+
self._has_probe_resp = has_probe_resp
|
|
38
|
+
|
|
39
|
+
def haslayer(self, layer):
|
|
40
|
+
if layer is dot11_frame.scapy.Dot11Elt:
|
|
41
|
+
return self._elements is not None
|
|
42
|
+
if layer is dot11_frame.scapy.Dot11Beacon:
|
|
43
|
+
return self._has_beacon
|
|
44
|
+
if layer is dot11_frame.scapy.Dot11ProbeResp:
|
|
45
|
+
return self._has_probe_resp
|
|
46
|
+
if layer is dot11_frame.scapy.RadioTap:
|
|
47
|
+
return True
|
|
48
|
+
return False
|
|
49
|
+
|
|
50
|
+
def getlayer(self, layer):
|
|
51
|
+
if layer is dot11_frame.scapy.Dot11Elt:
|
|
52
|
+
return self._elements
|
|
53
|
+
return None
|
|
54
|
+
|
|
55
|
+
def __getitem__(self, layer):
|
|
56
|
+
if layer is dot11_frame.scapy.Dot11Elt:
|
|
57
|
+
return self._elements
|
|
58
|
+
if layer is dot11_frame.scapy.RadioTap:
|
|
59
|
+
return FakeRadioTap()
|
|
60
|
+
raise KeyError(layer)
|
|
61
|
+
|
|
62
|
+
def __len__(self):
|
|
63
|
+
return 128
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class Dot11MapperTest(unittest.TestCase):
|
|
67
|
+
def test_trim_frames_to_window(self):
|
|
68
|
+
frames = [(1521090725, 0), (1521090726, 100), (1521090727, 200), (1521090728, 300),
|
|
69
|
+
(1521090729, 400), (1521090730, 500), (1521090731, 600), (1521090732, 700),
|
|
70
|
+
(1521090733, 800), (1521090734, 900), (1521090735, 1000), (1521090736, 1100),
|
|
71
|
+
(1521090737, 1200), (1521090738, 1300), (1521090739, 1400), (1521090740, 1500)]
|
|
72
|
+
expected_trimmed_frames = [(1521090736, 1100), (1521090737, 1200),
|
|
73
|
+
(1521090738, 1300), (1521090739, 1400), (1521090740, 1500)]
|
|
74
|
+
now = 1521090740.4395268
|
|
75
|
+
window = 5 # seconds
|
|
76
|
+
trimmed_frames = dot11_mapper.trim_frames_to_window(frames, window, now=now)
|
|
77
|
+
self.assertEqual(expected_trimmed_frames, trimmed_frames)
|
|
78
|
+
|
|
79
|
+
def test_access_point_channels_use_advertised_channel(self):
|
|
80
|
+
ds_set = FakeDot11Elt(3, bytes([6]))
|
|
81
|
+
beacon = FakeFrame(addr1='ff:ff:ff:ff:ff:ff',
|
|
82
|
+
addr2='00:11:22:33:44:55',
|
|
83
|
+
addr3='00:11:22:33:44:55',
|
|
84
|
+
frame_type=dot11_frame.Dot11Frame.DOT11_FRAME_TYPE_MANAGEMENT,
|
|
85
|
+
elements=ds_set,
|
|
86
|
+
has_beacon=True)
|
|
87
|
+
parsed_beacon = dot11_frame.Dot11Frame(beacon, channel=11)
|
|
88
|
+
|
|
89
|
+
wifi_map = dot11_mapper.Dot11Map()
|
|
90
|
+
wifi_map.add_frame(parsed_beacon)
|
|
91
|
+
|
|
92
|
+
self.assertEqual({6}, wifi_map.access_points['00:11:22:33:44:55']['channels'])
|
|
93
|
+
|
|
94
|
+
def test_access_point_data_frame_channel_is_only_fallback(self):
|
|
95
|
+
wifi_map = dot11_mapper.Dot11Map()
|
|
96
|
+
|
|
97
|
+
ds_set = FakeDot11Elt(3, bytes([6]))
|
|
98
|
+
beacon = FakeFrame(addr1='ff:ff:ff:ff:ff:ff',
|
|
99
|
+
addr2='00:11:22:33:44:55',
|
|
100
|
+
addr3='00:11:22:33:44:55',
|
|
101
|
+
frame_type=dot11_frame.Dot11Frame.DOT11_FRAME_TYPE_MANAGEMENT,
|
|
102
|
+
elements=ds_set,
|
|
103
|
+
has_beacon=True)
|
|
104
|
+
wifi_map.add_frame(dot11_frame.Dot11Frame(beacon, channel=11))
|
|
105
|
+
|
|
106
|
+
data_frame = FakeFrame(addr1='00:11:22:33:44:55',
|
|
107
|
+
addr2='66:77:88:99:aa:bb',
|
|
108
|
+
addr3='cc:dd:ee:ff:00:11',
|
|
109
|
+
frame_type=dot11_frame.Dot11Frame.DOT11_FRAME_TYPE_DATA,
|
|
110
|
+
fcfield=dot11_frame.Dot11Frame.TO_DS)
|
|
111
|
+
wifi_map.add_frame(dot11_frame.Dot11Frame(data_frame, channel=44))
|
|
112
|
+
|
|
113
|
+
ap_node = wifi_map.access_points['00:11:22:33:44:55']
|
|
114
|
+
self.assertEqual({6}, ap_node['channels'])
|
|
115
|
+
self.assertEqual({'66:77:88:99:aa:bb', 'cc:dd:ee:ff:00:11'}, ap_node['devices'])
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
if __name__ == '__main__':
|
|
119
|
+
unittest.main()
|
|
@@ -15,12 +15,27 @@ class Dot11Frame:
|
|
|
15
15
|
DOT11_FRAME_TYPE_CONTROL = 1
|
|
16
16
|
DOT11_FRAME_TYPE_DATA = 2
|
|
17
17
|
|
|
18
|
+
@staticmethod
|
|
19
|
+
def _iter_dot11_elements(frame):
|
|
20
|
+
elt = frame.getlayer(scapy.Dot11Elt)
|
|
21
|
+
while elt and hasattr(elt, 'ID') and hasattr(elt, 'info'):
|
|
22
|
+
yield elt
|
|
23
|
+
elt = elt.payload if hasattr(elt, 'payload') else None
|
|
24
|
+
|
|
25
|
+
@classmethod
|
|
26
|
+
def _get_advertised_channel(cls, frame):
|
|
27
|
+
for elt in cls._iter_dot11_elements(frame):
|
|
28
|
+
if elt.ID in (3, 61) and elt.info:
|
|
29
|
+
return elt.info[0]
|
|
30
|
+
return None
|
|
31
|
+
|
|
18
32
|
def __init__(self, frame, channel=0, iface=None):
|
|
19
33
|
self.frame = frame
|
|
20
34
|
self.bssid = None
|
|
21
35
|
self.ssid = None
|
|
22
36
|
self.signal_strength = 0
|
|
23
37
|
self.channel = channel
|
|
38
|
+
self.advertised_channel = None
|
|
24
39
|
self.iface = iface
|
|
25
40
|
self.frame_bytes = len(frame)
|
|
26
41
|
|
|
@@ -50,6 +65,7 @@ class Dot11Frame:
|
|
|
50
65
|
|
|
51
66
|
if (frame.haslayer(scapy.Dot11Elt) and
|
|
52
67
|
(frame.haslayer(scapy.Dot11Beacon) or frame.haslayer(scapy.Dot11ProbeResp))):
|
|
68
|
+
self.advertised_channel = self._get_advertised_channel(frame)
|
|
53
69
|
|
|
54
70
|
try:
|
|
55
71
|
self.ssid = frame[scapy.Dot11Elt].info.decode().replace('\x00', '[NULL]')
|
|
@@ -131,7 +131,7 @@ class Dot11Map:
|
|
|
131
131
|
ap_node = {'bssid': bssid,
|
|
132
132
|
'ssid': frame.ssid,
|
|
133
133
|
'vendor': self.mac_vendor_db.lookup(bssid),
|
|
134
|
-
'channels':
|
|
134
|
+
'channels': set(),
|
|
135
135
|
'devices': set(),
|
|
136
136
|
'frames': []}
|
|
137
137
|
self.access_points[bssid] = ap_node
|
|
@@ -163,11 +163,14 @@ class Dot11Map:
|
|
|
163
163
|
if frame.signal_strength:
|
|
164
164
|
ap_node['signal'] = frame.signal_strength
|
|
165
165
|
|
|
166
|
-
|
|
167
|
-
|
|
166
|
+
if frame.advertised_channel:
|
|
167
|
+
ap_node['channels'] |= {frame.advertised_channel}
|
|
168
|
+
|
|
169
|
+
# Data frames do not advertise the AP channel, so use the sniffing channel as a fallback there.
|
|
168
170
|
if frame.frame_type() == dot11_frame.Dot11Frame.DOT11_FRAME_TYPE_DATA:
|
|
169
171
|
ap_node['devices'] |= (frame.macs - MACS_TO_IGNORE - {bssid})
|
|
170
|
-
ap_node['channels']
|
|
172
|
+
if not ap_node['channels']:
|
|
173
|
+
ap_node['channels'] |= {frame.channel}
|
|
171
174
|
|
|
172
175
|
ap_node['frames'].append((time.time(), frame.frame_bytes))
|
|
173
176
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "2.2.0"
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
# pylint: disable=C0111, C0413, C0103, E0401, R0903
|
|
2
|
-
import os
|
|
3
|
-
import sys
|
|
4
|
-
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
|
|
5
|
-
|
|
6
|
-
import unittest
|
|
7
|
-
import trackerjacker.dot11_mapper as dot11_mapper
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class Dot11MapperTest(unittest.TestCase):
|
|
11
|
-
def test_trim_frames_to_window(self):
|
|
12
|
-
frames = [(1521090725, 0), (1521090726, 100), (1521090727, 200), (1521090728, 300),
|
|
13
|
-
(1521090729, 400), (1521090730, 500), (1521090731, 600), (1521090732, 700),
|
|
14
|
-
(1521090733, 800), (1521090734, 900), (1521090735, 1000), (1521090736, 1100),
|
|
15
|
-
(1521090737, 1200), (1521090738, 1300), (1521090739, 1400), (1521090740, 1500)]
|
|
16
|
-
expected_trimmed_frames = [(1521090736, 1100), (1521090737, 1200),
|
|
17
|
-
(1521090738, 1300), (1521090739, 1400), (1521090740, 1500)]
|
|
18
|
-
now = 1521090740.4395268
|
|
19
|
-
window = 5 # seconds
|
|
20
|
-
trimmed_frames = dot11_mapper.trim_frames_to_window(frames, window, now=now)
|
|
21
|
-
self.assertEqual(expected_trimmed_frames, trimmed_frames)
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
if __name__ == '__main__':
|
|
25
|
-
unittest.main()
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "2.1.0"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|