Now we can use Python + LibUSB to send Control Endpoint packets with the command
ctrl_transfer( bmRequestType, bmRequest, wValue, wIndex, nBytes)
This command can do both sending and receiving depending on what bmRequestType says (input or output). Still, there is a lot of options here. To send the right command you need to know theRequestType and the right Request and ther right Value as well as the Index and how many bytes to read or write.
If we were totally on our own, we would start by trying to read data from the device. This means we have to set the RequestType first
Direction | Type | Recipient | |||||
---|---|---|---|---|---|---|---|
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
For bmRequestType the value passed is very structured so that's not as hard to guess. (See lvr.com for more information )
- Bits 2, 3 and 4 are reserves so set them to 0.
- The direction is set by bit #7, 0 is a 'write' out to the device, 1 is a 'read' from the device
- The 'type' of message is two bits, 0 = Standard, 1 = Class, 2 = Vendor, 3 = Reserved. For many devices that are non-standard, you'll probably want 2 for vendor type. If its a more standard type of device, like a camera or mic, try 0 or 1. 3 Is unused
- The last two bits are usd to determine the recipient for the message 0 = Device, 1 = Interface, 2 = Endpoint, 3 = Other. Go with 0 to start, you can try 2 if there are other endpoints
The safest thing to do is read data (no way to overwrite anything or configure) you can do that by sending packets with 0b11000000 (Read Vendor data from Device) = 0xC0.
If I were to write a fuzzer, I'd start by setting Index to 0 and iterating through all the byte values (255 different values) of bmRequest and the first few hundred wValues. Its pretty safe to just read random data to a USB device. Start by reading one byte to see if anything shows up, then increase the value
import usb.core import usb.util import sys # find our device dev = usb.core.find(idVendor=0x045e, idProduct=0x02B0) # was it found? if dev is None: raise ValueError('Device not found') # set the active configuration. With no arguments, the first # configuration will be the active one dev.set_configuration() # Let's fuzz around! # Lets start by Reading 1 byte from the Device using different Requests # bRequest is a byte so there are 255 different values for bRequest in range(255): try: ret = dev.ctrl_transfer(0xC0, bRequest, 0, 0, 1) print "bRequest ",bRequest print ret except: # failed to get data for this request pass
Looks like Request values 0, 5, 16, 50, 54, 64, 80 and 112 all return some sort of data. The rest had nothing to read
Next we'll try to read more data by changing the last argument to 100 bytes
Page last edited June 13, 2012
Text editor powered by tinymce.