diff --git a/scapy/arch/pcapdnet.py b/scapy/arch/pcapdnet.py old mode 100644 new mode 100755 index 94673d7d284..c3333b0f28e --- a/scapy/arch/pcapdnet.py +++ b/scapy/arch/pcapdnet.py @@ -16,9 +16,307 @@ 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 4fbed76cb80..c4860da46e8 100755 --- a/scapy/arch/windows/__init__.py +++ b/scapy/arch/windows/__init__.py @@ -7,25 +7,129 @@ Customizations needed to support Microsoft Windows. """ -import os,re,sys,socket,time +from __future__ import with_statement +import os,re,sys,socket,time, itertools +import subprocess as sp from glob import glob +import tempfile + 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 * LOOPBACK_NAME="lo0" WINDOWS = True +def _exec_query_ps(cmd, fields): + """Execute a PowerShell query""" + ps = sp.Popen([conf.prog.powershell] + cmd + + ['|', 'select %s' % ', '.join(fields), '|', 'fl'], + stdout=sp.PIPE, + universal_newlines=True) + l=[] + for line in ps.stdout: + if not line.strip(): #skip empty lines + continue + l.append(line.split(':', 1)[1].strip()) + if len(l) == len(fields): + yield l + l=[] + +def _vbs_exec_code(code): + tmpfile = tempfile.NamedTemporaryFile(suffix=".vbs", delete=False) + tmpfile.write(code) + tmpfile.close() + ps = sp.Popen([conf.prog.cscript, tmpfile.name], + stdout=sp.PIPE, stderr=open(os.devnull), + universal_newlines=True) + for _ in xrange(3): + # skip 3 first lines + ps.stdout.readline() + for line in ps.stdout: + yield line + os.unlink(tmpfile.name) + +def _vbs_get_iface_guid(devid): + 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") +""" % devid).__iter__().next() + if guid.startswith('{') and guid.endswith('}\n'): + return guid[:-1] + except StopIteration: + pass + +# Some names differ between VBS and PS +## None: field will not be returned under VBS +_VBS_WMI_FIELDS = { + "Win32_NetworkAdapter": { + "InterfaceIndex": "Index", + "InterfaceDescription": "Description", + "GUID": "DeviceID", + } +} + +_VBS_WMI_OUTPUT = { + "Win32_NetworkAdapter": { + "DeviceID": _vbs_get_iface_guid, + } +} + +def _exec_query_vbs(cmd, fields): + """Execute a query using VBS. Currently Get-WmiObject queries are + supported. + + """ + 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:") +Set lines = wmi.InstancesOf("%s") +On Error Resume Next +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__() + while True: + yield [None if fld is None else + _VBS_WMI_OUTPUT.get(cmd[1], {}).get(fld, lambda x: x)( + values.next().strip() + ) + for fld in fields] + +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) + return _exec_query_ps(cmd, fields) + def _where(filename, dirs=[], env="PATH"): """Find file in current dir or system path""" @@ -66,266 +170,289 @@ class WinProgPath(ConfClass): display = _default hexedit = win_find_exe("hexer") wireshark = win_find_exe("wireshark", "wireshark") + powershell = win_find_exe( + "powershell", + installsubdir="System32\\WindowsPowerShell\\v1.0", + env="SystemRoot" + ) + cscript = win_find_exe("cscript", installsubdir="System32", + env="SystemRoot") conf.prog = WinProgPath() +if conf.prog.powershell == "powershell": + conf.prog.powershell = None - - -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 + query = exec_query(['Get-NetAdapter'], + ['Name', 'InterfaceIndex', 'InterfaceDescription', + 'InterfaceGuid', 'MacAddress']) + else: + query = exec_query(['Get-WmiObject', 'Win32_NetworkAdapter'], + ['Name', 'InterfaceIndex', 'InterfaceDescription', + 'GUID', 'MacAddress']) + return [ + iface for iface in + (dict(zip(['name', 'win_index', 'description', 'guid', 'mac'], line)) + for line in query) + if is_interface_valid(iface) + ] + +def get_ip_from_name(ifname, v6=False): + for descr, ipadrr in exec_query(['Get-WmiObject', + 'Win32_NetworkAdapterConfiguration'], + ['Description', 'IPAddress']): + if descr == ifname.strip(): + return ipaddr.split(",", 1)[v6].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) - - def update(self, dnetdict): + self.description = None + self.data = data + if data is not None: + self.update(data) + + 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'] + self.guid = data['guid'] # 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>" % (self.__class__.__name__, self.name, self.guid) -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.guid] = 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.") - - 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.""" - - try: - pcap_name = self.data[devname].pcap_name - except KeyError: - raise ValueError("Unknown network interface %r" % devname) - else: - 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.""" - - for devname, iface in self.items(): + "Deactivating unneeded interfaces and restarting Scapy might help." + "Check your winpcap and powershell installation, and access rights.") + + def dev_from_name(self, name): + """Return the first pcap device name for a given Windows + device name. + + """ + for iface in self.itervalues(): + if iface.name == name: + return iface + raise ValueError("Unknown network interface %r" % name) + + def dev_from_pcapname(self, pcap_name): + """Return Windows device name for given pcap device name.""" + for iface in self.itervalues(): if iface.pcap_name == pcap_name: - return iface.name + return iface raise ValueError("Unknown pypcap network interface %r" % pcap_name) - + + def dev_from_index(self, if_index): + """Return interface name from interface index""" + for devname, iface in self.items(): + if iface.win_index == str(if_index): + return iface + 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 = NetworkInterfaceDict() +IFACES.load_from_powershell() + +def pcapname(dev): + """Return pypcap device name for given interface or libdnet/Scapy + device name. -def pcap_name(devname): - """Return pypcap device name for given libdnet/Scapy device name""" + """ + if type(dev) is NetworkInterface: + return dev.pcap_name try: - pcap_name = ifaces.pcap_name(devname) + return IFACES.dev_from_name(dev).pcap_name except ValueError: - # pcap.pcap() will choose a sensible default for sniffing if iface=None - pcap_name = None - return pcap_name + # pcap.pcap() will choose a sensible default for sniffing if + # iface=None + return None -def devname(pcap_name): +def dev_from_pcapname(pcap_name): """Return libdnet/Scapy device name for given pypcap device name""" - return ifaces.devname(pcap_name) + return IFACES.dev_from_pcapname(pcap_name) + +def dev_from_index(if_index): + """Return Windows adapter name for given Windows interface index""" + return IFACES.dev_from_index(if_index) def show_interfaces(resolve_mac=True): """Print list of available network interfaces""" - return ifaces.show(resolve_mac) + return IFACES.show(resolve_mac) _orig_open_pcap = pcapdnet.open_pcap -pcapdnet.open_pcap = lambda iface,*args,**kargs: _orig_open_pcap(pcap_name(iface),*args,**kargs) +pcapdnet.open_pcap = lambda iface,*args,**kargs: _orig_open_pcap(pcapname(iface),*args,**kargs) + +_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') +) +get_if_raw_hwaddr = pcapdnet.get_if_raw_hwaddr + +def read_routes_xp(): + # The InterfaceIndex in Win32_IP4RouteTable does not match the + # InterfaceIndex in Win32_NetworkAdapter under some platforms + # (namely Windows XP): let's try an IP association + routes = [] + partial_routes = [] + # map local IP addresses to interfaces + local_addresses = dict((iface.ip, iface) + for iface in IFACES.itervalues()) + iface_indexes = {} + for line in exec_query(['Get-WmiObject', 'Win32_IP4RouteTable'], + ['Name', 'Mask', 'NextHop', 'InterfaceIndex']): + if line[2] in local_addresses: + iface = local_addresses[line[2]] + # This gives us an association InterfaceIndex <-> interface + iface_indexes[line[3]] = iface + routes.append((atol(line[0]), atol(line[1]), "0.0.0.0", iface, + iface.ip)) + else: + partial_routes.append((atol(line[0]), atol(line[1]), line[2], + line[3])) + for dst, mask, gw, ifidx in partial_routes: + if ifidx in iface_indexes: + iface = iface_indexes[ifidx] + routes.append((dst, mask, gw, iface, iface.ip)) + return routes + +def read_routes_7(): + routes=[] + for line in exec_query(['Get-WmiObject', 'win32_IP4RouteTable'], + ['Name', 'Mask', 'NextHop', 'InterfaceIndex']): + try: + iface = dev_from_index(line[3]) + except ValueError: + continue + routes.append((atol(line[0]), atol(line[1]), line[2], iface, iface.ip)) + return routes def read_routes(): - ok = 0 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 = '(.+)' + release = platform.release() + try: + if release in ["post2008Server", "8"]: + routes = read_routes_post2008() + elif release == "XP": + routes = read_routes_xp() + 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(): + # XXX TODO: FIX THIS XXX + routes = [] + 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([conf.prog.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 = dev_from_index(match.group(1)) + except: + continue + # 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((atol(match.group(2)), itom(int(match.group(3))), + match.group(4), iface, iface.ip)) 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 +522,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 +568,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 +601,7 @@ def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, m 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 +617,7 @@ def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=Non 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 +660,13 @@ def sniff(count=0, store=1, offline=None, prn = None, lfilter=None, L2socket=Non 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' + # return the interface associated with the route with smallest + # mask (route by default if it exists) + return min(read_routes(), key=lambda x: x[1])[3] + except ValueError: + # no route + return LOOPBACK_NAME + +conf.iface = get_working_if() diff --git a/scapy/arch/winpcapy.py b/scapy/arch/winpcapy.py new file mode 100755 index 00000000000..fc452a02cea --- /dev/null +++ b/scapy/arch/winpcapy.py @@ -0,0 +1,739 @@ +#------------------------------------------------------------------------------- +# Name: winpcapy.py +# +# Author: Massimo Ciani +# +# Created: 01/09/2009 +# Copyright: (c) Massimo Ciani 2009 +# +#------------------------------------------------------------------------------- + + +from ctypes import * +from ctypes.util import find_library +import sys + +WIN32=False +HAVE_REMOTE=False + + +if sys.platform.startswith('win'): + WIN32=True + HAVE_REMOTE=True + +if WIN32: + SOCKET = c_uint + _lib=CDLL('wpcap.dll') +else: + SOCKET = c_int + _lib_name = find_library('pcap') + if not _lib_name: + raise OSError("Cannot fine libpcap.so library") + _lib=CDLL(_lib_name) + + + +## +## misc +## +u_short = c_ushort +bpf_int32 = c_int +u_int = c_int +bpf_u_int32 = u_int +pcap = c_void_p +pcap_dumper = c_void_p +u_char = c_ubyte +FILE = c_void_p +STRING = c_char_p + +class bpf_insn(Structure): + _fields_=[("code",c_ushort), + ("jt",c_ubyte), + ("jf",c_ubyte), + ("k",bpf_u_int32)] + +class bpf_program(Structure): + pass +bpf_program._fields_ = [('bf_len', u_int), + ('bf_insns', POINTER(bpf_insn))] + +class bpf_version(Structure): + _fields_=[("bv_major",c_ushort), + ("bv_minor",c_ushort)] + + +class timeval(Structure): + pass +timeval._fields_ = [('tv_sec', c_long), + ('tv_usec', c_long)] + +## sockaddr is used by pcap_addr. +## For exapmle if sa_family==socket.AF_INET then we need cast +## with sockaddr_in +if WIN32: + class sockaddr(Structure): + _fields_ = [("sa_family", c_ushort), + ("sa_data",c_ubyte * 14)] + + class sockaddr_in(Structure): + _fields_ = [("sin_family", c_ushort), + ("sin_port", c_uint16), + ("sin_addr", 4 * c_ubyte)] + + class sockaddr_in6(Structure): + _fields_ = [("sin6_family", c_ushort), + ("sin6_port", c_uint16), + ("sin6_flowinfo", c_uint32), + ("sin6_addr", 16 * c_ubyte), + ("sin6_scope", c_uint32)] +else: + class sockaddr(Structure): + _fields_ = [("sa_len", c_ubyte), + ("sa_family",c_ubyte), + ("sa_data",c_ubyte * 14)] + + class sockaddr_in(Structure): + _fields_ = [("sin_len", c_ubyte), + ("sin_family", c_ubyte), + ("sin_port", c_uint16), + ("sin_addr", 4 * c_ubyte), + ("sin_zero", 8 * c_char)] + + class sockaddr_in6(Structure): + _fields_ = [("sin6_len", c_ubyte), + ("sin6_family", c_ubyte), + ("sin6_port", c_uint16), + ("sin6_flowinfo", c_uint32), + ("sin6_addr", 16 * c_ubyte), + ("sin6_scope", c_uint32)] + + class sockaddr_dl(Structure): + _fields_ = [("sdl_len", c_ubyte), + ("sdl_family", c_ubyte), + ("sdl_index", c_ushort), + ("sdl_type", c_ubyte), + ("sdl_nlen", c_ubyte), + ("sdl_alen", c_ubyte), + ("sdl_slen", c_ubyte), + ("sdl_data", 46 * c_ubyte)] +## +## END misc +## + +## +## Data Structures +## + +## struct pcap_file_header +## Header of a libpcap dump file. +class pcap_file_header(Structure): + _fields_ = [('magic', bpf_u_int32), + ('version_major', u_short), + ('version_minor', u_short), + ('thiszone', bpf_int32), + ('sigfigs', bpf_u_int32), + ('snaplen', bpf_u_int32), + ('linktype', bpf_u_int32)] + +## struct pcap_pkthdr +## Header of a packet in the dump file. +class pcap_pkthdr(Structure): + _fields_ = [('ts', timeval), + ('caplen', bpf_u_int32), + ('len', bpf_u_int32)] + +## struct pcap_stat +## Structure that keeps statistical values on an interface. +class pcap_stat(Structure): + pass +### _fields_ list in Structure is final. +### We need a temp list +_tmpList=[] +_tmpList.append(("ps_recv",c_uint)) +_tmpList.append(("ps_drop",c_uint)) +_tmpList.append(("ps_ifdrop",c_uint)) +if HAVE_REMOTE: + _tmpList.append(("ps_capt",c_uint)) + _tmpList.append(("ps_sent",c_uint)) + _tmpList.append(("ps_netdrop",c_uint)) +pcap_stat._fields_=_tmpList + +## struct pcap_addr +## Representation of an interface address, used by pcap_findalldevs(). +class pcap_addr(Structure): + pass +pcap_addr._fields_ = [('next', POINTER(pcap_addr)), + ('addr', POINTER(sockaddr)), + ('netmask', POINTER(sockaddr)), + ('broadaddr', POINTER(sockaddr)), + ('dstaddr', POINTER(sockaddr))] + +## struct pcap_if +## Item in a list of interfaces, used by pcap_findalldevs(). +class pcap_if(Structure): + pass +pcap_if._fields_ = [('next', POINTER(pcap_if)), + ('name', STRING), + ('description', STRING), + ('addresses', POINTER(pcap_addr)), + ('flags', bpf_u_int32)] + +## +## END Data Structures +## + +## +## Defines +## + +##define PCAP_VERSION_MAJOR 2 +# Major libpcap dump file version. +PCAP_VERSION_MAJOR = 2 +##define PCAP_VERSION_MINOR 4 +# Minor libpcap dump file version. +PCAP_VERSION_MINOR = 4 +##define PCAP_ERRBUF_SIZE 256 +# Size to use when allocating the buffer that contains the libpcap errors. +PCAP_ERRBUF_SIZE = 256 +##define PCAP_IF_LOOPBACK 0x00000001 +# interface is loopback +PCAP_IF_LOOPBACK = 1 +##define MODE_CAPT 0 +# Capture mode, to be used when calling pcap_setmode(). +MODE_CAPT = 0 +##define MODE_STAT 1 +# Statistical mode, to be used when calling pcap_setmode(). +MODE_STAT = 1 + +## +## END Defines +## + +## +## Typedefs +## + +#typedef int bpf_int32 (already defined) +# 32-bit integer +#typedef u_int bpf_u_int32 (already defined) +# 32-bit unsigned integer +#typedef struct pcap pcap_t +# Descriptor of an open capture instance. This structure is opaque to the user, that handles its content through the functions provided by wpcap.dll. +pcap_t = pcap +#typedef struct pcap_dumper pcap_dumper_t +# libpcap savefile descriptor. +pcap_dumper_t = pcap_dumper +#typedef struct pcap_if pcap_if_t +# Item in a list of interfaces, see pcap_if. +pcap_if_t = pcap_if +#typedef struct pcap_addr pcap_addr_t +# Representation of an interface address, see pcap_addr. +pcap_addr_t = pcap_addr + +## +## END Typedefs +## + + + + + +# values for enumeration 'pcap_direction_t' +#pcap_direction_t = c_int # enum + +## +## Unix-compatible Functions +## These functions are part of the libpcap library, and therefore work both on Windows and on Linux. +## + +#typedef void(* pcap_handler )(u_char *user, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data) +# Prototype of the callback function that receives the packets. +## This one is defined from programmer +pcap_handler=CFUNCTYPE(None,POINTER(c_ubyte),POINTER(pcap_pkthdr),POINTER(c_ubyte)) + +#pcap_t * pcap_open_live (const char *device, int snaplen, int promisc, int to_ms, char *ebuf) +# Open a live capture from the network. +pcap_open_live = _lib.pcap_open_live +pcap_open_live.restype = POINTER(pcap_t) +pcap_open_live.argtypes = [STRING, c_int, c_int, c_int, STRING] + +#pcap_t * pcap_open_dead (int linktype, int snaplen) +# Create a pcap_t structure without starting a capture. +pcap_open_dead = _lib.pcap_open_dead +pcap_open_dead.restype = POINTER(pcap_t) +pcap_open_dead.argtypes = [c_int, c_int] + +#pcap_t * pcap_open_offline (const char *fname, char *errbuf) +# Open a savefile in the tcpdump/libpcap format to read packets. +pcap_open_offline = _lib.pcap_open_offline +pcap_open_offline.restype = POINTER(pcap_t) +pcap_open_offline.argtypes = [STRING, STRING] + +#pcap_dumper_t * pcap_dump_open (pcap_t *p, const char *fname) +# Open a file to write packets. +pcap_dump_open = _lib.pcap_dump_open +pcap_dump_open.restype = POINTER(pcap_dumper_t) +pcap_dump_open.argtypes = [POINTER(pcap_t), STRING] + +#int pcap_setnonblock (pcap_t *p, int nonblock, char *errbuf) +# Switch between blocking and nonblocking mode. +pcap_setnonblock = _lib.pcap_setnonblock +pcap_setnonblock.restype = c_int +pcap_setnonblock.argtypes = [POINTER(pcap_t), c_int, STRING] + +#int pcap_getnonblock (pcap_t *p, char *errbuf) +# Get the "non-blocking" state of an interface. +pcap_getnonblock = _lib.pcap_getnonblock +pcap_getnonblock.restype = c_int +pcap_getnonblock.argtypes = [POINTER(pcap_t), STRING] + +#int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf) +# Construct a list of network devices that can be opened with pcap_open_live(). +pcap_findalldevs = _lib.pcap_findalldevs +pcap_findalldevs.restype = c_int +pcap_findalldevs.argtypes = [POINTER(POINTER(pcap_if_t)), STRING] + +#void pcap_freealldevs (pcap_if_t *alldevsp) +# Free an interface list returned by pcap_findalldevs(). +pcap_freealldevs = _lib.pcap_freealldevs +pcap_freealldevs.restype = None +pcap_freealldevs.argtypes = [POINTER(pcap_if_t)] + +#char * pcap_lookupdev (char *errbuf) +# Return the first valid device in the system. +pcap_lookupdev = _lib.pcap_lookupdev +pcap_lookupdev.restype = STRING +pcap_lookupdev.argtypes = [STRING] + +#int pcap_lookupnet (const char *device, bpf_u_int32 *netp, bpf_u_int32 *maskp, char *errbuf) +# Return the subnet and netmask of an interface. +pcap_lookupnet = _lib.pcap_lookupnet +pcap_lookupnet.restype = c_int +pcap_lookupnet.argtypes = [STRING, POINTER(bpf_u_int32), POINTER(bpf_u_int32), STRING] + +#int pcap_dispatch (pcap_t *p, int cnt, pcap_handler callback, u_char *user) +# Collect a group of packets. +pcap_dispatch = _lib.pcap_dispatch +pcap_dispatch.restype = c_int +pcap_dispatch.argtypes = [POINTER(pcap_t), c_int, pcap_handler, POINTER(u_char)] + +#int pcap_loop (pcap_t *p, int cnt, pcap_handler callback, u_char *user) +# Collect a group of packets. +pcap_loop = _lib.pcap_loop +pcap_loop.restype = c_int +pcap_loop.argtypes = [POINTER(pcap_t), c_int, pcap_handler, POINTER(u_char)] + +#u_char * pcap_next (pcap_t *p, struct pcap_pkthdr *h) +# Return the next available packet. +pcap_next = _lib.pcap_next +pcap_next.restype = POINTER(u_char) +pcap_next.argtypes = [POINTER(pcap_t), POINTER(pcap_pkthdr)] + +#int pcap_next_ex (pcap_t *p, struct pcap_pkthdr **pkt_header, const u_char **pkt_data) +# Read a packet from an interface or from an offline capture. +pcap_next_ex = _lib.pcap_next_ex +pcap_next_ex.restype = c_int +pcap_next_ex.argtypes = [POINTER(pcap_t), POINTER(POINTER(pcap_pkthdr)), POINTER(POINTER(u_char))] + +#void pcap_breakloop (pcap_t *) +# set a flag that will force pcap_dispatch() or pcap_loop() to return rather than looping. +pcap_breakloop = _lib.pcap_breakloop +pcap_breakloop.restype = None +pcap_breakloop.argtypes = [POINTER(pcap_t)] + +#int pcap_sendpacket (pcap_t *p, u_char *buf, int size) +# Send a raw packet. +pcap_sendpacket = _lib.pcap_sendpacket +pcap_sendpacket.restype = c_int +#pcap_sendpacket.argtypes = [POINTER(pcap_t), POINTER(u_char), c_int] +pcap_sendpacket.argtypes = [POINTER(pcap_t), c_void_p, c_int] + +#void pcap_dump (u_char *user, const struct pcap_pkthdr *h, const u_char *sp) +# Save a packet to disk. +pcap_dump = _lib.pcap_dump +pcap_dump.restype = None +pcap_dump.argtypes = [POINTER(pcap_dumper_t), POINTER(pcap_pkthdr), POINTER(u_char)] + +#long pcap_dump_ftell (pcap_dumper_t *) +# Return the file position for a "savefile". +pcap_dump_ftell = _lib.pcap_dump_ftell +pcap_dump_ftell.restype = c_long +pcap_dump_ftell.argtypes = [POINTER(pcap_dumper_t)] + +#int pcap_compile (pcap_t *p, struct bpf_program *fp, char *str, int optimize, bpf_u_int32 netmask) +# Compile a packet filter, converting an high level filtering expression (see Filtering expression syntax) in a program that can be interpreted by the kernel-level filtering engine. +pcap_compile = _lib.pcap_compile +pcap_compile.restype = c_int +pcap_compile.argtypes = [POINTER(pcap_t), POINTER(bpf_program), STRING, c_int, bpf_u_int32] + +#int pcap_compile_nopcap (int snaplen_arg, int linktype_arg, struct bpf_program *program, char *buf, int optimize, bpf_u_int32 mask) +# Compile a packet filter without the need of opening an adapter. This function converts an high level filtering expression (see Filtering expression syntax) in a program that can be interpreted by the kernel-level filtering engine. +pcap_compile_nopcap = _lib.pcap_compile_nopcap +pcap_compile_nopcap.restype = c_int +pcap_compile_nopcap.argtypes = [c_int, c_int, POINTER(bpf_program), STRING, c_int, bpf_u_int32] + +#int pcap_setfilter (pcap_t *p, struct bpf_program *fp) +# Associate a filter to a capture. +pcap_setfilter = _lib.pcap_setfilter +pcap_setfilter.restype = c_int +pcap_setfilter.argtypes = [POINTER(pcap_t), POINTER(bpf_program)] + +#void pcap_freecode (struct bpf_program *fp) +# Free a filter. +pcap_freecode = _lib.pcap_freecode +pcap_freecode.restype = None +pcap_freecode.argtypes = [POINTER(bpf_program)] + +#int pcap_datalink (pcap_t *p) +# Return the link layer of an adapter. +pcap_datalink = _lib.pcap_datalink +pcap_datalink.restype = c_int +pcap_datalink.argtypes = [POINTER(pcap_t)] + +#int pcap_list_datalinks (pcap_t *p, int **dlt_buf) +# list datalinks +pcap_list_datalinks = _lib.pcap_list_datalinks +pcap_list_datalinks.restype = c_int +#pcap_list_datalinks.argtypes = [POINTER(pcap_t), POINTER(POINTER(c_int))] + +#int pcap_set_datalink (pcap_t *p, int dlt) +# Set the current data link type of the pcap descriptor to the type specified by dlt. -1 is returned on failure. +pcap_set_datalink = _lib.pcap_set_datalink +pcap_set_datalink.restype = c_int +pcap_set_datalink.argtypes = [POINTER(pcap_t), c_int] + +#int pcap_datalink_name_to_val (const char *name) +# Translates a data link type name, which is a DLT_ name with the DLT_ removed, to the corresponding data link type value. The translation is case-insensitive. -1 is returned on failure. +pcap_datalink_name_to_val = _lib.pcap_datalink_name_to_val +pcap_datalink_name_to_val.restype = c_int +pcap_datalink_name_to_val.argtypes = [STRING] + +#const char * pcap_datalink_val_to_name (int dlt) +# Translates a data link type value to the corresponding data link type name. NULL is returned on failure. +pcap_datalink_val_to_name = _lib.pcap_datalink_val_to_name +pcap_datalink_val_to_name.restype = STRING +pcap_datalink_val_to_name.argtypes = [c_int] + +#const char * pcap_datalink_val_to_description (int dlt) +# Translates a data link type value to a short description of that data link type. NULL is returned on failure. +pcap_datalink_val_to_description = _lib.pcap_datalink_val_to_description +pcap_datalink_val_to_description.restype = STRING +pcap_datalink_val_to_description.argtypes = [c_int] + +#int pcap_snapshot (pcap_t *p) +# Return the dimension of the packet portion (in bytes) that is delivered to the application. +pcap_snapshot = _lib.pcap_snapshot +pcap_snapshot.restype = c_int +pcap_snapshot.argtypes = [POINTER(pcap_t)] + +#int pcap_is_swapped (pcap_t *p) +# returns true if the current savefile uses a different byte order than the current system. +pcap_is_swapped = _lib.pcap_is_swapped +pcap_is_swapped.restype = c_int +pcap_is_swapped.argtypes = [POINTER(pcap_t)] + +#int pcap_major_version (pcap_t *p) +# return the major version number of the pcap library used to write the savefile. +pcap_major_version = _lib.pcap_major_version +pcap_major_version.restype = c_int +pcap_major_version.argtypes = [POINTER(pcap_t)] + +#int pcap_minor_version (pcap_t *p) +# return the minor version number of the pcap library used to write the savefile. +pcap_minor_version = _lib.pcap_minor_version +pcap_minor_version.restype = c_int +pcap_minor_version.argtypes = [POINTER(pcap_t)] + +#FILE * pcap_file (pcap_t *p) +# Return the standard stream of an offline capture. +pcap_file=_lib.pcap_file +pcap_file.restype = FILE +pcap_file.argtypes = [POINTER(pcap_t)] + +#int pcap_stats (pcap_t *p, struct pcap_stat *ps) +# Return statistics on current capture. +pcap_stats = _lib.pcap_stats +pcap_stats.restype = c_int +pcap_stats.argtypes = [POINTER(pcap_t), POINTER(pcap_stat)] + +#void pcap_perror (pcap_t *p, char *prefix) +# print the text of the last pcap library error on stderr, prefixed by prefix. +pcap_perror = _lib.pcap_perror +pcap_perror.restype = None +pcap_perror.argtypes = [POINTER(pcap_t), STRING] + +#char * pcap_geterr (pcap_t *p) +# return the error text pertaining to the last pcap library error. +pcap_geterr = _lib.pcap_geterr +pcap_geterr.restype = STRING +pcap_geterr.argtypes = [POINTER(pcap_t)] + +#char * pcap_strerror (int error) +# Provided in case strerror() isn't available. +pcap_strerror = _lib.pcap_strerror +pcap_strerror.restype = STRING +pcap_strerror.argtypes = [c_int] + +#const char * pcap_lib_version (void) +# Returns a pointer to a string giving information about the version of the libpcap library being used; note that it contains more information than just a version number. +pcap_lib_version = _lib.pcap_lib_version +pcap_lib_version.restype = STRING +pcap_lib_version.argtypes = [] + +#void pcap_close (pcap_t *p) +# close the files associated with p and deallocates resources. +pcap_close = _lib.pcap_close +pcap_close.restype = None +pcap_close.argtypes = [POINTER(pcap_t)] + +#FILE * pcap_dump_file (pcap_dumper_t *p) +# return the standard I/O stream of the 'savefile' opened by pcap_dump_open(). +pcap_dump_file=_lib.pcap_dump_file +pcap_dump_file.restype=FILE +pcap_dump_file.argtypes= [POINTER(pcap_dumper_t)] + +#int pcap_dump_flush (pcap_dumper_t *p) +# Flushes the output buffer to the ``savefile,'' so that any packets written with pcap_dump() but not yet written to the ``savefile'' will be written. -1 is returned on error, 0 on success. +pcap_dump_flush = _lib.pcap_dump_flush +pcap_dump_flush.restype = c_int +pcap_dump_flush.argtypes = [POINTER(pcap_dumper_t)] + +#void pcap_dump_close (pcap_dumper_t *p) +# Closes a savefile. +pcap_dump_close = _lib.pcap_dump_close +pcap_dump_close.restype = None +pcap_dump_close.argtypes = [POINTER(pcap_dumper_t)] + +if not WIN32: + + pcap_get_selectable_fd = _lib.pcap_get_selectable_fd + pcap_get_selectable_fd.restype = c_int + pcap_get_selectable_fd.argtypes = [POINTER(pcap_t)] + +########################################### +## Windows-specific Extensions +## The functions in this section extend libpcap to offer advanced functionalities +## (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: + HANDLE = c_void_p + + ############## + ## Identifiers related to the new source syntax + ############## + #define PCAP_SRC_FILE 2 + #define PCAP_SRC_IFLOCAL 3 + #define PCAP_SRC_IFREMOTE 4 + #Internal representation of the type of source in use (file, remote/local interface). + PCAP_SRC_FILE = 2 + PCAP_SRC_IFLOCAL = 3 + PCAP_SRC_IFREMOTE = 4 + + ############## + ## Strings related to the new source syntax + ############## + #define PCAP_SRC_FILE_STRING "file://" + #define PCAP_SRC_IF_STRING "rpcap://" + #String that will be used to determine the type of source in use (file, remote/local interface). + PCAP_SRC_FILE_STRING="file://" + PCAP_SRC_IF_STRING="rpcap://" + + ############## + ## Flags defined in the pcap_open() function + ############## + # define PCAP_OPENFLAG_PROMISCUOUS 1 + # Defines if the adapter has to go in promiscuous mode. + PCAP_OPENFLAG_PROMISCUOUS=1 + # define PCAP_OPENFLAG_DATATX_UDP 2 + # Defines if the data trasfer (in case of a remote capture) has to be done with UDP protocol. + PCAP_OPENFLAG_DATATX_UDP=2 + # define PCAP_OPENFLAG_NOCAPTURE_RPCAP 4 + PCAP_OPENFLAG_NOCAPTURE_RPCAP=4 + # Defines if the remote probe will capture its own generated traffic. + # define PCAP_OPENFLAG_NOCAPTURE_LOCAL 8 + PCAP_OPENFLAG_NOCAPTURE_LOCAL = 8 + # define PCAP_OPENFLAG_MAX_RESPONSIVENESS 16 + # This flag configures the adapter for maximum responsiveness. + PCAP_OPENFLAG_MAX_RESPONSIVENESS=16 + + ############## + ## Sampling methods defined in the pcap_setsampling() function + ############## + # define PCAP_SAMP_NOSAMP 0 + # No sampling has to be done on the current capture. + PCAP_SAMP_NOSAMP=0 + # define PCAP_SAMP_1_EVERY_N 1 + # It defines that only 1 out of N packets must be returned to the user. + PCAP_SAMP_1_EVERY_N=1 + #define PCAP_SAMP_FIRST_AFTER_N_MS 2 + # It defines that we have to return 1 packet every N milliseconds. + PCAP_SAMP_FIRST_AFTER_N_MS=2 + + ############## + ## Authentication methods supported by the RPCAP protocol + ############## + # define RPCAP_RMTAUTH_NULL 0 + # It defines the NULL authentication. + RPCAP_RMTAUTH_NULL=0 + # define RPCAP_RMTAUTH_PWD 1 + # It defines the username/password authentication. + RPCAP_RMTAUTH_PWD=1 + + + ############## + ## Remote struct and defines + ############## + # define PCAP_BUF_SIZE 1024 + # Defines the maximum buffer size in which address, port, interface names are kept. + PCAP_BUF_SIZE = 1024 + # define RPCAP_HOSTLIST_SIZE 1024 + # Maximum lenght of an host name (needed for the RPCAP active mode). + RPCAP_HOSTLIST_SIZE = 1024 + + class pcap_send_queue(Structure): + _fields_=[("maxlen",c_uint), + ("len",c_uint), + ("buffer",c_char_p)] + + ## struct pcap_rmtauth + ## This structure keeps the information needed to autheticate the user on a remote machine + class pcap_rmtauth(Structure): + _fields_=[("type",c_int), + ("username",c_char_p), + ("password",c_char_p)] + + ## struct pcap_samp + ## This structure defines the information related to sampling + class pcap_samp(Structure): + _fields_=[("method",c_int), + ("value",c_int)] + + #PAirpcapHandle pcap_get_airpcap_handle (pcap_t *p) + # Returns the AirPcap handler associated with an adapter. This handler can be used to change the wireless-related settings of the CACE Technologies AirPcap wireless capture adapters. + + #bool pcap_offline_filter (struct bpf_program *prog, const struct pcap_pkthdr *header, const u_char *pkt_data) + # Returns if a given filter applies to an offline packet. + pcap_offline_filter = _lib.pcap_offline_filter + pcap_offline_filter.restype = c_bool + pcap_offline_filter.argtypes = [POINTER(bpf_program),POINTER(pcap_pkthdr),POINTER(u_char)] + + #int pcap_live_dump (pcap_t *p, char *filename, int maxsize, int maxpacks) + # Save a capture to file. + pcap_live_dump = _lib.pcap_live_dump + pcap_live_dump.restype = c_int + pcap_live_dump.argtypes = [POINTER(pcap_t), POINTER(c_char), c_int,c_int] + + #int pcap_live_dump_ended (pcap_t *p, int sync) + # Return the status of the kernel dump process, i.e. tells if one of the limits defined with pcap_live_dump() has been reached. + pcap_live_dump_ended = _lib.pcap_live_dump_ended + pcap_live_dump_ended.restype = c_int + pcap_live_dump_ended.argtypes = [POINTER(pcap_t), c_int] + + #struct pcap_stat * pcap_stats_ex (pcap_t *p, int *pcap_stat_size) + # Return statistics on current capture. + pcap_stats_ex = _lib.pcap_stats_ex + pcap_stats_ex.restype = POINTER(pcap_stat) + pcap_stats_ex.argtypes = [POINTER(pcap_t), POINTER(c_int)] + + #int pcap_setbuff (pcap_t *p, int dim) + # Set the size of the kernel buffer associated with an adapter. + pcap_setbuff = _lib.pcap_setbuff + pcap_setbuff.restype = c_int + pcap_setbuff.argtypes = [POINTER(pcap_t), c_int] + + #int pcap_setmode (pcap_t *p, int mode) + # Set the working mode of the interface p to mode. + pcap_setmode = _lib.pcap_setmode + pcap_setmode.restype = c_int + pcap_setmode.argtypes = [POINTER(pcap_t), c_int] + + #int pcap_setmintocopy (pcap_t *p, int size) + # Set the minumum amount of data received by the kernel in a single call. + pcap_setmintocopy = _lib.pcap_setmintocopy + pcap_setmintocopy.restype = c_int + pcap_setmintocopy.argtype = [POINTER(pcap_t), c_int] + + #HANDLE pcap_getevent (pcap_t *p) + # Return the handle of the event associated with the interface p. + pcap_getevent = _lib.pcap_getevent + pcap_getevent.restype = HANDLE + pcap_getevent.argtypes = [POINTER(pcap_t)] + + #pcap_send_queue * pcap_sendqueue_alloc (u_int memsize) + # Allocate a send queue. + pcap_sendqueue_alloc = _lib.pcap_sendqueue_alloc + pcap_sendqueue_alloc.restype = POINTER(pcap_send_queue) + pcap_sendqueue_alloc.argtypes = [c_uint] + + #void pcap_sendqueue_destroy (pcap_send_queue *queue) + # Destroy a send queue. + pcap_sendqueue_destroy = _lib.pcap_sendqueue_destroy + pcap_sendqueue_destroy.restype = None + pcap_sendqueue_destroy.argtypes = [POINTER(pcap_send_queue)] + + #int pcap_sendqueue_queue (pcap_send_queue *queue, const struct pcap_pkthdr *pkt_header, const u_char *pkt_data) + # Add a packet to a send queue. + pcap_sendqueue_queue = _lib.pcap_sendqueue_queue + pcap_sendqueue_queue.restype = c_int + pcap_sendqueue_queue.argtypes = [POINTER(pcap_send_queue), POINTER(pcap_pkthdr), POINTER(u_char)] + + #u_int pcap_sendqueue_transmit (pcap_t *p, pcap_send_queue *queue, int sync) + # Send a queue of raw packets to the network. + pcap_sendqueue_transmit = _lib.pcap_sendqueue_transmit + pcap_sendqueue_transmit.retype = u_int + pcap_sendqueue_transmit.argtypes = [POINTER(pcap_t), POINTER(pcap_send_queue), c_int] + + #int pcap_findalldevs_ex (char *source, struct pcap_rmtauth *auth, pcap_if_t **alldevs, char *errbuf) + # Create a list of network devices that can be opened with pcap_open(). + pcap_findalldevs_ex = _lib.pcap_findalldevs_ex + pcap_findalldevs_ex.retype = c_int + pcap_findalldevs_ex.argtypes = [STRING, POINTER(pcap_rmtauth), POINTER(POINTER(pcap_if_t)), STRING] + + #int pcap_createsrcstr (char *source, int type, const char *host, const char *port, const char *name, char *errbuf) + # Accept a set of strings (host name, port, ...), and it returns the complete source string according to the new format (e.g. 'rpcap://1.2.3.4/eth0'). + pcap_createsrcstr = _lib.pcap_createsrcstr + pcap_createsrcstr.restype = c_int + pcap_createsrcstr.argtypes = [STRING, c_int, STRING, STRING, STRING, STRING] + + #int pcap_parsesrcstr (const char *source, int *type, char *host, char *port, char *name, char *errbuf) + # Parse the source string and returns the pieces in which the source can be split. + pcap_parsesrcstr = _lib.pcap_parsesrcstr + pcap_parsesrcstr.retype = c_int + pcap_parsesrcstr.argtypes = [STRING, POINTER(c_int), STRING, STRING, STRING, STRING] + + #pcap_t * pcap_open (const char *source, int snaplen, int flags, int read_timeout, struct pcap_rmtauth *auth, char *errbuf) + # Open a generic source in order to capture / send (WinPcap only) traffic. + pcap_open = _lib.pcap_open + pcap_open.restype = POINTER(pcap_t) + pcap_open.argtypes = [STRING, c_int, c_int, c_int, POINTER(pcap_rmtauth), STRING] + + #struct pcap_samp * pcap_setsampling (pcap_t *p) + # Define a sampling method for packet capture. + pcap_setsampling = _lib.pcap_setsampling + pcap_setsampling.restype = POINTER(pcap_samp) + pcap_setsampling.argtypes = [POINTER(pcap_t)] + + #SOCKET pcap_remoteact_accept (const char *address, const char *port, const char *hostlist, char *connectinghost, struct pcap_rmtauth *auth, char *errbuf) + # Block until a network connection is accepted (active mode only). + pcap_remoteact_accept = _lib.pcap_remoteact_accept + pcap_remoteact_accept.restype = SOCKET + pcap_remoteact_accept.argtypes = [STRING, STRING, STRING, STRING, POINTER(pcap_rmtauth), STRING] + + #int pcap_remoteact_close (const char *host, char *errbuf) + # Drop an active connection (active mode only). + pcap_remoteact_close = _lib.pcap_remoteact_close + pcap_remoteact_close.restypes = c_int + pcap_remoteact_close.argtypes = [STRING, STRING] + + #void pcap_remoteact_cleanup () + # Clean the socket that is currently used in waiting active connections. + pcap_remoteact_cleanup = _lib.pcap_remoteact_cleanup + pcap_remoteact_cleanup.restypes = None + pcap_remoteact_cleanup.argtypes = [] + + #int pcap_remoteact_list (char *hostlist, char sep, int size, char *errbuf) + # Return the hostname of the host that have an active connection with us (active mode only). + pcap_remoteact_list = _lib.pcap_remoteact_list + pcap_remoteact_list.restype = c_int + pcap_remoteact_list.argtypes = [STRING, c_char, c_int, STRING] diff --git a/scapy/config.py b/scapy/config.py old mode 100644 new mode 100755 index 14d024abfeb..39d476b69f5 --- a/scapy/config.py +++ b/scapy/config.py @@ -360,6 +360,7 @@ class Conf(ConfClass): emph = Emphasize() use_pcap = False use_dnet = False + use_winpcapy = False ipv6_enabled = socket.has_ipv6 ethertypes = ETHER_TYPES protocols = IP_PROTOS