Jump to content
Tuts 4 You

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


bekindpleaserewind

Recommended Posts

bekindpleaserewind

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

  • Like 1
Link to comment
Share on other sites

  • 2 weeks later...
bekindpleaserewind

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.

  • Like 1
  • Thanks 1
Link to comment
Share on other sites

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...