Пример #1
0
    def _prepare(self):
        err = None
        bss_status_attr = None
        rsn_ie_data = None
        vendor_ie_data = None

        # Scan first
        try:
            err, bss_status_attr, rsn_ie_data, vendor_ie_data = self._scan()
            while err or (not rsn_ie_data and not vendor_ie_data):
                time.sleep(0.5)
                g_default_logger.info("Looking for %s ...", self._ssid)
                err, bss_status_attr, rsn_ie_data, vendor_ie_data = \
                    self._scan()
        except KeyboardInterrupt as keyboard_interrupt:
            # This exception should be caught (ra.py)
            raise keyboard_interrupt

        if bss_status_attr:
            if bss_status_attr == 0:
                # Send a Deauthentication frame
                self._authentication_status = \
                    WiFiTrafficHandler.AUTH_STATUS_NOT_AUTHENTICATED
                self._deauthenticate()
            elif bss_status_attr == 1:
                # Send a Disassociation frame
                self._association_status = \
                    WiFiTrafficHandler.ASSO_STATUS_NOT_ASSOCIATED
                self._disassociate()

        if rsn_ie_data:
            packed_ies = struct.pack("!B", 48) + \
                struct.pack("!B", len(rsn_ie_data)) + rsn_ie_data
            info_elements = Dot11Elt(packed_ies)
            if Dot11EltRSN in info_elements:
                self._rsn = info_elements[Dot11EltRSN]

        if vendor_ie_data:
            for vendor_ie in vendor_ie_data:
                packed_ies = struct.pack("!B", 221) + \
                    struct.pack("!B", len(vendor_ie)) + vendor_ie
                info_element = Dot11Elt(packed_ies)
                if isinstance(info_element, Dot11EltMicrosoftWPA):
                    self._ms_wpa_ie = info_element[Dot11EltMicrosoftWPA]

        if not self._expected_akm_found():
            g_default_logger.warning(
                "(%s) AKM is not IEEE 802.1X / PMKSA \
caching.", self._ssid)
Пример #2
0
    def send_frame(self, eapol_frame):
        """
        Send an EAPOL frame.
        """

        # Prevent frames from being sent once the handler has been stopped
        # (this may happen when ending the scanning process, when there are
        # still events in the stack).
        if not self._running:
            return

        if EAP in eapol_frame:
            g_traffic_logger.info("%s ->", eapol_frame[EAP].summary())
        elif EAPOL in eapol_frame:
            g_traffic_logger.info("%s ->", eapol_frame[EAPOL].summary())
        else:
            g_traffic_logger.info(eapol_frame.summary())

        if self._bssid:
            dest_addr = self._bssid.replace(':', '')
            packed_dest_addr = binascii.unhexlify(dest_addr)
            self._socket.sendto(
                bytes(eapol_frame),
                (self._iface, IEEE_802_1X_ETHERTYPE, 0, 0, packed_dest_addr))
        else:
            if EAP in eapol_frame:
                g_default_logger.warning("Could not send frame:  %s", \
eapol_frame[EAP].summary())
            elif EAPOL in eapol_frame:
                g_default_logger.warning("Could not send frame:  %s", \
eapol_frame[EAPOL].summary())
            else:
                g_default_logger.warning("Could not send frame:  %s", \
eapol_frame.summary())
Пример #3
0
    def start(self):

        """
        Start listening for incoming frames.
        """

        # Open a socket that will be used to send frames
        self._socket = socket.socket(
            socket.AF_PACKET,
            socket.SOCK_DGRAM,
            socket.htons(ETH_P_ALL)
        )

        # Open a socket on the monitor interface
        self._monitor_socket = L2ListenSocket(iface=MONITOR_INTERFACE_NAME)

        i = 0
        self._running = True
        while self._running:
            try:
                read, _, __ = select.select([self._monitor_socket.fileno()], [], [], 0.05)
                if read:
                    data_ = self._monitor_socket.recv(4096)
                    frame = RadioTap(data_)

                    if Dot11 in frame and\
                        frame[Dot11].addr2 != self._local_mac_addr:
                        self._handle_received_frame(frame)

                # Every 2.5+ seconds, try to detect any association loss
                if not i % 50:
                    association_loss = self._detect_association_loss()
                    if association_loss:
                        g_default_logger.info("Not associated with %s \
anymore.", self._bssid)
                        self._clear_ssid_info()
                    i = 0

                # If we're not associated, trigger a new scan in order to
                # retrieve necessary information
                if not self._has_ssid_info():
                    self._prepare()
                else:
                    if self._association_status != \
                        WiFiTrafficHandler.ASSO_STATUS_NOT_ASSOCIATED:
                        # Info retrieved in a Probe Response ?
                        # If so, scan in order to get (hopefully) up-to-date
                        # data in another Probe Response
                        if self._previously_associated and \
                            self._ssid_info_learned_in_presp:
                            self._prepare()
                    else:
                        if not self._authentication_status == \
                            WiFiTrafficHandler.AUTH_STATUS_AUTHENTICATING or \
                            not i % 20:
                            if not self._authenticate():
                                self._authentication_status = \
                                    WiFiTrafficHandler.AUTH_STATUS_AUTHENTICATING
                            else:
                                g_default_logger.warning("Could not \
authenticate")

                i = i + 1

            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
Пример #4
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