Exemple #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)")
Exemple #2
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)")
Exemple #3
0
 def debug_repr(self, name, secret):
     if conf.debug_tls and secret:
         log_runtime.debug("TLS: %s %s %s: %s",
                           self.connection_end,
                           self.row,
                           name,
                           repr_hex(secret))
    def _wait(cls, handle):
        # type: (Optional[TimeoutScheduler.Handle]) -> None
        """Waits until it is time to execute the provided handle, or until
        another thread calls _event.set()"""

        now = cls._time()

        # Check how much time until the next timeout
        if handle is None:
            to_wait = cls.GRACE
        else:
            to_wait = handle._when - now

        # Wait until the next timeout,
        # or until event.set() gets called in another thread.
        if to_wait > 0:
            log_runtime.debug(
                "TimeoutScheduler Thread going to sleep @ %f " + "for %fs",
                now, to_wait)
            interrupted = cls._event.wait(to_wait)
            new = cls._time()
            log_runtime.debug(
                "TimeoutScheduler Thread awake @ %f, slept for" +
                " %f, interrupted=%d", new, new - now, interrupted)

        # Clear the event so that we can wait on it again,
        # Must be done before doing the callbacks to avoid losing a set().
        cls._event.clear()
    def _task(cls):
        # type: () -> None
        """Executed in a background thread, this thread will automatically
        start when the first timeout is added and stop when the last timeout
        is removed or executed."""

        log_runtime.debug("TimeoutScheduler Thread spawning @ %f", cls._time())

        time_empty = None

        try:
            while 1:
                handle = cls._peek_next()
                if handle is None:
                    now = cls._time()
                    if time_empty is None:
                        time_empty = now
                    # 100 ms of grace time before killing the thread
                    if cls.GRACE < now - time_empty:
                        return
                else:
                    time_empty = None
                cls._wait(handle)
                cls._poll()

        finally:
            # Worst case scenario: if this thread dies, the next scheduled
            # timeout will start a new one
            log_runtime.debug("TimeoutScheduler Thread died @ %f", cls._time())
            cls._thread = None
Exemple #6
0
 def debug_repr(self, name, secret):
     if conf.debug_tls and secret:
         log_runtime.debug("TLS: %s %s %s: %s",
                           self.connection_end,
                           self.row,
                           name,
                           repr_hex(secret))
    def _recv_fc(self, data):
        # type: (bytes) -> None
        """Process a received 'Flow Control' frame"""
        log_runtime.debug("Processing FC")

        if (self.tx_state != ISOTP_WAIT_FC
                and self.tx_state != ISOTP_WAIT_FIRST_FC):
            return

        if self.tx_timeout_handle is not None:
            self.tx_timeout_handle.cancel()
            self.tx_timeout_handle = None

        if len(data) < 3:
            self.tx_state = ISOTP_IDLE
            warning("CF frame discarded because it was too short")
            return

        # get communication parameters only from the first FC frame
        if self.tx_state == ISOTP_WAIT_FIRST_FC:
            self.txfc_bs = six.indexbytes(data, 1)
            self.txfc_stmin = six.indexbytes(data, 2)

        if ((self.txfc_stmin > 0x7F)
                and ((self.txfc_stmin < 0xF1) or (self.txfc_stmin > 0xF9))):
            self.txfc_stmin = 0x7F

        if six.indexbytes(data, 2) <= 127:
            tx_gap = six.indexbytes(data, 2) / 1000.0
        elif 0xf1 <= six.indexbytes(data, 2) <= 0xf9:
            tx_gap = (six.indexbytes(data, 2) & 0x0f) / 10000.0
        else:
            tx_gap = 0
        self.tx_gap = tx_gap

        self.tx_state = ISOTP_WAIT_FC

        isotp_fc = six.indexbytes(data, 0) & 0x0f

        if isotp_fc == ISOTP_FC_CTS:
            self.tx_bs = 0
            self.tx_state = ISOTP_SENDING
            # start cyclic timer for sending CF frame
            self.tx_timeout_handle = TimeoutScheduler.schedule(
                self.tx_gap, self._tx_timer_handler)
        elif isotp_fc == ISOTP_FC_WT:
            # start timer to wait for next FC frame
            self.tx_state = ISOTP_WAIT_FC
            self.tx_timeout_handle = TimeoutScheduler.schedule(
                self.fc_timeout, self._tx_timer_handler)
        elif isotp_fc == ISOTP_FC_OVFLW:
            # overflow in receiver side
            self.tx_state = ISOTP_IDLE
            warning("Overflow happened at the receiver side")
            return
        else:
            self.tx_state = ISOTP_IDLE
            warning("Unknown FC frame type")
            return
Exemple #8
0
 def start(self):
     if self.thread_lock.acquire(0):
         _t = Thread(target=self.run)
         _t.setDaemon(True)
         _t.start()
         self.thread = _t
     else:
         log_runtime.debug("Pipe engine already running")
Exemple #9
0
 def start(self):
     if self.thread_lock.acquire(0):
         _t = Thread(target=self.run, name="scapy.pipetool.PipeEngine")
         _t.daemon = True
         _t.start()
         self.thread = _t
     else:
         log_runtime.debug("Pipe engine already running")
    def _recv_ff(self, data, ts):
        # type: (bytes, Union[float, EDecimal]) -> None
        """Process a received 'First Frame' frame"""
        log_runtime.debug("Processing FF")

        if self.rx_timeout_handle is not None:
            self.rx_timeout_handle.cancel()
            self.rx_timeout_handle = None

        if self.rx_state != ISOTP_IDLE:
            if conf.verb > 2:
                warning("RX state was reset because first frame was received")
            self.rx_state = ISOTP_IDLE

        if len(data) < 7:
            return
        self.rx_ll_dl = len(data)

        # get the FF_DL
        self.rx_len = (six.indexbytes(data, 0) & 0x0f) * 256 + six.indexbytes(
            data, 1)
        ff_pci_sz = 2

        # Check for FF_DL escape sequence supporting 32 bit PDU length
        if self.rx_len == 0:
            # FF_DL = 0 => get real length from next 4 bytes
            self.rx_len = six.indexbytes(data, 2) << 24
            self.rx_len += six.indexbytes(data, 3) << 16
            self.rx_len += six.indexbytes(data, 4) << 8
            self.rx_len += six.indexbytes(data, 5)
            ff_pci_sz = 6

        # copy the first received data bytes
        data_bytes = data[ff_pci_sz:]
        self.rx_idx = len(data_bytes)
        self.rx_buf = data_bytes
        self.rx_ts = ts

        # initial setup for this pdu reception
        self.rx_sn = 1
        self.rx_state = ISOTP_WAIT_DATA

        # no creation of flow control frames
        if not self.listen_only:
            # send our first FC frame
            load = self.ea_hdr
            load += struct.pack("BBB", N_PCI_FC, self.rxfc_bs, self.rxfc_stmin)
            self.can_send(load)

        # wait for a CF
        self.rx_bs = 0
        self.rx_timeout_handle = TimeoutScheduler.schedule(
            self.cf_timeout, self._rx_timer_handler)
Exemple #11
0
    def compute_master_secret(self):
        if self.pre_master_secret is None:
            warning("Missing pre_master_secret while computing master_secret!")
        if self.client_random is None:
            warning("Missing client_random while computing master_secret!")
        if self.server_random is None:
            warning("Missing server_random while computing master_secret!")

        ms = self.pwcs.prf.compute_master_secret(self.pre_master_secret,
                                                 self.client_random,
                                                 self.server_random)
        self.master_secret = ms
        if conf.debug_tls:
            log_runtime.debug("TLS: master secret: %s", repr_hex(ms))
Exemple #12
0
    def compute_master_secret(self):
        if self.pre_master_secret is None:
            warning("Missing pre_master_secret while computing master_secret!")
        if self.client_random is None:
            warning("Missing client_random while computing master_secret!")
        if self.server_random is None:
            warning("Missing server_random while computing master_secret!")

        ms = self.pwcs.prf.compute_master_secret(self.pre_master_secret,
                                                 self.client_random,
                                                 self.server_random)
        self.master_secret = ms
        if conf.debug_tls:
            log_runtime.debug("TLS: master secret: %s", repr_hex(ms))
Exemple #13
0
 def stop(self, _cmd="X"):
     try:
         with self.command_lock:
             if self.thread is not None:
                 self._write_cmd(_cmd)
                 self.thread.join()
                 try:
                     self.thread_lock.release()
                 except Exception:
                     pass
             else:
                 log_runtime.debug("Pipe engine thread not running")
     except KeyboardInterrupt:
         print("Interrupted by user.")
Exemple #14
0
    def compute_sslv2_key_material(self):
        if self.master_secret is None:
            warning("Missing master_secret while computing key_material!")
        if self.sslv2_challenge is None:
            warning("Missing challenge while computing key_material!")
        if self.sslv2_connection_id is None:
            warning("Missing connection_id while computing key_material!")

        km = self.pwcs.prf.derive_key_block(self.master_secret,
                                            self.sslv2_challenge,
                                            self.sslv2_connection_id,
                                            2 * self.pwcs.cipher.key_len)
        self.sslv2_key_material = km
        if conf.debug_tls:
            log_runtime.debug("TLS: master secret: %s", repr_hex(self.master_secret))  # noqa: E501
            log_runtime.debug("TLS: key material: %s", repr_hex(km))
Exemple #15
0
    def compute_sslv2_key_material(self):
        if self.master_secret is None:
            warning("Missing master_secret while computing key_material!")
        if self.sslv2_challenge is None:
            warning("Missing challenge while computing key_material!")
        if self.sslv2_connection_id is None:
            warning("Missing connection_id while computing key_material!")

        km = self.pwcs.prf.derive_key_block(self.master_secret,
                                            self.sslv2_challenge,
                                            self.sslv2_connection_id,
                                            2*self.pwcs.cipher.key_len)
        self.sslv2_key_material = km
        if conf.debug_tls:
            log_runtime.debug("TLS: master secret: %s", repr_hex(self.master_secret))
            log_runtime.debug("TLS: key material: %s", repr_hex(km))
Exemple #16
0
 def run(self):
     # type: () -> None
     log_runtime.debug("Pipe engine thread started.")
     try:
         for p in self.active_pipes:
             p.start()
         sources = self.active_sources
         sources.add(self)
         exhausted = set([])  # type: Set[Union[Source, PipeEngine]]
         RUN = True
         STOP_IF_EXHAUSTED = False
         while RUN and (not STOP_IF_EXHAUSTED or len(sources) > 1):
             fds = select_objects(sources, 0.5)
             for fd in fds:
                 if fd is self:
                     cmd = self._read_cmd()
                     if cmd == "X":
                         RUN = False
                         break
                     elif cmd == "B":
                         STOP_IF_EXHAUSTED = True
                     elif cmd == "A":
                         sources = self.active_sources - exhausted
                         sources.add(self)
                     else:
                         warning(
                             "Unknown internal pipe engine command: %r."
                             " Ignoring.", cmd)
                 elif fd in sources:
                     try:
                         fd.deliver()
                     except Exception as e:
                         log_runtime.exception("piping from %s failed: %s",
                                               fd.name, e)
                     else:
                         if fd.exhausted():
                             exhausted.add(fd)
                             sources.remove(fd)
     except KeyboardInterrupt:
         pass
     finally:
         try:
             for p in self.active_pipes:
                 p.stop()
         finally:
             self.thread_lock.release()
             log_runtime.debug("Pipe engine thread stopped.")
Exemple #17
0
def test_and_setup_socket_can(iface_name):
    # type: (str) -> None
    if 0 != subprocess.call(("cansend %s 000#" % iface_name).split()):
        # iface_name is not enabled
        if 0 != subprocess.call("modprobe vcan".split()):
            raise Exception("modprobe vcan failed")
        if 0 != subprocess.call(
            ("ip link add name %s type vcan" % iface_name).split()):
            log_runtime.debug("add %s failed: Maybe it was already up?" %
                              iface_name)
        if 0 != subprocess.call(
            ("ip link set dev %s up" % iface_name).split()):
            raise Exception("could not bring up %s" % iface_name)

    if 0 != subprocess.call(("cansend %s 000#12" % iface_name).split()):
        raise Exception("cansend doesn't work")

    sys.__stderr__.write("SocketCAN setup done!\n")
    def _recv_sf(self, data, ts):
        # type: (bytes, Union[float, EDecimal]) -> None
        """Process a received 'Single Frame' frame"""
        log_runtime.debug("Processing SF")

        if self.rx_timeout_handle is not None:
            self.rx_timeout_handle.cancel()
            self.rx_timeout_handle = None

        if self.rx_state != ISOTP_IDLE:
            if conf.verb > 2:
                warning("RX state was reset because single frame was received")
            self.rx_state = ISOTP_IDLE

        length = six.indexbytes(data, 0) & 0xf
        if len(data) - 1 < length:
            return

        msg = data[1:1 + length]
        self.rx_queue.send((msg, ts))
Exemple #19
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)
Exemple #20
0
                              iface_name)
        if 0 != subprocess.call(
            ("ip link set dev %s up" % iface_name).split()):
            raise Exception("could not bring up %s" % iface_name)

    if 0 != subprocess.call(("cansend %s 000#12" % iface_name).split()):
        raise Exception("cansend doesn't work")

    sys.__stderr__.write("SocketCAN setup done!\n")


if LINUX and _root and _not_pypy:
    try:
        test_and_setup_socket_can(iface0)
        test_and_setup_socket_can(iface1)
        log_runtime.debug("CAN should work now")
        _socket_can_support = True
    except Exception as e:
        sys.__stderr__.write("ERROR %s!\n" % e)

sys.__stderr__.write("SocketCAN support: %s\n" % _socket_can_support)

# ############################################################################
# """ Define helper functions for CANSocket creation on all platforms """
# ############################################################################
if _socket_can_support:
    if six.PY3:
        from scapy.contrib.cansocket_native import *  # noqa: F403
        new_can_socket = NativeCANSocket
        new_can_socket0 = lambda: NativeCANSocket(iface0)
        new_can_socket1 = lambda: NativeCANSocket(iface1)
Exemple #21
0
 def RENEW_GTK(self):
     log_runtime.debug("State RENEW_GTK")
Exemple #22
0
 def ANALYZE_DATA(self):
     log_runtime.debug("State ANALYZE_DATA")
Exemple #23
0
 def send_beacon(self):
     log_runtime.debug("Send a beacon")
     rep = self.build_ap_info_pkt(Dot11Beacon, dest="ff:ff:ff:ff:ff:ff")
     self.send(rep)
Exemple #24
0
 def WAIT_GTK_ACCEPT(self):
     log_runtime.debug("State WAIT_GTK_ACCEPT")
Exemple #25
0
 def ASSOC_RESPONSE_SENT(self):
     log_runtime.debug("State ASSOC_RESPONSE_SENT")
Exemple #26
0
 def EXIT(self):
     log_runtime.debug("State EXIT")
Exemple #27
0
 def debug(self, lvl, msg):
     # type: (int, str) -> None
     if self.debug_level >= lvl:
         log_runtime.debug(msg)
Exemple #28
0
 def WAIT_GTK_ACCEPT(self):
     log_runtime.debug("State WAIT_GTK_ACCEPT")
Exemple #29
0
 def KRACK_DISPATCHER(self):
     log_runtime.debug("State KRACK_DISPATCHER")
Exemple #30
0
 def ANALYZE_DATA(self):
     log_runtime.debug("State ANALYZE_DATA")
Exemple #31
0
 def WPA_HANDSHAKE_STEP_3_SENT(self):
     log_runtime.debug("State WPA_HANDSHAKE_STEP_3_SENT")
Exemple #32
0
 def AUTH_RESPONSE_SENT(self):
     log_runtime.debug("State AUTH_RESPONSE_SENT")
Exemple #33
0
 def WAIT_ARP_REPLIES(self):
     log_runtime.debug("State WAIT_ARP_REPLIES")
Exemple #34
0
 def KRACK_DISPATCHER(self):
     log_runtime.debug("State KRACK_DISPATCHER")
Exemple #35
0
 def WAIT_ARP_REPLIES(self):
     log_runtime.debug("State WAIT_ARP_REPLIES")
Exemple #36
0
 def WPA_HANDSHAKE_STEP_3_SENT(self):
     log_runtime.debug("State WPA_HANDSHAKE_STEP_3_SENT")
Exemple #37
0
 def EXIT(self):
     log_runtime.debug("State EXIT")
Exemple #38
0
 def RENEW_GTK(self):
     log_runtime.debug("State RENEW_GTK")
Exemple #39
0
 def send_beacon(self):
     log_runtime.debug("Send a beacon")
     rep = self.build_ap_info_pkt(Dot11Beacon, dest="ff:ff:ff:ff:ff:ff")
     self.send(rep)
    def _recv_cf(self, data):
        # type: (bytes) -> None
        """Process a received 'Consecutive Frame' frame"""
        log_runtime.debug("Processing CF")

        if self.rx_state != ISOTP_WAIT_DATA:
            return

        if self.rx_timeout_handle is not None:
            self.rx_timeout_handle.cancel()
            self.rx_timeout_handle = None

        # CFs are never longer than the FF
        if len(data) > self.rx_ll_dl:
            return

        # CFs have usually the LL_DL length
        if len(data) < self.rx_ll_dl:
            # this is only allowed for the last CF
            if self.rx_len - self.rx_idx > self.rx_ll_dl:
                if conf.verb > 2:
                    warning("Received a CF with insufficient length")
                return

        if six.indexbytes(data, 0) & 0x0f != self.rx_sn:
            # Wrong sequence number
            if conf.verb > 2:
                warning("RX state was reset because wrong sequence number was "
                        "received")
            self.rx_state = ISOTP_IDLE
            return

        if self.rx_buf is None:
            if conf.verb > 2:
                warning("rx_buf not filled with data!")
            self.rx_state = ISOTP_IDLE
            return

        self.rx_sn = (self.rx_sn + 1) % 16
        self.rx_buf += data[1:]
        self.rx_idx = len(self.rx_buf)

        if self.rx_idx >= self.rx_len:
            # we are done
            self.rx_buf = self.rx_buf[0:self.rx_len]
            self.rx_state = ISOTP_IDLE
            self.rx_queue.send((self.rx_buf, self.rx_ts))
            self.rx_buf = None
            return

        # perform blocksize handling, if enabled
        if self.rxfc_bs != 0:
            self.rx_bs += 1

            # check if we reached the end of the block
            if self.rx_bs >= self.rxfc_bs and not self.listen_only:
                # send our FC frame
                load = self.ea_hdr
                load += struct.pack("BBB", N_PCI_FC, self.rxfc_bs,
                                    self.rxfc_stmin)
                self.rx_bs = 0
                self.can_send(load)

        # wait for another CF
        log_runtime.debug("Wait for another CF")
        self.rx_timeout_handle = TimeoutScheduler.schedule(
            self.cf_timeout, self._rx_timer_handler)
Exemple #41
0
 def WAIT_AUTH_REQUEST(self):
     log_runtime.debug("State WAIT_AUTH_REQUEST")
Exemple #42
0
 def debug(self, lvl, msg):
     if self.debug_level >= lvl:
         log_runtime.debug(msg)
Exemple #43
0
 def AUTH_RESPONSE_SENT(self):
     log_runtime.debug("State AUTH_RESPONSE_SENT")
Exemple #44
0
 def ASSOC_RESPONSE_SENT(self):
     log_runtime.debug("State ASSOC_RESPONSE_SENT")
Exemple #45
0
 def WAIT_AUTH_REQUEST(self):
     log_runtime.debug("State WAIT_AUTH_REQUEST")