예제 #1
0
    def listen(self):
        """
        Recupera as mensagens recebidas por ground station através do ADS-B In
        :return: None
        """

        while True:
            message = self.adsbin.retrieve_msg()

            if message is None:
                time.sleep(0.2)
            else:

                if self.icao24_rewrite:
                    icao24 = adsb_decoder.get_icao_addr(message)

                    # Do not spoof our own spoofed messages
                    if icao24 in self.icao24_spoofed and not self.flood:
                        continue

                    if icao24 not in self.icao24:
                        new_icao24 = binascii.b2a_hex(os.urandom(3))
                        self.icao24.append(icao24)
                        self.icao24_spoofed.append(new_icao24)
                        self.icao24_table[icao24] = new_icao24

                    message = self.rewrite_icao24(message)

                t1 = threading.Thread(target=adsb_replay,
                                      args=(message, self.delay, self.adsbout))
                t1.start()
예제 #2
0
    def __get_declared_xy(self, ls_adsb_msg):
        """
        get declared xy
        """
        # get aircraft (ICAO24 address)
        ls_icao24 = str(dcdr.get_icao_addr(ls_adsb_msg)).upper()

        # airborne position msg type (9-18) ok ?
        if 8 < dcdr.get_tc(ls_adsb_msg) < 19:
            # get airborne position
            lf_lat, lf_lon, lf_alt = self.__decode_position(
                ls_icao24, ls_adsb_msg)
            #M_LOG.debug("declared_ll: {} / {} / {}".format(lf_lat, lf_lon, lf_alt))

            # valid position ?
            if (lf_lat is not None) and (lf_lon is not None) and (lf_alt
                                                                  is not None):
                # convert lat/lng/alt to x, y, z
                return gutl.geog2ecef(lf_lat, lf_lon, lf_alt)

        # senão, already have a position ?
        elif ls_icao24 in self.__dct_lst_pos:
            # use last reported position as reference
            lf_lat, lf_lon, lf_alt = self.__dct_lst_pos[ls_icao24]
            #M_LOG.debug("declared_ll: {} / {} / {}".format(lf_lat, lf_lon, lf_alt))

            # convert lat/lng/alt to x, y, z
            return gutl.geog2ecef(lf_lat, lf_lon, lf_alt)

        # return
        return None, None, None
예제 #3
0
    def get_declared_xy(self, message):

        icao24 = decoder.get_icao_addr(message)

        # Checks for airborne position msg type
        if decoder.get_tc(message) in range(9, 19):
            lat, lon, alt = self.decode_position(message)

            if lat is not None and lon is not None:
                # x, y = self.latlon2xy(lat,lon)
                x, y, z = geoutils.geog2enu(lat, lon, alt, self.lat0,
                                            self.lon0, self.alt0)
            else:
                x = None
                y = None

            return x, y

        else:
            # Using last reported position as reference

            if icao24 in self.lastLatitude:
                lat = self.lastLatitude[icao24]
                lon = self.lastLongitude[icao24]
                alt = self.lastAltitude[icao24]

                x, y, z = geoutils.geog2enu(lat, lon, alt, self.lat0,
                                            self.lon0, self.alt0)
            else:
                x = None
                y = None

            return x, y
예제 #4
0
    def run(self):
        """
        Executa o cyber ataque.

        :return:
        """
        logging.info(">> CyberAttack.run")

        self.__disclaimer()

        # Receive message ADS-B
        self.__o_adsbIn.run()

        # for all configured cyber attacks start simulation...
        for l_attack in self.__lst_cyber_attack:
            # start attack
            logging.debug("!! attack :[%s]" % l_attack)
            l_attack.start(self.__i_time_to_attack,
                           self.__i_interval_to_attack)
            l_attack.set_position(self.__f_latitude, self.__f_longitude,
                                  self.__f_altitude)

        while True:
            logging.info("!! Retrieve message ADS-B.")
            ls_message = self.__o_adsbIn.retrieve_msg()

            if ls_message is None:
                time.sleep(0.2)
            else:
                logging.debug("!! message ADS-B: %s" % str(ls_message).upper())
                # Retrieve ICAO code
                li_icao24 = AdsbDecoder.get_icao_addr(ls_message)

                # Do not handle fake messages
                if li_icao24 in self.__lst_icao24_fake:
                    continue

                if li_icao24 not in self.__lst_icao24:
                    self.__lst_icao24.append(li_icao24)

                logging.debug("!! List of ICAO 24 %s" % self.__lst_icao24)
                # eavesdropping ads-b messages
                self.__eavesdropping(li_icao24, ls_message)

                logging.debug("!! Table of aircraft %s" %
                              self.__dct_aircraft_table)

                # for all configured cyber attacks...
                for l_attack in self.__lst_cyber_attack:
                    # attack received ADS-B message
                    logging.debug("!! attack :[%s]" % l_attack)
                    l_attack.spy(self.__dct_aircraft_table,
                                 self.__lst_icao24_fake)

        logging.info("<< CyberAttack.run")
예제 #5
0
    def rewrite_icao24(self, message):
        msg_icao24 = adsb_decoder.get_icao_addr(message)
        new_icao24 = self.icao24_table[msg_icao24]

        # Replace old ICAO address
        new_message_hex = message[0:2] + new_icao24 + message[8:22]
        new_message_bin = bin(int(new_message_hex, 16))[2:].zfill(24)

        # Re-calculate the CRC
        crc = adsb_utils.calc_crc(new_message_bin)
        crc_hex = hex(int(crc, 2)).rstrip("L").lstrip("0x")

        return new_message_hex + crc_hex
예제 #6
0
    def __estimate_toa(self, fs_message):
        """
        make a estimate of time of arrival
        """
        # clear to go
        assert fs_message

        # split message
        llst_msg = fs_message.split()
        #M_LOG.debug("llst_msg: {}".format(llst_msg))

        # ads-b message
        ls_msg_adsb = llst_msg[0]

        # received position
        lf_rcv_lat = float(llst_msg[1])
        lf_rcv_lon = float(llst_msg[2])
        lf_rcv_alt = float(llst_msg[3])

        # get aircraft (ICAO24 address)
        ls_icao24 = str(dcdr.get_icao_addr(ls_msg_adsb)).upper()
        #M_LOG.debug(">>>>>>>>>>>>>>>>>>>> Aeronave: {} <<<<<<<<<<<<<<<<<<<<<<<<".format(ls_icao24))
        #M_LOG.debug("position lat: {}, lng: {}, alt: {}".format(lf_rcv_lat, lf_rcv_lon, lf_rcv_alt))

        # aircraft position (ECEF)
        lf_anv_x, lf_anv_y, lf_anv_z = gutl.geog2ecef(lf_rcv_lat, lf_rcv_lon,
                                                      lf_rcv_alt)
        #M_LOG.debug("lf_anv_x: {}, lf_anv_y: {}, lf_anv_z: {}".format(lf_anv_x, lf_anv_y, lf_anv_z))

        # convert lat/lng to enu
        #lf_flt_x, lf_flt_y, lf_flt_z = gutl.geog2enu(lf_rcv_lat, lf_rcv_lon, lf_rcv_alt,
        #                                             self.__f_lat, self.__f_lng, self.__f_alt)
        #M_LOG.debug("lf_flt_x: {}, lf_flt_y: {}, lf_flt_z: {}".format(lf_flt_x, lf_flt_y, lf_flt_z))

        # euclidean distance
        #lf_dist = math.sqrt(lf_flt_x * lf_flt_x + lf_flt_y * lf_flt_y + lf_flt_z * lf_flt_z)
        #M_LOG.debug("lf_dist: {}".format(lf_dist))

        # 2D distance between aircraft and sensor positions
        #lf_dist_2d = math.sqrt(pow(lf_anv_x - self.__f_x, 2) + pow(lf_anv_y - self.__f_y, 2))
        #M_LOG.debug("lf_dist_2d: {}".format(lf_dist_2d))

        # 3D distance between aircraft and sensor positions
        lf_dist_3d = math.sqrt(
            pow(lf_anv_x - self.__f_x, 2) + pow(lf_anv_y - self.__f_y, 2) +
            pow(lf_anv_z - self.__f_z, 2))
        #M_LOG.debug("lf_dist_3d: {}".format(lf_dist_3d))

        # return ads-b message, estimated time (distance / speed of light)
        return ls_msg_adsb, lf_dist_3d / M_LIGHT_SPEED
예제 #7
0
    def rewrite_icao24(self, message):
        """
        Reescreve o código ICAO 24 bit code da mensagem ADS-B. E recalcula o CRC da
        mensagem ADS-B.
        :param message: a mensagem ADS-B
        :return: None
        """
        msg_icao24 = adsb_decoder.get_icao_addr(message)
        new_icao24 = self.icao24_table[msg_icao24]

        # Replace old ICAO address
        new_message_hex = message[0:2] + new_icao24 + message[8:22]
        new_message_bin = bin(int(new_message_hex, 16))[2:].zfill(24)

        # Re-calculate the CRC
        crc = adsb_utils.calc_crc(new_message_bin)
        crc_hex = hex(int(crc, 2)).rstrip("L").lstrip("0x")

        return new_message_hex + crc_hex
예제 #8
0
    def decode_position(self, message):

        # Aircraft (ICAO24 address)
        icaoaddr = decoder.get_icao_addr(message)

        # Check if message is even or odd
        if int(decoder.get_oe_flag(message)) == MlatServer.ODD_MSG:
            self.lastOddMsg[icaoaddr] = message
            t0 = 0
            t1 = 1
        else:
            self.lastEvenMsg[icaoaddr] = message
            t0 = 1
            t1 = 0

        if icaoaddr in self.lastOddMsg and icaoaddr in self.lastEvenMsg:

            # If CPR cannot be decoded, the method returns (None, None)
            _lat, _lon = decoder.get_position(self.lastEvenMsg[icaoaddr],
                                              self.lastOddMsg[icaoaddr], t0,
                                              t1)

            if _lat and _lon:
                lat = _lat
                lon = _lon
                alt = decoder.get_alt(message) * self.FT_TO_M

                self.lastLatitude[icaoaddr] = lat
                self.lastLongitude[icaoaddr] = lon
                self.lastAltitude[icaoaddr] = alt

                return lat, lon, alt
            else:
                print bcolors.WARNING + "Warning: cannot decode position message" + bcolors.ENDC
                return None, None, None

        return None, None, None
예제 #9
0
    def process_msg(self, message, delete=False):
        icao24 = decoder.get_icao_addr(message)

        cursor = self.db.cursor()

        # Checking which sensors have received the same message
        query1 = "SELECT id, sensor_id, toa, created FROM adsb_messages WHERE message='%s' ORDER BY created ASC LIMIT %s" % (
            message, self.nsensors)
        nrows = cursor.execute(query1)

        rows = cursor.fetchall()

        if nrows == 0:
            if delete:
                cursor.execute("DELETE FROM adsb_messages WHERE message='%s'" %
                               message)
                self.db.commit()
            return False

        # Message ID
        msg_id = [0] * nrows

        # Sensor ID
        sensor_id = [0] * nrows

        # Time of arrival
        toa = [0] * nrows

        # Position of sensor
        xpos = [0] * nrows
        ypos = [0] * nrows
        zpos = [0] * nrows

        i = 0
        for row in rows:
            # Time of arrival
            toa[i] = row[2]

            # Sensor ID
            sensor_id[i] = row[1]

            # Message ID
            msg_id[i] = row[0]

            # Location of sensor
            xpos[i] = self.sensors[sensor_id[i]].xpos
            ypos[i] = self.sensors[sensor_id[i]].ypos
            zpos[i] = self.sensors[sensor_id[i]].altitude

            i += 1

        # Do not process it with insufficient data
        if nrows < self.nsensors:
            # Deleting messages from database
            if delete:
                for i in msg_id:
                    cursor.execute("DELETE FROM adsb_messages WHERE id=%s" % i)

            return False

        # Verifying declared position (in X, Y)
        x, y = self.get_declared_xy(message)

        # Determining source of transmission using multilateration
        _x, _y = self.get_estimated_xy(xpos, ypos, zpos, toa)

        # Determining reliability of message
        if x is not None and y is not None and _x is not None and _y is not None:

            # 2D distance between reported and estimated positions
            distance = math.sqrt((x - _x)**2 + (y - _y)**2)

            if distance <= 1000:
                print "'%s'\t%d\t%s[PASS]%s" % (message, distance,
                                                bcolors.OKBLUE, bcolors.ENDC)
                self.logger.info(
                    "'%s'\t%d\t%s[PASS]%s" %
                    (message, distance, bcolors.OKBLUE, bcolors.ENDC))

                # Forward received ADS-B message to all configured forwarders
                for f in self.forwarders:
                    f.forward(message, None)
            else:
                print "'%s'\t%d\t%s[DROP]%s" % (message, distance,
                                                bcolors.FAIL, bcolors.ENDC)
                self.logger.warn(
                    "'%s'\t%d\t%s[DROP]%s" %
                    (message, distance, bcolors.FAIL, bcolors.ENDC))

        # Deleting processed messages from database
        for i in msg_id:
            cursor.execute("DELETE FROM adsb_messages WHERE id=%s" % i)

        self.db.commit()

        cursor.close()

        return True