mirror of https://github.com/secdev/scapy.git
389 lines
10 KiB
Plaintext
389 lines
10 KiB
Plaintext
% 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 |