[Windows/Networking] Fix LOOPBACK_NAME + IPv4 read_routes (#405)

This commit is contained in:
gpotter2 2016-12-20 15:15:32 +01:00 committed by Pierre Lalet
parent db7c72f041
commit a454ef4836
3 changed files with 64 additions and 17 deletions

View File

@ -5,6 +5,7 @@
import os
from sys import platform
import platform as platform_lib
LINUX = platform.startswith("linux")
OPENBSD = platform.startswith("openbsd")
@ -18,9 +19,15 @@ BSD = DARWIN or FREEBSD or OPENBSD or NETBSD
if WINDOWS:
X86_64 = False
ARM_64 = False
try:
if float(platform_lib.release()) >= 8.1:
LOOPBACK_NAME = "Microsoft KM-TEST Loopback Adapter"
else:
LOOPBACK_NAME = "Microsoft Loopback Adapter"
except ValueError:
LOOPBACK_NAME = "Microsoft Loopback Adapter"
else:
uname = os.uname()
X86_64 = uname[4] == 'x86_64'
ARM_64 = uname[4] == 'aarch64'
LOOPBACK_NAME = "lo" if LINUX else "lo0"
LOOPBACK_NAME = "lo" if LINUX else "lo0"

View File

@ -18,11 +18,13 @@ from scapy.utils import atol, itom, inet_aton, inet_ntoa, PcapReader
from scapy.base_classes import Gen, Net, SetGen
import scapy.plist as plist
from scapy.data import MTU, ETHER_BROADCAST, ETH_P_ARP
from scapy.arch.consts import LOOPBACK_NAME
conf.use_pcap = False
conf.use_dnet = False
conf.use_winpcapy = True
WINDOWS = (os.name == 'nt')
#hot-patching socket for missing variables on Windows
import socket
@ -37,8 +39,6 @@ if not hasattr(socket, 'IPPROTO_ESP'):
from scapy.arch import pcapdnet
from scapy.arch.pcapdnet import *
WINDOWS = True
def _exec_query_ps(cmd, fields):
"""Execute a PowerShell query"""
ps = sp.Popen([conf.prog.powershell] + cmd +
@ -49,12 +49,19 @@ def _exec_query_ps(cmd, fields):
for line in ps.stdout:
if not line.strip(): #skip empty lines
continue
l.append(line.split(':', 1)[1].strip())
sl = line.split(':', 1)
if len(sl) == 1:
l[-1] += sl[0].strip()
continue
else:
l.append(sl[1].strip())
if len(l) == len(fields):
yield l
l=[]
def _vbs_exec_code(code):
if not WINDOWS:
return
tmpfile = tempfile.NamedTemporaryFile(suffix=".vbs", delete=False)
tmpfile.write(code)
tmpfile.close()
@ -69,6 +76,8 @@ def _vbs_exec_code(code):
os.unlink(tmpfile.name)
def _vbs_get_iface_guid(devid):
if not WINDOWS:
return
try:
devid = str(int(devid) + 1)
guid = _vbs_exec_code("""WScript.Echo CreateObject("WScript.Shell").RegRead("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\NetworkCards\\%s\\ServiceName")
@ -99,6 +108,8 @@ def _exec_query_vbs(cmd, fields):
supported.
"""
if not WINDOWS:
return
assert len(cmd) == 2 and cmd[0] == "Get-WmiObject"
fields = [_VBS_WMI_FIELDS.get(cmd[1], {}).get(fld, fld) for fld in fields]
values = _vbs_exec_code("""Set wmi = GetObject("winmgmts:")
@ -144,6 +155,8 @@ def _where(filename, dirs=None, env="PATH"):
def win_find_exe(filename, installsubdir=None, env="ProgramFiles"):
"""Find executable in current dir, system path or given ProgramFiles subdir"""
if not WINDOWS:
return
for fn in [filename, filename+".exe"]:
try:
if installsubdir is None:
@ -157,6 +170,16 @@ def win_find_exe(filename, installsubdir=None, env="ProgramFiles"):
return path
def is_new_release():
release = platform.release()
try:
if float(release) >= 8:
return True
except ValueError:
if (release=="post2008Server"):
return True
return False
class WinProgPath(ConfClass):
_default = "<System default>"
# We try some magic to find the appropriate executables
@ -190,11 +213,15 @@ def is_interface_valid(iface):
return False
def get_windows_if_list():
if platform.release()=="post2008Server" or platform.release()=="8":
if is_new_release():
# This works only starting from Windows 8/2012 and up. For older Windows another solution is needed
# Careful: this is weird, but Get-NetAdaptater works like: (Name isn't the interface name)
# Name InterfaceDescription ifIndex Status MacAddress LinkSpeed
# ---- -------------------- ------- ------ ---------- ---------
# Ethernet Killer E2200 Gigabit Ethernet Contro... 13 Up D0-50-99-56-DD-F9 1 Gbps
query = exec_query(['Get-NetAdapter'],
['Name', 'InterfaceIndex', 'InterfaceDescription',
'InterfaceGuid', 'MacAddress'])
['InterfaceDescription', 'InterfaceIndex', 'Name',
'InterfaceGuid', 'MacAddress']) #Weird order, but normal
else:
query = exec_query(['Get-WmiObject', 'Win32_NetworkAdapter'],
['Name', 'InterfaceIndex', 'InterfaceDescription',
@ -223,15 +250,18 @@ class NetworkInterface(object):
self.pcap_name = None
self.description = None
self.data = data
self.invalid = False
if data is not None:
self.update(data)
def update(self, data):
"""Update info about network interface according to given dnet dictionary"""
self.name = data["name"]
self.name = data['name']
self.description = data['description']
self.win_index = data['win_index']
self.guid = data['guid']
if 'invalid' in data:
self.invalid = data['invalid']
# Other attributes are optional
self._update_pcapdata()
@ -251,6 +281,8 @@ class NetworkInterface(object):
pass
def _update_pcapdata(self):
if self.is_invalid():
return
for i in winpcapy_get_if_list():
if i.endswith(self.data['guid']):
self.pcap_name = i
@ -258,6 +290,9 @@ class NetworkInterface(object):
raise PcapNameNotFoundError
def is_invalid(self):
return self.invalid
def __repr__(self):
return "<%s %s %s>" % (self.__class__.__name__, self.name, self.guid)
@ -273,7 +308,7 @@ class NetworkInterfaceDict(UserDict):
except (KeyError, PcapNameNotFoundError):
pass
if len(self.data) == 0:
if len(self.data) == 0 and conf.use_winpcapy:
log_loading.warning("No match between your pcap and windows network interfaces found. "
"You probably won't be able to send packets. "
"Deactivating unneeded interfaces and restarting Scapy might help."
@ -322,6 +357,8 @@ def pcapname(dev):
"""
if type(dev) is NetworkInterface:
if dev.is_invalid():
return None
return dev.pcap_name
try:
return IFACES.dev_from_name(dev).pcap_name
@ -347,7 +384,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, IFACES.dev_from_pcapname(iface.pcap_name).mac.replace(':', '').decode('hex')
ARPHDR_ETHER, mac2str(IFACES.dev_from_pcapname(pcapname(iface)).mac.replace('-', ':'))
)
get_if_raw_hwaddr = pcapdnet.get_if_raw_hwaddr
@ -383,16 +420,16 @@ def read_routes_7():
['Name', 'Mask', 'NextHop', 'InterfaceIndex']):
try:
iface = dev_from_index(line[3])
routes.append((atol(line[0]), atol(line[1]), line[2], iface, iface.ip))
except ValueError:
continue
routes.append((atol(line[0]), atol(line[1]), line[2], iface, iface.ip))
return routes
def read_routes():
routes = []
release = platform.release()
try:
if release in ["post2008Server", "8"]:
if is_new_release():
routes = read_routes_post2008()
elif release == "XP":
routes = read_routes_xp()
@ -406,7 +443,6 @@ def read_routes():
return routes
def read_routes_post2008():
# XXX TODO: FIX THIS XXX
routes = []
if_index = '(\d+)'
dest = '(\d+\.\d+\.\d+\.\d+)/(\d+)'
@ -423,6 +459,8 @@ def read_routes_post2008():
if match:
try:
iface = dev_from_index(match.group(1))
if iface.ip == "0.0.0.0":
continue
except:
continue
# try:

View File

@ -8,7 +8,7 @@ Routing and handling of network interfaces.
"""
import socket
from scapy.arch.consts import LOOPBACK_NAME, WINDOWS
from scapy.arch.consts import LOOPBACK_NAME
from scapy.utils import atol,ltoa,itom
from scapy.config import conf
from scapy.error import Scapy_Exception,warning
@ -36,7 +36,7 @@ class Route:
rt += "%-15s %-15s %-15s %-15s %-15s\n" % (ltoa(net),
ltoa(msk),
gw,
(iface.name if WINDOWS else iface),
(iface.name if not isinstance(iface, basestring) else iface),
addr)
return rt
@ -137,6 +137,8 @@ class Route:
dst = atol(dst)
pathes=[]
for d,m,gw,i,a in self.routes:
if not a: # some interfaces may not currently be connected
continue
aa = atol(a)
if aa == dst:
pathes.append((0xffffffffL,(LOOPBACK_NAME,a,"0.0.0.0")))