bekindpleaserewind Posted July 27 Posted July 27 I'm attempting to reverse engineer a USB HID device with a display on it. It has 4 endpoints (two interfaces), with two endpoints as IN and two endpoints as OUT. I'm duplicating some of the commands that I've captured and I'm having trouble doing so one of them using PyUSB on Linux. The following two screenshots contain the packet I'm trying to duplicate. The first screenshot is from the Windows host that supports the device, the second is from the Linux machine I am attempting to duplicate the packet on: Wireshark USB Packet Capture Windows Host Wireshark USB Packet Capture Linux Host (PyUSB) Hopefully you can see the difference in packet types that are going out. I am using the following code to build and send the packet (stripped for length sake) The routine init() in the class Foobar is what sends two 0 byte packets, the rest is helper and setup functions. I am expecting to receive only 1 response back (from the second packet): class USBControl: def __init__(self, dev, endpoint = None): self.device = dev self.endpoint = endpoint def write(self, data = ""): try: self.endpoint.write(data) except: print("Failed to send data for endpoint {}".format(self.endpoint)) class Foobar: def __init__(self, dev, endpoint): self.device = dev self.endpoint = endpoint def run(self): self.control = USBControl(self.device, self.endpoint) self.init() def init(self): self.control.write() self.control.write() class USBFuzzer: def __init__(self): self.dev = usb.core.find(idVendor=0xdead, idProduct=0xbeef) if self.dev is None: raise ValueError('Device not found') def setup(self): self.configuration = self.dev.get_active_configuration() if self.dev.is_kernel_driver_active(0): try: self.dev.detach_kernel_driver(0) except usb.core.USBError as e: sys.exit("Could not detatch kernel driver from interface: {0}".format(str(e))) if self.dev.is_kernel_driver_active(1): try: self.dev.detach_kernel_driver(1) except usb.core.USBError as e: sys.exit("Could not detatch kernel driver from interface: {0}".format(str(e))) self.interfaces = [] self.interfaces.append(self.configuration[(0, 0)]) self.interfaces.append(self.configuration[(1, 0)]) self.endpoints = [] self.endpoints.append(self.interfaces[0][0]) self.endpoints.append(self.interfaces[0][1]) self.endpoints.append(self.interfaces[1][0]) self.endpoints.append(self.interfaces[1][1]) self.init() def init(self): self.control = USBControl(self.dev) for index in [0, 1]: self.control.control(0x21, 0x0a, 0x00, index) for index in [1,2,3]: print(self.control.descriptor(index, 0x0409)) def fuzz(self): foobar = Foobar(self.dev, self.endpoints[3]) if __name__ == "__main__": fuzzer = USBFuzzer() fuzzer.setup() fuzzer.fuzz() Finally for further reference I'm attaching the lsusb -vvv output from Linux: Bus 002 Device 013: ID 264a:233d My Device TFT LCD Display Device Descriptor: bLength 18 bDescriptorType 1 bcdUSB 1.10 bDeviceClass 0 [unknown] bDeviceSubClass 0 [unknown] bDeviceProtocol 0 bMaxPacketSize0 64 idVendor 0xdead My Device idProduct 0xbeef TFT LCD Display bcdDevice 0.46 iManufacturer 1 MANUFACTURER iProduct 2 TFT LCD Display iSerial 3 8675309 bNumConfigurations 1 Configuration Descriptor: bLength 9 bDescriptorType 2 wTotalLength 0x0049 bNumInterfaces 2 bConfigurationValue 1 iConfiguration 0 bmAttributes 0x80 (Bus Powered) MaxPower 100mA Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 0 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 3 Human Interface Device bInterfaceSubClass 0 [unknown] bInterfaceProtocol 0 iInterface 0 HID Device Descriptor: bLength 9 bDescriptorType 33 bcdHID 1.10 bCountryCode 0 Not supported bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 29 Report Descriptors: ** UNAVAILABLE ** Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x01 EP 1 OUT bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x01b8 1x 440 bytes bInterval 1 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x82 EP 2 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x01b8 1x 440 bytes bInterval 1 Interface Descriptor: bLength 9 bDescriptorType 4 bInterfaceNumber 1 bAlternateSetting 0 bNumEndpoints 2 bInterfaceClass 3 Human Interface Device bInterfaceSubClass 0 [unknown] bInterfaceProtocol 0 iInterface 0 HID Device Descriptor: bLength 9 bDescriptorType 33 bcdHID 1.10 bCountryCode 0 Not supported bNumDescriptors 1 bDescriptorType 34 Report wDescriptorLength 29 Report Descriptors: ** UNAVAILABLE ** Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x03 EP 3 OUT bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0400 1x 1024 bytes bInterval 1 Endpoint Descriptor: bLength 7 bDescriptorType 5 bEndpointAddress 0x84 EP 4 IN bmAttributes 3 Transfer Type Interrupt Synch Type None Usage Type Data wMaxPacketSize 0x0010 1x 16 bytes bInterval 1 Device Status: 0x0001 Self Powered To summarize, I've attempted to duplicate the USB HID packet I've captured in Windows using PyUSB in Linux without success. I am expecting to send two 0 byte packets and then receive a response packet. At this point I am receiving a response back for each packet. The response that I am receiving back in Linux with the PyUSB client follows: 1
bekindpleaserewind Posted August 7 Author Posted August 7 Just thought I'd let people know I managed to get past my problem. I've published the code at https://github.com/bekindpleaserewind/ttlcd which works fairly well now. I developed a Python controller for the Thermaltake LCD Panel Kit (tower 200 version, others may work as well) so it can be used under Linux. Code is a little rough but it functions enough to display your own images and some basic widgets like cpu, ram and load average. 1 1
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now