From 40ad5b67b1a0ea7d4152d03681ae39794513bc70 Mon Sep 17 00:00:00 2001 From: gpotter2 Date: Fri, 3 Feb 2017 19:32:34 +0100 Subject: [PATCH] Fix VBS fallback --- scapy/arch/windows/__init__.py | 40 ++++++++++++++++------- test/mock_windows.uts | 59 ++++++++++++++++++++++++++++++++++ 2 files changed, 87 insertions(+), 12 deletions(-) diff --git a/scapy/arch/windows/__init__.py b/scapy/arch/windows/__init__.py index e92fdcf60..a5fdbfa96 100755 --- a/scapy/arch/windows/__init__.py +++ b/scapy/arch/windows/__init__.py @@ -58,7 +58,7 @@ def _exec_query_ps(cmd, fields): yield l l=[] -def _vbs_exec_code(code): +def _vbs_exec_code(code, split_tag="@"): if not WINDOWS: return tmpfile = tempfile.NamedTemporaryFile(suffix=".vbs", delete=False) @@ -71,7 +71,9 @@ def _vbs_exec_code(code): # skip 3 first lines ps.stdout.readline() for line in ps.stdout: - yield line + data = line.replace("\n", "").split(split_tag) + for l in data: + yield l os.unlink(tmpfile.name) def _vbs_get_iface_guid(devid): @@ -92,7 +94,12 @@ _VBS_WMI_FIELDS = { "Win32_NetworkAdapter": { "InterfaceIndex": "Index", "InterfaceDescription": "Description", - "GUID": "DeviceID", + } +} + +_VBS_WMI_REPLACE = { + "Win32_NetworkAdapterConfiguration": { + "line.IPAddress": "\"{\" & Join( line.IPAddress, \", \" ) & \"}\"", } } @@ -103,16 +110,20 @@ _VBS_WMI_OUTPUT = { } def _exec_query_vbs(cmd, fields): - if not WINDOWS: - return """Execute a query using VBS. Currently Get-WmiObject queries are supported. - """ if not WINDOWS: return - assert len(cmd) == 2 and cmd[0] == "Get-WmiObject" + if not(len(cmd) == 2 and cmd[0] == "Get-WmiObject"): + return + fields = [_VBS_WMI_FIELDS.get(cmd[1], {}).get(fld, fld) for fld in fields] + parsed_command = "WScript.Echo " + " & \" @ \" & ".join("line.%s" % fld for fld in fields + if fld is not None) + # The IPAddress is an array: convert it to a string + for key,val in _VBS_WMI_REPLACE.get(cmd[1], {}).items(): + parsed_command = parsed_command.replace(key, val) values = _vbs_exec_code("""Set wmi = GetObject("winmgmts:") Set lines = wmi.InstancesOf("%s") On Error Resume Next @@ -120,8 +131,8 @@ Err.clear For Each line in lines %s Next -""" % (cmd[1], "\n ".join("WScript.Echo line.%s" % fld for fld in fields - if fld is not None))).__iter__() +""" % (cmd[1], parsed_command), "@") + while True: yield [None if fld is None else _VBS_WMI_OUTPUT.get(cmd[1], {}).get(fld, lambda x: x)( @@ -132,7 +143,6 @@ Next def exec_query(cmd, fields): """Execute a system query using PowerShell if it is available, and using VBS/cscript as a fallback. - """ if conf.prog.powershell is None: return _exec_query_vbs(cmd, fields) @@ -171,8 +181,10 @@ def win_find_exe(filename, installsubdir=None, env="ProgramFiles"): return path -def is_new_release(): +def is_new_release(ignoreVBS=False): release = platform.release() + if conf.prog.powershell is None and not ignoreVBS: + return False try: if float(release) >= 8: return True @@ -211,6 +223,9 @@ import platform def is_interface_valid(iface): if "guid" in iface and iface["guid"]: + # Fix '-' instead of ':' + if "mac" in iface: + iface["mac"] = iface["mac"].replace("-", ":") return True return False @@ -225,6 +240,7 @@ def get_windows_if_list(): query = exec_query(['Get-NetAdapter'], ['InterfaceDescription', 'InterfaceIndex', 'Name', 'InterfaceGuid', 'MacAddress']) # It is normal that it is in this order + else: query = exec_query(['Get-WmiObject', 'Win32_NetworkAdapter'], ['Name', 'InterfaceIndex', 'InterfaceDescription', @@ -388,7 +404,7 @@ pcapdnet.open_pcap = lambda iface,*args,**kargs: _orig_open_pcap(pcapname(iface) _orig_get_if_raw_hwaddr = pcapdnet.get_if_raw_hwaddr pcapdnet.get_if_raw_hwaddr = lambda iface, *args, **kargs: ( - ARPHDR_ETHER, mac2str(IFACES.dev_from_pcapname(pcapname(iface)).mac.replace('-', ':')) + ARPHDR_ETHER, mac2str(IFACES.dev_from_pcapname(pcapname(iface)).mac) ) get_if_raw_hwaddr = pcapdnet.get_if_raw_hwaddr diff --git a/test/mock_windows.uts b/test/mock_windows.uts index 191938d06..65acbeb21 100644 --- a/test/mock_windows.uts +++ b/test/mock_windows.uts @@ -147,3 +147,62 @@ emulate_main_input(data) from ctypes import wintypes data = ["#AUTOCOMPLETE{scapy.config.conf.vers}", "assert _ == scapy.config.conf.version"] emulate_main_input(data) + +############ +############ ++ Windows arch unit tests + += Test PowerShell availability +from scapy.config import conf +assert conf.prog.powershell != None + += Test all VBS fallback +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 +assert get_ip_from_name(conf.iface.name) == ps_ip + +# Test get_windows_if_list + +def is_in_if_list(i, list): + 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() +_correct = True +for i in ps_if_list: + if not is_in_if_list(i, vbs_if_list): + _correct = False + break + +assert _correct + +# Test read_routes + +def is_in_route_list(i, list): + for j in list: + #Ignore all empty IP + if j[4] == '' or i[4] == '': + return True + 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() +_correct = True +for i in ps_read_routes: + if not is_in_route_list(i, vbs_read_routes): + _correct = False + break + +assert _correct