diff --git a/scapy/arch/pcapdnet.py b/scapy/arch/pcapdnet.py old mode 100644 new mode 100755 index 94673d7d284695cfa9569e41d67646301a250f19..c3333b0f28e1106504b6add31d78f9a5a4fdb5ef --- a/scapy/arch/pcapdnet.py +++ b/scapy/arch/pcapdnet.py @@ -16,9 +16,307 @@ from scapy.utils import warning from scapy.supersocket import SuperSocket from scapy.error import Scapy_Exception import scapy.arch +import socket +if conf.use_winpcapy: + #mostly code from https://github.com/phaethon/scapy translated to python2.X + try: + from .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) + except OSError as e: + if conf.interactive: + log_loading.error("Unable to import libpcap library: %s" % e) + conf.use_winpcapy = False + else: + raise + + # From BSD net/bpf.h + #BIOCIMMEDIATE=0x80044270 + BIOCIMMEDIATE=-2147204496 + + class PcapTimeoutElapsed(Scapy_Exception): + pass + + def get_if_raw_hwaddr(iff): + err = create_string_buffer(PCAP_ERRBUF_SIZE) + devs = POINTER(pcap_if_t)() + ret = "\0\0\0\0\0\0" + + if pcap_findalldevs(byref(devs), err) < 0: + return ret + try: + p = devs + while p: + if p.contents.name.endswith(iff): + a = p.contents.addresses + while a: + if hasattr(socket, 'AF_LINK') and a.contents.addr.contents.sa_family == socket.AF_LINK: + ap = a.contents.addr + val = cast(ap, POINTER(sockaddr_dl)) + ret = str(val.contents.sdl_data[ val.contents.sdl_nlen : val.contents.sdl_nlen + val.contents.sdl_alen ]) + a = a.contents.next + break + p = p.contents.next + return ret + finally: + pcap_freealldevs(devs) + def get_if_raw_addr(iff): + err = create_string_buffer(PCAP_ERRBUF_SIZE) + devs = POINTER(pcap_if_t)() + ret = "\0\0\0\0" + + if pcap_findalldevs(byref(devs), err) < 0: + return ret + try: + p = devs + while p: + if p.contents.name.endswith(iff): + a = p.contents.addresses + while a: + if a.contents.addr.contents.sa_family == socket.AF_INET: + ap = a.contents.addr + val = cast(ap, POINTER(sockaddr_in)) + #ret = bytes(val.contents.sin_addr[:4]) + ret = "".join([chr(x) for x in val.contents.sin_addr[:4]]) + a = a.contents.next + break + p = p.contents.next + return ret + finally: + pcap_freealldevs(devs) + get_if_list = winpcapy_get_if_list + def in6_getifaddr(): + 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 + ret = [] + while p: + a = p.contents.addresses + while a: + if a.contents.addr.contents.sa_family == socket.AF_INET6: + ap = a.contents.addr + val = cast(ap, POINTER(sockaddr_in6)) + addr = socket.inet_ntop(socket.AF_INET6, str(val.contents.sin6_addr[:])) + scope = scapy.utils6.in6_getscope(addr) + ret.append((addr, scope, p.contents.name.decode('ascii'))) + a = a.contents.next + p = p.contents.next + return ret + finally: + pcap_freealldevs(devs) + + from ctypes import POINTER, byref, create_string_buffer + class _PcapWrapper_pypcap: + def __init__(self, device, snaplen, promisc, to_ms): + self.errbuf = create_string_buffer(PCAP_ERRBUF_SIZE) + self.iface = create_string_buffer(device) + self.pcap = pcap_open_live(self.iface, snaplen, promisc, to_ms, self.errbuf) + self.header = POINTER(pcap_pkthdr)() + self.pkt_data = POINTER(c_ubyte)() + self.bpf_program = bpf_program() + def next(self): + c = pcap_next_ex(self.pcap, byref(self.header), byref(self.pkt_data)) + if not c > 0: + return + ts = self.header.contents.ts.tv_sec + pkt = "".join([ chr(i) for i in self.pkt_data[:self.header.contents.len] ]) + #pkt = bytes(self.pkt_data[:self.header.contents.len]) + return ts, pkt + def datalink(self): + return pcap_datalink(self.pcap) + def fileno(self): + if sys.platform.startswith("win"): + error("Cannot get selectable PCAP fd on Windows") + return 0 + return pcap_get_selectable_fd(self.pcap) + def setfilter(self, f): + filter_exp = create_string_buffer(f) + if pcap_compile(self.pcap, byref(self.bpf_program), filter_exp, 0, -1) == -1: + error("Could not compile filter expression %s" % f) + return False + else: + if pcap_setfilter(self.pcap, byref(self.bpf_program)) == -1: + error("Could not install filter %s" % f) + return False + return True + def setnonblock(self, i): + pcap_setnonblock(self.pcap, i, self.errbuf) + def send(self, x): + pcap_sendpacket(self.pcap, x, len(x)) + def close(self): + pcap_close(self.pcap) + open_pcap = lambda *args,**kargs: _PcapWrapper_pypcap(*args,**kargs) + class PcapTimeoutElapsed(Scapy_Exception): + pass + + class L2pcapListenSocket(SuperSocket): + desc = "read packets at layer 2 using libpcap" + def __init__(self, iface = None, type = ETH_P_ALL, promisc=None, filter=None): + self.type = type + self.outs = None + self.iface = iface + if iface is None: + iface = conf.iface + if promisc is None: + promisc = conf.sniff_promisc + self.promisc = promisc + self.ins = open_pcap(iface, 1600, self.promisc, 100) + try: + ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1)) + except: + pass + if type == ETH_P_ALL: # Do not apply any filter if Ethernet type is given + if conf.except_filter: + if filter: + filter = "(%s) and not (%s)" % (filter, conf.except_filter) + else: + filter = "not (%s)" % conf.except_filter + if filter: + self.ins.setfilter(filter) + + def close(self): + self.ins.close() + + def recv(self, x=MTU): + ll = self.ins.datalink() + if ll in conf.l2types: + cls = conf.l2types[ll] + else: + cls = conf.default_l2 + warning("Unable to guess datalink type (interface=%s linktype=%i). Using %s" % (self.iface, ll, cls.name)) + + pkt = None + while pkt is None: + pkt = self.ins.next() + if pkt is not None: + ts,pkt = pkt + if scapy.arch.WINDOWS and pkt is None: + raise PcapTimeoutElapsed + try: + pkt = cls(pkt) + except KeyboardInterrupt: + raise + except: + if conf.debug_dissector: + raise + pkt = conf.raw_layer(pkt) + pkt.time = ts + return pkt + + def send(self, x): + raise Scapy_Exception("Can't send anything with L2pcapListenSocket") + + + conf.L2listen = L2pcapListenSocket + class L2pcapSocket(SuperSocket): + desc = "read/write packets at layer 2 using only libpcap" + def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0): + if iface is None: + iface = conf.iface + self.iface = iface + self.ins = open_pcap(iface, 1600, 0, 100) + try: + ioctl(self.ins.fileno(),BIOCIMMEDIATE,struct.pack("I",1)) + except: + pass + if nofilter: + if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap + filter = "ether proto %i" % type + else: + filter = None + else: + if conf.except_filter: + if filter: + filter = "(%s) and not (%s)" % (filter, conf.except_filter) + else: + filter = "not (%s)" % conf.except_filter + if type != ETH_P_ALL: # PF_PACKET stuff. Need to emulate this for pcap + if filter: + filter = "(ether proto %i) and (%s)" % (type,filter) + else: + filter = "ether proto %i" % type + if filter: + self.ins.setfilter(filter) + def send(self, x): + sx = str(x) + if hasattr(x, "sent_time"): + x.sent_time = time.time() + return self.ins.send(sx) + + def recv(self,x=MTU): + ll = self.ins.datalink() + if ll in conf.l2types: + cls = conf.l2types[ll] + else: + cls = conf.default_l2 + warning("Unable to guess datalink type (interface=%s linktype=%i). Using %s" % (self.iface, ll, cls.name)) + + pkt = self.ins.next() + if pkt is not None: + ts,pkt = pkt + if pkt is None: + return + + try: + pkt = cls(pkt) + except KeyboardInterrupt: + raise + except: + if conf.debug_dissector: + raise + pkt = conf.raw_layer(pkt) + pkt.time = ts + return pkt + + def nonblock_recv(self): + self.ins.setnonblock(1) + p = self.recv(MTU) + self.ins.setnonblock(0) + return p + + def close(self): + if hasattr(self, "ins"): + self.ins.close() + if hasattr(self, "outs"): + self.outs.close() + + class L3pcapSocket(L2pcapSocket): + #def __init__(self, iface = None, type = ETH_P_ALL, filter=None, nofilter=0): + # L2pcapSocket.__init__(self, iface, type, filter, nofilter) + def recv(self, x = MTU): + r = L2pcapSocket.recv(self, x) + if r: + return r.payload + else: + return + def send(self, x): + cls = conf.l2types[1] + sx = str(cls()/x) + if hasattr(x, "sent_time"): + x.sent_time = time.time() + return self.ins.send(sx) + conf.L2socket=L2pcapSocket + conf.L3socket=L3pcapSocket + if conf.use_pcap: diff --git a/scapy/arch/windows/__init__.py b/scapy/arch/windows/__init__.py index 4fbed76cb80fa13377f1148fe960d2b6e3179fbd..c66a933537ca4c50a05187086336c28a3e2674ab 100755 --- a/scapy/arch/windows/__init__.py +++ b/scapy/arch/windows/__init__.py @@ -7,19 +7,33 @@ Customizations needed to support Microsoft Windows. """ -import os,re,sys,socket,time +import os,re,sys,socket,time, itertools +import subprocess as sp from glob import glob from scapy.config import conf,ConfClass from scapy.error import Scapy_Exception,log_loading,log_runtime -from scapy.utils import atol, inet_aton, inet_ntoa, PcapReader +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.sendrecv import debug, srp1 from scapy.layers.l2 import Ether, ARP from scapy.data import MTU, ETHER_BROADCAST, ETH_P_ARP -conf.use_pcap = 1 -conf.use_dnet = 1 +conf.use_pcap = False +conf.use_dnet = False +conf.use_winpcapy = True + + +#hot-patching socket for missing variables on Windows +import socket +if not hasattr(socket, 'IPPROTO_IPIP'): + socket.IPPROTO_IPIP=4 +if not hasattr(socket, 'IPPROTO_AH'): + socket.IPPROTO_AH=51 +if not hasattr(socket, 'IPPROTO_ESP'): + socket.IPPROTO_ESP=50 + + from scapy.arch import pcapdnet from scapy.arch.pcapdnet import * @@ -69,120 +83,137 @@ class WinProgPath(ConfClass): conf.prog = WinProgPath() - - -import _winreg - - - class PcapNameNotFoundError(Scapy_Exception): pass - +import platform + +def is_interface_valid(iface): + if "guid" in iface and iface["guid"]: + return True + return False +def get_windows_if_list(): + if platform.release()=="post2008Server" or platform.release()=="8": + # This works only starting from Windows 8/2012 and up. For older Windows another solution is needed + ps = sp.Popen(['powershell', 'Get-NetAdapter', '|', 'select Name, InterfaceIndex, InterfaceDescription, InterfaceGuid, MacAddress', '|', 'fl'], stdout = sp.PIPE, universal_newlines = True) + else: + ps = sp.Popen(['powershell', 'Get-WmiObject', 'Win32_NetworkAdapter', '|', 'select Name, InterfaceIndex, InterfaceDescription, GUID, MacAddress', '|', 'fl'], stdout = sp.PIPE, universal_newlines = True) + #no solution implemented for xp + + stdout, stdin = ps.communicate() + current_interface = None + interface_list = [] + for i in stdout.split('\n'): + if not i.strip(): + continue + if i.find(':')<0: + continue + name, value = [ j.strip() for j in i.split(':',1) ] + if name == 'Name': + if current_interface and is_interface_valid(current_interface): + interface_list.append(current_interface) + current_interface = {} + current_interface['name'] = value + elif name == 'InterfaceIndex': + current_interface['win_index'] = int(value) + elif name == 'InterfaceDescription': + current_interface['description'] = value + elif name == 'InterfaceGuid': + current_interface['guid'] = value + elif name == 'GUID': + current_interface['guid'] = value + elif name == 'MacAddress': + current_interface['mac'] = ':'.join([ j for j in value.split('-')]) + if current_interface and is_interface_valid(current_interface): + interface_list.append(current_interface) + + return interface_list +def get_ip_from_name(ifname, v6=False): + ps = sp.Popen(['powershell', 'Get-WmiObject', 'Win32_NetworkAdapterConfiguration', '|', 'select Description, IPAddress', '|', 'fl'], stdout = sp.PIPE, universal_newlines = True) + stdout, stdin = ps.communicate() + selected=False + for i in stdout.split('\n'): + if not i.strip(): + continue + if i.find(':')<0: + continue + name, value = [ j.strip() for j in i.split(':',1) ] + if name=="Description" and value.strip()==ifname.strip(): + selected=True + elif selected: + if v6: + return value.split(",",1)[1].strip('{}').strip() + else: + return value.split(",",1)[0].strip('{}').strip() + class NetworkInterface(object): """A network interface of your local host""" - def __init__(self, dnetdict=None): + def __init__(self, data=None): self.name = None self.ip = None self.mac = None self.pcap_name = None - self.win_name = None - self.uuid = None - self.dnetdict = dnetdict - if dnetdict is not None: - self.update(dnetdict) + self.description = None + self.data = data + if data is not None: + self.update(data) - def update(self, dnetdict): + def update(self, data): """Update info about network interface according to given dnet dictionary""" - self.name = dnetdict["name"] + self.name = data["name"] + self.description = data['description'] + self.win_index = data['win_index'] # Other attributes are optional + self._update_pcapdata() + try: - self.ip = socket.inet_ntoa(dnetdict["addr"].ip) + self.ip = socket.inet_ntoa(get_if_raw_addr(data['guid'])) except (KeyError, AttributeError, NameError): pass + try: - self.mac = dnetdict["link_addr"] + if not self.ip: + self.ip=get_ip_from_name(data['name']) + except (KeyError, AttributeError, NameError) as e: + print e + try: + self.mac = data['mac'] except KeyError: pass - self._update_pcapdata() - + def _update_pcapdata(self): - """Supplement more info from pypcap and the Windows registry""" - - # XXX: We try eth0 - eth29 by bruteforce and match by IP address, - # because only the IP is available in both pypcap and dnet. - # This may not work with unorthodox network configurations and is - # slow because we have to walk through the Windows registry. - for n in xrange(30): - guess = "eth%s" % n - win_name = pcapdnet.pcap.ex_name(guess) - if win_name.endswith("}"): - try: - uuid = win_name[win_name.index("{"):win_name.index("}")+1] - keyname = r"SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\Interfaces\%s" % uuid - try: - key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, keyname) - except WindowsError: - log_loading.debug("Couldn't open 'HKEY_LOCAL_MACHINE\\%s' (for guessed pcap iface name '%s')." % (keyname, guess)) - continue - try: - fixed_ip = _winreg.QueryValueEx(key, "IPAddress")[0][0].encode("utf-8") - except (WindowsError, UnicodeDecodeError, IndexError): - fixed_ip = None - try: - dhcp_ip = _winreg.QueryValueEx(key, "DhcpIPAddress")[0].encode("utf-8") - except (WindowsError, UnicodeDecodeError, IndexError): - dhcp_ip = None - # "0.0.0.0" or None means the value is not set (at least not correctly). - # If both fixed_ip and dhcp_ip are set, fixed_ip takes precedence - if fixed_ip is not None and fixed_ip != "0.0.0.0": - ip = fixed_ip - elif dhcp_ip is not None and dhcp_ip != "0.0.0.0": - ip = dhcp_ip - else: - continue - except IOError: - continue - else: - if ip == self.ip: - self.pcap_name = guess - self.win_name = win_name - self.uuid = uuid - break - else: - raise PcapNameNotFoundError - + for i in winpcapy_get_if_list(): + if i.endswith(self.data['guid']): + self.pcap_name = i + return + + raise PcapNameNotFoundError + def __repr__(self): - return "<%s: %s %s %s pcap_name=%s win_name=%s>" % (self.__class__.__name__, - self.name, self.ip, self.mac, self.pcap_name, self.win_name) + return "<%s: %s %s %s pcap_name=%s description=%s>" % (self.__class__.__name__, + self.name, self.ip, self.mac, repr(self.pcap_name), repr(self.description)) -from UserDict import IterableUserDict +from UserDict import UserDict -class NetworkInterfaceDict(IterableUserDict): +class NetworkInterfaceDict(UserDict): """Store information about network interfaces and convert between names""" - - def load_from_dnet(self): - """Populate interface table via dnet""" - for i in pcapdnet.dnet.intf(): + def load_from_powershell(self): + for i in get_windows_if_list(): try: - # XXX: Only Ethernet for the moment: localhost is not supported by dnet and pcap - # We only take interfaces that have an IP address, because the IP - # is used for the mapping between dnet and pcap interface names - # and this significantly improves Scapy's startup performance - if i["name"].startswith("eth") and "addr" in i: - self.data[i["name"]] = NetworkInterface(i) + interface = NetworkInterface(i) + self.data[interface.name] = interface except (KeyError, PcapNameNotFoundError): pass + if len(self.data) == 0: - log_loading.warning("No match between your pcap and dnet network interfaces found. " + 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.") + "Deactivating unneeded interfaces and restarting Scapy might help." + "Check your winpcap and powershell installation, and access rights.") def pcap_name(self, devname): - """Return pypcap device name for given libdnet/Scapy device name - - This mapping is necessary because pypcap numbers the devices differently.""" - + """Return pcap device name for given Windows device name.""" + try: pcap_name = self.data[devname].pcap_name except KeyError: @@ -191,30 +222,37 @@ class NetworkInterfaceDict(IterableUserDict): return pcap_name def devname(self, pcap_name): - """Return libdnet/Scapy device name for given pypcap device name - - This mapping is necessary because pypcap numbers the devices differently.""" + """Return Windows device name for given pcap device name.""" for devname, iface in self.items(): if iface.pcap_name == pcap_name: return iface.name raise ValueError("Unknown pypcap network interface %r" % pcap_name) + def devname_from_index(self, if_index): + """Return interface name from interface index""" + for devname, iface in self.items(): + if iface.win_index == if_index: + return iface.name + raise ValueError("Unknown network interface index %r" % if_index) + def show(self, resolve_mac=True): """Print list of available network interfaces in human readable form""" - print "%s %s %s" % ("IFACE".ljust(5), "IP".ljust(15), "MAC") + print "%s %s %s %s" % ("INDEX".ljust(5), "IFACE".ljust(35), "IP".ljust(15), "MAC") for iface_name in sorted(self.data.keys()): dev = self.data[iface_name] - mac = str(dev.mac) + mac = dev.mac if resolve_mac: mac = conf.manufdb._resolve_MAC(mac) - print "%s %s %s" % (str(dev.name).ljust(5), str(dev.ip).ljust(15), mac) + print "%s %s %s %s" % (str(dev.win_index).ljust(5), str(dev.name).ljust(35), str(dev.ip).ljust(15), mac) ifaces = NetworkInterfaceDict() -ifaces.load_from_dnet() +ifaces.load_from_powershell() def pcap_name(devname): """Return pypcap device name for given libdnet/Scapy device name""" + if type(devname) is NetworkInterface: + return devname.pcap_name try: pcap_name = ifaces.pcap_name(devname) except ValueError: @@ -225,6 +263,10 @@ def pcap_name(devname): def devname(pcap_name): """Return libdnet/Scapy device name for given pypcap device name""" return ifaces.devname(pcap_name) + +def devname_from_index(if_index): + """Return Windows adapter name for given Windows interface index""" + return ifaces.devname_from_index(if_index) def show_interfaces(resolve_mac=True): """Print list of available network interfaces""" @@ -233,99 +275,102 @@ def show_interfaces(resolve_mac=True): _orig_open_pcap = pcapdnet.open_pcap pcapdnet.open_pcap = lambda iface,*args,**kargs: _orig_open_pcap(pcap_name(iface),*args,**kargs) +_orig_get_if_raw_hwaddr = pcapdnet.get_if_raw_hwaddr +pcapdnet.get_if_raw_hwaddr = lambda iface,*args,**kargs: (ARPHDR_ETHER,''.join([ chr(int(i, 16)) for i in ifaces[iface].mac.split(':') ])) +get_if_raw_hwaddr = pcapdnet.get_if_raw_hwaddr + + +def read_routes_7(): + routes=[] + ps = sp.Popen(['powershell', 'Get-WmiObject', 'win32_IP4RouteTable', '|', 'select Name,Mask,NextHop,InterfaceIndex', '|', 'fl'], stdout = sp.PIPE, universal_newlines = True) + stdout, stdin = ps.communicate() + dest=None + mask=None + gw=None + ifIndex=None + for i in stdout.split('\n'): + if not i.strip(): + continue + if i.find(':')<0: + continue + name, value = [ j.strip().lower() for j in i.split(':',1) ] + if name=="name": + dest=atol(value) + elif name=="mask": + mask=atol(value) + elif name=="nexthop": + gw=value + elif name=="interfaceindex": + ifIndex=value + try: + iface = devname_from_index(int(ifIndex)) + except ValueError: + continue + addr = ifaces[iface].ip + routes.append((dest, mask, gw, iface, addr)) + return routes + def read_routes(): - ok = 0 + routes=[] + try: + if platform.release()=="post2008Server" or platform.release()=="8": + routes=read_routes_post2008() + else: + routes=read_routes_7() + except Exception as e: + log_loading.warning("Error building scapy routing table : %s"%str(e)) + else: + if not routes: + log_loading.warning("No default IPv4 routes found. Your Windows release may no be supported and you have to enter your routes manually") + return routes + +def read_routes_post2008(): routes = [] - ip = '(\d+\.\d+\.\d+\.\d+)' - # On Vista and Windows 7 the gateway can be IP or 'On-link'. - # But the exact 'On-link' string depends on the locale, so we allow any text. - gw_pattern = '(.+)' + if_index = '(\d+)' + dest = '(\d+\.\d+\.\d+\.\d+)/(\d+)' + next_hop = '(\d+\.\d+\.\d+\.\d+)' metric_pattern = "(\d+)" delim = "\s+" # The columns are separated by whitespace - netstat_line = delim.join([ip, ip, gw_pattern, ip, metric_pattern]) + netstat_line = delim.join([if_index, dest, next_hop, metric_pattern]) pattern = re.compile(netstat_line) - f=os.popen("netstat -rn") - for l in f.readlines(): + # This works only starting from Windows 8/2012 and up. For older Windows another solution is needed + ps = sp.Popen(['powershell', 'Get-NetRoute', '-AddressFamily IPV4', '|', 'select ifIndex, DestinationPrefix, NextHop, RouteMetric'], stdout = sp.PIPE, universal_newlines = True) + stdout, stdin = ps.communicate() + for l in stdout.split('\n'): match = re.search(pattern,l) if match: - dest = match.group(1) - mask = match.group(2) - gw = match.group(3) - netif = match.group(4) - metric = match.group(5) try: - intf = pcapdnet.dnet.intf().get_dst(pcapdnet.dnet.addr(type=2, addrtxt=dest)) - except OSError: - log_loading.warning("Building Scapy's routing table: Couldn't get outgoing interface for destination %s" % dest) - continue - if not intf.has_key("addr"): - break - addr = str(intf["addr"]) - addr = addr.split("/")[0] - - dest = atol(dest) - mask = atol(mask) - # If the gateway is no IP we assume it's on-link - gw_ipmatch = re.search('\d+\.\d+\.\d+\.\d+', gw) - if gw_ipmatch: - gw = gw_ipmatch.group(0) - else: - gw = netif - routes.append((dest,mask,gw, str(intf["name"]), addr)) - f.close() + iface = devname_from_index(int(match.group(1))) + addr = ifaces[iface].ip + except: + continue + dest = atol(match.group(2)) + mask = itom(int(match.group(3))) + gw = match.group(4) + # try: + # intf = pcapdnet.dnet.intf().get_dst(pcapdnet.dnet.addr(type=2, addrtxt=dest)) + # except OSError: + # log_loading.warning("Building Scapy's routing table: Couldn't get outgoing interface for destination %s" % dest) + # continue + routes.append((dest, mask, gw, iface, addr)) return routes def read_routes6(): return [] -def getmacbyip(ip, chainCC=0): - """Return MAC address corresponding to a given IP address""" - if isinstance(ip,Net): - ip = iter(ip).next() - tmp = map(ord, inet_aton(ip)) - if (tmp[0] & 0xf0) == 0xe0: # mcast @ - return "01:00:5e:%.2x:%.2x:%.2x" % (tmp[1]&0x7f,tmp[2],tmp[3]) - iff,a,gw = conf.route.route(ip) - if ( (iff == LOOPBACK_NAME) or (ip == conf.route.get_if_bcast(iff)) ): - return "ff:ff:ff:ff:ff:ff" - # Windows uses local IP instead of 0.0.0.0 to represent locally reachable addresses - ifip = str(pcapdnet.dnet.intf().get(iff)['addr']) - if gw != ifip.split('/')[0]: - ip = gw - - mac = conf.netcache.arp_cache.get(ip) - if mac: - return mac - - res = srp1(Ether(dst=ETHER_BROADCAST)/ARP(op="who-has", pdst=ip), - type=ETH_P_ARP, - iface = iff, - timeout=2, - verbose=0, - chainCC=chainCC, - nofilter=1) - if res is not None: - mac = res.payload.hwsrc - conf.netcache.arp_cache[ip] = mac - return mac - return None - -import scapy.layers.l2 -scapy.layers.l2.getmacbyip = getmacbyip - -try: - import readline - console = readline.GetOutputFile() -except (ImportError, AttributeError): - log_loading.info("Could not get readline console. Will not interpret ANSI color codes.") -else: - conf.readfunc = readline.rl.readline - orig_stdout = sys.stdout - sys.stdout = console - - - - +if conf.interactive_shell != 'ipython': + try: + __IPYTHON__ + except NameError: + try: + import readline + console = readline.GetOutputFile() + except (ImportError, AttributeError): + log_loading.info("Could not get readline console. Will not interpret ANSI color codes.") + else: + conf.readfunc = readline.rl.readline + orig_stdout = sys.stdout + sys.stdout = console def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, multi=0): if not isinstance(pkt, Gen): @@ -395,7 +440,6 @@ def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, m else: stoptime = 0 remaintime = None - inmask = [pks.ins.fd] try: try: while 1: @@ -442,9 +486,9 @@ def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, m finally: pass - remain = reduce(list.__add__, hsent.values(), []) + remain = list(itertools.chain(*[ i for i in hsent.values() ])) if multi: - remain = filter(lambda p: not hasattr(p, '_answered'), remain); + remain = [ p for p in remain if not hasattr(p, '_answered')] if autostop and len(remain) > 0 and len(remain) != len(tobesent): retry = autostop @@ -475,7 +519,7 @@ scapy.sendrecv.sndrcv = sndrcv def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=None, timeout=None, *arg, **karg): """Sniff packets sniff([count=0,] [prn=None,] [store=1,] [offline=None,] [lfilter=None,] + L2ListenSocket args) -> list of packets - +Select interface to sniff by setting conf.iface. Use show_interfaces() to see interface names. count: number of packets to capture. 0 means infinity store: wether to store sniffed packets or discard them prn: function to apply to each packet. If something is returned, @@ -491,6 +535,7 @@ L2socket: use the provided L2socket c = 0 if offline is None: + log_runtime.info('Sniffing on %s' % conf.iface) if L2socket is None: L2socket = conf.L2listen s = L2socket(type=ETH_P_ALL, *arg, **karg) @@ -533,11 +578,17 @@ L2socket: use the provided L2socket import scapy.sendrecv scapy.sendrecv.sniff = sniff -def get_if_list(): - return sorted(ifaces.keys()) - def get_working_if(): try: - return devname(pcap.lookupdev()) - except Exception: - return 'lo0' + if 'Ethernet' in ifaces and ifaces['Ethernet'].ip != '0.0.0.0': + return 'Ethernet' + elif 'Wi-Fi' in ifaces and ifaces['Wi-Fi'].ip != '0.0.0.0': + return 'Wi-Fi' + elif len(ifaces) > 0: + return ifaces[list(ifaces.keys())[0]] + else: + return LOOPBACK_NAME + except: + return LOOPBACK_NAME + +conf.iface = get_working_if() diff --git a/scapy/config.py b/scapy/config.py old mode 100644 new mode 100755 index 14d024abfebea7e61a528e826381bd116bd2b847..39d476b69f5ee09336e82ce0083ee4ce04cd8740 --- a/scapy/config.py +++ b/scapy/config.py @@ -360,6 +360,7 @@ extensions_paths: path or list of paths where extensions are to be looked for emph = Emphasize() use_pcap = False use_dnet = False + use_winpcapy = False ipv6_enabled = socket.has_ipv6 ethertypes = ETHER_TYPES protocols = IP_PROTOS