Fix VBS fallback

This commit is contained in:
gpotter2 2017-02-03 19:32:34 +01:00
parent afec3130e3
commit 40ad5b67b1
2 changed files with 87 additions and 12 deletions

View File

@ -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

View File

@ -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