Example #1
0
    def on_message(self, msg):
        try:
            dl_msg_type = msg[1]
            if dl_msg_type == DataLoggerMessages.EXTRACT_GENERAL:
                self.uid = msg[2]
                self.n_columns = parse_uint32(msg[3:7])
                self.n_entries = parse_uint32(msg[7:11])
                self.schema_name = stringify(msg[11:])
            elif dl_msg_type == DataLoggerMessages.EXTRACT_COLUMN:
                column_idx = msg[2]
                self.column_done[column_idx] = True
                self.column_type[column_idx] = msg[3]
                self.column_name[column_idx] = stringify(msg[4:])
            elif dl_msg_type == DataLoggerMessages.EXTRACT_DATA:
                entry_idx = parse_uint32(msg[2:6])
                self.entry_done[entry_idx] = True
                entry = []
                offset = 6
                for column_type in self.column_type:
                    if column_type == ColumnType.FLOAT:
                        entry.append(parse_float(msg[offset:(offset+4)]))
                        offset += 4
                    if column_type == ColumnType.UINT32:
                        entry.append(parse_uint32(msg[offset:(offset+4)]))
                        offset += 4
                self.entry[entry_idx] = tuple(entry)

            if (self.schema_name is not None and
                    all(self.column_done) and
                    all(self.entry_done)):
                self.done = True
        except Exception as e:
            print(e)
            self.failure = True
Example #2
0
    def parse_budget(self, raw_misc_data):
        """
        Parses the budget data segment from MISC into budget data.
        Args:
            raw_misc_data (bytes): Raw segment from Misc
        """
        # Ordinances
        ordinance_raw = raw_misc_data[0x0FA0:0x0FA0 + 4]
        self.ordinance_flags = int_to_bitstring(parse_uint32(ordinance_raw))

        # bonds
        start_offset = 0x0610
        bonds_len = 50 * 4
        self.bonds = bytes_to_int32s(raw_misc_data[start_offset:start_offset +
                                                   bonds_len])

        # various sub-budgets
        sub_len = 27 * 4
        for name, start_offset in self._sub_budget_indices.items():
            chunk = raw_misc_data[start_offset:start_offset + sub_len]
            sub_budget = deepcopy(self._blank_budget)
            chunk_data = bytes_to_int32s(chunk)
            for idx, k in enumerate(self._blank_budget):
                sub_budget[k] = chunk_data[idx]
            self.budget_items[name] = sub_budget
Example #3
0
def parse_data(raw_file):
    """
    Parses the data file containing bitmaps.
    Works for Win95 version of SMALLMED.DAT, SPECIAL.DAT and LARGE.DAT
    Args:
        raw_file (bytes): Raw datafile to parse.
    Returns:
        A dictionary, where the key is the ID of the tile stored in that segment of the file, and the value being the raw bytes.
    """
    large_metadata = {}
    large_data = {}
    large_metaentry = namedtuple("large_metadata",
                                 ["offset", "width", "height"])
    large_entry = namedtuple("large_data",
                             ["offset", "width", "height", "length", "data"])
    entries = parse_uint16(raw_file[0:2])
    index = raw_file[2:2 + entries * 10]  # 10B per entry.
    # Generate the metadata on what's in the rest of the file from the header at the start.
    for idx in range(0, len(index), 10):
        item_id = parse_uint16(index[idx:idx + 2])
        offset = parse_uint32(index[idx + 2:idx + 6])
        height = parse_uint16(index[idx + 6:idx + 8])
        width = parse_uint16(index[idx + 8:idx + 10])
        # For duplicates in the data file, allow them, but give the second a -ve ID for later tracking.
        if item_id in large_metadata.keys():
            item_id *= -1
        large_metadata[item_id] = large_metaentry(offset, width, height)
    # Generate the lengths of each chunk.
    end = len(raw_file)
    offsets = []
    for v in large_metadata.values():
        offsets.extend([v.offset])
    offsets.extend([end])
    lengths = [
        offsets[x] - offsets[x - 1] for x in range(1,
                                                   len(large_metadata) + 1)
    ]
    # Combine the metadata together with the data.
    idx = 0
    dupes = [x * -1 for x in large_metadata.keys() if x < 0]
    for k, v in large_metadata.items():
        length = lengths[idx]
        idx += 1
        data = raw_file[v.offset:v.offset + length]
        entry = large_entry(v.offset, v.width, v.height, length, data)
        # Now we need to perform some cleanup on the duplicated entries.
        # In this case, we want the second entries, which have a -'ve id, and if we've got the first, ignore them.
        if k < 0:
            k *= -1
        elif k in dupes:
            continue
        large_data[k] = entry
    return large_data
Example #4
0
    def disconnect(self):
        '''Cleanly close the connection to the remote server.'''

        # Send our exit status
        msg = []
        msg.append(generate_byte(SSH_MSG_NUMS['SSH_MSG_CHANNEL_REQUEST']))
        msg.append(generate_uint32(self._remote_channel_number))
        msg.append(generate_string('exit-status'))
        msg.append(generate_byte(0))  # False
        msg.append(generate_uint32(0))  # Exit status = 0
        self._ssh_transport_connection.send(''.join(msg))

        # Then close the channel
        msg = []
        msg.append(generate_byte(SSH_MSG_NUMS['SSH_MSG_CHANNEL_CLOSE']))
        msg.append(generate_uint32(self._remote_channel_number))
        self._ssh_transport_connection.send(''.join(msg))

        # Read back the remote side's exit status
        data = self._ssh_transport_connection.read()
        index, msg_type = parse_byte(data, 0)
        index, recipient_channel = parse_uint32(data, index)
        index, request_type = parse_string(data, index)
        index, want_reply_byte = parse_byte(data, index)
        want_reply = want_reply_byte != 0
        index, exit_status = parse_uint32(data, index)

        assert msg_type == SSH_MSG_NUMS['SSH_MSG_CHANNEL_REQUEST']
        assert recipient_channel == self._local_channel_number
        assert request_type == 'exit-status'
        assert not want_reply

        # Disconnect at the transport layer
        self._ssh_transport_connection.disconnect()

        return exit_status
Example #5
0
  def disconnect(self):
    '''Cleanly close the connection to the remote server.'''

    # Send our exit status
    msg = []
    msg.append(generate_byte(SSH_MSG_NUMS['SSH_MSG_CHANNEL_REQUEST']))
    msg.append(generate_uint32(self._remote_channel_number))
    msg.append(generate_string('exit-status'))
    msg.append(generate_byte(0)) # False
    msg.append(generate_uint32(0)) # Exit status = 0
    self._ssh_transport_connection.send(''.join(msg))

    # Then close the channel
    msg = []
    msg.append(generate_byte(SSH_MSG_NUMS['SSH_MSG_CHANNEL_CLOSE']))
    msg.append(generate_uint32(self._remote_channel_number))
    self._ssh_transport_connection.send(''.join(msg))

    # Read back the remote side's exit status
    data = self._ssh_transport_connection.read()
    index, msg_type = parse_byte(data, 0)
    index, recipient_channel = parse_uint32(data, index)
    index, request_type = parse_string(data, index)
    index, want_reply_byte = parse_byte(data, index)
    want_reply = want_reply_byte != 0
    index, exit_status = parse_uint32(data, index)

    assert msg_type == SSH_MSG_NUMS['SSH_MSG_CHANNEL_REQUEST']
    assert recipient_channel == self._local_channel_number
    assert request_type == 'exit-status'
    assert not want_reply

    # Disconnect at the transport layer
    self._ssh_transport_connection.disconnect()

    return exit_status
Example #6
0
def get_chunk_from_offset(input_data, offset):
    """
    Parses an IFF chunk by reading the header and using the size to determine which bytes belong to it.
    An IFF chunk has an 8 byte header, of which the first 4 bytes is the type and the second 4 bytes is the size (exclusive of the header).
    Args:
        input_data (bytes): raw city information.
        offset (int): starting offset in input to start parsing at.
    Returns:
        A list containing the id of the chunk (a 4 byte ascii value), an int length of the chunk of finally bytes of the chunk data.
    """
    location_index = offset
    chunk_id = input_data[location_index : location_index + 4].decode('ascii')
    # Maximum 32b/4B, so 2^32 in length.
    chunk_size = parse_uint32(input_data[location_index + 4 : location_index + 8])
    chunk_data = input_data[location_index + 8 : location_index + 8 + chunk_size]
    return [chunk_id, chunk_size, chunk_data]
Example #7
0
    def read(self):
        '''Read data from the remote server.

    This data will be encrypted, and its authenticity guaranteed (both client-to-server and
    server-to-client).

    Returns (string): the data sent by the remote server.
    '''

        data = self._ssh_transport_connection.read()
        index, msg_type = parse_byte(data, 0)
        index, recipient_channel = parse_uint32(data, index)
        index, channel_data = parse_string(data, index)

        assert msg_type == SSH_MSG_NUMS['SSH_MSG_CHANNEL_DATA']
        assert recipient_channel == self._local_channel_number

        return channel_data
Example #8
0
  def read(self):
    '''Read data from the remote server.

    This data will be encrypted, and its authenticity guaranteed (both client-to-server and
    server-to-client).

    Returns (string): the data sent by the remote server.
    '''

    data = self._ssh_transport_connection.read()
    index, msg_type = parse_byte(data, 0)
    index, recipient_channel = parse_uint32(data, index)
    index, channel_data = parse_string(data, index)

    assert msg_type == SSH_MSG_NUMS['SSH_MSG_CHANNEL_DATA']
    assert recipient_channel == self._local_channel_number

    return channel_data
Example #9
0
  def read(self):
    '''Read a packet from the remote server.

    Assuming the initial connection has completed (i.e. #connect has been called, and returned),
    this data will be encrypted, and its authenticity guaranteed.

    Returns (string): the data sent by the remote server.
    '''

    # Read the first <block_len> bytes of the packet, decrypt it if necessary, and parse out the
    # remaining packet length
    initial_packet = self._socket.recv(AES_BLOCK_LEN)
    if self._encryption_negotiated:
      initial_packet = self._aes_server_to_client.decrypt(initial_packet)
    _, packet_len = parse_uint32(initial_packet, 0)

    # Read the remaining bytes of the packet, decrypting if necessary, and checking the MAC
    remaining_msg = self._socket.recv(packet_len - (AES_BLOCK_LEN - 4))
    if self._encryption_negotiated:
      remaining_msg = self._aes_server_to_client.decrypt(remaining_msg)

      # Read and verify the MAC
      received_mac = self._socket.recv(SHA1_LEN)
      calculated_mac = hmac.new(
          self._integrity_key_server_to_client,
          generate_uint32(self._packets_received_counter) + initial_packet + remaining_msg,
          hashlib.sha1
      ).digest()
      assert received_mac == calculated_mac, \
        'MACs did not match: %s != %s' % (repr(received_mac), repr(calculated_mac))
      print colors.cyan('MAC validated correctly!')

    # Pull the payload out of the message
    data = (initial_packet + remaining_msg)[4:]
    index, padding_len = parse_byte(data, 0)
    payload_len = packet_len - padding_len - index
    payload = data[index:payload_len + index]

    self._packets_received_counter += 1
    print colors.green('< Received: %s' % repr(payload))

    return payload
Example #10
0
    def read(self):
        '''Read a packet from the remote server.

    Assuming the initial connection has completed (i.e. #connect has been called, and returned),
    this data will be encrypted, and its authenticity guaranteed.

    Returns (string): the data sent by the remote server.
    '''

        # Read the first <block_len> bytes of the packet, decrypt it if necessary, and parse out the
        # remaining packet length
        initial_packet = self._socket.recv(AES_BLOCK_LEN)
        if self._encryption_negotiated:
            initial_packet = self._aes_server_to_client.decrypt(initial_packet)
        _, packet_len = parse_uint32(initial_packet, 0)

        # Read the remaining bytes of the packet, decrypting if necessary, and checking the MAC
        remaining_msg = self._socket.recv(packet_len - (AES_BLOCK_LEN - 4))
        if self._encryption_negotiated:
            remaining_msg = self._aes_server_to_client.decrypt(remaining_msg)

            # Read and verify the MAC
            received_mac = self._socket.recv(SHA1_LEN)
            calculated_mac = hmac.new(
                self._integrity_key_server_to_client,
                generate_uint32(self._packets_received_counter) +
                initial_packet + remaining_msg, hashlib.sha1).digest()
            assert received_mac == calculated_mac, \
              'MACs did not match: %s != %s' % (repr(received_mac), repr(calculated_mac))
            print colors.cyan('MAC validated correctly!')

        # Pull the payload out of the message
        data = (initial_packet + remaining_msg)[4:]
        index, padding_len = parse_byte(data, 0)
        payload_len = packet_len - padding_len - index
        payload = data[index:payload_len + index]

        self._packets_received_counter += 1
        print colors.green('< Received: %s' % repr(payload))

        return payload
Example #11
0
def parse_message(msg):
    parsed_message = []
    i = 0
    last_open_str = 0

    def store_string_so_far():
        if last_open_str != i:
            parsed_message.append(stringify(msg[last_open_str:i]))

    while i < len(msg):
        if stringify(msg[i:(i+2)]) == '%d':
            store_string_so_far()
            int_bytes = msg[(i+2):(i+4)]
            parsed_int = parse_int(int_bytes)
            parsed_message.append(parsed_int)
            last_open_str = i + 4
            i = i + 4
        elif stringify(msg[i:(i+2)]) == '%f':
            store_string_so_far()
            float_bytes = msg[(i+2):(i+6)]
            parsed_float = parse_float(float_bytes)
            parsed_message.append(parsed_float)
            last_open_str = i + 6
            i = i + 6
        elif stringify(msg[i:(i+2)]) == '%l':
            store_string_so_far()
            uint32_bytes = msg[(i+2):(i+6)]
            parsed_uint32 = parse_uint32(uint32_bytes)
            parsed_message.append(parsed_uint32)
            last_open_str = i + 6
            i = i + 6
        else:
            if i+1 == len(msg):
                i += 1
                store_string_so_far()
            else:
                i += 1

    return parsed_message
Example #12
0
    def handle(self, msg):
        if len(msg) == 0:
            print ('WARNING: Empty message')
            return
        msg_type = msg[0]
        if msg_type == ToComputer.DEBUG:
            # debug message
            subsystems = [
                'INFO',
                'ERROR',
                'CRON',
            ]
            if (0 > msg[1] or msg[1] >= len(subsystems)):
                print  ("WARNING: Unknown debug category: %d.." % (msg[1],))
                subsystem = 'UNKNOWN'
                print (stringify(msg[2:]))
            else:
                subsystem = subsystems[msg[1]]

            content = parse_message(msg[2:])
            content = ''.join([str(m) for m in content])
            content = '[%s] %s' % (subsystem, content)
            self.log(content)
        elif msg_type == ToComputer.GET_SETTINGS_REPLY:
            time_since_epoch_s = parse_uint32(msg[1:5])
            date = datetime.fromtimestamp(time_since_epoch_s)
            box_uid = msg[5]
            box_node_type = chr(msg[6])
            box_balance = parse_uint32(msg[7:11])
            state_of_charge       = parse_float(msg[11:15])
            uncertainty_of_charge = parse_float(msg[15:19])
            battery_capacity = parse_float(msg[19:23])

            off_threshold = parse_float(msg[23:27])
            red_threshold = parse_float(msg[27:31])
            yellow_threshold = parse_float(msg[31:35])

            balance_update_hours = parse_int(msg[35:37])
            balance_update_minutes = parse_int(msg[37:39])
            balance_update_ammount = parse_uint32(msg[39:43])

            #self.log('Time on device is ' + str(date))

            self.update_if_not_focused(self.ui_root.settings.box_time, str(date))
            self.update_if_not_focused(self.ui_root.settings.box_uid, str(box_uid))
            self.update_if_not_focused(self.ui_root.settings.box_node_type, str(box_node_type))
            self.update_if_not_focused(self.ui_root.settings.box_balance, str(box_balance))
            self.update_if_not_focused(self.ui_root.settings.state_of_charge,       str(state_of_charge))
            self.update_if_not_focused(self.ui_root.settings.uncertainty_of_charge, str(uncertainty_of_charge))
            self.update_if_not_focused(self.ui_root.settings.battery_capacity, str(battery_capacity))

            self.update_if_not_focused(self.ui_root.settings.off_threshold, str(off_threshold)[:6])
            self.update_if_not_focused(self.ui_root.settings.red_threshold, str(red_threshold)[:6])
            self.update_if_not_focused(self.ui_root.settings.yellow_threshold, str(yellow_threshold)[:6])

            self.update_if_not_focused(self.ui_root.settings.balance_update_hours, str(balance_update_hours))
            self.update_if_not_focused(self.ui_root.settings.balance_update_minutes, str(balance_update_minutes))
            self.update_if_not_focused(self.ui_root.settings.balance_update_ammount, str(balance_update_ammount))

        elif msg_type == ToComputer.DATA_LOGGER_REPLY:
            controller.get.data_logger.on_message(msg)
        else:
            print( 'WARNING: Uknown message type :', msg[0])
Example #13
0
    def parse_misc(self, misc_data):
        """
        Parses the MISC section of the .sc2 file and populates the City object with its values.
        See .sc2 file spec docs for more, at:
        Args:
            misc_data (bytes): MISC segment of the raw data from the .sc2 file.
        """
        # This is the offset of the section that's being parsed from MISC.
        parse_order = {
            '0x0000': 'FirstEntry',  # nominally the same in every city.
            '0x0004': 'GameMode',
            '0x0008': 'Compass',  # rotation
            '0x000c': 'baseYear',
            '0x0010': 'simCycle',
            '0x0014': 'TotalFunds',
            '0x0018': 'TotalBonds',
            '0x001c': 'GameLevel',
            '0x0020': 'CityStatus',
            '0x0024': 'CityValue',
            '0x0028': 'LandValue',
            '0x002c': 'CrimeCount',
            '0x0030': 'TrafficCount',
            '0x0034': 'Pollution',
            '0x0038': 'CityFame',
            '0x003c': 'Advertising',
            '0x0040': 'Garbage',
            '0x0044': 'WorkerPercent',
            '0x0048': 'WorkerHealth',
            '0x004c': 'WorkerEducate',
            '0x0050': 'NationalPop',
            '0x0054': 'NationalValue',
            '0x0058': 'NationalTax',
            '0x005c': 'NationalTrend',
            '0x0060': 'heat',
            '0x0064': 'wind',
            '0x0068': 'humid',
            '0x006c': 'weatherTrend',
            '0x0070': 'NewDisaster',
            '0x0074': 'oldResPop',
            '0x0078': 'Rewards',
            '0x007c': 'Population Graphs',
            '0x016c': 'Industry Graphs',
            '0x01f0': 'Tile Counts',
            '0x05f0': 'ZonePop|0',
            '0x05f4': 'ZonePop|1',
            '0x05f8': 'ZonePop|2',
            '0x05fc': 'ZonePop|3',
            '0x0600': 'ZonePop|4',
            '0x0604': 'ZonePop|5',
            '0x0608': 'ZonePop|6',
            '0x060c': 'ZonePop|7',
            '0x0610': 'Bonds',
            '0x06d8': 'Neighbours',
            '0x0718': 'Valve?|0',  # reverse engineered from the game, may be a typo in original.
            '0x071c': 'Valve?|1',
            '0x0720': 'Valve?|2',
            '0x0724': 'Valve?|3',
            '0x0728': 'Valve?|4',
            '0x072c': 'Valve?|5',
            '0x0730': 'Valve?|6',
            '0x0734': 'Valve?|7',
            '0x0738': 'gas_power',
            '0x073c': 'nuclear_power',
            '0x0740': 'solar_power',
            '0x0744': 'wind_power',
            '0x0748': 'microwave_power',
            '0x074c': 'fusion_power',
            '0x0750': 'airport',
            '0x0754': 'highways',
            '0x0758': 'buses',
            '0x075c': 'subways',
            '0x0760': 'water_treatment',
            '0x0764': 'desalinisation',
            '0x0768': 'plymouth',
            '0x076c': 'forest',
            '0x0770': 'darco',
            '0x0774': 'launch',
            '0x0778': 'highway_2',
            '0x077c': 'Budget',
            '0x0e3c': 'YearEnd',
            '0x0e40': 'GlobalSeaLevel',
            '0x0e44': 'terCoast',
            '0x0e48': 'terRiver',
            '0x0e4c': 'Military',
            '0x0e50': 'Paper List',
            '0x0ec8': 'News List',
            '0x0fa0': 'Ordinances',
            '0x0fa4': 'unemployed',
            '0x0fa8': 'Military Count',
            '0x0fe8': 'SubwayCnt',
            '0x0fec': 'GameSpeed',
            '0x0ff0': 'AutoBudget',
            '0x0ff4': 'AutoGo',
            '0x0ff8': 'UserSoundOn',
            '0x0ffc': 'UserMusicOn',
            '0x1000': 'NoDisasters',
            '0x1004': 'PaperDeliver',
            '0x1008': 'PaperExtra',
            '0x100c': 'PaperChoice',
            '0x1010': 'unknown128',
            '0x1014': 'Zoom',
            '0x1018': 'CityCentX',
            '0x101c': 'CityCentY',
            '0x1020': 'GlobalArcoPop',
            '0x1024': 'ConnectTiles',
            '0x1028': 'TeamsActive',
            '0x102c': 'TotalPop',
            '0x1030': 'IndustryBonus',
            '0x1034': 'PolluteBonus',
            '0x1038': 'oldArrest',
            '0x103c': 'PoliceBonus',
            '0x1040': 'DisasterObject',
            '0x1044': 'CurrentDisaster',
            '0x1048': 'GoDisaster',
            '0x104c': 'SewerBonus',
            '0x1050': 'Extra', }
        handle_special = ['Population Graphs', 'Industry Graphs', 'Tile Counts', 'Bonds', 'Neighbours', 'Budget',
                          'Military Count', 'Paper List', 'News List', 'Extra', 'Ordinances'] + list(
            self.simulator_settings.keys()) + list(self.game_settings.keys()) + list(self.inventions.keys())

        # Make sure the dict is sorted because following code requires the sorting.
        #sorted(parse_order.keys())

        # Parse misc and generate city attributes.
        for k, v in parse_order.items():
            offset = int(k, 16)
            if v not in handle_special:
                self.city_attributes[v] = parse_uint32(misc_data[offset : offset + 4])
            elif v == 'Population Graphs':
                length = 240
                self.population_graphs = self.misc_uninterleave_data(self._population_graph_names, offset, length, misc_data)
            elif v == 'Industry Graphs':
                length = 132
                self.industry_graphs = self.misc_uninterleave_data(self._industry_graph_names, offset, length, misc_data)
            elif v == 'Tile Counts':
                for x in range(0, 256):
                    self.building_count[x] = parse_int32(misc_data[offset: offset + 4])
                    offset += 4
            elif v in ('Bonds', 'Ordinances'):
                # Handled along with the budget.
                continue
            elif v == 'Neighbours':
                neighbour_types = ['Name', 'Population', 'Value', 'Fame']
                # Calculate their offsets. 64 = 4 neighbours at 4 x 4B entries each
                for idx, start_offset in enumerate(range(offset, offset + 64, 16)):
                    # 16 = 4 entries x 4B per entry.
                    neighbour = collections.OrderedDict()
                    for x in range(start_offset, start_offset + 16, 4):
                        type_key = neighbour_types[((x + 8) % 16) // 4]
                        neighbour[type_key] = parse_int32(misc_data[x : x + 4])
                    self.neighbor_info[idx] = neighbour
            elif v == 'Budget':
                self.budget = Budget()
                self.budget.parse_budget(misc_data)
            elif v == 'Military Count':
                num_items = 16
                for idx, x in enumerate(range(offset, offset + num_items * 4, 4)):
                    key = "{}|{}".format(v, idx)
                    self.city_attributes[key] = parse_int32(misc_data[x : x + 4])
            elif v == 'Paper List':
                num_items = 6 * 5
                for idx, x in enumerate(range(offset, offset + num_items * 4, 4)):
                    key = "{}|{}".format(v, idx)
                    self.city_attributes[key] = parse_int32(misc_data[x : x + 4])
            elif v == 'News List':
                num_items = 9 * 6
                for idx, x in enumerate(range(offset, offset + num_items * 4, 4)):
                    key = "{}|{}".format(v, idx)
                    self.city_attributes[key] = parse_int32(misc_data[x : x + 4])
            elif v == 'Extra':
                for idx, x in enumerate(range(offset, 4800, 4)):
                    key = "{}|{}".format(v, idx)
                    self.city_attributes[key] = parse_int32(misc_data[x : x + 4])
            elif v in list(self.simulator_settings.keys()):
                self.simulator_settings[v] = parse_int32(misc_data[offset : offset + 4])
            elif v in list(self.game_settings.keys()):
                self.game_settings[v] = parse_int32(misc_data[offset : offset + 4])
            elif v in list(self.inventions.keys()):
                self.inventions[v] = parse_int32(misc_data[offset : offset + 4])
            else:
                # Fallthrough, this should never, ever, be hit.
                print("MISC is missing something!", k, v)
Example #14
0
    def _create_ssh_connection(self):
        # Read the global request that SSH sends us - this is trying to let us know all host keys, but
        # it's OpenSSH-specific, and we don't need it
        data = self._ssh_transport_connection.read()
        index, msg_type = parse_byte(data, 0)
        index, request_name = parse_string(data, index)
        index, want_reply_byte = parse_byte(data, index)
        want_reply = want_reply_byte != 0

        assert msg_type == SSH_MSG_NUMS['SSH_MSG_GLOBAL_REQUEST']
        assert request_name == '*****@*****.**'
        assert not want_reply

        # Reply to let OpenSSH know that we don't know what they're talking about
        msg = []
        msg.append(generate_byte(SSH_MSG_NUMS['SSH_MSG_REQUEST_FAILURE']))
        self._ssh_transport_connection.send(''.join(msg))

        # Actually get started with opening a channel for SSH communication
        window_size = 1048576
        maximum_packet_size = 16384

        # Request to open a session channel
        msg = []
        msg.append(generate_byte(SSH_MSG_NUMS['SSH_MSG_CHANNEL_OPEN']))
        msg.append(generate_string('session'))
        msg.append(generate_uint32(self._local_channel_number))
        msg.append(generate_uint32(window_size))
        msg.append(generate_uint32(maximum_packet_size))
        self._ssh_transport_connection.send(''.join(msg))

        # Check that a channel was opened successfully
        data = self._ssh_transport_connection.read()
        index, msg_type = parse_byte(data, 0)
        index, recipient_channel = parse_uint32(data, index)
        index, self._remote_channel_number = parse_uint32(data, index)
        index, initial_window_size = parse_uint32(data, index)
        index, maximum_packet_size = parse_uint32(data, index)

        print colors.cyan('Message type: %d' % msg_type)
        assert msg_type == SSH_MSG_NUMS['SSH_MSG_CHANNEL_OPEN_CONFIRMATION']
        assert recipient_channel == self._local_channel_number
        print colors.cyan('Remote channel number: %d' %
                          self._remote_channel_number)
        print colors.cyan('Initial window size: %d' % initial_window_size)
        print colors.cyan('Maximum window size: %d' % maximum_packet_size)

        # Ask to turn that session channel into a shell
        msg = []
        msg.append(generate_byte(SSH_MSG_NUMS['SSH_MSG_CHANNEL_REQUEST']))
        msg.append(generate_uint32(self._remote_channel_number))
        msg.append(generate_string('shell'))
        msg.append(generate_byte(1))  # True, we do want a reply here
        self._ssh_transport_connection.send(''.join(msg))

        # OpenSSH then asks to increase their window size, that's fine, do it
        data = self._ssh_transport_connection.read()
        index, msg_type = parse_byte(data, 0)
        index, recipient_channel = parse_uint32(data, index)
        index, bytes_to_add = parse_uint32(data, index)
        assert msg_type == SSH_MSG_NUMS['SSH_MSG_CHANNEL_WINDOW_ADJUST']
        initial_window_size += bytes_to_add

        # Check that they tell us they've opened a channel successfully
        data = self._ssh_transport_connection.read()
        index, msg_type = parse_byte(data, 0)

        assert msg_type == SSH_MSG_NUMS['SSH_MSG_CHANNEL_SUCCESS']
        assert recipient_channel == self._local_channel_number

        print colors.cyan('Successfully opened shell!')
Example #15
0
  def _create_ssh_connection(self):
    # Read the global request that SSH sends us - this is trying to let us know all host keys, but
    # it's OpenSSH-specific, and we don't need it
    data = self._ssh_transport_connection.read()
    index, msg_type = parse_byte(data, 0)
    index, request_name = parse_string(data, index)
    index, want_reply_byte = parse_byte(data, index)
    want_reply = want_reply_byte != 0

    assert msg_type == SSH_MSG_NUMS['SSH_MSG_GLOBAL_REQUEST']
    assert request_name == '*****@*****.**'
    assert not want_reply

    # Reply to let OpenSSH know that we don't know what they're talking about
    msg = []
    msg.append(generate_byte(SSH_MSG_NUMS['SSH_MSG_REQUEST_FAILURE']))
    self._ssh_transport_connection.send(''.join(msg))

    # Actually get started with opening a channel for SSH communication
    window_size = 1048576
    maximum_packet_size = 16384

    # Request to open a session channel
    msg = []
    msg.append(generate_byte(SSH_MSG_NUMS['SSH_MSG_CHANNEL_OPEN']))
    msg.append(generate_string('session'))
    msg.append(generate_uint32(self._local_channel_number))
    msg.append(generate_uint32(window_size))
    msg.append(generate_uint32(maximum_packet_size))
    self._ssh_transport_connection.send(''.join(msg))

    # Check that a channel was opened successfully
    data = self._ssh_transport_connection.read()
    index, msg_type = parse_byte(data, 0)
    index, recipient_channel = parse_uint32(data, index)
    index, self._remote_channel_number = parse_uint32(data, index)
    index, initial_window_size = parse_uint32(data, index)
    index, maximum_packet_size = parse_uint32(data, index)

    print colors.cyan('Message type: %d' % msg_type)
    assert msg_type == SSH_MSG_NUMS['SSH_MSG_CHANNEL_OPEN_CONFIRMATION']
    assert recipient_channel == self._local_channel_number
    print colors.cyan('Remote channel number: %d' % self._remote_channel_number)
    print colors.cyan('Initial window size: %d' % initial_window_size)
    print colors.cyan('Maximum window size: %d' % maximum_packet_size)

    # Ask to turn that session channel into a shell
    msg = []
    msg.append(generate_byte(SSH_MSG_NUMS['SSH_MSG_CHANNEL_REQUEST']))
    msg.append(generate_uint32(self._remote_channel_number))
    msg.append(generate_string('shell'))
    msg.append(generate_byte(1)) # True, we do want a reply here
    self._ssh_transport_connection.send(''.join(msg))

    # OpenSSH then asks to increase their window size, that's fine, do it
    data = self._ssh_transport_connection.read()
    index, msg_type = parse_byte(data, 0)
    index, recipient_channel = parse_uint32(data, index)
    index, bytes_to_add = parse_uint32(data, index)
    assert msg_type == SSH_MSG_NUMS['SSH_MSG_CHANNEL_WINDOW_ADJUST']
    initial_window_size += bytes_to_add

    # Check that they tell us they've opened a channel successfully
    data = self._ssh_transport_connection.read()
    index, msg_type = parse_byte(data, 0)

    assert msg_type == SSH_MSG_NUMS['SSH_MSG_CHANNEL_SUCCESS']
    assert recipient_channel == self._local_channel_number

    print colors.cyan('Successfully opened shell!')