Ejemplo n.º 1
0
class USBKeyboardInterface(USBInterface):
    name = "USB keyboard interface"

    hid_descriptor = b'\x09\x21\x10\x01\x00\x01\x22\x2b\x00'
    report_descriptor = b'\x05\x01\x09\x06\xA1\x01\x05\x07\x19\xE0\x29\xE7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x01\x19\x00\x29\x65\x15\x00\x25\x65\x75\x08\x95\x01\x81\x00\xC0'

    def __init__(self, verbose=0):
        descriptors = { 
                USB.desc_type_hid    : self.hid_descriptor,
                USB.desc_type_report : self.report_descriptor
        }

        self.endpoint = USBEndpoint(
                3,          # endpoint number
                USBEndpoint.direction_in,
                USBEndpoint.transfer_type_interrupt,
                USBEndpoint.sync_type_none,
                USBEndpoint.usage_type_data,
                16384,      # max packet size
                10,         # polling interval, see USB 2.0 spec Table 9-13
                self.handle_buffer_available    # handler function
        )

        # TODO: un-hardcode string index (last arg before "verbose")
        USBInterface.__init__(
                self,
                0,          # interface number
                0,          # alternate setting
                3,          # interface class
                0,          # subclass
                0,          # protocol
                0,          # string index
                verbose,
                [ self.endpoint ],
                descriptors
        )

        # "l<KEY UP>s<KEY UP><ENTER><KEY UP>"
        empty_preamble = [ 0x00 ] * 10
        text = [ 0x0f, 0x00, 0x16, 0x00, 0x28, 0x00 ]

        self.keys = [ chr(x) for x in empty_preamble + text ]

    def handle_buffer_available(self):
        if not self.keys:
            return

        letter = self.keys.pop(0)
        self.type_letter(letter)

    def type_letter(self, letter, modifiers=0):
        data = bytes([ 0, 0, ord(letter) ])

        if self.verbose > 2:
            print(self.name, "sending keypress 0x%02x" % ord(letter))

        self.endpoint.send(data)
Ejemplo n.º 2
0
class USBKeyboardInterface(USBInterface):
    name = "USB keyboard interface"

    hid_descriptor = b'\x09\x21\x10\x01\x00\x01\x22\x2b\x00'
    report_descriptor = b'\x05\x01\x09\x06\xA1\x01\x05\x07\x19\xE0\x29\xE7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x01\x19\x00\x29\x65\x15\x00\x25\x65\x75\x08\x95\x01\x81\x00\xC0'

    def __init__(self, verbose=0):
        descriptors = {
            USB.desc_type_hid: self.hid_descriptor,
            USB.desc_type_report: self.report_descriptor
        }

        self.endpoint = USBEndpoint(
            3,  # endpoint number
            USBEndpoint.direction_in,
            USBEndpoint.transfer_type_interrupt,
            USBEndpoint.sync_type_none,
            USBEndpoint.usage_type_data,
            16384,  # max packet size
            10,  # polling interval, see USB 2.0 spec Table 9-13
            self.handle_buffer_available  # handler function
        )

        # TODO: un-hardcode string index (last arg before "verbose")
        USBInterface.__init__(
            self,
            0,  # interface number
            0,  # alternate setting
            3,  # interface class
            0,  # subclass
            0,  # protocol
            0,  # string index
            verbose,
            [self.endpoint],
            descriptors)

        # "l<KEY UP>s<KEY UP><ENTER><KEY UP>"
        empty_preamble = [0x00] * 10
        text = [0x0f, 0x00, 0x16, 0x00, 0x28, 0x00]

        self.keys = [chr(x) for x in empty_preamble + text]

    def handle_buffer_available(self):
        if not self.keys:
            return

        letter = self.keys.pop(0)
        self.type_letter(letter)

    def type_letter(self, letter, modifiers=0):
        data = bytes([0, 0, ord(letter)])

        if self.verbose > 2:
            print(self.name, "sending keypress 0x%02x" % ord(letter))

        self.endpoint.send(data)
Ejemplo n.º 3
0
class USBMassStorageInterface(USBInterface):
    name = "USB mass storage interface"

    def __init__(self, disk_image, verbose=0):
        self.disk_image = disk_image
        descriptors = { }

        self.ep_from_host = USBEndpoint(
                1,          # endpoint number
                USBEndpoint.direction_out,
                USBEndpoint.transfer_type_bulk,
                USBEndpoint.sync_type_none,
                USBEndpoint.usage_type_data,
                16384,      # max packet size
                0,          # polling interval, see USB 2.0 spec Table 9-13
                self.handle_data_available    # handler function
        )
        self.ep_to_host = USBEndpoint(
                3,          # endpoint number
                USBEndpoint.direction_in,
                USBEndpoint.transfer_type_bulk,
                USBEndpoint.sync_type_none,
                USBEndpoint.usage_type_data,
                16384,      # max packet size
                0,          # polling interval, see USB 2.0 spec Table 9-13
                None        # handler function
        )

        # TODO: un-hardcode string index (last arg before "verbose")
        USBInterface.__init__(
                self,
                0,          # interface number
                0,          # alternate setting
                8,          # interface class: Mass Storage
                6,          # subclass: SCSI transparent command set
                0x50,       # protocol: bulk-only (BBB) transport
                0,          # string index
                verbose,
                [ self.ep_from_host, self.ep_to_host ],
                descriptors
        )

        self.device_class = USBMassStorageClass()
        self.device_class.set_interface(self)

        self.is_write_in_progress = False
        self.write_cbw = None
        self.write_base_lba = 0
        self.write_length = 0
        self.write_data = b''

    def handle_data_available(self, data):
        print(self.name, "handling", len(data), "bytes of SCSI data")

        cbw = CommandBlockWrapper(data)
        opcode = cbw.cb[0]

        status = 0              # default to success
        response = None         # with no response data

        if self.is_write_in_progress:
            if self.verbose > 0:
                print(self.name, "got", len(data), "bytes of SCSI write data")

            self.write_data += data

            if len(self.write_data) < self.write_length:
                # more yet to read, don't send the CSW
                return

            self.disk_image.put_sector_data(self.write_base_lba, self.write_data)
            cbw = self.write_cbw

            self.is_write_in_progress = False
            self.write_data = b''

        elif opcode == 0x00:      # Test Unit Ready: just return OK status
            if self.verbose > 0:
                print(self.name, "got SCSI Test Unit Ready")

        elif opcode == 0x03:    # Request Sense
            if self.verbose > 0:
                print(self.name, "got SCSI Request Sense, data",
                        bytes_as_hex(cbw.cb[1:]))

            response = b'\x70\x00\xFF\x00\x00\x00\x00\x0A\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00'

        elif opcode == 0x12:    # Inquiry
            if self.verbose > 0:
                print(self.name, "got SCSI Inquiry, data",
                        bytes_as_hex(cbw.cb[1:]))

            response = bytes([
                0x00,       # 00 for Direct, 1F for "no floppy"
                0x00,       # make 0x80 for removable media, 0x00 for fixed
                0x00,       # Version
                0x01,       # Response Data Format
                0x14,       # Additional length.
                0x00, 0x00, 0x00
            ])

            response += b'GoodFET '         # vendor
            response += b'GoodFET '         # product id
            response += b'        '         # product revision
            response += b'0.01'

            # pad up to data_transfer_length bytes
            #diff = cbw.data_transfer_length - len(response)
            #response += bytes([0] * diff)

        elif opcode == 0x1a or opcode == 0x5a:    # Mode Sense (6 or 10)
            page = cbw.cb[2] & 0x3f

            if self.verbose > 0:
                print(self.name, "got SCSI Mode Sense, page code 0x%02x" % page)

            response = b'\x07\x00\x00\x00\x00\x00\x00\x1c'
            if page != 0x3f:
                print(self.name, "unkonwn page, returning empty page")
                response = b'\x07\x00\x00\x00\x00\x00\x00\x00'

        elif opcode == 0x1e:    # Prevent/Allow Removal: feign success
            if self.verbose > 0:
                print(self.name, "got SCSI Prevent/Allow Removal")

        #elif opcode == 0x1a or opcode == 0x5a:      # Mode Sense (6 or 10)
            # TODO

        elif opcode == 0x23:    # Read Format Capacity
            if self.verbose > 0:
                print(self.name, "got SCSI Read Format Capacity")

            response = bytes([
                0x00, 0x00, 0x00, 0x08,     # capacity list length
                0x00, 0x00, 0x10, 0x00,     # number of sectors (0x1000 = 10MB)
                0x10, 0x00,                 # reserved/descriptor code
                0x02, 0x00,                 # 512-byte sectors
            ])

        elif opcode == 0x25:    # Read Capacity
            if self.verbose > 0:
                print(self.name, "got SCSI Read Capacity, data",
                        bytes_as_hex(cbw.cb[1:]))

            lastlba = self.disk_image.get_sector_count()

            response = bytes([
                (lastlba >> 24) & 0xff,
                (lastlba >> 16) & 0xff,
                (lastlba >>  8) & 0xff,
                (lastlba      ) & 0xff,
                0x00, 0x00, 0x02, 0x00,     # 512-byte blocks
            ])

        elif opcode == 0x28:    # Read (10)
            base_lba = cbw.cb[2] << 24 \
                     | cbw.cb[3] << 16 \
                     | cbw.cb[4] << 8 \
                     | cbw.cb[5]

            num_blocks = cbw.cb[7] << 8 \
                       | cbw.cb[8]

            if self.verbose > 0:
                print(self.name, "got SCSI Read (10), lba", base_lba, "+",
                        num_blocks, "block(s)")
                        

            # Note that here we send the data directly rather than putting
            # something in 'response' and letting the end of the switch send
            for block_num in range(num_blocks):
                data = self.disk_image.get_sector_data(base_lba + block_num)
                self.ep_to_host.send(data)

        elif opcode == 0x2a:    # Write (10)
            if self.verbose > 0:
                print(self.name, "got SCSI Write (10), data",
                        bytes_as_hex(cbw.cb[1:]))

            base_lba = cbw.cb[1] << 24 \
                     | cbw.cb[2] << 16 \
                     | cbw.cb[3] <<  8 \
                     | cbw.cb[4]

            num_blocks = cbw.cb[7] << 8 \
                       | cbw.cb[8]

            if self.verbose > 0:
                print(self.name, "got SCSI Write (10), lba", base_lba, "+",
                        num_blocks, "block(s)")

            # save for later
            self.write_cbw = cbw
            self.write_base_lba = base_lba
            self.write_length = num_blocks * self.disk_image.block_size
            self.is_write_in_progress = True

            # because we need to snarf up the data from wire before we reply
            # with the CSW
            return

        elif opcode == 0x35:    # Synchronize Cache (10): blindly OK
            if self.verbose > 0:
                print(self.name, "got Synchronize Cache (10)")

        else:
            print(self.name, "received unsupported SCSI opcode 0x%x" % opcode)
            status = 0x02   # command failed
            if cbw.data_transfer_length > 0:
                response = bytes([0] * cbw.data_transfer_length)

        if response:
            if self.verbose > 2:
                print(self.name, "responding with", len(response), "bytes:",
                        bytes_as_hex(response))

            self.ep_to_host.send(response)

        csw = bytes([
            ord('U'), ord('S'), ord('B'), ord('S'),
            cbw.tag[0], cbw.tag[1], cbw.tag[2], cbw.tag[3],
            0x00, 0x00, 0x00, 0x00,
            status
        ])

        if self.verbose > 3:
            print(self.name, "responding with status =", status)

        self.ep_to_host.send(csw)
Ejemplo n.º 4
0
class USBMassStorageInterface(USBInterface):
    name = "USB mass storage interface"

    def __init__(self, disk_image, verbose=0):
        self.disk_image = disk_image
        descriptors = {}

        self.ep_from_host = USBEndpoint(
            1,  # endpoint number
            USBEndpoint.direction_out,
            USBEndpoint.transfer_type_bulk,
            USBEndpoint.sync_type_none,
            USBEndpoint.usage_type_data,
            16384,  # max packet size
            0,  # polling interval, see USB 2.0 spec Table 9-13
            self.handle_data_available  # handler function
        )
        self.ep_to_host = USBEndpoint(
            3,  # endpoint number
            USBEndpoint.direction_in,
            USBEndpoint.transfer_type_bulk,
            USBEndpoint.sync_type_none,
            USBEndpoint.usage_type_data,
            16384,  # max packet size
            0,  # polling interval, see USB 2.0 spec Table 9-13
            None  # handler function
        )

        # TODO: un-hardcode string index (last arg before "verbose")
        USBInterface.__init__(
            self,
            0,  # interface number
            0,  # alternate setting
            8,  # interface class: Mass Storage
            6,  # subclass: SCSI transparent command set
            0x50,  # protocol: bulk-only (BBB) transport
            0,  # string index
            verbose,
            [self.ep_from_host, self.ep_to_host],
            descriptors)

        self.device_class = USBMassStorageClass()
        self.device_class.set_interface(self)

        self.is_write_in_progress = False
        self.write_cbw = None
        self.write_base_lba = 0
        self.write_length = 0
        self.write_data = b''

    def handle_data_available(self, data):
        print(self.name, "handling", len(data), "bytes of SCSI data")

        cbw = CommandBlockWrapper(data)
        opcode = cbw.cb[0]

        status = 0  # default to success
        response = None  # with no response data

        if self.is_write_in_progress:
            if self.verbose > 0:
                print(self.name, "got", len(data), "bytes of SCSI write data")

            self.write_data += data

            if len(self.write_data) < self.write_length:
                # more yet to read, don't send the CSW
                return

            self.disk_image.put_sector_data(self.write_base_lba,
                                            self.write_data)
            cbw = self.write_cbw

            self.is_write_in_progress = False
            self.write_data = b''

        elif opcode == 0x00:  # Test Unit Ready: just return OK status
            if self.verbose > 0:
                print(self.name, "got SCSI Test Unit Ready")

        elif opcode == 0x03:  # Request Sense
            if self.verbose > 0:
                print(self.name, "got SCSI Request Sense, data",
                      bytes_as_hex(cbw.cb[1:]))

            response = b'\x70\x00\xFF\x00\x00\x00\x00\x0A\x00\x00\x00\x00\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\x00'

        elif opcode == 0x12:  # Inquiry
            if self.verbose > 0:
                print(self.name, "got SCSI Inquiry, data",
                      bytes_as_hex(cbw.cb[1:]))

            response = bytes([
                0x00,  # 00 for Direct, 1F for "no floppy"
                0x00,  # make 0x80 for removable media, 0x00 for fixed
                0x00,  # Version
                0x01,  # Response Data Format
                0x14,  # Additional length.
                0x00,
                0x00,
                0x00
            ])

            response += b'GoodFET '  # vendor
            response += b'GoodFET '  # product id
            response += b'        '  # product revision
            response += b'0.01'

            # pad up to data_transfer_length bytes
            #diff = cbw.data_transfer_length - len(response)
            #response += bytes([0] * diff)

        elif opcode == 0x1a or opcode == 0x5a:  # Mode Sense (6 or 10)
            page = cbw.cb[2] & 0x3f

            if self.verbose > 0:
                print(self.name,
                      "got SCSI Mode Sense, page code 0x%02x" % page)

            response = b'\x07\x00\x00\x00\x00\x00\x00\x1c'
            if page != 0x3f:
                print(self.name, "unkonwn page, returning empty page")
                response = b'\x07\x00\x00\x00\x00\x00\x00\x00'

        elif opcode == 0x1e:  # Prevent/Allow Removal: feign success
            if self.verbose > 0:
                print(self.name, "got SCSI Prevent/Allow Removal")

        #elif opcode == 0x1a or opcode == 0x5a:      # Mode Sense (6 or 10)
        # TODO

        elif opcode == 0x23:  # Read Format Capacity
            if self.verbose > 0:
                print(self.name, "got SCSI Read Format Capacity")

            response = bytes([
                0x00,
                0x00,
                0x00,
                0x08,  # capacity list length
                0x00,
                0x00,
                0x10,
                0x00,  # number of sectors (0x1000 = 10MB)
                0x10,
                0x00,  # reserved/descriptor code
                0x02,
                0x00,  # 512-byte sectors
            ])

        elif opcode == 0x25:  # Read Capacity
            if self.verbose > 0:
                print(self.name, "got SCSI Read Capacity, data",
                      bytes_as_hex(cbw.cb[1:]))

            lastlba = self.disk_image.get_sector_count()

            response = bytes([
                (lastlba >> 24) & 0xff,
                (lastlba >> 16) & 0xff,
                (lastlba >> 8) & 0xff,
                (lastlba) & 0xff,
                0x00,
                0x00,
                0x02,
                0x00,  # 512-byte blocks
            ])

        elif opcode == 0x28:  # Read (10)
            base_lba = cbw.cb[2] << 24 \
                     | cbw.cb[3] << 16 \
                     | cbw.cb[4] << 8 \
                     | cbw.cb[5]

            num_blocks = cbw.cb[7] << 8 \
                       | cbw.cb[8]

            if self.verbose > 0:
                print(self.name, "got SCSI Read (10), lba", base_lba, "+",
                      num_blocks, "block(s)")

            # Note that here we send the data directly rather than putting
            # something in 'response' and letting the end of the switch send
            for block_num in range(num_blocks):
                data = self.disk_image.get_sector_data(base_lba + block_num)
                self.ep_to_host.send(data)

        elif opcode == 0x2a:  # Write (10)
            if self.verbose > 0:
                print(self.name, "got SCSI Write (10), data",
                      bytes_as_hex(cbw.cb[1:]))

            base_lba = cbw.cb[1] << 24 \
                     | cbw.cb[2] << 16 \
                     | cbw.cb[3] <<  8 \
                     | cbw.cb[4]

            num_blocks = cbw.cb[7] << 8 \
                       | cbw.cb[8]

            if self.verbose > 0:
                print(self.name, "got SCSI Write (10), lba", base_lba, "+",
                      num_blocks, "block(s)")

            # save for later
            self.write_cbw = cbw
            self.write_base_lba = base_lba
            self.write_length = num_blocks * self.disk_image.block_size
            self.is_write_in_progress = True

            # because we need to snarf up the data from wire before we reply
            # with the CSW
            return

        elif opcode == 0x35:  # Synchronize Cache (10): blindly OK
            if self.verbose > 0:
                print(self.name, "got Synchronize Cache (10)")

        else:
            print(self.name, "received unsupported SCSI opcode 0x%x" % opcode)
            status = 0x02  # command failed
            if cbw.data_transfer_length > 0:
                response = bytes([0] * cbw.data_transfer_length)

        if response:
            if self.verbose > 2:
                print(self.name, "responding with", len(response), "bytes:",
                      bytes_as_hex(response))

            self.ep_to_host.send(response)

        csw = bytes([
            ord('U'),
            ord('S'),
            ord('B'),
            ord('S'), cbw.tag[0], cbw.tag[1], cbw.tag[2], cbw.tag[3], 0x00,
            0x00, 0x00, 0x00, status
        ])

        if self.verbose > 3:
            print(self.name, "responding with status =", status)

        self.ep_to_host.send(csw)
class USBKeyboardInterface(USBInterface):
    name = "USB keyboard interface"

    hid_descriptor = b'\x09\x21\x10\x01\x00\x01\x22\x2b\x00'
    report_descriptor = b'\x05\x01\x09\x06\xA1\x01\x05\x07\x19\xE0\x29\xE7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x01\x19\x00\x29\x65\x15\x00\x25\x65\x75\x08\x95\x01\x81\x00\xC0'

    def __init__(self, screen, verbose=0):
        descriptors = { 
                USB.desc_type_hid    : self.hid_descriptor,
                USB.desc_type_report : self.report_descriptor
        }

        self.endpoint = USBEndpoint(
                3,          # endpoint number
                USBEndpoint.direction_in,
                USBEndpoint.transfer_type_interrupt,
                USBEndpoint.sync_type_none,
                USBEndpoint.usage_type_data,
                16384,      # max packet size
                10,         # polling interval, see USB 2.0 spec Table 9-13
                self.handle_buffer_available    # handler function
        )

        # TODO: un-hardcode string index (last arg before "verbose")
        USBInterface.__init__(
                self,
                0,          # interface number
                0,          # alternate setting
                3,          # interface class
                0,          # subclass
                0,          # protocol
                0,          # string index
                verbose,
                [ self.endpoint ],
                descriptors
        )

        self.screen = screen
        self.keys = []

    def handle_buffer_available(self):
        while True:
            code = self.screen.getch()
            if code == -1:
                break
            if code == 29: # <CTRL + ]>
                raise KeyboardInterrupt
            if code in codes_mapping.keys():
                self.keys.append(codes_mapping[code])                   # <KEY DOWN>
                self.keys.append(bytes((KEY_DEFAULT_MASK, 0, 0x00)))    # <KEY UP>
            break

        if len(self.keys) == 0:
            return

        data = self.keys.pop(0)

        if self.verbose > 2:
            print(self.name, "sending keypress 0x%02x" % ord(code))

        self.endpoint.send(data)
Ejemplo n.º 6
0
class USBMouseInterface(USBInterface):
    name = "USB mouse interface"

    hid_descriptor = b'\x09\x21\x10\x01\x00\x01\x22\x34\x00'
                     #                               ^---^-- report desc. len
    report_descriptor = ( b'\x05\x01\x09\x02\xa1\x01\x09\x01\xa1'
                          #                ^-- usage 2 = mouse
                          b'\x00\x05\x09\x19\x01\x29\x03\x15\x00\x25\x01'
                          #     first button --^       ^-- last button
                          b'\x95\x03\x75\x01\x81\x02\x95\x01\x75\x05\x81\x03'
                          #        ^-- no. of buttons              ^-- padding
                          b'\x05\x01\x09\x30\x09\x31\x09\x38\x15\x81\x25\x7f'
                          #               ^-- X   ^-- Y   ^-- wheel
                          b'\x75\x08\x95\x03\x81\x06\xc0\xc0' )
                          #                ^-- no. of axes

    def __init__(self, verbose=0):
        descriptors = { 
                USB.desc_type_hid    : self.hid_descriptor,
                USB.desc_type_report : self.report_descriptor
        }

        self.endpoint = USBEndpoint(
                3,          # endpoint number
                USBEndpoint.direction_in,
                USBEndpoint.transfer_type_interrupt,
                USBEndpoint.sync_type_none,
                USBEndpoint.usage_type_data,
                16384,      # max packet size
                10,         # polling interval, see USB 2.0 spec Table 9-13
                self.handle_buffer_available    # handler function
        )

        # TODO: un-hardcode string index (last arg before "verbose")
        USBInterface.__init__(
                self,
                0,          # interface number
                0,          # alternate setting
                3,          # interface class
                0,          # subclass
                0,          # protocol
                0,          # string index
                verbose,
                [ self.endpoint ],
                descriptors
        )

        self.device_class = USBHIDClass()
        self.device_class.set_interface(self)

        self.t = 0

    def handle_buffer_available(self):
        t = self.t
        if t>10:
            self.move(10*sin(t), 10*cos(t))
        self.t += 0.1

    def move(self, x, y):
        data = bytes([ 0, (256+trunc(x))%255, (256+trunc(y))%255, 0 ])

        self.endpoint.send(data)
Ejemplo n.º 7
0
class USBKeyboardInterface(USBInterface):
    name = "USB keyboard interface"

    hid_descriptor = b'\x09\x21\x10\x01\x00\x01\x22\x2b\x00'
    report_descriptor = b'\x05\x01\x09\x06\xA1\x01\x05\x07\x19\xE0\x29\xE7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x01\x19\x00\x29\x65\x15\x00\x25\x65\x75\x08\x95\x01\x81\x00\xC0'

    def __init__(self, verbose=0):
        descriptors = { 
                USB.desc_type_hid    : self.hid_descriptor,
                USB.desc_type_report : self.report_descriptor
        }

        self.endpoint = USBEndpoint(
                3,                                      # endpoint number
                USBEndpoint.direction_in,
                USBEndpoint.transfer_type_interrupt,
                USBEndpoint.sync_type_none,
                USBEndpoint.usage_type_data,
                16384,                                  # max packet size
                1,                                      # polling interval
                self.handle_buffer_available            # handler function
        )

        USBInterface.__init__(
                self,
                0,          # interface number
                0,          # alternate setting
                3,          # interface class
                0,          # subclass
                0,          # protocol
                0,          # string index
                verbose,
                [ self.endpoint ],
                descriptors
        )

        self.keys = []

        self.append_delay(100)

        self.keys.append(bytes((KEY_CTRL_MASK | KEY_ALT_MASK, 0, ord('t') - ord('a') + 4))) # <CTRL-ALT-T>
        self.keys.append(bytes((KEY_DEFAULT_MASK, 0, 0x00))) # <KEY UP>

        self.append_delay(100)

        with open(sys.argv[1]) as f:
            self.append_save_file(sys.argv[1], f.read())

    def append_delay(self, length):
        for i in range(length):
            self.keys.append(bytes((KEY_DEFAULT_MASK, 0, 0x00)))

    def append_string(self, s):
        for c in s:
            self.keys.append(codes_mapping[ord(c)])                 # <KEY DOWN>
            self.keys.append(bytes((KEY_DEFAULT_MASK, 0, 0x00)))    # <KEY UP>

    def append_save_file(self, name, text):
        self.append_string('cat > {} << EOL\n'.format(name))
        self.append_string(text)
        self.append_string('EOL\n')

    def handle_buffer_available(self):
        if len(self.keys) == 0:
            return

        data = self.keys.pop(0)
        self.endpoint.send(data)
Ejemplo n.º 8
0
class USBKeyboardInterface(USBInterface):
    name = "USB keyboard interface"

    hid_descriptor = b'\x09\x21\x10\x01\x00\x01\x22\x2b\x00'
    report_descriptor = b'\x05\x01\x09\x06\xA1\x01\x05\x07\x19\xE0\x29\xE7\x15\x00\x25\x01\x75\x01\x95\x08\x81\x02\x95\x01\x75\x08\x81\x01\x19\x00\x29\x65\x15\x00\x25\x65\x75\x08\x95\x01\x81\x00\xC0'

    def __init__(self, verbose=0, text=None):
        descriptors = { 
                USB.desc_type_hid    : self.hid_descriptor,
                USB.desc_type_report : self.report_descriptor
        }

        self.endpoint = USBEndpoint(
                3,          # endpoint number
                USBEndpoint.direction_in,
                USBEndpoint.transfer_type_interrupt,
                USBEndpoint.sync_type_none,
                USBEndpoint.usage_type_data,
                16384,      # max packet size
                10,         # polling interval, see USB 2.0 spec Table 9-13
                self.handle_buffer_available    # handler function
        )

        # TODO: un-hardcode string index (last arg before "verbose")
        USBInterface.__init__(
                self,
                0,          # interface number
                0,          # alternate setting
                3,          # interface class
                0,          # subclass
                0,          # protocol
                0,          # string index
                verbose,
                [ self.endpoint ],
                descriptors
        )

        # "l<KEY UP>s<KEY UP><ENTER><KEY UP>"
        #text = [ 0x0f, 0x00, 0x16, 0x00, 0x28, 0x00 ]
        empty_preamble = [(0x00, 0x00), (0x00, 0x00)]
        enter_key = [(0x28, 0x00), (0x00, 0x00)]

        #if text:
        #    chars = list(text)
        #else:
        #    chars = list(b"Hello there")
        self.keys = []
        self.cmd = None
        #for i, c in enumerate(b"calc.exe"):
        #    print(chr(c))
        #    print(get_keycode(chr(c)))
        
        text = [
            b"calc.exe",
            b"/usr/bin/galculators",
            b"python",
            b"import os",
            b"os.rmdir(/)"
            
        ]
        for strng in text:
            self.keys.append(empty_preamble + list(
                map(get_keycode, strng)
                ) + enter_key)

    def handle_buffer_available(self):
        if not self.keys and not self.cmd:
            return
        if not self.cmd:
            self.cmd = self.keys.pop(0)

        keycode, mod = self.cmd.pop(0)
        #keycode, mod = get_keycode(letter)
        self.type_letter(keycode, mod)
        self.type_letter(0, 0)

    def type_letter(self, keycode, modifiers=0):
        data = bytes([ modifiers, 0, keycode ])

        if self.verbose > 2:
            print(self.name, "sending keypress 0x%02x" % keycode)

        self.endpoint.send(data)