Beispiel #1
0
def get_if_raw_hwaddr(ifname):
    """Returns the packed MAC address configured on 'ifname'."""

    NULL_MAC_ADDRESS = b'\x00' * 6

    # Handle the loopback interface separately
    if ifname == conf.loopback_name:
        return (ARPHDR_LOOPBACK, NULL_MAC_ADDRESS)

    # Get ifconfig output
    subproc = subprocess.Popen([conf.prog.ifconfig, ifname],
                               close_fds=True,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
    stdout, stderr = subproc.communicate()
    if subproc.returncode:
        raise Scapy_Exception("Failed to execute ifconfig: (%s)" %
                              (plain_str(stderr)))

    # Get MAC addresses
    addresses = [
        line for line in plain_str(stdout).splitlines()
        if ("ether" in line or "lladdr" in line or "address" in line)
    ]
    if not addresses:
        raise Scapy_Exception("No MAC address found on %s !" % ifname)

    # Pack and return the MAC address
    mac = addresses[0].split(' ')[1]
    mac = [chr(int(b, 16)) for b in mac.split(':')]
    return (ARPHDR_ETHER, ''.join(mac))
Beispiel #2
0
 def stop(self, join=True):
     """Stops AsyncSniffer if not in async mode"""
     if self.running:
         try:
             self.stop_cb()
         except AttributeError:
             raise Scapy_Exception(
                 "Unsupported (offline or unsupported socket)"
             )
         if join:
             self.join()
             return self.results
     else:
         raise Scapy_Exception("Not started !")
Beispiel #3
0
 def send(self, x):
     data = raw(x)
     if self.cls not in x:
         raise Scapy_Exception("L3WinSocket can only send IP/IPv6 packets !"
                               " Install Npcap/Winpcap to send more")
     dst_ip = str(x[self.cls].dst)
     self.outs.sendto(data, (dst_ip, 0))
Beispiel #4
0
def attach_filter(fd, bpf_filter, iface):
    """Attach a BPF filter to the BPF file descriptor"""
    bp = compile_filter(bpf_filter, iface)
    # Assign the BPF program to the interface
    ret = LIBC.ioctl(c_int(fd), BIOCSETF, cast(pointer(bp), c_char_p))
    if ret < 0:
        raise Scapy_Exception("Can't attach the BPF filter !")
Beispiel #5
0
    def set_promisc(self, value):
        """Set the interface in promiscuous mode"""

        try:
            fcntl.ioctl(self.ins, BIOCPROMISC, struct.pack('i', value))
        except IOError:
            raise Scapy_Exception("Cannot set promiscuous mode on interface "
                                  "(%s)!" % self.iface)
 def _check_npcap_requirement(self):
     if not conf.use_npcap:
         raise OSError("This operation requires Npcap.")
     if self.raw80211 is None:
         val = _get_npcap_config("Dot11Support")
         self.raw80211 = bool(int(val)) if val else False
     if not self.raw80211:
         raise Scapy_Exception("This interface does not support raw 802.11")
Beispiel #7
0
def compile_filter(filter_exp, iface=None, linktype=None, promisc=False):
    """Asks libpcap to parse the filter, then build the matching
    BPF bytecode.

    :param iface: if provided, use the interface to compile
    :param linktype: if provided, use the linktype to compile
    """
    try:
        from pocsuite3.thirdparty.scapy.winpcapy import (PCAP_ERRBUF_SIZE,
                                                         pcap_open_live,
                                                         pcap_compile,
                                                         pcap_compile_nopcap,
                                                         pcap_close)
        from pocsuite3.thirdparty.scapy.structures import bpf_program
    except OSError:
        raise ImportError("libpcap is not available. Cannot compile filter !")
    from ctypes import create_string_buffer
    bpf = bpf_program()
    bpf_filter = create_string_buffer(filter_exp.encode("utf8"))
    if not linktype:
        # Try to guess linktype to avoid root
        if not iface:
            if not conf.iface:
                raise Scapy_Exception(
                    "Please provide an interface or linktype!")
            if WINDOWS:
                iface = conf.iface.pcap_name
            else:
                iface = conf.iface
        # Try to guess linktype to avoid requiring root
        try:
            arphd = get_if_raw_hwaddr(iface)[0]
            linktype = ARPHRD_TO_DLT.get(arphd)
        except Exception:
            # Failed to use linktype: use the interface
            pass
    if linktype is not None:
        ret = pcap_compile_nopcap(MTU, linktype, ctypes.byref(bpf), bpf_filter,
                                  0, -1)
    elif iface:
        err = create_string_buffer(PCAP_ERRBUF_SIZE)
        iface = create_string_buffer(iface.encode("utf8"))
        pcap = pcap_open_live(iface, MTU, promisc, 0, err)
        error = bytes(bytearray(err)).strip(b"\x00")
        if error:
            raise OSError(error)
        ret = pcap_compile(pcap, ctypes.byref(bpf), bpf_filter, 0, -1)
        pcap_close(pcap)
    # if ret == -1:
    #     raise Scapy_Exception(
    #         "Failed to compile filter expression %s (%s)" % (filter_exp, ret)
    #     )
    if conf.use_pypy and sys.pypy_version_info <= (7, 3, 0):
        # PyPy < 7.3.0 has a broken behavior
        # https://bitbucket.org/pypy/pypy/issues/3114
        return struct.pack('HL', bpf.bf_len,
                           ctypes.addressof(bpf.bf_insns.contents))
    return bpf
Beispiel #8
0
def get_dev_bpf():
    """Returns an opened BPF file object"""

    # Get the first available BPF handle
    for bpf in range(256):
        try:
            fd = os.open("/dev/bpf%i" % bpf, os.O_RDWR)
            return (fd, bpf)
        except OSError:
            continue

    raise Scapy_Exception("No /dev/bpf handle is available !")
Beispiel #9
0
def get_working_ifaces():
    """
    Returns an ordered list of interfaces that could be used with BPF.
    Note: the order mimics pcap_findalldevs() behavior
    """

    # Only root is allowed to perform the following ioctl() call
    if os.getuid() != 0:
        return []

    # Test all network interfaces
    interfaces = []
    for ifname in get_if_list():

        # Unlike pcap_findalldevs(), we do not care of loopback interfaces.
        if ifname == conf.loopback_name:
            continue

        # Get interface flags
        try:
            result = get_if(ifname, SIOCGIFFLAGS)
        except IOError:
            warning("ioctl(SIOCGIFFLAGS) failed on %s !", ifname)
            continue

        # Convert flags
        ifflags = struct.unpack("16xH14x", result)[0]
        if ifflags & 0x1:  # IFF_UP

            # Get a BPF handle
            fd = get_dev_bpf()[0]
            if fd is None:
                raise Scapy_Exception("No /dev/bpf are available !")

            # Check if the interface can be used
            try:
                fcntl.ioctl(fd, BIOCSETIF,
                            struct.pack("16s16x", ifname.encode()))
            except IOError:
                pass
            else:
                ifnum, ifab = _IFNUM.search(ifname).groups()
                interfaces.append((ifname, int(ifnum) if ifnum else -1, ifab))
            finally:
                # Close the file descriptor
                os.close(fd)

    # Sort to mimic pcap_findalldevs() order
    interfaces.sort(key=lambda elt: (elt[1], elt[2], elt[0]))

    return [iface[0] for iface in interfaces]
Beispiel #10
0
def in6_cidr2mask(m):
    """
    Return the mask (bitstring) associated with provided length
    value. For instance if function is called on 48, return value is
    b'\xff\xff\xff\xff\xff\xff\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'.

    """
    if m > 128 or m < 0:
        raise Scapy_Exception(
            "value provided to in6_cidr2mask outside [0, 128] domain (%d)" %
            m)  # noqa: E501

    t = []
    for i in range(0, 4):
        t.append(max(0, 2**32 - 2**(32 - min(32, m))))
        m -= 32

    return b"".join(struct.pack('!I', x) for x in t)
Beispiel #11
0
def get_if_list():
    """Returns a list containing all network interfaces."""

    # Get ifconfig output
    subproc = subprocess.Popen([conf.prog.ifconfig],
                               close_fds=True,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
    stdout, stderr = subproc.communicate()
    if subproc.returncode:
        raise Scapy_Exception("Failed to execute ifconfig: (%s)" %
                              (plain_str(stderr)))

    interfaces = [
        line[:line.find(':')] for line in plain_str(stdout).splitlines()
        if ": flags" in line.lower()
    ]
    return interfaces
 def open_pcap(iface, *args, **kargs):
     """open_pcap: Windows routine for creating a pcap from an interface.
     This function is also responsible for detecting monitor mode.
     """
     iface_pcap_name = pcapname(iface)
     if not isinstance(iface, NetworkInterface) and \
             iface_pcap_name is not None:
         iface = IFACES.dev_from_name(iface)
     if iface is None or iface.is_invalid():
         raise Scapy_Exception(
             "Interface is invalid (no pcap match found) !")
     # Only check monitor mode when manually specified.
     # Checking/setting for monitor mode will slow down the process, and the
     # common is case is not to use monitor mode
     kw_monitor = kargs.get("monitor", None)
     if conf.use_npcap and kw_monitor is not None:
         monitored = iface.ismonitor()
         if kw_monitor is not monitored:
             # The monitor param is specified, and not matching the current
             # interface state
             iface.setmonitor(kw_monitor)
     return _orig_open_pcap(iface_pcap_name, *args, **kargs)
Beispiel #13
0
    def send(self, pkt):
        """Send a packet"""

        # Use the routing table to find the output interface
        iff = pkt.route()[0]
        if iff is None:
            iff = conf.iface

        # Assign the network interface to the BPF handle
        if self.assigned_interface != iff:
            try:
                fcntl.ioctl(self.outs, BIOCSETIF,
                            struct.pack("16s16x", iff.encode()))  # noqa: E501
            except IOError:
                raise Scapy_Exception("BIOCSETIF failed on %s" % iff)
            self.assigned_interface = iff

        # Build the frame
        frame = raw(self.guessed_cls() / pkt)
        pkt.sent_time = time.time()

        # Send the frame
        L2bpfSocket.send(self, frame)
Beispiel #14
0
def get_if_lists():
    """Returns a list containing all network interfaces."""

    # Get ifconfig output
    subproc = subprocess.Popen([conf.prog.ifconfig],
                               close_fds=True,
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
    stdout, stderr = subproc.communicate()
    if subproc.returncode:
        raise Scapy_Exception("Failed to execute ifconfig: (%s)" %
                              (plain_str(stderr)))

    interfaces = []
    ips = []
    for line in plain_str(stdout).splitlines():
        if ": flags" in line.lower():
            interfaces.append(line[:line.find(':')])
        elif "inet " in line.lower():
            ips.append(
                line.split("inet")[1].split("netmask")[0].replace(" ", ''))

    return interfaces, ips
Beispiel #15
0
 def send(self, x):
     raise Scapy_Exception("Can't send anything with L2pcapListenSocket")  # noqa: E501
Beispiel #16
0
    def __init__(self,
                 iface=None,
                 type=ETH_P_ALL,
                 promisc=None,
                 filter=None,
                 nofilter=0,
                 monitor=False):
        self.fd_flags = None
        self.assigned_interface = None

        # SuperSocket mandatory variables
        if promisc is None:
            self.promisc = conf.sniff_promisc
        else:
            self.promisc = promisc

        if iface is None:
            self.iface = conf.iface
        else:
            self.iface = iface

        # Get the BPF handle
        (self.ins, self.dev_bpf) = get_dev_bpf()
        self.outs = self.ins

        # Set the BPF buffer length
        try:
            fcntl.ioctl(self.ins, BIOCSBLEN,
                        struct.pack('I', BPF_BUFFER_LENGTH))  # noqa: E501
        except IOError:
            raise Scapy_Exception("BIOCSBLEN failed on /dev/bpf%i" %
                                  self.dev_bpf)

        # Assign the network interface to the BPF handle
        try:
            fcntl.ioctl(self.ins, BIOCSETIF,
                        struct.pack("16s16x",
                                    self.iface.encode()))  # noqa: E501
        except IOError:
            raise Scapy_Exception("BIOCSETIF failed on %s" % self.iface)
        self.assigned_interface = self.iface

        # Set the interface into promiscuous
        if self.promisc:
            self.set_promisc(1)

        # Set the interface to monitor mode
        # Note: - trick from libpcap/pcap-bpf.c - monitor_mode()
        #       - it only works on OS X 10.5 and later
        if DARWIN and monitor:
            dlt_radiotap = struct.pack('I', DLT_IEEE802_11_RADIO)
            try:
                fcntl.ioctl(self.ins, BIOCSDLT, dlt_radiotap)
            except IOError:
                raise Scapy_Exception("Can't set %s into monitor mode!" %
                                      self.iface)

        # Don't block on read
        try:
            fcntl.ioctl(self.ins, BIOCIMMEDIATE, struct.pack('I', 1))
        except IOError:
            raise Scapy_Exception("BIOCIMMEDIATE failed on /dev/bpf%i" %
                                  self.dev_bpf)

        # Scapy will provide the link layer source address
        # Otherwise, it is written by the kernel
        try:
            fcntl.ioctl(self.ins, BIOCSHDRCMPLT, struct.pack('i', 1))
        except IOError:
            raise Scapy_Exception("BIOCSHDRCMPLT failed on /dev/bpf%i" %
                                  self.dev_bpf)

        # Configure the BPF filter
        if not nofilter:
            if conf.except_filter:
                if filter:
                    filter = "(%s) and not (%s)" % (filter, conf.except_filter)
                else:
                    filter = "not (%s)" % conf.except_filter
            if filter is not None:
                try:
                    attach_filter(self.ins, filter, self.iface)
                except ImportError as ex:
                    warning("Cannot set filter: %s" % ex)

        # Set the guessed packet class
        self.guessed_cls = self.guess_cls()