From 42d4672c9e21c4388fb581cc947aed7d25354931 Mon Sep 17 00:00:00 2001 From: gpotter2 <gabriel@potter.fr> Date: Thu, 23 Feb 2017 19:58:57 +0100 Subject: [PATCH] Routing fixes --- scapy/arch/pcapdnet.py | 54 +++++++++++++++++++++------------- scapy/arch/windows/__init__.py | 28 +++++++++++++----- scapy/arch/winpcapy.py | 37 +++++++++++++---------- scapy/config.py | 1 + scapy/route.py | 17 +++++++---- scapy/tools/UTscapy.py | 2 +- 6 files changed, 87 insertions(+), 52 deletions(-) diff --git a/scapy/arch/pcapdnet.py b/scapy/arch/pcapdnet.py index a5a1e273..24f4081e 100644 --- a/scapy/arch/pcapdnet.py +++ b/scapy/arch/pcapdnet.py @@ -18,32 +18,44 @@ from scapy.utils import mac2str from scapy.supersocket import SuperSocket from scapy.error import Scapy_Exception, log_loading, warning import scapy.arch +import scapy.consts if conf.use_winpcapy: #mostly code from https://github.com/phaethon/scapy translated to python2.X try: - from scapy.arch.winpcapy import * - def winpcapy_get_if_list(): - err = create_string_buffer(PCAP_ERRBUF_SIZE) - devs = POINTER(pcap_if_t)() - ret = [] - if pcap_findalldevs(byref(devs), err) < 0: - return ret - try: - p = devs - while p: - ret.append(p.contents.name.decode('ascii')) - p = p.contents.next - return ret - finally: - pcap_freealldevs(devs) - + from scapy.arch.winpcapy import * + def winpcapy_get_if_list(): + err = create_string_buffer(PCAP_ERRBUF_SIZE) + devs = POINTER(pcap_if_t)() + ret = [] + if pcap_findalldevs(byref(devs), err) < 0: + return ret + try: + p = devs + while p: + ret.append(p.contents.name.decode('ascii')) + p = p.contents.next + return ret + except: + raise + finally: + pcap_freealldevs(devs) + # Detect Pcap version + version = pcap_lib_version() + if "winpcap" in version.lower(): + if os.path.exists(os.environ["WINDIR"] + "\\System32\\Npcap\\wpcap.dll"): + warning("Winpcap is installed over Npcap. Will use Winpcap (see 'Winpcap/Npcap conflicts' in scapy's docs)", True) + else: + warning("WinPcap is now deprecated (not maintened). Please use Npcap instead", True) + elif "npcap" in version.lower(): + conf.use_npcap = True + LOOPBACK_NAME = scapy.consts.LOOPBACK_NAME = "Npcap Loopback Adapter" except OSError as e: - def winpcapy_get_if_list(): - return [] - conf.use_winpcapy = False - if conf.interactive: - log_loading.warning("wpcap.dll is not installed. You won't be able to send/recieve packets. Visit the scapy's doc to install it") + def winpcapy_get_if_list(): + return [] + conf.use_winpcapy = False + if conf.interactive: + log_loading.warning("wpcap.dll is not installed. You won't be able to send/recieve packets. Visit the scapy's doc to install it") # From BSD net/bpf.h #BIOCIMMEDIATE=0x80044270 diff --git a/scapy/arch/windows/__init__.py b/scapy/arch/windows/__init__.py index 62256a78..24b6008e 100755 --- a/scapy/arch/windows/__init__.py +++ b/scapy/arch/windows/__init__.py @@ -6,8 +6,7 @@ """ Customizations needed to support Microsoft Windows. """ - -import os,re,sys,socket,time, itertools +import os, re, sys, socket, time, itertools, platform import subprocess as sp from glob import glob import tempfile @@ -24,6 +23,7 @@ conf.use_dnet = False conf.use_winpcapy = True WINDOWS = (os.name == 'nt') +NEW_RELEASE = False #hot-patching socket for missing variables on Windows import socket @@ -37,6 +37,18 @@ if not hasattr(socket, 'IPPROTO_ESP'): from scapy.arch import pcapdnet from scapy.arch.pcapdnet import * +def is_new_release(): + release = platform.release() + try: + if float(release) >= 8: + return True + except ValueError: + if (release=="post2008Server"): + return True + return False + +NEW_RELEASE = is_new_release() + def _exec_query_ps(cmd, fields): """Execute a PowerShell query""" if not WINDOWS: @@ -221,7 +233,6 @@ def win_find_exe(filename, installsubdir=None, env="ProgramFiles"): break return path - def is_new_release(ignoreVBS=False): release = platform.release() if conf.prog.powershell is None and not ignoreVBS: @@ -272,7 +283,6 @@ if conf.prog.sox == "sox": class PcapNameNotFoundError(Scapy_Exception): pass -import platform def is_interface_valid(iface): if "guid" in iface and iface["guid"]: @@ -283,13 +293,13 @@ def is_interface_valid(iface): return False def get_windows_if_list(): - if is_new_release(): + """Returns windows interfaces""" + if 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'], ['InterfaceDescription', 'InterfaceIndex', 'Name', 'InterfaceGuid', 'MacAddress']) # It is normal that it is in this order @@ -346,6 +356,8 @@ class NetworkInterface(object): self.ip=get_ip_from_name(data['name']) except (KeyError, AttributeError, NameError) as e: print e + if not self.ip and self.name == LOOPBACK_NAME: + self.ip = "127.0.0.1" try: self.mac = data['mac'] except KeyError: @@ -501,7 +513,7 @@ def read_routes(): routes = [] release = platform.release() try: - if is_new_release(): + if NEW_RELEASE: routes = read_routes_post2008() elif release == "XP": routes = read_routes_xp() @@ -513,7 +525,7 @@ def read_routes(): if not routes: warning("No default IPv4 routes found. Your Windows release may no be supported and you have to enter your routes manually", True) return routes - + def read_routes_post2008(): routes = [] if_index = '(\d+)' diff --git a/scapy/arch/winpcapy.py b/scapy/arch/winpcapy.py index c1b7af52..9b51723c 100755 --- a/scapy/arch/winpcapy.py +++ b/scapy/arch/winpcapy.py @@ -1,3 +1,4 @@ +# Original license #------------------------------------------------------------------------------- # Name: winpcapy.py # @@ -7,31 +8,34 @@ # Copyright: (c) Massimo Ciani 2009 # #------------------------------------------------------------------------------- +# Modified for scapy's usage +## This file is part of Scapy +## See http://www.secdev.org/projects/scapy for more informations +## This program is published under a GPLv2 license from ctypes import * from ctypes.util import find_library -import sys +import sys, os +from scapy.consts import WINDOWS -WIN32=False HAVE_REMOTE=False - -if sys.platform.startswith('win'): - WIN32=True +if WINDOWS: HAVE_REMOTE=True - -if WIN32: SOCKET = c_uint - _lib=CDLL('wpcap.dll') + npcap_folder = os.environ["WINDIR"] + "\\System32\\Npcap" + if os.path.exists(npcap_folder): + # Try to load npcap + os.environ['PATH'] = npcap_folder + ";" + os.environ['PATH'] + _lib=CDLL("wpcap.dll") else: SOCKET = c_int - _lib_name = find_library('pcap') + _lib_name = find_library("pcap") if not _lib_name: - raise OSError("Cannot fine libpcap.so library") + raise OSError("Cannot fine libpcap.so library") _lib=CDLL(_lib_name) - - + ## ## misc @@ -70,7 +74,7 @@ timeval._fields_ = [('tv_sec', c_long), ## sockaddr is used by pcap_addr. ## For example if sa_family==socket.AF_INET then we need cast ## with sockaddr_in -if WIN32: +if WINDOWS: class sockaddr(Structure): _fields_ = [("sa_family", c_ushort), ("sa_data",c_ubyte * 14)] @@ -501,8 +505,9 @@ pcap_dump_close = _lib.pcap_dump_close pcap_dump_close.restype = None pcap_dump_close.argtypes = [POINTER(pcap_dumper_t)] -if not WIN32: - +if not WINDOWS: + #int pcap_get_selectable_fd(pcap_t, *p) + # Returns, on UNIX, a file descriptor number for a file descriptor on which one can do a select(), poll(). -1 is returned if no such descriptor exists. pcap_get_selectable_fd = _lib.pcap_get_selectable_fd pcap_get_selectable_fd.restype = c_int pcap_get_selectable_fd.argtypes = [POINTER(pcap_t)] @@ -513,7 +518,7 @@ if not WIN32: ## (like remote packet capture, packet buffer size variation or high-precision packet injection). ## Howerver, at the moment they can be used only in Windows. ########################################### -if WIN32: +if WINDOWS: HANDLE = c_void_p ############## diff --git a/scapy/config.py b/scapy/config.py index b858065e..93537958 100755 --- a/scapy/config.py +++ b/scapy/config.py @@ -391,6 +391,7 @@ debug_tls:When 1, print some TLS session secrets when they are computed. use_dnet = os.getenv("SCAPY_USE_PCAPDNET", "").lower().startswith("y") use_bpf = False use_winpcapy = False + use_npcap = False ipv6_enabled = socket.has_ipv6 ethertypes = ETHER_TYPES protocols = IP_PROTOS diff --git a/scapy/route.py b/scapy/route.py index 9c3ad897..017ac7b7 100644 --- a/scapy/route.py +++ b/scapy/route.py @@ -32,13 +32,18 @@ class Route: self.routes = read_routes() def __repr__(self): - rt = "Network Netmask Gateway Iface Output IP\n" + rtlst = [("Network", "Netmask", "Gateway", "Iface", "Output IP")] + for net,msk,gw,iface,addr in self.routes: - rt += "%-15s %-15s %-15s %-15s %-15s\n" % (ltoa(net), - ltoa(msk), - gw, - (iface.name if not isinstance(iface, basestring) else iface), - addr) + rtlst.append((ltoa(net), + ltoa(msk), + gw, + (iface.name if not isinstance(iface, basestring) else iface), + addr)) + + colwidth = map(lambda x: max(map(lambda y: len(y), x)), apply(zip, rtlst)) + fmt = " ".join(map(lambda x: "%%-%ds"%x, colwidth)) + rt = "\n".join(map(lambda x: fmt % x, rtlst)) return rt def make_route(self, host=None, net=None, gw=None, dev=None): diff --git a/scapy/tools/UTscapy.py b/scapy/tools/UTscapy.py index 28b12461..46d52a93 100755 --- a/scapy/tools/UTscapy.py +++ b/scapy/tools/UTscapy.py @@ -362,7 +362,7 @@ def remove_empty_testsets(test_campaign): def run_campaign(test_campaign, get_interactive_session, verb=3): if WINDOWS: - # Add a route to 127.0.0.1 + # Add a route to 127.0.0.1 and ::1 from scapy.arch.windows import route_add_loopback route_add_loopback() passed=failed=0 -- GitLab