def handle(self, data, addr):
        """
        Handle incoming smartglass packets

        Args:
            data (bytes): Raw packet
            addr (str): IP address of sender

        Returns: None
        """
        try:
            host, _ = addr

            if self.crypto:
                msg = packer.unpack(data, self.crypto)
            else:
                msg = packer.unpack(data)

            if msg.header.pkt_type == PacketType.DiscoveryResponse:
                log.debug("Received DiscoverResponse from %s",
                          host,
                          extra={'_msg': msg})
                self._discovered[host] = msg
                self.on_discover(host, msg)

            elif msg.header.pkt_type == PacketType.ConnectResponse:
                log.debug("Received ConnectResponse from %s",
                          host,
                          extra={'_msg': msg})
                if 'connect' in self._pending:
                    self._set_result('connect', msg)

            elif msg.header.pkt_type == PacketType.Message:
                channel = self._chl_mgr.get_channel(msg.header.channel_id)
                log.debug("Received %s message on ServiceChannel %s from %s",
                          msg.header.flags.msg_type.name,
                          channel.name,
                          host,
                          extra={'_msg': msg})
                seq_num = msg.header.sequence_number
                self._seq_mgr.add_received(seq_num)

                if msg.header.flags.need_ack:
                    self.ack([msg.header.sequence_number], [],
                             ServiceChannel.Core)

                self._on_message(msg, channel)
                self._seq_mgr.low_watermark = seq_num
            else:
                self._on_unk(msg)
        except Exception as e:
            log.exception("Exception in CoreProtocol datagram handler")
def parse(pcap_filepath, crypto):
    width = shutil.get_terminal_size().columns
    col_width = width // 2 - 3
    wrapper = textwrap.TextWrapper(col_width, replace_whitespace=False)

    for packet, is_client, ts in packet_filter(pcap_filepath):
        try:
            msg = packer.unpack(packet, crypto)
        except Exception as e:
            print("Error: {}".format(e))
            continue

        msg_type = msg.header.pkt_type
        type_str = msg_type.name

        if msg_type == PacketType.Message:
            type_str = msg.header.flags.msg_type.name

        direction = '>' if is_client else '<'
        print(' {} '.format(type_str).center(width, direction))

        lines = str(msg).split('\n')
        for line in lines:
            line = wrapper.wrap(line)
            for i in line:
                if is_client:
                    print('{0: <{1}}'.format(i, col_width), '│')
                else:
                    print(' ' * col_width, '│', '{0}'.format(i, col_width))
def test_channel_manager(packets, crypto):
    from xbox.sg.enum import ServiceChannel
    from xbox.sg.packer import unpack

    start_channel_resp = unpack(packets['start_channel_response'], crypto)
    mgr = ChannelManager()

    request_id = 0
    while request_id != start_channel_resp.protected_payload.channel_request_id:
        request_id = mgr.get_next_request_id(ServiceChannel.SystemInputTVRemote)

    service_channel = mgr.handle_channel_start_response(start_channel_resp)

    assert service_channel == ServiceChannel.SystemInputTVRemote

    # Deleting channel references
    mgr.reset()

    with pytest.raises(ChannelError):
        mgr.get_channel(123)

    with pytest.raises(ChannelError):
        mgr.get_channel_id(ServiceChannel.SystemInputTVRemote)

    with pytest.raises(ChannelError):
        mgr.handle_channel_start_response(start_channel_resp)

    assert mgr.get_channel(0) == ServiceChannel.Core
    assert mgr.get_channel(0x1000000000000000) == ServiceChannel.Ack

    assert mgr.get_channel_id(ServiceChannel.Core) == 0
    assert mgr.get_channel_id(ServiceChannel.Ack) == 0x1000000000000000
Exemplo n.º 4
0
def test_fragment_manager_fragment_messages(packets, crypto):
    from xbox.sg.packer import unpack

    fragments = [
        unpack(packets['fragment_media_state_0'], crypto),
        unpack(packets['fragment_media_state_1'], crypto),
        unpack(packets['fragment_media_state_2'], crypto)
    ]

    mgr = FragmentManager()
    assert mgr.reassemble_message(fragments.pop()) is None
    assert mgr.reassemble_message(fragments.pop()) is None
    msg = mgr.reassemble_message(fragments.pop())
    assert msg is not None

    assert msg.aum_id == 'Microsoft.BlurayPlayer_8wekyb3d8bbwe!Xbox.BlurayPlayer.Application'
    assert msg.max_seek == 50460000
    assert len(msg.asset_id) == 2184
Exemplo n.º 5
0
def packets():
    secret = unhexlify(
        '82bba514e6d19521114940bd65121af234c53654a8e67add7710b3725db44f77'
        '30ed8e3da7015a09fe0f08e9bef3853c0506327eb77c9951769d923d863a2f5e')
    sg_crypto = Crypto.from_shared_secret(secret)

    # Who cares about RAM anyway?
    data = {}
    data_path = os.path.join(os.path.dirname(__file__), 'data', 'packets')
    for f in os.listdir(data_path):
        with open(os.path.join(data_path, f), 'rb') as fh:
            data[f] = packer.unpack(fh.read(), sg_crypto)

    return data
Exemplo n.º 6
0
def parse(pcap_filepath, crypto):
    width = shutil.get_terminal_size().columns
    col_width = width // 2 - 3
    wrapper = textwrap.TextWrapper(col_width, replace_whitespace=False)

    for packet, is_client, ts in packet_filter(pcap_filepath):
        try:
            msg = packer.unpack(packet, crypto)
        except Exception as e:
            print("Error: {}".format(e))
            continue

        msg_type = msg.header.pkt_type
        type_str = msg_type.name

        if msg_type == PacketType.Message:
            type_str = msg.header.flags.msg_type.name


        if msg_type != PacketType.Message or msg.header.flags.msg_type != MessageType.AuxilaryStream:
            continue

        def un(d):
            return hexlify(d).decode('utf-8')

        if msg.protected_payload.connection_info_flag == 1:
            info = msg.protected_payload.connection_info
            print('Crypto Key: %s' % un(info.crypto_key))
            print('Client IV: %s' % un(info.client_iv))
            print('Server IV: %s' % un(info.server_iv))
            print('Sign Hash: %s' % un(info.sign_hash))

        direction = '>' if is_client else '<'
        print(' {} '.format(type_str).center(width, direction))

        lines = str(msg).split('\n')
        for line in lines:
            line = wrapper.wrap(line)
            for i in line:
                if is_client:
                    print('{0: <{1}}'.format(i, col_width), '│')
                else:
                    print(' ' * col_width, '│', '{0}'.format(i, col_width))
Exemplo n.º 7
0
def test_init_from_message(packets, crypto, uuid_dummy):
    msg = packer.unpack(packets['discovery_response'], crypto)

    c = console.Console.from_message('10.0.0.23', msg)

    assert c.address == '10.0.0.23'
    assert c.flags == enum.PrimaryDeviceFlag.AllowAuthenticatedUsers
    assert c.name == 'XboxOne'
    assert c.uuid == uuid_dummy
    assert c.liveid == 'FFFFFFFFFFF'
    assert c._public_key is not None
    assert c._crypto is not None
    assert c.device_status == enum.DeviceStatus.Available
    assert c.connection_state == enum.ConnectionState.Disconnected
    assert c.pairing_state == enum.PairedIdentityState.NotPaired
    assert c.paired is False
    assert c.available is True
    assert c.connected is False

    assert c.authenticated_users_allowed is True
    assert c.anonymous_connection_allowed is False
    assert c.console_users_allowed is False
    assert c.is_certificate_pending is False
Exemplo n.º 8
0
    def datagram_received(self, data: bytes, addr: str) -> None:
        """
        Handle incoming smartglass packets

        Args:
            data: Raw packet
            addr: IP address of sender

        Returns: None
        """
        try:
            host, _ = addr

            if self.crypto:
                msg = packer.unpack(data, self.crypto)
            else:
                msg = packer.unpack(data)

            if msg.header.pkt_type == PacketType.DiscoveryResponse:
                LOGGER.debug(f"Received DiscoverResponse from {host}",
                             extra={'_msg': msg})
                self._discovered[host] = msg
                self.on_discover(host, msg)

            elif msg.header.pkt_type == PacketType.ConnectResponse:
                LOGGER.debug(f"Received ConnectResponse from {host}",
                             extra={'_msg': msg})
                if 'connect' in self._pending:
                    self._set_result('connect', msg)

            elif msg.header.pkt_type == PacketType.Message:
                channel = self._chl_mgr.get_channel(msg.header.channel_id)
                message_info = msg.header.flags.msg_type.name

                if msg.header.flags.is_fragment:
                    message_info = 'MessageFragment ({0})'.format(message_info)

                LOGGER.debug(
                    "Received %s message on ServiceChannel %s from %s",
                    message_info,
                    channel.name,
                    host,
                    extra={'_msg': msg})
                seq_num = msg.header.sequence_number
                self._seq_mgr.add_received(seq_num)

                if msg.header.flags.need_ack:
                    asyncio.create_task(
                        self.ack([msg.header.sequence_number], [],
                                 ServiceChannel.Core))

                self._seq_mgr.low_watermark = seq_num

                if msg.header.flags.is_fragment:
                    sequence_begin = msg.protected_payload.sequence_begin
                    sequence_end = msg.protected_payload.sequence_end
                    fragment_payload = self._frg_mgr.reassemble_message(msg)
                    if not fragment_payload:
                        return

                    msg(protected_payload=fragment_payload)
                    LOGGER.debug("Assembled {0} (Seq {1}:{2})".format(
                        message_info, sequence_begin, sequence_end),
                                 extra={'_msg': msg})

                self._on_message(msg, channel)
            else:
                self._on_unk(msg)
        except Exception:
            LOGGER.exception("Exception in CoreProtocol datagram handler")
Exemplo n.º 9
0
def _unpack(data, crypto):
    return packer.unpack(data, crypto)
Exemplo n.º 10
0
def decrypted_packets(packets, crypto):
    return {k: packer.unpack(v, crypto) for k, v in packets.items()}