Example #1
0
    def _process_eapol_frame(self, request):
        eapol_frames = []

        # 1. Check EAPOL type
        if request[EAPOL].type == EAPOL.EAP_PACKET:

            # Process EAP packet
            eap_packet = self._eap_handler.process_eap_packet(request[EAP])
            if eap_packet:
                resp = EAPOL(version=request[EAPOL].version,
                             type=0) / eap_packet
                eapol_frames.append(resp)

                # If the EAP response contains a TLS Alert, add an EAPOL-Logoff
                # frame to the frames that are to be sent.
                tls_data = get_tls_data(eap_packet)
                if tls_data:
                    if tls_data.msg and isinstance(tls_data.msg[0], TLSAlert):
                        eapol_frames.append(EAPOL(version=resp.version,
                                                  type=2))
            else:
                # After having received an EAP-Failure or an EAP-Request
                # matching the current authentication method, send a Logoff
                # message.
                eapol_frames.append(
                    EAPOL(version=request[EAPOL].version, type=2))

        return eapol_frames
Example #2
0
    def stop(self):

        """
        Stop listening, free resources.
        """

        # Send an EAPOL-Logoff frame
        eapol_logoff_frame = EAPOL(version=self._eapol_version, type=2)
        self.send_frame(eapol_logoff_frame)

        if self._association_status != \
            WiFiTrafficHandler.ASSO_STATUS_NOT_ASSOCIATED and \
                self._bssid:
            self._disassociate()
        if self._socket:
            self._socket.close()
        if self._monitor_socket:
            self._monitor_socket.close()

        # Set interface operational state to "DOWN", and linkmode to default
        set_interface_operstate(
            self._iface_index,
            0,
            "UP"
        )
        self._running = False
Example #3
0
    def start(self):
        """
        Start listening for incoming frames.
        """

        resume_scanning = True
        self._running = True

        try:
            self._socket = L2ListenSocket(iface=self._iface)
        except OSError as err:
            g_default_logger.error(
                "Cannot listen on the provided interface \
(%s).", self._iface)
            g_exception_logger.exception(err)

        while self._running:
            try:
                read, _, __ = select.select([self._socket], [], [], 0.05)
                if read:
                    frame = self._socket.recv()
                    if frame.src != self._local_mac_addr:
                        self._handle_received_frame(frame)

                if resume_scanning:
                    # Send an EAPOL-Start frame to try to start the authentication
                    # process.
                    eapol_start_frame = EAPOL(version=self._eapol_version,
                                              type=1)
                    self.send_frame(eapol_start_frame)
                    resume_scanning = False

            except socket.error as err_mess:
                g_exception_logger.exception(err_mess)
                self._running = False

            except KeyboardInterrupt as keyboard_interrupt:
                # This exception should be caught (ra.py)
                raise keyboard_interrupt
Example #4
0
    def build_EAPOL_Key_8021X2004(
            key_information,
            replay_counter,
            nonce,
            data=None,
            key_mic=None,
            key_data_encrypt=None,
            key_rsc=0,
            key_id=0,
            key_descriptor_type=2,  # EAPOL RSN Key
    ):
        pkt = EAPOL(version="802.1X-2004", type="EAPOL-Key")

        key_iv = KrackAP.gen_nonce(16)

        assert key_rsc == 0  # Other values unsupported
        assert key_id == 0  # Other values unsupported
        payload = b"".join([
            chb(key_descriptor_type),
            struct.pack(">H", key_information),
            b'\x00\x20',  # Key length
            struct.pack(">Q", replay_counter),
            nonce,
            key_iv,
            struct.pack(">Q", key_rsc),
            struct.pack(">Q", key_id),
        ])

        # MIC field is set to 0's during MIC computation
        offset_MIC = len(payload)
        payload += b'\x00' * 0x10

        if data is None and key_mic is None and key_data_encrypt is None:
            # If key is unknown and there is no data, no MIC is needed
            # Exemple: handshake 1/4
            payload += b'\x00' * 2  # Length
            return pkt / Raw(load=payload)

        assert data is not None
        assert key_mic is not None
        assert key_data_encrypt is not None

        # Skip 256 first bytes
        # REF: 802.11i 8.5.2
        # Key Descriptor Version 1:
        # ...
        # No padding shall be used. The encryption key is generated by
        # concatenating the EAPOL-Key IV field and the KEK. The first 256 octets
        # of the RC4 key stream shall be discarded following RC4 stream cipher
        # initialization with the KEK, and encryption begins using the 257th key
        # stream octet.
        enc_data = ARC4_encrypt(key_iv + key_data_encrypt, data, skip=256)

        payload += struct.pack(">H", len(data))
        payload += enc_data

        # Compute MIC and set at the right place
        temp_mic = pkt.copy()
        temp_mic /= Raw(load=payload)
        to_mic = raw(temp_mic[EAPOL])
        mic = hmac.new(key_mic, to_mic, hashlib.md5).digest()
        final_payload = payload[:offset_MIC] + mic + payload[offset_MIC +
                                                             len(mic):]
        assert len(final_payload) == len(payload)

        return pkt / Raw(load=final_payload)
Example #5
0
    def _handle_received_frame(self, frame):

        """
        If a frame carrying an EAP packet has been received, add it to the
        queue and notify the observers.
        Handle 802.11 authentication and association.
        """

        #
        # 802.11
        #

        dot11_frame = frame[Dot11]

        # Is it a Probe Response ?
        if frame[Dot11].type == 0b00 and frame[Dot11].subtype == 5:
            if self._authentication_status == \
                WiFiTrafficHandler.AUTH_STATUS_AUTHENTICATED:
                # If we're already authenticated, there is no need to process
                # a Probe Response.
                return
            # Look for the SSID
            if Dot11Elt in frame[Dot11]:
                data = frame[Dot11][Dot11Elt]
                ssid_found = self._parse_ies(data)
                if ssid_found and self._authentication_status == \
                    WiFiTrafficHandler.AUTH_STATUS_NOT_AUTHENTICATED:
                    if not self._authentication_status == \
                        WiFiTrafficHandler.AUTH_STATUS_AUTHENTICATING:
                        # Attempt to authenticate
                        self._authentication_status = \
                            WiFiTrafficHandler.AUTH_STATUS_AUTHENTICATING
                        if self._authenticate():
                            # At this point, the authentication process probably
                            # failed
                            g_default_logger.warning("Could not authenticate.")
                            self._authentication_status = \
                                WiFiTrafficHandler.AUTH_STATUS_NOT_AUTHENTICATED

        # Is it a Deauthentication frame ?
        elif Dot11Deauth in dot11_frame:
            g_default_logger.warning("Deauthenticated.\tBSSID: %s", self._bssid)
            self._authentication_status = \
                WiFiTrafficHandler.AUTH_STATUS_NOT_AUTHENTICATED

        elif Dot11Disas in dot11_frame:
            g_default_logger.warning(
                "Disassociated.\tSSID: %s, BSSID: %s",
                self._ssid,
                self._bssid
            )
            self._association_status = \
                WiFiTrafficHandler.ASSO_STATUS_NOT_ASSOCIATED
            # Consider we're not authenticated anymore, as well
            self._authentication_status = \
                WiFiTrafficHandler.AUTH_STATUS_NOT_AUTHENTICATED
            self._clear_ssid_info()

        elif Dot11Auth in dot11_frame:
            if self._authentication_status == \
                WiFiTrafficHandler.AUTH_STATUS_AUTHENTICATING:
                if dot11_frame.algo == 0 and dot11_frame.status == 0:
                    g_default_logger.info(
                        "Authenticated.\tBSSID: %s",
                        self._bssid
                    )
                    self._authentication_status = \
                            WiFiTrafficHandler.AUTH_STATUS_AUTHENTICATED

                    # Attempt to associate
                    self._association_status =\
                        WiFiTrafficHandler.ASSO_STATUS_ASSOCIATING
                    if self._associate():
                        # At this point, the association process probably
                        # failed
                        g_default_logger.warning(
                            "Could not associate with %s",
                            self._bssid
                        )
                        self._association_status = \
                            WiFiTrafficHandler.ASSO_STATUS_NOT_ASSOCIATED

        elif Dot11AssoResp in dot11_frame:
            if dot11_frame.status == 0:
                # The association succeeded
                g_default_logger.info(
                    "Associated.\tSSID: %s, BSSID: %s",
                    self._ssid,
                    self._bssid
                )
                self._association_status = \
                    WiFiTrafficHandler.ASSO_STATUS_ASSOCIATED
                self._previously_associated = True

                # Resume the scanning process, if it was interrupted
                eapol_start_frame = EAPOL(version=self._eapol_version, type=1)
                self.send_frame(eapol_start_frame)

        #
        # EAPOL / EAP
        #

        elif EAPOL in frame:
            if EAP in frame:
                g_traffic_logger.info("\t<- %s", frame[EAP].summary())
                try:
                    self._received_frames.put(frame, block=False)
                except queue.Full:
                    # The authentication process is made of ordered request /
                    # response exchanges. This should not happen ...
                    while not self._received_frames.empty():
                        self._received_frames.get()
                    self._received_frames.put(frame, block=False)

                event = common.FrameReceivedEvent()
                self.notify_observers(event)

            # Use the same EAPOL version
            self._eapol_version = frame[EAPOL].version
Example #6
0
	def check_eap_type(self, essid, eaptype, outer_identity='user', eapol_start=False, rsnInfo=''):
		"""
		Check that an eaptype is supported.
		errDict = {
			0:"supported",
			1:"not supported",
			2:"could not determine",
			3:"identity rejected"
		}
		"""

		eapid = randint(1, 254)
		if eapol_start:
			eapol_start_request = (
				RadioTap()/
				Dot11(FCfield=0x01, addr1=self.bssid, addr2=self.source_mac, addr3=self.bssid, SC=self.__fixSC__(), type=2, subtype=8)/
				Dot11QoS()/
				LLC(dsap=170, ssap=170, ctrl=3)/
				SNAP(code=0x888e)/
				EAPOL(version=1, type=1)
			)
			self.sequence += 1
			i = 0
			for i in range(0, EAP_MAX_TRIES):
				self.__thread_sendp__(eapol_start_request)
				if not self.lastpacket is None:
					if self.lastpacket.haslayer('EAP'):
						fields = self.lastpacket.getlayer('EAP').fields
						if 'type' in fields and fields['type'] == 1 and fields['code'] == 1:
							i = 0
							eapid = fields['id']
							break
			if i == 2:
				return 2
		eap_identity_response = (
			RadioTap()/
			Dot11(FCfield=0x01, addr1=self.bssid, addr2=self.source_mac, addr3=self.bssid, SC=self.__fixSC__(), type=2, subtype=8)/
			Dot11QoS()/
			LLC(dsap=170, ssap=170, ctrl=3)/
			SNAP(code=0x888e)/
			EAPOL(version=1, type=0)/
			EAP(code=2, type=1, id=eapid, identity=outer_identity)
		)
		eap_legacy_nak = (
			RadioTap()/
			Dot11(FCfield=0x01, addr1=self.bssid, addr2=self.source_mac, addr3=self.bssid, SC=self.__fixSC__(), type=2, subtype=8)/
			Dot11QoS()/
			LLC(dsap=170, ssap=170, ctrl=3)/
			SNAP(code=0x888e)/
			EAPOL(version=1, type=0, len=6)/
			EAP(code=2, type=3, id=eapid + 1, eap_types=[eaptype])
		)
		self.sequence += 1

		for i in range(0, EAP_MAX_TRIES):
			self.__thread_sendp__(eap_identity_response)
			if not self.lastpacket is None:
				if self.lastpacket.haslayer('EAP'):
					fields = self.lastpacket.getlayer('EAP').fields
					if fields['code'] == 4:	# 4 is a failure
						return 3
					if 'type' in fields and fields['type'] == eaptype:
						return 0
					i = 0
					break
		if i == 2:
			return 2
		for i in range(0, EAP_MAX_TRIES):
			self.__thread_sendp__(eap_legacy_nak)
			if not self.lastpacket is None:
				if self.lastpacket.haslayer('EAP'):
					fields = self.lastpacket.getlayer('EAP').fields
					if 'type' in fields and fields['type'] == eaptype:
						return 0
					else:
						return 1
		return 2