1 % Regression tests on Windows only for Scapy 2 3 # More informations at http://www.secdev.org/projects/UTscapy/ 4 5 ############ 6 ############ 7 + Networking tests 8 9 = Automaton - SelectableSelector system timeout 10 11 class TimeOutSelector(SelectableObject): 12 def check_recv(self): 13 return False 14 15 assert select_objects([TimeOutSelector()], 0) == [] 16 assert select_objects([TimeOutSelector()], 1) == [] 17 18 ############ 19 ############ 20 + Windows Networking tests 21 22 = Mocked read_routes6() calls 23 24 import mock 25 from scapy.tools.UTscapy import Bunch 26 from scapy.arch.windows import _read_routes6_post2008 27 28 def check_mandatory_ipv6_routes(routes6): 29 """Ensure that mandatory IPv6 routes are present.""" 30 if len([r for r in routes6 if r[0] == "::" and r[4] == ["::1"]]) < 1: 31 return False 32 if len([r for r in routes6 if r[0] == "fe80::" and (r[1] == 64 or r[1] == 32)]) < 1: 33 return False 34 if len([r for r in routes6 if in6_islladdr(r[0]) and r[1] == 128]) < 1: 35 return False 36 return True 37 38 def dev_from_index_custom(if_index): 39 if_list = [{'mac': 'D0:50:99:56:DD:F9', 'win_index': '13', 'guid': '{C56DFFB3-992C-4964-B000-3E7C0F76E8BA}', 'name': 'Killer E2200 Gigabit Ethernet Controller', 'description': 'Ethernet'}, {'mac': '00:FF:0E:C7:25:37', 'win_index': '3', 'guid': '{0EC72537-B662-4F5D-B34E-48BFAE799BBE}', 'name': 'TAP-Windows Adapter V9', 'description': 'Ethernet 2'}] 40 values = {} 41 for i in if_list: 42 try: 43 interface = NetworkInterface(i) 44 values[interface.guid] = interface 45 except (KeyError, PcapNameNotFoundError): 46 pass 47 for devname, iface in values.items(): 48 if iface.win_index == str(if_index): 49 return iface 50 raise ValueError("Unknown network interface index %r" % if_index) 51 52 @mock.patch("scapy.arch.windows.construct_source_candidate_set") 53 @mock.patch("scapy.arch.windows.get_if_list") 54 @mock.patch("scapy.arch.windows.dev_from_index") 55 @mock.patch("scapy.arch.windows.POWERSHELL_PROCESS.query") 56 def test_read_routes6_windows(mock_comm, mock_dev_from_index, mock_winpcapylist, mock_utils6cset): 57 """Test read_routes6() on Windows""" 58 # 'Get-NetRoute -AddressFamily IPV6 | select ifIndex, DestinationPrefix, NextHop' 59 get_net_route_output = """ 60 ifIndex : 3 61 DestinationPrefix : ff00::/8 62 NextHop : :: 63 RouteMetric : 0 64 InterfaceMetric : 1 65 66 ifIndex : 16 67 DestinationPrefix : ff00::/8 68 NextHop : :: 69 RouteMetric : 0 70 InterfaceMetric : 1 71 72 ifIndex : 13 73 DestinationPrefix : ff00::/8 74 NextHop : :: 75 RouteMetric : 0 76 InterfaceMetric : 1 77 78 ifIndex : 1 79 DestinationPrefix : ff00::/8 80 NextHop : :: 81 RouteMetric : 0 82 InterfaceMetric : 1 83 84 ifIndex : 13 85 DestinationPrefix : fe80::dc1d:24e8:af00:125e/128 86 NextHop : :: 87 RouteMetric : 20 88 InterfaceMetric : 256 89 90 ifIndex : 3 91 DestinationPrefix : fe80::9402:5804:cb16:fb3b/128 92 NextHop : :: 93 RouteMetric : 1 94 InterfaceMetric : 0 95 96 ifIndex : 16 97 DestinationPrefix : fe80::100:7f:fffe/128 98 NextHop : :: 99 RouteMetric : 1 100 InterfaceMetric : 0 101 102 ifIndex : 3 103 DestinationPrefix : fe80::/64 104 NextHop : :: 105 RouteMetric : 0 106 InterfaceMetric : 1 107 108 ifIndex : 16 109 DestinationPrefix : fe80::/64 110 NextHop : :: 111 RouteMetric : 0 112 InterfaceMetric : 1 113 114 ifIndex : 13 115 DestinationPrefix : fe80::/64 116 NextHop : :: 117 RouteMetric : 0 118 InterfaceMetric : 1 119 120 ifIndex : 13 121 DestinationPrefix : 2a01:e35:2f17:fe60:dc1d:24e8:af00:125e/128 122 NextHop : :: 123 RouteMetric : 20 124 InterfaceMetric : 256 125 126 ifIndex : 13 127 DestinationPrefix : 2a01:e35:2f17:fe60::/64 128 NextHop : :: 129 RouteMetric : 30 130 InterfaceMetric : 256 131 132 ifIndex : 1 133 DestinationPrefix : ::1/128 134 NextHop : :: 135 RouteMetric : 0 136 InterfaceMetric : 256 137 138 ifIndex : 13 139 DestinationPrefix : ::/0 140 NextHop : fe80::224:d4ff:fea0:a6d7 141 RouteMetric : 0 142 InterfaceMetric : 256 143 """ 144 mock_comm.return_value = get_net_route_output.split("\n") 145 mock_winpcapylist.return_value = [u'\\Device\\NPF_{0EC72537-B662-4F5D-B34E-48BFAE799BBE}', u'\\Device\\NPF_{C56DFFB3-992C-4964-B000-3E7C0F76E8BA}'] 146 # Mocked in6_getifaddr() output 147 mock_dev_from_index.side_effect = dev_from_index_custom 148 # Random 149 mock_utils6cset.side_effect = lambda x,y,z: ["::1"] if x=="::" else ["fdbb:d995:ddd8:51fc::"] 150 # Test the function 151 routes = _read_routes6_post2008() 152 for r in routes: 153 print(r) 154 print(len(routes)) 155 assert(len(routes) == 9) 156 assert(check_mandatory_ipv6_routes(routes)) 157 158 159 test_read_routes6_windows() 160 161 = Test _read_routes_post2008 with missing InterfaceMetric 162 163 from scapy.arch.windows import _read_routes_post2008 164 165 @mock.patch("scapy.arch.windows._get_metrics") 166 @mock.patch("scapy.arch.windows.POWERSHELL_PROCESS.query") 167 @mock.patch("scapy.arch.windows.get_if_list") 168 @mock.patch("scapy.arch.windows.dev_from_index") 169 def test_missing_ifacemetric(mock_dev_from_index, mock_winpcapylist, mock_exec_query, mock_get_metrics): 170 exc_query_output = """ifIndex : 3 171 DestinationPrefix : 255.255.255.255/0 172 NextHop : 192.168.103.1 173 RouteMetric : 10 174 InterfaceMetric : 256 175 176 ifIndex : 13 177 DestinationPrefix : 255.255.255.255/32 178 NextHop : 0.0.0.0 179 RouteMetric : 20 180 InterfaceMetric : 181 """ 182 mock_exec_query.side_effect = lambda *args, **kargs: exc_query_output.split("\n") 183 mock_winpcapylist.return_value = [u'\\Device\\NPF_{0EC72537-B662-4F5D-B34E-48BFAE799BBE}', u'\\Device\\NPF_{C56DFFB3-992C-4964-B000-3E7C0F76E8BA}'] 184 mock_dev_from_index.side_effect = dev_from_index_custom 185 mock_get_metrics.side_effect = lambda: {'16': 0, '13': 123} 186 routes = _read_routes_post2008() 187 for r in routes: 188 print(r) 189 assert len(routes) == 2 190 # Test if metrics were correctly read/guessed 191 assert routes[0][5] == 266 192 assert routes[1][5] == 143 193 194 test_missing_ifacemetric() 195 196 = Test _get_metrics with weird netsh length 197 198 from scapy.arch.windows import _get_metrics 199 200 @mock.patch("scapy.arch.windows.POWERSHELL_PROCESS.query") 201 def test_get_metrics(mock_exec_query): 202 exc_query_output = """Interface Loopback Pseudo-Interface 1 Parameters 203 ------------------------------- 204 IfLuid : loopback_0 205 IfIndex : 1 206 State : connected 207 Metric : 75 208 Link MTU : 4294967295 byt 209 Reachable Time : 40500 ms 210 Base Reachable Time : 30000 ms 211 Retransmission Interval : 1000 ms 212 DAD Transmits : 0 213 Site Prefix Length : 64 214 Site Id : 1 215 Forwarding : disabled 216 Advertising : disabled 217 Neighbor Discovery : disabled 218 Neighbor Unreachability Detection : disabled 219 Router Discovery : dhcp 220 Managed Address Configuration : enabled 221 Other Stateful Configuration : enabled 222 Weak Host Sends : disabled 223 Weak Host Receives : disabled 224 Use Automatic Metric : enabled 225 Ignore Default Routes : disabled 226 Advertised Router Lifetime : 1800 seconds 227 Advertise Default Route : disabled 228 Current Hop Limit : 0 229 Force ARPND Wake up patterns : disabled 230 Directed MAC Wake up patterns : disabled 231 ECN capability : application 232 233 Interface Wi-Fi Parameters 234 ------------------------------- 235 IfLuid : wireless_32768 236 IfIndex : 7 237 State : connected 238 Metric : 55 239 Link MTU : 1500 bytes 240 Reachable Time : 43500 ms 241 Base Reachable Time : 30000 ms 242 Retransmission Interval : 1000 ms 243 DAD Transmits : 3 244 Site Prefix Length : 64 245 Site Id : 1 246 Forwarding : disabled 247 Advertising : disabled 248 Neighbor Discovery : enabled 249 Neighbor Unreachability Detection : enabled 250 Router Discovery : dhcp 251 Managed Address Configuration : enabled 252 Other Stateful Configuration : enabled 253 Weak Host Sends : disabled 254 Weak Host Receives : disabled 255 Use Automatic Metric : enabled 256 Ignore Default Routes : disabled 257 Advertised Router Lifetime : 1800 seconds 258 Advertise Default Route : disabled 259 Current Hop Limit : 0 260 Force ARPND Wake up patterns : disabled 261 Directed MAC Wake up patterns : disabled 262 ECN capability : application 263 """ 264 mock_exec_query.side_effect = lambda *args, **kargs: exc_query_output.split("\n") 265 metrics = _get_metrics() 266 print(metrics) 267 assert metrics == {'1': 75, '7': 55} 268 269 test_get_metrics() 270 271 ############ 272 ############ 273 + Windows arch unit tests 274 275 = Test PowerShell availability 276 from scapy.config import conf 277 assert conf.prog.powershell != None 278 279 = Store powershell results 280 import mock 281 from scapy.config import conf 282 283 ps_ip = get_ip_from_name(conf.iface.name) 284 ps_if_list = get_windows_if_list() 285 ps_read_routes = read_routes() 286 287 # Turn on VBS mode 288 conf.prog.powershell = None 289 290 = Test get_ip_from_name with VBS 291 ps_ip 292 293 assert get_ip_from_name(conf.iface.name) == ps_ip 294 295 = Test get_windows_if_list with VBS 296 ps_if_list 297 298 def is_in_if_list(i, list): 299 if not i["mac"]: 300 return True 301 for j in list: 302 if j["guid"] == i["guid"] and j["name"] == i["name"]: 303 return True 304 return False 305 306 vbs_if_list = get_windows_if_list() 307 vbs_if_list 308 _correct = True 309 for i in vbs_if_list: 310 if not is_in_if_list(i, ps_if_list): 311 _correct = False 312 break 313 314 assert _correct 315 316 = Test read_routes with VBS 317 ps_read_routes 318 319 def is_in_route_list(i, list): 320 # Ignore all empty IP or macs 321 if i[4] == '': 322 return True 323 if i[3].mac == '' or i[3].guid == '' or i[3].ip == '': 324 return True 325 for j in list: 326 if j[2] == i[2] and j[4] == i[4] and j[3].guid == i[3].guid: 327 return True 328 return False 329 330 vbs_read_routes = read_routes() 331 vbs_if_list 332 _correct = True 333 for i in vbs_read_routes: 334 if not is_in_route_list(i, ps_read_routes): 335 _correct = False 336 break 337 338 assert _correct 339 340 conf.prog._reload() 341 342 = show_interfaces 343 344 from scapy.arch import show_interfaces 345 346 with ContextManagerCaptureOutput() as cmco: 347 show_interfaces() 348 lines = cmco.get_output().split("\n")[1:] 349 for l in lines: 350 if not l.strip(): 351 continue 352 int(l[:2]) 353 354 = dev_from_pcapname 355 356 from scapy.config import conf 357 358 assert dev_from_pcapname(conf.iface.pcap_name).guid == conf.iface.guid 359 360 = test pcap_service_status 361 362 status = pcap_service_status() 363 status 364 assert status[0] in ["npcap", "npf"] 365 assert status[2] == True 366 367 = test pcap_service_stop 368 369 pcap_service_stop() 370 assert pcap_service_status()[2] == False 371 372 = test pcap_service_start 373 374 pcap_service_start() 375 assert pcap_service_status()[2] == True 376 377 = Test auto-pcap start UI 378 379 old_ifaces = IFACES.data 380 381 @mock.patch("scapy.arch.windows.get_if_list") 382 def _test_autostart_ui(mocked_getiflist): 383 mocked_getiflist.side_effect = lambda: [] 384 IFACES.reload() 385 assert IFACES.data == {} 386 387 _test_autostart_ui() 388 389 IFACES.data = old_ifaces