Exemplo n.º 1
0
    def check_arp_reply(self, pkt):
        data = parse_data_pkt(pkt, self.tk)
        try:
            data_clear = check_MIC_ICV(data, self.mic_sta_to_ap, pkt.addr2,
                                       pkt.addr3)
        except (ICVError, MICError):
            return

        decoded_pkt = LLC(data_clear)
        log_runtime.debug(hexdump(decoded_pkt, dump=True))
        log_runtime.debug(repr(decoded_pkt))
        self.deal_common_pkt(decoded_pkt)
        if ARP not in decoded_pkt:
            return

        # ARP.op 2: is-at
        if decoded_pkt[ARP].op == 2 and \
           decoded_pkt[ARP].psrc == self.arp_target_ip and \
           decoded_pkt[ARP].pdst == self.arp_source_ip:
            # Got the expected ARP
            if self.krack_state & 4 == 0:
                # First time, normal behavior
                log_runtime.info("Got ARP reply, this is normal")
                self.krack_state |= 4
                log_runtime.info("Trying to trigger CVE-2017-13080")
                raise self.RENEW_GTK()
            else:
                # Second time, the packet has been accepted twice!
                log_runtime.warning("Broadcast packet accepted twice!! "
                                    "(CVE-2017-13080)")
Exemplo n.º 2
0
    def rem(self, session):
        s = self.find(session)
        if s:
            log_runtime.info("TLS: previous session shall not be overwritten")
            return

        h = session.hash()
        self.sessions[h].remove(session)
Exemplo n.º 3
0
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,
         it is displayed. Ex:
         ex: prn = lambda x: x.summary()
lfilter: python function applied to each packet to determine
         if further action may be done
         ex: lfilter = lambda x: x.haslayer(Padding)
offline: pcap file to read packets from, instead of sniffing them
timeout: stop sniffing after a given time (default: None)
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)
    else:
        s = PcapReader(offline)

    lst = []
    if timeout is not None:
        stoptime = time.time()+timeout
    remain = None
    while 1:
        try:
            if timeout is not None:
                remain = stoptime-time.time()
                if remain <= 0:
                    break

            try:
                p = s.recv(MTU)
            except PcapTimeoutElapsed:
                continue
            if p is None:
                break
            if lfilter and not lfilter(p):
                continue
            if store:
                lst.append(p)
            c += 1
            if prn:
                r = prn(p)
                if r is not None:
                    print(r)
            if count > 0 and c >= count:
                break
        except KeyboardInterrupt:
            break
    s.close()
    return plist.PacketList(lst,"Sniffed")
Exemplo n.º 4
0
def sendpfast(x, pps=None, mbps=None, realtime=None, loop=0, file_cache=False, iface=None, replay_args=None,  # noqa: E501
              parse_results=False):
    """Send packets at layer 2 using tcpreplay for performance
    pps:  packets per second
    mpbs: MBits per second
    realtime: use packet's timestamp, bending time with real-time value
    loop: number of times to process the packet list
    file_cache: cache packets in RAM instead of reading from disk at each iteration  # noqa: E501
    iface: output interface
    replay_args: List of additional tcpreplay args (List[str])
    parse_results: Return a dictionary of information outputted by tcpreplay (default=False)  # noqa: E501
    :returns stdout, stderr, command used"""
    if iface is None:
        iface = conf.iface
    argv = [conf.prog.tcpreplay, "--intf1=%s" % iface]
    if pps is not None:
        argv.append("--pps=%i" % pps)
    elif mbps is not None:
        argv.append("--mbps=%f" % mbps)
    elif realtime is not None:
        argv.append("--multiplier=%f" % realtime)
    else:
        argv.append("--topspeed")

    if loop:
        argv.append("--loop=%i" % loop)
    if file_cache:
        argv.append("--preload-pcap")

    # Check for any additional args we didn't cover.
    if replay_args is not None:
        argv.extend(replay_args)

    f = get_temp_file()
    argv.append(f)
    wrpcap(f, x)
    results = None
    with ContextManagerSubprocess("sendpfast()", conf.prog.tcpreplay):
        try:
            cmd = subprocess.Popen(argv, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        except KeyboardInterrupt:
            log_interactive.info("Interrupted by user")
        except Exception:
            os.unlink(f)
            raise
        else:
            stdout, stderr = cmd.communicate()
            if stderr:
                log_runtime.warning(stderr.decode())
            if parse_results:
                results = _parse_tcpreplay_result(stdout, stderr, argv)
            elif conf.verb > 2:
                log_runtime.info(stdout.decode())
    os.unlink(f)
    return results
Exemplo n.º 5
0
 def post_dissection(self, r):
     if not self.tls_session.frozen:
         for kse in self.client_shares:
             if kse.pubkey:
                 pubshares = self.tls_session.tls13_client_pubshares
                 if _tls_named_curves[kse.group] in pubshares:
                     pkt_info = r.firstlayer().summary()
                     log_runtime.info("TLS: group %s used twice in the same ClientHello [%s]", kse.group, pkt_info)
                     break
                 pubshares[_tls_named_curves[kse.group]] = kse.pubkey
     return super(TLS_Ext_KeyShare_CH, self).post_dissection(r)
Exemplo n.º 6
0
 def post_build(self, pkt, pay):
     if not self.tls_session.frozen:
         privshares = self.tls_session.tls13_client_privshares
         for kse in self.client_shares:
             if kse.privkey:
                 if _tls_named_curves[kse.group] in privshares:
                     pkt_info = pkt.firstlayer().summary()
                     log_runtime.info("TLS: group %s used twice in the same ClientHello [%s]", kse.group, pkt_info)
                     break
                 privshares[_tls_named_groups[kse.group]] = kse.privkey
     return super(TLS_Ext_KeyShare_CH, self).post_build(pkt, pay)
Exemplo n.º 7
0
 def find(self, session):
     h = session.hash()
     if h in self.sessions:
         for k in self.sessions[h]:
             if k.eq(session):
                 if conf.tls_verbose:
                     log_runtime.info("TLS: found session matching %s", k)
                 return k
     if conf.tls_verbose:
         log_runtime.info("TLS: did not find session matching %s", session)
     return None
Exemplo n.º 8
0
    def add(self, session):
        s = self.find(session)
        if s:
            log_runtime.info("TLS: previous session shall not be overwritten")
            return

        h = session.hash()
        if h in self.sessions:
            self.sessions[h].append(session)
        else:
            self.sessions[h] = [session]
Exemplo n.º 9
0
 def post_dissection(self, r):
     if not self.tls_session.frozen:
         for kse in self.client_shares:
             if kse.pubkey:
                 pubshares = self.tls_session.tls13_client_pubshares
                 if _tls_named_curves[kse.group] in pubshares:
                     pkt_info = r.firstlayer().summary()
                     log_runtime.info("TLS: group %s used twice in the same ClientHello [%s]", kse.group, pkt_info)
                     break
                 pubshares[_tls_named_curves[kse.group]] = kse.pubkey
     return super(TLS_Ext_KeyShare_CH, self).post_dissection(r)
Exemplo n.º 10
0
 def find(self, session):
     h = session.hash()
     if h in self.sessions:
         for k in self.sessions[h]:
             if k.eq(session):
                 if conf.tls_verbose:
                     log_runtime.info("TLS: found session matching %s", k)
                 return k
     if conf.tls_verbose:
         log_runtime.info("TLS: did not find session matching %s", session)
     return None
Exemplo n.º 11
0
 def post_build(self, pkt, pay):
     if not self.tls_session.frozen:
         privshares = self.tls_session.tls13_client_privshares
         for kse in self.client_shares:
             if kse.privkey:
                 if _tls_named_curves[kse.group] in privshares:
                     pkt_info = pkt.firstlayer().summary()
                     log_runtime.info("TLS: group %s used twice in the same ClientHello [%s]", kse.group, pkt_info)
                     break
                 privshares[_tls_named_groups[kse.group]] = kse.privkey
     return super(TLS_Ext_KeyShare_CH, self).post_build(pkt, pay)
Exemplo n.º 12
0
    def add(self, session):
        s = self.find(session)
        if s:
            log_runtime.info("TLS: previous session shall not be overwritten")
            return

        h = session.hash()
        if h in self.sessions:
            self.sessions[h].append(session)
        else:
            self.sessions[h] = [session]
Exemplo n.º 13
0
 def m2i(self, pkt, s):
     ret_s = list()
     tmp_s = s
     # RDATA contains a list of strings, each are prepended with
     # a byte containing the size of the following string.
     while tmp_s:
         tmp_len = orb(tmp_s[0]) + 1
         if tmp_len > len(tmp_s):
             log_runtime.info(
                 "DNS RR TXT prematured end of character-string "
                 "(size=%i, remaining bytes=%i)", tmp_len, len(tmp_s))
         ret_s.append(tmp_s[1:tmp_len])
         tmp_s = tmp_s[tmp_len:]
     return ret_s
    def pre_dissect(self, s):
        if len(s) < 2:
            raise Exception("Invalid record: header is too short.")

        msglen = struct.unpack("!H", s[:2])[0]
        if msglen & 0x8000:
            hdrlen = 2
            msglen_clean = msglen & 0x7fff
        else:
            hdrlen = 3
            msglen_clean = msglen & 0x3fff

        hdr = s[:hdrlen]
        efrag = s[hdrlen:hdrlen + msglen_clean]
        self.protected_record = s[:hdrlen + msglen_clean]
        r = s[hdrlen + msglen_clean:]

        mac = pad = ""

        cipher_type = self.tls_session.rcs.cipher.type

        # Decrypt (with implicit IV if block cipher)
        mfrag = self._tls_decrypt(efrag)

        # Extract MAC
        maclen = self.tls_session.rcs.mac_len
        if maclen == 0:
            mac, pfrag = "", mfrag
        else:
            mac, pfrag = mfrag[:maclen], mfrag[maclen:]

        # Extract padding
        padlen = 0
        if hdrlen == 3:
            padlen = struct.unpack("B", s[2])[0]
        if padlen == 0:
            cfrag, pad = pfrag, ""
        else:
            cfrag, pad = pfrag[:-padlen], pfrag[-padlen:]

        # Verify integrity
        is_mac_ok = self._sslv2_mac_verify(cfrag + pad, mac)
        if not is_mac_ok:
            pkt_info = self.firstlayer().summary()
            log_runtime.info("TLS: record integrity check failed [%s]",
                             pkt_info)

        reconstructed_body = mac + cfrag + pad
        return hdr + reconstructed_body + r
Exemplo n.º 15
0
    def krack_dispatch(self):
        now = time.time()
        # Handshake 3/4 replay
        if self.double_3handshake and (self.krack_state & 1 == 0) and \
           (now - self.time_handshake_end) > self.wait_3handshake:
            log_runtime.info("Trying to trigger CVE-2017-13077")
            raise self.ANALYZE_DATA().action_parameters(send_3handshake=True)

        # GTK rekeying
        if (self.krack_state & 2 == 0) and \
           (now - self.time_handshake_end) > self.wait_gtk:
            raise self.ANALYZE_DATA().action_parameters(send_gtk=True)

        # Fallback in data analysis
        raise self.ANALYZE_DATA().action_parameters()
Exemplo n.º 16
0
    def krack_dispatch(self):
        now = time.time()
        # Handshake 3/4 replay
        if self.double_3handshake and (self.krack_state & 1 == 0) and \
           (now - self.time_handshake_end) > self.wait_3handshake:
            log_runtime.info("Trying to trigger CVE-2017-13077")
            raise self.ANALYZE_DATA().action_parameters(send_3handshake=True)

        # GTK rekeying
        if (self.krack_state & 2 == 0) and \
           (now - self.time_handshake_end) > self.wait_gtk:
            raise self.ANALYZE_DATA().action_parameters(send_gtk=True)

        # Fallback in data analysis
        raise self.ANALYZE_DATA().action_parameters()
Exemplo n.º 17
0
    def pre_dissect(self, s):
        if len(s) < 2:
            raise Exception("Invalid record: header is too short.")

        msglen = struct.unpack("!H", s[:2])[0]
        if msglen & 0x8000:
            hdrlen = 2
            msglen_clean = msglen & 0x7fff
        else:
            hdrlen = 3
            msglen_clean = msglen & 0x3fff

        hdr = s[:hdrlen]
        efrag = s[hdrlen:hdrlen+msglen_clean]
        self.protected_record = s[:hdrlen+msglen_clean]
        r = s[hdrlen+msglen_clean:]

        mac = pad = b""

        cipher_type = self.tls_session.rcs.cipher.type

        # Decrypt (with implicit IV if block cipher)
        mfrag = self._tls_decrypt(efrag)

        # Extract MAC
        maclen = self.tls_session.rcs.mac_len
        if maclen == 0:
            mac, pfrag = b"", mfrag
        else:
            mac, pfrag = mfrag[:maclen], mfrag[maclen:]

        # Extract padding
        padlen = 0
        if hdrlen == 3:
            padlen = orb(s[2])
        if padlen == 0:
            cfrag, pad = pfrag, b""
        else:
            cfrag, pad = pfrag[:-padlen], pfrag[-padlen:]

        # Verify integrity
        is_mac_ok = self._sslv2_mac_verify(cfrag + pad, mac)
        if not is_mac_ok:
            pkt_info = self.firstlayer().summary()
            log_runtime.info("TLS: record integrity check failed [%s]", pkt_info)

        reconstructed_body = mac + cfrag + pad
        return hdr + reconstructed_body + r
Exemplo n.º 18
0
    def extract_iv(self, pkt):
        # Get IV
        TSC, _, _ = parse_TKIP_hdr(pkt)
        iv = TSC[0] | (TSC[1] << 8) | (TSC[2] << 16) | (TSC[3] << 24) | \
             (TSC[4] << 32) | (TSC[5] << 40)
        log_runtime.info("Got a packet with IV: %s", hex(iv))

        if self.last_iv is None:
            self.last_iv = iv
        else:
            if iv <= self.last_iv:
                log_runtime.warning("IV re-use!! Client seems to be "
                                    "vulnerable to handshake 3/4 replay "
                                    "(CVE-2017-13077)"
                )

        data_clear = None

        # Normal decoding
        data = parse_data_pkt(pkt, self.tk)
        try:
            data_clear = check_MIC_ICV(data, self.mic_sta_to_ap, pkt.addr2,
                                       pkt.addr3)
        except (ICVError, MICError):
            pass

        # Decoding with a 0's TK
        if data_clear is None:
            data = parse_data_pkt(pkt, "\x00" * len(self.tk))
            try:
                mic_key = "\x00" * len(self.mic_sta_to_ap)
                data_clear = check_MIC_ICV(data, mic_key, pkt.addr2, pkt.addr3)
                log_runtime.warning("Client has installed an all zero "
                                    "encryption key (TK)!!")
            except (ICVError, MICError):
                pass

        if data_clear is None:
            log_runtime.warning("Unable to decode the packet, something went "
                                "wrong")
            log_runtime.debug(hexdump(pkt, dump=True))
            self.deal_common_pkt(pkt)
            return

        log_runtime.debug(hexdump(data_clear, dump=True))
        pkt = LLC(data_clear)
        log_runtime.debug(repr(pkt))
        self.deal_common_pkt(pkt)
Exemplo n.º 19
0
    def post_dissection_tls_session_update(self, msg_str):
        self.tls_session_update(msg_str)

        s = self.tls_session
        test = (len(s.client_certs) > 0 and
                s.sslv2_key_material is not None and
                s.sslv2_challenge_clientcert is not None and
                len(s.server_certs) > 0)
        if test:
            m = (s.sslv2_key_material +
                 s.sslv2_challenge_clientcert +
                 s.server_certs[0].der)
            sig_test = self.responsedata._verify_sig(m, s.client_certs[0])
            if not sig_test:
                pkt_info = self.firstlayer().summary()
                log_runtime.info("TLS: invalid client CertificateVerify signature [%s]", pkt_info)  # noqa: E501
Exemplo n.º 20
0
    def post_dissection_tls_session_update(self, msg_str):
        self.tls_session_update(msg_str)

        s = self.tls_session
        test = (len(s.client_certs) > 0 and
                s.sslv2_key_material is not None and
                s.sslv2_challenge_clientcert is not None and
                len(s.server_certs) > 0)
        if test:
            m = (s.sslv2_key_material +
                 s.sslv2_challenge_clientcert +
                 s.server_certs[0].der)
            sig_test = self.responsedata._verify_sig(m, s.client_certs[0])
            if not sig_test:
                pkt_info = self.firstlayer().summary()
                log_runtime.info("TLS: invalid client CertificateVerify signature [%s]", pkt_info)
Exemplo n.º 21
0
 def _tls_auth_decrypt(self, s):
     """
     Provided with the record header and AEAD-ciphered data, return the
     sliced and clear tuple (TLSInnerPlaintext, tag). Note that
     we still return the slicing of the original input in case of decryption
     failure. Also, if the integrity check fails, a warning will be issued,
     but we still return the sliced (unauthenticated) plaintext.
     """
     rcs = self.tls_session.rcs
     read_seq_num = struct.pack("!Q", rcs.seq_num)
     rcs.seq_num += 1
     try:
         return rcs.cipher.auth_decrypt(b"", s, read_seq_num)
     except CipherError as e:
         return e.args
     except AEADTagError as e:
         pkt_info = self.firstlayer().summary()
         log_runtime.info("TLS: record integrity check failed [%s]", pkt_info)
         return e.args
Exemplo n.º 22
0
 def _tls_auth_decrypt(self, s):
     """
     Provided with the record header and AEAD-ciphered data, return the
     sliced and clear tuple (TLSInnerPlaintext, tag). Note that
     we still return the slicing of the original input in case of decryption
     failure. Also, if the integrity check fails, a warning will be issued,
     but we still return the sliced (unauthenticated) plaintext.
     """
     rcs = self.tls_session.rcs
     read_seq_num = struct.pack("!Q", rcs.seq_num)
     rcs.seq_num += 1
     try:
         return rcs.cipher.auth_decrypt(b"", s, read_seq_num)
     except CipherError as e:
         return e.args
     except AEADTagError as e:
         pkt_info = self.firstlayer().summary()
         log_runtime.info("TLS: record integrity check failed [%s]", pkt_info)
         return e.args
Exemplo n.º 23
0
 def post_dissection(self, pkt):
     s = self.tls_session
     if not s.frozen:
         handshake_msg = "".join(s.handshake_messages)
         if s.tls_version < 0x0304 and s.master_secret is not None:
             ms = s.master_secret
             con_end = s.connection_end
             verify_data = s.rcs.prf.compute_verify_data(
                 con_end, "read", handshake_msg, ms)
             if self.vdata != verify_data:
                 pkt_info = pkt.firstlayer().summary()
                 log_runtime.info("TLS: invalid Finished received [%s]",
                                  pkt_info)
         elif s.tls_version >= 0x0304:
             con_end = s.connection_end
             verify_data = s.compute_tls13_verify_data(con_end, "read")
             if self.vdata != verify_data:
                 pkt_info = pkt.firstlayer().summary()
                 log_runtime.info("TLS: invalid Finished received [%s]",
                                  pkt_info)
Exemplo n.º 24
0
    def post_dissection(self, pkt):
        """
        While previously dissecting Server*DHParams, the session
        server_kx_pubkey should have been updated.

        XXX Add a 'fixed_dh' OR condition to the 'anonymous' test.
        """
        s = self.tls_session
        if s.prcs and s.prcs.key_exchange.no_ske:
            pkt_info = pkt.firstlayer().summary()
            log_runtime.info("TLS: useless ServerKeyExchange [%s]", pkt_info)
        if (s.prcs and not s.prcs.key_exchange.anonymous and s.client_random
                and s.server_random and s.server_certs
                and len(s.server_certs) > 0):
            m = s.client_random + s.server_random + str(self.params)
            sig_test = self.sig._verify_sig(m, s.server_certs[0])
            if not sig_test:
                pkt_info = pkt.firstlayer().summary()
                log_runtime.info(
                    "TLS: invalid ServerKeyExchange signature [%s]", pkt_info)
Exemplo n.º 25
0
def _sndrcv_snd(pks, timeout, inter, verbose, tobesent, stopevent):
    """Function used in the sending thread of sndrcv()"""
    try:
        i = 0
        if verbose:
            print("Begin emission:")
        for p in tobesent:
            pks.send(p)
            i += 1
            time.sleep(inter)
        if verbose:
            print("Finished to send %i packets." % i)
    except SystemExit:
        pass
    except KeyboardInterrupt:
        pass
    except:
        log_runtime.info("--- Error sending packets", exc_info=True)
    if timeout is not None:
        stopevent.wait(timeout)
        stopevent.set()
Exemplo n.º 26
0
def _sndrcv_snd(pks, timeout, inter, verbose, tobesent, stopevent):
    """Function used in the sending thread of sndrcv()"""
    try:
        i = 0
        if verbose:
            print("Begin emission:")
        for p in tobesent:
            pks.send(p)
            i += 1
            time.sleep(inter)
        if verbose:
            print("Finished to send %i packets." % i)
    except SystemExit:
        pass
    except KeyboardInterrupt:
        pass
    except:
        log_runtime.info("--- Error sending packets", exc_info=True)
    if timeout is not None:
        stopevent.wait(timeout)
        stopevent.set()
Exemplo n.º 27
0
    def pre_dissect(self, s):
        """
        Check that a valid DNS over TCP message can be decoded
        """
        if isinstance(self.underlayer, TCP):

            # Compute the length of the DNS packet
            if len(s) >= 2:
                dns_len = struct.unpack("!H", s[:2])[0]
            else:
                message = "Malformed DNS message: too small!"
                log_runtime.info(message)
                raise Scapy_Exception(message)

            # Check if the length is valid
            if dns_len < 14 or len(s) < dns_len:
                message = "Malformed DNS message: invalid length!"
                log_runtime.info(message)
                raise Scapy_Exception(message)

        return s
Exemplo n.º 28
0
def pretty_list(rtlst, header, sortBy=0):
    """Pretty list to fit the terminal, and add header"""
    _space = "  "
    # Windows has a fat terminal border
    _spacelen = len(_space) * (len(header) - 1) + (10 if WINDOWS else 0)
    _croped = False
    # Sort correctly
    rtlst.sort(key=lambda x: x[sortBy])
    # Append tag
    rtlst = header + rtlst
    # Detect column's width
    colwidth = [max([len(y) for y in x]) for x in zip(*rtlst)]
    # Make text fit in box (if required)
    width = get_terminal_width()
    if conf.auto_crop_tables and width:
        width = width - _spacelen
        while sum(colwidth) > width:
            _croped = True
            # Needs to be cropped
            # Get the longest row
            i = colwidth.index(max(colwidth))
            # Get all elements of this row
            row = [len(x[i]) for x in rtlst]
            # Get biggest element of this row: biggest of the array
            j = row.index(max(row))
            # Re-build column tuple with the edited element
            t = list(rtlst[j])
            t[i] = t[i][:-2] + "_"
            rtlst[j] = tuple(t)
            # Update max size
            row[j] = len(t[i])
            colwidth[i] = max(row)
    if _croped:
        log_runtime.info(
            "Table cropped to fit the terminal (conf.auto_crop_tables==True)")
    # Generate padding scheme
    fmt = _space.join(["%%-%ds" % x for x in colwidth])
    # Compile
    rt = "\n".join(((fmt % x).strip() for x in rtlst))
    return rt
    def post_dissection(self, r):
        if not self.tls_session.frozen and self.server_share.pubkey:
            # if there is a pubkey, we assume the crypto library is ok
            pubshare = self.tls_session.tls13_server_pubshare
            if len(pubshare) > 0:
                pkt_info = r.firstlayer().summary()
                log_runtime.info("TLS: overwriting previous server key share [%s]", pkt_info)
            group_name = _tls_named_groups[self.server_share.group]
            pubshare[group_name] = self.server_share.pubkey

            if group_name in self.tls_session.tls13_client_privshares:
                pubkey = self.server_share.pubkey
                privkey = self.tls_session.tls13_client_privshares[group_name]
                if group_name in six.itervalues(_tls_named_ffdh_groups):
                    pms = privkey.exchange(pubkey)
                elif group_name in six.itervalues(_tls_named_curves):
                    if group_name == "x25519":
                        pms = privkey.exchange(pubkey)
                    else:
                        pms = privkey.exchange(ec.ECDH(), pubkey)
                self.tls_session.tls13_dhe_secret = pms
        return super(TLS_Ext_KeyShare_SH, self).post_dissection(r)
Exemplo n.º 30
0
 def getfield(self, pkt, s):
     if isinstance(s, tuple):
         s, p = s
     else:
         p = 0
     ret = None
     c = getattr(pkt, self.countfld)
     if c > len(s):
         log_runtime.info("DNS wrong value: DNS.%s=%i", self.countfld, c)
         return s, b""
     while c:
         c -= 1
         name, p, _, _ = dns_get_str(s, p, _fullpacket=True)
         rr, p = self.decodeRR(name, s, p)
         if ret is None:
             ret = rr
         else:
             ret.add_payload(rr)
     if self.passon:
         return (s, p), ret
     else:
         return s[p:], ret
Exemplo n.º 31
0
 def __init__(self, type=ETH_P_IP, filter=None, iface=None, promisc=None, nofilter=0):  # noqa: E501
     self.outs = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)  # noqa: E501
     self.outs.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
     self.ins = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))  # noqa: E501
     self.iface = iface
     if iface is not None:
         self.ins.bind((self.iface, type))
     if not six.PY2:
         try:
             # Receive Auxiliary Data (VLAN tags)
             self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)
             self.ins.setsockopt(
                 socket.SOL_SOCKET,
                 SO_TIMESTAMPNS,
                 1
             )
             self.auxdata_available = True
         except OSError:
             # Note: Auxiliary Data is only supported since
             #       Linux 2.6.21
             msg = "Your Linux Kernel does not support Auxiliary Data!"
             log_runtime.info(msg)
Exemplo n.º 32
0
    def send_arp_req(self):

        if self.krack_state & 4 == 0:
            # Set the address for future uses
            self.arp_target_ip = self.dhcp_server.leases.get(self.client,
                                                             self.arp_target_ip)
            assert self.arp_target_ip is not None

            # Send the first ARP requests, for control test
            log_runtime.info("Send ARP who-was from '%s' to '%s'",
                             self.arp_source_ip,
                             self.arp_target_ip)
            arp_pkt = self.send_wpa_to_group(
                LLC()/SNAP()/ARP(op="who-has",
                                 psrc=self.arp_source_ip,
                                 pdst=self.arp_target_ip,
                                 hwsrc=self.mac),
                dest='ff:ff:ff:ff:ff:ff',
            )
            self.arp_sent.append(arp_pkt)
        else:
            if self.arp_to_send < len(self.arp_sent):
                # Re-send the ARP requests already sent
                self.send(self.arp_sent[self.arp_to_send])
                self.arp_to_send += 1
            else:
                # Re-send GTK
                self.arp_to_send = 0
                self.arp_retry += 1
                log_runtime.info("Trying to trigger CVE-2017-13080 %d/%d",
                              self.arp_retry, self.ARP_MAX_RETRY)
                if self.arp_retry > self.ARP_MAX_RETRY:
                    # We retries 100 times to send GTK, then already sent ARPs
                    log_runtime.warning("Client is likely not vulnerable to "
                                        "CVE-2017-13080")
                    raise self.EXIT()

                raise self.RENEW_GTK()
Exemplo n.º 33
0
def bitmap2RRlist(bitmap):
    """
    Decode the 'Type Bit Maps' field of the NSEC Resource Record into an
    integer list.
    """
    # RFC 4034, 4.1.2. The Type Bit Maps Field

    RRlist = []

    while bitmap:

        if len(bitmap) < 2:
            log_runtime.info("bitmap too short (%i)", len(bitmap))
            return

        window_block = orb(bitmap[0])  # window number
        offset = 256 * window_block  # offset of the Resource Record
        bitmap_len = orb(bitmap[1])  # length of the bitmap in bytes

        if bitmap_len <= 0 or bitmap_len > 32:
            log_runtime.info("bitmap length is no valid (%i)", bitmap_len)
            return

        tmp_bitmap = bitmap[2:2 + bitmap_len]

        # Let's compare each bit of tmp_bitmap and compute the real RR value
        for b in range(len(tmp_bitmap)):
            v = 128
            for i in range(8):
                if orb(tmp_bitmap[b]) & v:
                    # each of the RR is encoded as a bit
                    RRlist += [offset + b * 8 + i]
                v = v >> 1

        # Next block if any
        bitmap = bitmap[2 + bitmap_len:]

    return RRlist
Exemplo n.º 34
0
    def deal_common_pkt(self, pkt):
        # Send to DHCP server
        # LLC / SNAP to Ether
        if SNAP in pkt:
            ether_pkt = Ether(src=self.client,dst=self.mac) / pkt[SNAP].payload
            self.dhcp_server.reply(ether_pkt)

        # If an ARP request is made, extract client IP and answer
        if ARP in pkt and \
           pkt[ARP].op == 1 and pkt[ARP].pdst == self.dhcp_server.gw:
            if self.arp_target_ip is None:
                self.arp_target_ip = pkt[ARP].psrc
                log_runtime.info("Detected IP: %s", self.arp_target_ip)

            # Reply
            ARP_ans = LLC()/SNAP()/ARP(
                op="is-at",
                psrc=self.arp_source_ip,
                pdst=self.arp_target_ip,
                hwsrc=self.mac,
                hwdst=self.client,
            )
            self.send_wpa_to_client(ARP_ans)
Exemplo n.º 35
0
 def _tls_auth_decrypt(self, hdr, s):
     """
     Provided with the record header and AEAD-ciphered data, return the
     sliced and clear tuple (nonce, TLSCompressed.fragment, mac). Note that
     we still return the slicing of the original input in case of decryption
     failure. Also, if the integrity check fails, a warning will be issued,
     but we still return the sliced (unauthenticated) plaintext.
     """
     try:
         read_seq_num = struct.pack("!Q", self.tls_session.rcs.seq_num)
         self.tls_session.rcs.seq_num += 1
         # self.type and self.version have not been parsed yet,
         # this is why we need to look into the provided hdr.
         add_data = read_seq_num + chb(hdr[0]) + hdr[1:3]
         # Last two bytes of add_data are appended by the return function
         return self.tls_session.rcs.cipher.auth_decrypt(add_data, s,
                                                         read_seq_num)
     except CipherError as e:
         return e.args
     except AEADTagError as e:
         pkt_info = self.firstlayer().summary()
         log_runtime.info("TLS: record integrity check failed [%s]", pkt_info)  # noqa: E501
         return e.args
Exemplo n.º 36
0
 def _tls_auth_decrypt(self, hdr, s):
     """
     Provided with the record header and AEAD-ciphered data, return the
     sliced and clear tuple (nonce, TLSCompressed.fragment, mac). Note that
     we still return the slicing of the original input in case of decryption
     failure. Also, if the integrity check fails, a warning will be issued,
     but we still return the sliced (unauthenticated) plaintext.
     """
     try:
         read_seq_num = struct.pack("!Q", self.tls_session.rcs.seq_num)
         self.tls_session.rcs.seq_num += 1
         # self.type and self.version have not been parsed yet,
         # this is why we need to look into the provided hdr.
         add_data = read_seq_num + chb(hdr[0]) + hdr[1:3]
         # Last two bytes of add_data are appended by the return function
         return self.tls_session.rcs.cipher.auth_decrypt(add_data, s,
                                                         read_seq_num)
     except CipherError as e:
         return e.args
     except AEADTagError as e:
         pkt_info = self.firstlayer().summary()
         log_runtime.info("TLS: record integrity check failed [%s]", pkt_info)  # noqa: E501
         return e.args
Exemplo n.º 37
0
 def post_dissection(self, pkt):
     s = self.tls_session
     if s.sslv2_challenge is not None:
         if self.challenge != s.sslv2_challenge:
             pkt_info = pkt.firstlayer().summary()
             log_runtime.info("TLS: invalid ServerVerify received [%s]", pkt_info)  # noqa: E501
Exemplo n.º 38
0
 def __init__(self, iface=None, type=ETH_P_ALL, promisc=None, filter=None,
              nofilter=0, monitor=None):
     self.iface = network_name(iface or conf.iface)
     self.type = type
     self.promisc = conf.sniff_promisc if promisc is None else promisc
     if monitor is not None:
         log_runtime.info(
             "The 'monitor' argument has no effect on native linux sockets."
         )
     self.ins = socket.socket(
         socket.AF_PACKET, socket.SOCK_RAW, socket.htons(type))
     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, iface)
             except ImportError as ex:
                 log_runtime.error("Cannot set filter: %s", ex)
     if self.promisc:
         set_promisc(self.ins, self.iface)
     self.ins.bind((self.iface, type))
     _flush_fd(self.ins)
     self.ins.setsockopt(
         socket.SOL_SOCKET,
         socket.SO_RCVBUF,
         conf.bufsize
     )
     if not six.PY2:
         # Receive Auxiliary Data (VLAN tags)
         try:
             self.ins.setsockopt(SOL_PACKET, PACKET_AUXDATA, 1)
             self.ins.setsockopt(
                 socket.SOL_SOCKET,
                 SO_TIMESTAMPNS,
                 1
             )
             self.auxdata_available = True
         except OSError:
             # Note: Auxiliary Data is only supported since
             #       Linux 2.6.21
             msg = "Your Linux Kernel does not support Auxiliary Data!"
             log_runtime.info(msg)
     if isinstance(self, L2ListenSocket):
         self.outs = None
     else:
         self.outs = self.ins
         self.outs.setsockopt(
             socket.SOL_SOCKET,
             socket.SO_SNDBUF,
             conf.bufsize
         )
     sa_ll = self.ins.getsockname()
     if sa_ll[3] in conf.l2types:
         self.LL = conf.l2types[sa_ll[3]]
         self.lvl = 2
     elif sa_ll[1] in conf.l3types:
         self.LL = conf.l3types[sa_ll[1]]
         self.lvl = 3
     else:
         self.LL = conf.default_l2
         self.lvl = 2
         warning("Unable to guess type (interface=%s protocol=%#x family=%i). Using %s", sa_ll[0], sa_ll[1], sa_ll[3], self.LL.name)  # noqa: E501
Exemplo n.º 39
0
    def pre_dissect(self, s):
        """
        Decrypt, verify and decompress the message,
        i.e. apply the previous methods according to the reading cipher type.
        If the decryption was successful, 'len' will be the length of the
        TLSPlaintext.fragment. Else, it should be the length of the
        _TLSEncryptedContent.
        """
        if len(s) < 5:
            raise Exception("Invalid record: header is too short.")

        msglen = struct.unpack('!H', s[3:5])[0]
        hdr, efrag, r = s[:5], s[5:5 + msglen], s[msglen + 5:]

        iv = mac = pad = b""
        self.padlen = None
        decryption_success = False

        cipher_type = self.tls_session.rcs.cipher.type

        if cipher_type == 'block':
            version = struct.unpack("!H", s[1:3])[0]

            # Decrypt
            try:
                if version >= 0x0302:
                    # Explicit IV for TLS 1.1 and 1.2
                    block_size = self.tls_session.rcs.cipher.block_size
                    iv, efrag = efrag[:block_size], efrag[block_size:]
                    self.tls_session.rcs.cipher.iv = iv
                    pfrag = self._tls_decrypt(efrag)
                else:
                    # Implicit IV for SSLv3 and TLS 1.0
                    pfrag = self._tls_decrypt(efrag)
            except CipherError as e:
                # This will end up dissected as _TLSEncryptedContent.
                cfrag = e.args[0]
            else:
                decryption_success = True
                # Excerpt below better corresponds to TLS 1.1 IV definition,
                # but the result is the same as with TLS 1.2 anyway.
                # This leading *IV* has been decrypted by _tls_decrypt with a
                # random IV, hence it does not correspond to anything.
                # What actually matters is that we got the first encrypted block  # noqa: E501
                # in order to decrypt the second block (first data block).
                # if version >= 0x0302:
                #    block_size = self.tls_session.rcs.cipher.block_size
                #    iv, pfrag = pfrag[:block_size], pfrag[block_size:]
                #    l = struct.unpack('!H', hdr[3:5])[0]
                #    hdr = hdr[:3] + struct.pack('!H', l-block_size)

                # Extract padding ('pad' actually includes the trailing padlen)
                padlen = orb(pfrag[-1]) + 1
                mfrag, pad = pfrag[:-padlen], pfrag[-padlen:]
                self.padlen = padlen

                # Extract MAC
                tmp_len = self.tls_session.rcs.mac_len
                if tmp_len != 0:
                    cfrag, mac = mfrag[:-tmp_len], mfrag[-tmp_len:]
                else:
                    cfrag, mac = mfrag, b""

                # Verify integrity
                chdr = hdr[:3] + struct.pack('!H', len(cfrag))
                is_mac_ok = self._tls_hmac_verify(chdr, cfrag, mac)
                if not is_mac_ok:
                    pkt_info = self.firstlayer().summary()
                    log_runtime.info("TLS: record integrity check failed [%s]", pkt_info)  # noqa: E501

        elif cipher_type == 'stream':
            # Decrypt
            try:
                pfrag = self._tls_decrypt(efrag)
            except CipherError as e:
                # This will end up dissected as _TLSEncryptedContent.
                cfrag = e.args[0]
            else:
                decryption_success = True
                mfrag = pfrag

                # Extract MAC
                tmp_len = self.tls_session.rcs.mac_len
                if tmp_len != 0:
                    cfrag, mac = mfrag[:-tmp_len], mfrag[-tmp_len:]
                else:
                    cfrag, mac = mfrag, b""

                # Verify integrity
                chdr = hdr[:3] + struct.pack('!H', len(cfrag))
                is_mac_ok = self._tls_hmac_verify(chdr, cfrag, mac)
                if not is_mac_ok:
                    pkt_info = self.firstlayer().summary()
                    log_runtime.info("TLS: record integrity check failed [%s]", pkt_info)  # noqa: E501

        elif cipher_type == 'aead':
            # Authenticated encryption
            # crypto/cipher_aead.py prints a warning for integrity failure
            if (conf.crypto_valid_advanced and
                    isinstance(self.tls_session.rcs.cipher, Cipher_CHACHA20_POLY1305)):  # noqa: E501
                iv = b""
                cfrag, mac = self._tls_auth_decrypt(hdr, efrag)
            else:
                iv, cfrag, mac = self._tls_auth_decrypt(hdr, efrag)
            decryption_success = True       # see XXX above

        frag = self._tls_decompress(cfrag)

        if (decryption_success and
                not isinstance(self.tls_session.rcs.cipher, Cipher_NULL)):
            self.deciphered_len = len(frag)
        else:
            self.deciphered_len = None

        reconstructed_body = iv + frag + mac + pad

        return hdr + reconstructed_body + r
Exemplo n.º 40
0
 def post_dissection(self, pkt):
     s = self.tls_session
     if s.sslv2_connection_id is not None:
         if self.connection_id != s.sslv2_connection_id:
             pkt_info = pkt.firstlayer().summary()
             log_runtime.info("TLS: invalid client Finished received [%s]", pkt_info)  # noqa: E501
Exemplo n.º 41
0
def dns_get_str(s, pointer=0, pkt=None, _fullpacket=False):
    """This function decompresses a string s, starting
    from the given pointer.

    :param s: the string to decompress
    :param pointer: first pointer on the string (default: 0)
    :param pkt: (optional) an InheritOriginDNSStrPacket packet

    :returns: (decoded_string, end_index, left_string)
    """
    # The _fullpacket parameter is reserved for scapy. It indicates
    # that the string provided is the full dns packet, and thus
    # will be the same than pkt._orig_str. The "Cannot decompress"
    # error will not be prompted if True.
    max_length = len(s)
    # The result = the extracted name
    name = b""
    # Will contain the index after the pointer, to be returned
    after_pointer = None
    processed_pointers = []  # Used to check for decompression loops
    # Analyse given pkt
    if pkt and hasattr(pkt, "_orig_s") and pkt._orig_s:
        s_full = pkt._orig_s
    else:
        s_full = None
    bytes_left = None
    while True:
        if abs(pointer) >= max_length:
            log_runtime.info("DNS RR prematured end (ofs=%i, len=%i)", pointer,
                             len(s))
            break
        cur = orb(s[pointer])  # get pointer value
        pointer += 1  # make pointer go forward
        if cur & 0xc0:  # Label pointer
            if after_pointer is None:
                # after_pointer points to where the remaining bytes start,
                # as pointer will follow the jump token
                after_pointer = pointer + 1
            if pointer >= max_length:
                log_runtime.info("DNS incomplete jump token at (ofs=%i)",
                                 pointer)
                break
            # Follow the pointer
            pointer = ((cur & ~0xc0) << 8) + orb(s[pointer]) - 12
            if pointer in processed_pointers:
                warning("DNS decompression loop detected")
                break
            if not _fullpacket:
                # Do we have access to the whole packet ?
                if s_full:
                    # Yes -> use it to continue
                    bytes_left = s[after_pointer:]
                    s = s_full
                    max_length = len(s)
                    _fullpacket = True
                else:
                    # No -> abort
                    raise Scapy_Exception("DNS message can't be compressed " +
                                          "at this point!")
            processed_pointers.append(pointer)
            continue
        elif cur > 0:  # Label
            # cur = length of the string
            name += s[pointer:pointer + cur] + b"."
            pointer += cur
        else:
            break
    if after_pointer is not None:
        # Return the real end index (not the one we followed)
        pointer = after_pointer
    if bytes_left is None:
        bytes_left = s[pointer:]
    # name, end_index, remaining
    return name, pointer, bytes_left, len(processed_pointers) != 0
Exemplo n.º 42
0
def sndrcv(pks, pkt, timeout = None, inter = 0, verbose=None, chainCC=0, retry=0, multi=0):
    if not isinstance(pkt, Gen):
        pkt = SetGen(pkt)
        
    if verbose is None:
        verbose = conf.verb
    debug.recv = plist.PacketList([],"Unanswered")
    debug.sent = plist.PacketList([],"Sent")
    debug.match = plist.SndRcvList([])
    nbrecv=0
    ans = []
    # do it here to fix random fields, so that parent and child have the same
    all_stimuli = tobesent = [p for p in pkt]
    notans = len(tobesent)

    hsent={}
    for i in tobesent:
        h = i.hashret()
        if h in hsent:
            hsent[h].append(i)
        else:
            hsent[h] = [i]
    if retry < 0:
        retry = -retry
        autostop=retry
    else:
        autostop=0


    while retry >= 0:
        found=0
    
        if timeout < 0:
            timeout = None
            
        rdpipe,wrpipe = os.pipe()
        rdpipe=os.fdopen(rdpipe)
        wrpipe=os.fdopen(wrpipe,"w")

        pid=1
        try:
            pid = os.fork()
            if pid == 0:
                try:
                    sys.stdin.close()
                    rdpipe.close()
                    try:
                        i = 0
                        if verbose:
                            print("Begin emission:")
                        for p in tobesent:
                            pks.send(p)
                            i += 1
                            time.sleep(inter)
                        if verbose:
                            print("Finished to send %i packets." % i)
                    except SystemExit:
                        pass
                    except KeyboardInterrupt:
                        pass
                    except:
                        log_runtime.exception("--- Error in child %i" % os.getpid())
                        log_runtime.info("--- Error in child %i" % os.getpid())
                finally:
                    try:
                        os.setpgrp() # Chance process group to avoid ctrl-C
                        sent_times = [p.sent_time for p in all_stimuli if p.sent_time]
                        six.moves.cPickle.dump( (conf.netcache,sent_times), wrpipe )
                        wrpipe.close()
                    except:
                        pass
            elif pid < 0:
                log_runtime.error("fork error")
            else:
                wrpipe.close()
                stoptime = 0
                remaintime = None
                inmask = [rdpipe,pks]
                try:
                    try:
                        while True:
                            if stoptime:
                                remaintime = stoptime-time.time()
                                if remaintime <= 0:
                                    break
                            r = None
                            if conf.use_bpf:
                                from scapy.arch.bpf.supersocket import bpf_select
                                inp = bpf_select(inmask)
                                if pks in inp:
                                    r = pks.recv()
                            elif not isinstance(pks, StreamSocket) and (FREEBSD or DARWIN or OPENBSD):
                                inp, out, err = select(inmask,[],[], 0.05)
                                if len(inp) == 0 or pks in inp:
                                    r = pks.nonblock_recv()
                            else:
                                inp = []
                                try:
                                    inp, out, err = select(inmask,[],[], remaintime)
                                except (IOError, select_error) as exc:
                                    # select.error has no .errno attribute
                                    if exc.args[0] != errno.EINTR:
                                        raise
                                if len(inp) == 0:
                                    break
                                if pks in inp:
                                    r = pks.recv(MTU)
                            if rdpipe in inp:
                                if timeout:
                                    stoptime = time.time()+timeout
                                del(inmask[inmask.index(rdpipe)])
                            if r is None:
                                continue
                            ok = 0
                            h = r.hashret()
                            if h in hsent:
                                hlst = hsent[h]
                                for i, sentpkt in enumerate(hlst):
                                    if r.answers(sentpkt):
                                        ans.append((sentpkt, r))
                                        if verbose > 1:
                                            os.write(1, "*")
                                        ok = 1
                                        if not multi:
                                            del hlst[i]
                                            notans -= 1
                                        else:
                                            if not hasattr(sentpkt, '_answered'):
                                                notans -= 1
                                            sentpkt._answered = 1
                                        break
                            if notans == 0 and not multi:
                                break
                            if not ok:
                                if verbose > 1:
                                    os.write(1, ".")
                                nbrecv += 1
                                if conf.debug_match:
                                    debug.recv.append(r)
                    except KeyboardInterrupt:
                        if chainCC:
                            raise
                finally:
                    try:
                        nc,sent_times = six.moves.cPickle.load(rdpipe)
                    except EOFError:
                        warning("Child died unexpectedly. Packets may have not been sent %i"%os.getpid())
                    else:
                        conf.netcache.update(nc)
                        for p,t in zip(all_stimuli, sent_times):
                            p.sent_time = t
                    os.waitpid(pid,0)
        finally:
            if pid == 0:
                os._exit(0)

        remain = list(itertools.chain(*six.itervalues(hsent)))
        if multi:
            remain = [p for p in remain if not hasattr(p, '_answered')]

        if autostop and len(remain) > 0 and len(remain) != len(tobesent):
            retry = autostop
            
        tobesent = remain
        if len(tobesent) == 0:
            break
        retry -= 1
        
    if conf.debug_match:
        debug.sent=plist.PacketList(remain[:],"Sent")
        debug.match=plist.SndRcvList(ans[:])

    #clean the ans list to delete the field _answered
    if (multi):
        for s,r in ans:
            if hasattr(s, '_answered'):
                del(s._answered)
    
    if verbose:
        print("\nReceived %i packets, got %i answers, remaining %i packets" % (nbrecv+len(ans), len(ans), notans))
    return plist.SndRcvList(ans),plist.PacketList(remain,"Unanswered")
Exemplo n.º 43
0
def read_routes():
    # type: () -> List[Tuple[int, int, str, str, str, int]]
    """Return a list of IPv4 routes than can be used by Scapy.

    This function parses netstat.
    """
    if SOLARIS:
        f = os.popen("netstat -rvn -f inet")
    elif FREEBSD:
        f = os.popen("netstat -rnW -f inet")  # -W to show long interface names
    else:
        f = os.popen("netstat -rn -f inet")
    ok = 0
    mtu_present = False
    prio_present = False
    refs_present = False
    use_present = False
    routes = []  # type: List[Tuple[int, int, str, str, str, int]]
    pending_if = []  # type: List[Tuple[int, int, str]]
    for line in f.readlines():
        if not line:
            break
        line = line.strip().lower()
        if line.find("----") >= 0:  # a separation line
            continue
        if not ok:
            if line.find("destination") >= 0:
                ok = 1
                mtu_present = "mtu" in line
                prio_present = "prio" in line
                refs_present = "ref" in line  # There is no s on Solaris
                use_present = "use" in line or "nhop" in line
            continue
        if not line:
            break
        rt = line.split()
        if SOLARIS:
            dest_, netmask_, gw, netif = rt[:4]
            flg = rt[4 + mtu_present + refs_present]
        else:
            dest_, gw, flg = rt[:3]
            locked = OPENBSD and rt[6] == "l"
            offset = mtu_present + prio_present + refs_present + locked
            offset += use_present
            netif = rt[3 + offset]
        if flg.find("lc") >= 0:
            continue
        elif dest_ == "default":
            dest = 0
            netmask = 0
        elif SOLARIS:
            dest = scapy.utils.atol(dest_)
            netmask = scapy.utils.atol(netmask_)
        else:
            if "/" in dest_:
                dest_, netmask_ = dest_.split("/")
                netmask = scapy.utils.itom(int(netmask_))
            else:
                netmask = scapy.utils.itom((dest_.count(".") + 1) * 8)
            dest_ += ".0" * (3 - dest_.count("."))
            dest = scapy.utils.atol(dest_)
        # XXX: TODO: add metrics for unix.py (use -e option on netstat)
        metric = 1
        if "g" not in flg:
            gw = '0.0.0.0'
        if netif is not None:
            from scapy.arch import get_if_addr
            try:
                ifaddr = get_if_addr(netif)
                routes.append((dest, netmask, gw, netif, ifaddr, metric))
            except OSError as exc:
                if 'Device not configured' in str(exc):
                    # This means the interface name is probably truncated by
                    # netstat -nr. We attempt to guess it's name and if not we
                    # ignore it.
                    guessed_netif = _guess_iface_name(netif)
                    if guessed_netif is not None:
                        ifaddr = get_if_addr(guessed_netif)
                        routes.append((dest, netmask, gw, guessed_netif,
                                       ifaddr, metric))  # noqa: E501
                    else:
                        log_runtime.info(
                            "Could not guess partial interface name: %s",
                            netif)
                else:
                    raise
        else:
            pending_if.append((dest, netmask, gw))
    f.close()

    # On Solaris, netstat does not provide output interfaces for some routes
    # We need to parse completely the routing table to route their gw and
    # know their output interface
    for dest, netmask, gw in pending_if:
        gw_l = scapy.utils.atol(gw)
        max_rtmask, gw_if, gw_if_addr = 0, None, None
        for rtdst, rtmask, _, rtif, rtaddr, _ in routes[:]:
            if gw_l & rtmask == rtdst:
                if rtmask >= max_rtmask:
                    max_rtmask = rtmask
                    gw_if = rtif
                    gw_if_addr = rtaddr
        # XXX: TODO add metrics
        metric = 1
        if gw_if and gw_if_addr:
            routes.append((dest, netmask, gw, gw_if, gw_if_addr, metric))
        else:
            warning("Did not find output interface to reach gateway %s", gw)

    return routes
Exemplo n.º 44
0
 def post_dissection(self, pkt):
     s = self.tls_session
     if s.sslv2_connection_id is not None:
         if self.connection_id != s.sslv2_connection_id:
             pkt_info = pkt.firstlayer().summary()
             log_runtime.info("TLS: invalid client Finished received [%s]", pkt_info)
Exemplo n.º 45
0
 def post_dissection(self, pkt):
     s = self.tls_session
     if s.sslv2_challenge is not None:
         if self.challenge != s.sslv2_challenge:
             pkt_info = pkt.firstlayer().summary()
             log_runtime.info("TLS: invalid ServerVerify received [%s]", pkt_info)
Exemplo n.º 46
0
def sndrcv(pks, pkt, timeout = 2, inter = 0, verbose=None, chainCC=0, retry=0, multi=0):
    if not isinstance(pkt, Gen):
        pkt = SetGen(pkt)
        
    if verbose is None:
        verbose = conf.verb
    debug.recv = plist.PacketList([],"Unanswered")
    debug.sent = plist.PacketList([],"Sent")
    debug.match = plist.SndRcvList([])
    nbrecv=0
    ans = []
    # do it here to fix random fields, so that parent and child have the same
    all_stimuli = tobesent = [p for p in pkt]
    notans = len(tobesent)

    hsent={}
    for i in tobesent:
        h = i.hashret()
        if h in hsent:
            hsent[h].append(i)
        else:
            hsent[h] = [i]
    if retry < 0:
        retry = -retry
        autostop=retry
    else:
        autostop=0


    while retry >= 0:
        found=0
    
        if timeout < 0:
            timeout = None

        pid=1
        try:
            if WINDOWS or pid == 0:
                try:
                    try:
                        i = 0
                        if verbose:
                            print "Begin emission:"
                        for p in tobesent:
                            pks.send(p)
                            i += 1
                            time.sleep(inter)
                        if verbose:
                            print "Finished to send %i packets." % i
                    except SystemExit:
                        pass
                    except KeyboardInterrupt:
                        pass
                    except:
                        log_runtime.exception("--- Error sending packets")
                        log_runtime.info("--- Error sending packets")
                finally:
                    try:
                        sent_times = [p.sent_time for p in all_stimuli if p.sent_time]
                    except:
                        pass
            if WINDOWS or pid > 0:
                # Timeout starts after last packet is sent (as in Unix version) 
                if timeout:
                    stoptime = time.time()+timeout
                else:
                    stoptime = 0
                remaintime = None
                inmask = [pks.ins.fd]
                try:
                    try:
                        while 1:
                            if stoptime:
                                remaintime = stoptime-time.time()
                                if remaintime <= 0:
                                    break
                            r = pks.recv(MTU)
                            if r is None:
                                continue
                            ok = 0
                            h = r.hashret()
                            if h in hsent:
                                hlst = hsent[h]
                                for i in range(len(hlst)):
                                    if r.answers(hlst[i]):
                                        ans.append((hlst[i],r))
                                        if verbose > 1:
                                            os.write(1, "*")
                                        ok = 1                                
                                        if not multi:
                                            del(hlst[i])
                                            notans -= 1;
                                        else:
                                            if not hasattr(hlst[i], '_answered'):
                                                notans -= 1;
                                            hlst[i]._answered = 1;
                                        break
                            if notans == 0 and not multi:
                                break
                            if not ok:
                                if verbose > 1:
                                    os.write(1, ".")
                                nbrecv += 1
                                if conf.debug_match:
                                    debug.recv.append(r)
                    except KeyboardInterrupt:
                        if chainCC:
                            raise
                finally:
                    if WINDOWS:
                        for p,t in zip(all_stimuli, sent_times):
                            p.sent_time = t
        finally:
            pass

        remain = reduce(list.__add__, hsent.values(), [])
        if multi:
            remain = filter(lambda p: not hasattr(p, '_answered'), remain);
            
        if autostop and len(remain) > 0 and len(remain) != len(tobesent):
            retry = autostop
            
        tobesent = remain
        if len(tobesent) == 0:
            break
        retry -= 1
        
    if conf.debug_match:
        debug.sent=plist.PacketList(remain[:],"Sent")
        debug.match=plist.SndRcvList(ans[:])

    #clean the ans list to delete the field _answered
    if (multi):
        for s,r in ans:
            if hasattr(s, '_answered'):
                del(s._answered)
    
    if verbose:
        print "\nReceived %i packets, got %i answers, remaining %i packets" % (nbrecv+len(ans), len(ans), notans)
    return plist.SndRcvList(ans),plist.PacketList(remain,"Unanswered")
Exemplo n.º 47
0
def sendpfast(x,  # type: _PacketIterable
              pps=None,  # type: Optional[float]
              mbps=None,  # type: Optional[float]
              realtime=False,  # type: bool
              loop=0,  # type: int
              file_cache=False,  # type: bool
              iface=None,  # type: Optional[_GlobInterfaceType]
              replay_args=None,  # type: Optional[List[str]]
              parse_results=False,  # type: bool
              ):
    # type: (...) -> Optional[Dict[str, Any]]
    """Send packets at layer 2 using tcpreplay for performance

    :param pps:  packets per second
    :param mpbs: MBits per second
    :param realtime: use packet's timestamp, bending time with real-time value
    :param loop: number of times to process the packet list
    :param file_cache: cache packets in RAM instead of reading from
        disk at each iteration
    :param iface: output interface
    :param replay_args: List of additional tcpreplay args (List[str])
    :param parse_results: Return a dictionary of information
        outputted by tcpreplay (default=False)
    :returns: stdout, stderr, command used
    """
    if iface is None:
        iface = conf.iface
    argv = [conf.prog.tcpreplay, "--intf1=%s" % network_name(iface)]
    if pps is not None:
        argv.append("--pps=%i" % pps)
    elif mbps is not None:
        argv.append("--mbps=%f" % mbps)
    elif realtime is not None:
        argv.append("--multiplier=%f" % realtime)
    else:
        argv.append("--topspeed")

    if loop:
        argv.append("--loop=%i" % loop)
    if file_cache:
        argv.append("--preload-pcap")

    # Check for any additional args we didn't cover.
    if replay_args is not None:
        argv.extend(replay_args)

    f = get_temp_file()
    argv.append(f)
    wrpcap(f, x)
    results = None
    with ContextManagerSubprocess(conf.prog.tcpreplay):
        try:
            cmd = subprocess.Popen(argv, stdout=subprocess.PIPE,
                                   stderr=subprocess.PIPE)
        except KeyboardInterrupt:
            log_interactive.info("Interrupted by user")
        except Exception:
            os.unlink(f)
            raise
        else:
            stdout, stderr = cmd.communicate()
            if stderr:
                log_runtime.warning(stderr.decode())
            if parse_results:
                results = _parse_tcpreplay_result(stdout, stderr, argv)
            elif conf.verb > 2:
                log_runtime.info(stdout.decode())
    os.unlink(f)
    return results
Exemplo n.º 48
0
def sndrcv(pks,
           pkt,
           timeout=None,
           inter=0,
           verbose=None,
           chainCC=0,
           retry=0,
           multi=0):
    if not isinstance(pkt, Gen):
        pkt = SetGen(pkt)

    if verbose is None:
        verbose = conf.verb
    debug.recv = plist.PacketList([], "Unanswered")
    debug.sent = plist.PacketList([], "Sent")
    debug.match = plist.SndRcvList([])
    nbrecv = 0
    ans = []
    # do it here to fix random fields, so that parent and child have the same
    all_stimuli = tobesent = [p for p in pkt]
    notans = len(tobesent)

    hsent = {}
    for i in tobesent:
        h = i.hashret()
        if h in hsent:
            hsent[h].append(i)
        else:
            hsent[h] = [i]
    if retry < 0:
        retry = -retry
        autostop = retry
    else:
        autostop = 0

    while retry >= 0:
        found = 0

        if timeout < 0:
            timeout = None

        rdpipe, wrpipe = os.pipe()
        rdpipe = os.fdopen(rdpipe)
        wrpipe = os.fdopen(wrpipe, "w")

        pid = 1
        try:
            pid = os.fork()
            if pid == 0:
                try:
                    sys.stdin.close()
                    rdpipe.close()
                    try:
                        i = 0
                        if verbose:
                            print "Begin emission:"
                        for p in tobesent:
                            pks.send(p)
                            i += 1
                            time.sleep(inter)
                        if verbose:
                            print "Finished to send %i packets." % i
                    except SystemExit:
                        pass
                    except KeyboardInterrupt:
                        pass
                    except:
                        log_runtime.exception("--- Error in child %i" %
                                              os.getpid())
                        log_runtime.info("--- Error in child %i" % os.getpid())
                finally:
                    try:
                        os.setpgrp()  # Chance process group to avoid ctrl-C
                        sent_times = [
                            p.sent_time for p in all_stimuli if p.sent_time
                        ]
                        cPickle.dump((conf.netcache, sent_times), wrpipe)
                        wrpipe.close()
                    except:
                        pass
            elif pid < 0:
                log_runtime.error("fork error")
            else:
                wrpipe.close()
                stoptime = 0
                remaintime = None
                inmask = [rdpipe, pks]
                try:
                    try:
                        while 1:
                            if stoptime:
                                remaintime = stoptime - time.time()
                                if remaintime <= 0:
                                    break
                            r = None
                            if not isinstance(
                                    pks, StreamSocket) and (FREEBSD or DARWIN):
                                inp, out, err = select(inmask, [], [], 0.05)
                                if len(inp) == 0 or pks in inp:
                                    r = pks.nonblock_recv()
                            else:
                                inp = []
                                try:
                                    inp, out, err = select(
                                        inmask, [], [], remaintime)
                                except IOError, exc:
                                    if exc.errno != errno.EINTR:
                                        raise
                                if len(inp) == 0:
                                    break
                                if pks in inp:
                                    r = pks.recv(MTU)
                            if rdpipe in inp:
                                if timeout:
                                    stoptime = time.time() + timeout
                                del (inmask[inmask.index(rdpipe)])
                            if r is None:
                                continue
                            ok = 0
                            h = r.hashret()
                            if h in hsent:
                                hlst = hsent[h]
                                for i, sentpkt in enumerate(hlst):
                                    if r.answers(sentpkt):
                                        ans.append((sentpkt, r))
                                        if verbose > 1:
                                            os.write(1, "*")
                                        ok = 1
                                        if not multi:
                                            del hlst[i]
                                            notans -= 1
                                        else:
                                            if not hasattr(
                                                    sentpkt, '_answered'):
                                                notans -= 1
                                            sentpkt._answered = 1
                                        break
                            if notans == 0 and not multi:
                                break
                            if not ok:
                                if verbose > 1:
                                    os.write(1, ".")
                                nbrecv += 1
                                if conf.debug_match:
                                    debug.recv.append(r)
                    except KeyboardInterrupt:
                        if chainCC:
                            raise
                finally:
                    try:
                        nc, sent_times = cPickle.load(rdpipe)
                    except EOFError:
                        warning(
                            "Child died unexpectedly. Packets may have not been sent %i"
                            % os.getpid())
                    else:
                        conf.netcache.update(nc)
                        for p, t in zip(all_stimuli, sent_times):
                            p.sent_time = t
                    os.waitpid(pid, 0)
        finally:
            if pid == 0:
                os._exit(0)

        remain = list(itertools.chain(*hsent.itervalues()))
        if multi:
            remain = [p for p in remain if not hasattr(p, '_answered')]

        if autostop and len(remain) > 0 and len(remain) != len(tobesent):
            retry = autostop

        tobesent = remain
        if len(tobesent) == 0:
            break
        retry -= 1

    if conf.debug_match:
        debug.sent = plist.PacketList(remain[:], "Sent")
        debug.match = plist.SndRcvList(ans[:])

    #clean the ans list to delete the field _answered
    if (multi):
        for s, r in ans:
            if hasattr(s, '_answered'):
                del (s._answered)

    if verbose:
        print "\nReceived %i packets, got %i answers, remaining %i packets" % (
            nbrecv + len(ans), len(ans), notans)
    return plist.SndRcvList(ans), plist.PacketList(remain, "Unanswered")
Exemplo n.º 49
0
    def pre_dissect(self, s):
        """
        Decrypt, verify and decompress the message,
        i.e. apply the previous methods according to the reading cipher type.
        If the decryption was successful, 'len' will be the length of the
        TLSPlaintext.fragment. Else, it should be the length of the
        _TLSEncryptedContent.
        """
        if len(s) < 5:
            raise Exception("Invalid record: header is too short.")

        msglen = struct.unpack('!H', s[3:5])[0]
        hdr, efrag, r = s[:5], s[5:5 + msglen], s[msglen + 5:]

        iv = mac = pad = b""
        self.padlen = None
        decryption_success = False

        cipher_type = self.tls_session.rcs.cipher.type

        if cipher_type == 'block':
            version = struct.unpack("!H", s[1:3])[0]

            # Decrypt
            try:
                if version >= 0x0302:
                    # Explicit IV for TLS 1.1 and 1.2
                    block_size = self.tls_session.rcs.cipher.block_size
                    iv, efrag = efrag[:block_size], efrag[block_size:]
                    self.tls_session.rcs.cipher.iv = iv
                    pfrag = self._tls_decrypt(efrag)
                else:
                    # Implicit IV for SSLv3 and TLS 1.0
                    pfrag = self._tls_decrypt(efrag)
            except CipherError as e:
                # This will end up dissected as _TLSEncryptedContent.
                cfrag = e.args[0]
            else:
                decryption_success = True
                # Excerpt below better corresponds to TLS 1.1 IV definition,
                # but the result is the same as with TLS 1.2 anyway.
                # This leading *IV* has been decrypted by _tls_decrypt with a
                # random IV, hence it does not correspond to anything.
                # What actually matters is that we got the first encrypted block
                # in order to decrypt the second block (first data block).
                # if version >= 0x0302:
                #    block_size = self.tls_session.rcs.cipher.block_size
                #    iv, pfrag = pfrag[:block_size], pfrag[block_size:]
                #    l = struct.unpack('!H', hdr[3:5])[0]
                #    hdr = hdr[:3] + struct.pack('!H', l-block_size)

                # Extract padding ('pad' actually includes the trailing padlen)
                padlen = orb(pfrag[-1]) + 1
                mfrag, pad = pfrag[:-padlen], pfrag[-padlen:]
                self.padlen = padlen

                # Extract MAC
                l = self.tls_session.rcs.mac_len
                if l != 0:
                    cfrag, mac = mfrag[:-l], mfrag[-l:]
                else:
                    cfrag, mac = mfrag, b""

                # Verify integrity
                chdr = hdr[:3] + struct.pack('!H', len(cfrag))
                is_mac_ok = self._tls_hmac_verify(chdr, cfrag, mac)
                if not is_mac_ok:
                    pkt_info = self.firstlayer().summary()
                    log_runtime.info("TLS: record integrity check failed [%s]",
                                     pkt_info)

        elif cipher_type == 'stream':
            # Decrypt
            try:
                pfrag = self._tls_decrypt(efrag)
            except CipherError as e:
                # This will end up dissected as _TLSEncryptedContent.
                cfrag = e.args[0]
            else:
                decryption_success = True
                mfrag = pfrag

                # Extract MAC
                l = self.tls_session.rcs.mac_len
                if l != 0:
                    cfrag, mac = mfrag[:-l], mfrag[-l:]
                else:
                    cfrag, mac = mfrag, b""

                # Verify integrity
                chdr = hdr[:3] + struct.pack('!H', len(cfrag))
                is_mac_ok = self._tls_hmac_verify(chdr, cfrag, mac)
                if not is_mac_ok:
                    pkt_info = self.firstlayer().summary()
                    log_runtime.info("TLS: record integrity check failed [%s]",
                                     pkt_info)

        elif cipher_type == 'aead':
            # Authenticated encryption
            # crypto/cipher_aead.py prints a warning for integrity failure
            if (conf.crypto_valid_advanced and isinstance(
                    self.tls_session.rcs.cipher, Cipher_CHACHA20_POLY1305)):
                iv = b""
                cfrag, mac = self._tls_auth_decrypt(hdr, efrag)
            else:
                iv, cfrag, mac = self._tls_auth_decrypt(hdr, efrag)
            decryption_success = True  # see XXX above

        frag = self._tls_decompress(cfrag)

        if (decryption_success
                and not isinstance(self.tls_session.rcs.cipher, Cipher_NULL)):
            self.deciphered_len = len(frag)
        else:
            self.deciphered_len = None

        reconstructed_body = iv + frag + mac + pad

        return hdr + reconstructed_body + r