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.
Files changed (33) hide show
  1. {trackerjacker-2.1.0/trackerjacker.egg-info → trackerjacker-2.2.0}/PKG-INFO +1 -1
  2. trackerjacker-2.2.0/tests/test_dot11map.py +119 -0
  3. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/dot11_frame.py +16 -0
  4. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/dot11_mapper.py +7 -4
  5. trackerjacker-2.2.0/trackerjacker/version.py +1 -0
  6. {trackerjacker-2.1.0 → trackerjacker-2.2.0/trackerjacker.egg-info}/PKG-INFO +1 -1
  7. trackerjacker-2.1.0/tests/test_dot11map.py +0 -25
  8. trackerjacker-2.1.0/trackerjacker/version.py +0 -1
  9. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/LICENSE +0 -0
  10. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/MANIFEST.in +0 -0
  11. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/README.md +0 -0
  12. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/requirements.txt +0 -0
  13. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/setup.cfg +0 -0
  14. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/setup.py +0 -0
  15. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/tests/test_config_management.py +0 -0
  16. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/tests/test_macvendordb.py +0 -0
  17. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/__init__.py +0 -0
  18. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/__main__.py +0 -0
  19. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/common.py +0 -0
  20. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/config_management.py +0 -0
  21. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/dot11_tracker.py +0 -0
  22. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/ieee_mac_vendor_db.py +0 -0
  23. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/linux_device_management.py +0 -0
  24. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/macos_device_management.py +0 -0
  25. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/oui.txt +0 -0
  26. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/plugin_parser.py +0 -0
  27. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/plugins/__init__.py +0 -0
  28. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker/plugins/foxhunt.py +0 -0
  29. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker.egg-info/SOURCES.txt +0 -0
  30. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker.egg-info/dependency_links.txt +0 -0
  31. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker.egg-info/entry_points.txt +0 -0
  32. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker.egg-info/requires.txt +0 -0
  33. {trackerjacker-2.1.0 → trackerjacker-2.2.0}/trackerjacker.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trackerjacker
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: Finds and tracks wifi devices through raw 802.11 monitoring
5
5
  Home-page: https://github.com/calebmadrigal/trackerjacker
6
6
  Author: Caleb Madrigal
@@ -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': {frame.channel},
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
- # Only associate with channels and devices for data packets since, for example, APs
167
- # send beacons on channels that they don't actually communicate on.
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'] |= {frame.channel}
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: trackerjacker
3
- Version: 2.1.0
3
+ Version: 2.2.0
4
4
  Summary: Finds and tracks wifi devices through raw 802.11 monitoring
5
5
  Home-page: https://github.com/calebmadrigal/trackerjacker
6
6
  Author: Caleb Madrigal
@@ -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