% Regression tests on Windows only for Scapy # More informations at http://www.secdev.org/projects/UTscapy/ ############ ############ + Networking tests = Automaton - SelectableSelector system timeout class TimeOutSelector(SelectableObject): def check_recv(self): return False assert select_objects([TimeOutSelector()], 0) == [] assert select_objects([TimeOutSelector()], 1) == [] ############ ############ + Windows Networking tests = Mocked read_routes6() calls import mock from scapy.tools.UTscapy import Bunch from scapy.arch.windows import _read_routes6_post2008 def check_mandatory_ipv6_routes(routes6): """Ensure that mandatory IPv6 routes are present.""" if len([r for r in routes6 if r[0] == "::" and r[4] == ["::1"]]) < 1: return False if len([r for r in routes6 if r[0] == "fe80::" and (r[1] == 64 or r[1] == 32)]) < 1: return False if len([r for r in routes6 if in6_islladdr(r[0]) and r[1] == 128]) < 1: return False return True def dev_from_index_custom(if_index): 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'}] values = {} for i in if_list: try: interface = NetworkInterface(i) values[interface.guid] = interface except (KeyError, PcapNameNotFoundError): pass for devname, iface in values.items(): if iface.win_index == str(if_index): return iface raise ValueError("Unknown network interface index %r" % if_index) @mock.patch("scapy.arch.windows.construct_source_candidate_set") @mock.patch("scapy.arch.windows.get_if_list") @mock.patch("scapy.arch.windows.dev_from_index") @mock.patch("scapy.arch.windows.POWERSHELL_PROCESS.query") def test_read_routes6_windows(mock_comm, mock_dev_from_index, mock_winpcapylist, mock_utils6cset): """Test read_routes6() on Windows""" # 'Get-NetRoute -AddressFamily IPV6 | select ifIndex, DestinationPrefix, NextHop' get_net_route_output = """ ifIndex : 3 DestinationPrefix : ff00::/8 NextHop : :: RouteMetric : 0 InterfaceMetric : 1 ifIndex : 16 DestinationPrefix : ff00::/8 NextHop : :: RouteMetric : 0 InterfaceMetric : 1 ifIndex : 13 DestinationPrefix : ff00::/8 NextHop : :: RouteMetric : 0 InterfaceMetric : 1 ifIndex : 1 DestinationPrefix : ff00::/8 NextHop : :: RouteMetric : 0 InterfaceMetric : 1 ifIndex : 13 DestinationPrefix : fe80::dc1d:24e8:af00:125e/128 NextHop : :: RouteMetric : 20 InterfaceMetric : 256 ifIndex : 3 DestinationPrefix : fe80::9402:5804:cb16:fb3b/128 NextHop : :: RouteMetric : 1 InterfaceMetric : 0 ifIndex : 16 DestinationPrefix : fe80::100:7f:fffe/128 NextHop : :: RouteMetric : 1 InterfaceMetric : 0 ifIndex : 3 DestinationPrefix : fe80::/64 NextHop : :: RouteMetric : 0 InterfaceMetric : 1 ifIndex : 16 DestinationPrefix : fe80::/64 NextHop : :: RouteMetric : 0 InterfaceMetric : 1 ifIndex : 13 DestinationPrefix : fe80::/64 NextHop : :: RouteMetric : 0 InterfaceMetric : 1 ifIndex : 13 DestinationPrefix : 2a01:e35:2f17:fe60:dc1d:24e8:af00:125e/128 NextHop : :: RouteMetric : 20 InterfaceMetric : 256 ifIndex : 13 DestinationPrefix : 2a01:e35:2f17:fe60::/64 NextHop : :: RouteMetric : 30 InterfaceMetric : 256 ifIndex : 1 DestinationPrefix : ::1/128 NextHop : :: RouteMetric : 0 InterfaceMetric : 256 ifIndex : 13 DestinationPrefix : ::/0 NextHop : fe80::224:d4ff:fea0:a6d7 RouteMetric : 0 InterfaceMetric : 256 """ mock_comm.return_value = get_net_route_output.split("\n") mock_winpcapylist.return_value = [u'\\Device\\NPF_{0EC72537-B662-4F5D-B34E-48BFAE799BBE}', u'\\Device\\NPF_{C56DFFB3-992C-4964-B000-3E7C0F76E8BA}'] # Mocked in6_getifaddr() output mock_dev_from_index.side_effect = dev_from_index_custom # Random mock_utils6cset.side_effect = lambda x,y,z: ["::1"] if x=="::" else ["fdbb:d995:ddd8:51fc::"] # Test the function routes = _read_routes6_post2008() for r in routes: print(r) print(len(routes)) assert(len(routes) == 9) assert(check_mandatory_ipv6_routes(routes)) test_read_routes6_windows() = Test _read_routes_post2008 with missing InterfaceMetric from scapy.arch.windows import _read_routes_post2008 @mock.patch("scapy.arch.windows._get_metrics") @mock.patch("scapy.arch.windows.POWERSHELL_PROCESS.query") @mock.patch("scapy.arch.windows.get_if_list") @mock.patch("scapy.arch.windows.dev_from_index") def test_missing_ifacemetric(mock_dev_from_index, mock_winpcapylist, mock_exec_query, mock_get_metrics): exc_query_output = """ifIndex : 3 DestinationPrefix : 255.255.255.255/0 NextHop : 192.168.103.1 RouteMetric : 10 InterfaceMetric : 256 ifIndex : 13 DestinationPrefix : 255.255.255.255/32 NextHop : 0.0.0.0 RouteMetric : 20 InterfaceMetric : """ mock_exec_query.side_effect = lambda *args, **kargs: exc_query_output.split("\n") mock_winpcapylist.return_value = [u'\\Device\\NPF_{0EC72537-B662-4F5D-B34E-48BFAE799BBE}', u'\\Device\\NPF_{C56DFFB3-992C-4964-B000-3E7C0F76E8BA}'] mock_dev_from_index.side_effect = dev_from_index_custom mock_get_metrics.side_effect = lambda: {'16': 0, '13': 123} routes = _read_routes_post2008() for r in routes: print(r) assert len(routes) == 2 # Test if metrics were correctly read/guessed assert routes[0][5] == 266 assert routes[1][5] == 143 test_missing_ifacemetric() = Test _get_metrics with weird netsh length from scapy.arch.windows import _get_metrics @mock.patch("scapy.arch.windows.POWERSHELL_PROCESS.query") def test_get_metrics(mock_exec_query): exc_query_output = """Interface Loopback Pseudo-Interface 1 Parameters ------------------------------- IfLuid : loopback_0 IfIndex : 1 State : connected Metric : 75 Link MTU : 4294967295 byt Reachable Time : 40500 ms Base Reachable Time : 30000 ms Retransmission Interval : 1000 ms DAD Transmits : 0 Site Prefix Length : 64 Site Id : 1 Forwarding : disabled Advertising : disabled Neighbor Discovery : disabled Neighbor Unreachability Detection : disabled Router Discovery : dhcp Managed Address Configuration : enabled Other Stateful Configuration : enabled Weak Host Sends : disabled Weak Host Receives : disabled Use Automatic Metric : enabled Ignore Default Routes : disabled Advertised Router Lifetime : 1800 seconds Advertise Default Route : disabled Current Hop Limit : 0 Force ARPND Wake up patterns : disabled Directed MAC Wake up patterns : disabled ECN capability : application Interface Wi-Fi Parameters ------------------------------- IfLuid : wireless_32768 IfIndex : 7 State : connected Metric : 55 Link MTU : 1500 bytes Reachable Time : 43500 ms Base Reachable Time : 30000 ms Retransmission Interval : 1000 ms DAD Transmits : 3 Site Prefix Length : 64 Site Id : 1 Forwarding : disabled Advertising : disabled Neighbor Discovery : enabled Neighbor Unreachability Detection : enabled Router Discovery : dhcp Managed Address Configuration : enabled Other Stateful Configuration : enabled Weak Host Sends : disabled Weak Host Receives : disabled Use Automatic Metric : enabled Ignore Default Routes : disabled Advertised Router Lifetime : 1800 seconds Advertise Default Route : disabled Current Hop Limit : 0 Force ARPND Wake up patterns : disabled Directed MAC Wake up patterns : disabled ECN capability : application """ mock_exec_query.side_effect = lambda *args, **kargs: exc_query_output.split("\n") metrics = _get_metrics() print(metrics) assert metrics == {'1': 75, '7': 55} test_get_metrics() ############ ############ + Windows arch unit tests = Test PowerShell availability from scapy.config import conf assert conf.prog.powershell != None = Store powershell results import mock from scapy.config import conf ps_ip = get_ip_from_name(conf.iface.name) ps_if_list = get_windows_if_list() ps_read_routes = read_routes() # Turn on VBS mode conf.prog.powershell = None = Test get_ip_from_name with VBS ps_ip assert get_ip_from_name(conf.iface.name) == ps_ip = Test get_windows_if_list with VBS ps_if_list def is_in_if_list(i, list): if not i["mac"]: return True for j in list: if j["guid"] == i["guid"] and j["name"] == i["name"]: return True return False vbs_if_list = get_windows_if_list() vbs_if_list _correct = True for i in vbs_if_list: if not is_in_if_list(i, ps_if_list): _correct = False break assert _correct = Test read_routes with VBS ps_read_routes def is_in_route_list(i, list): # Ignore all empty IP or macs if i[4] == '': return True if i[3].mac == '' or i[3].guid == '' or i[3].ip == '': return True for j in list: if j[2] == i[2] and j[4] == i[4] and j[3].guid == i[3].guid: return True return False vbs_read_routes = read_routes() vbs_if_list _correct = True for i in vbs_read_routes: if not is_in_route_list(i, ps_read_routes): _correct = False break assert _correct conf.prog._reload() = show_interfaces from scapy.arch import show_interfaces with ContextManagerCaptureOutput() as cmco: show_interfaces() lines = cmco.get_output().split("\n")[1:] for l in lines: if not l.strip(): continue int(l[:2]) = dev_from_pcapname from scapy.config import conf assert dev_from_pcapname(conf.iface.pcap_name).guid == conf.iface.guid = test pcap_service_status status = pcap_service_status() status assert status[0] in ["npcap", "npf"] assert status[2] == True = test pcap_service_stop pcap_service_stop() assert pcap_service_status()[2] == False = test pcap_service_start pcap_service_start() assert pcap_service_status()[2] == True = Test auto-pcap start UI old_ifaces = IFACES.data @mock.patch("scapy.arch.windows.get_if_list") def _test_autostart_ui(mocked_getiflist): mocked_getiflist.side_effect = lambda: [] IFACES.reload() assert IFACES.data == {} _test_autostart_ui() IFACES.data = old_ifaces