Jump to content
View in the app

A better way to browse. Learn more.

Tuts 4 You

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

Help with Duplicating Reverse Engineered USB Commands from Wireshark Using PyUSB on Linux

Featured Replies

Posted

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

image.png.b8225bb56c565b2294038f38f071857c.png

 

Wireshark USB Packet Capture Linux Host (PyUSB)

image.png.016724e827c6e964178c0c01f56550bf.png

 

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:

 

three.png.3ab78f01b7e91c1eb16f7ce7829db52e.png

  • 2 weeks later...
  • Author

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.

Create an account or sign in to comment

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.