Created
April 20, 2020 00:40
-
-
Save userlandkernel/5a69d2f1f25a98f7b58a175af4322810 to your computer and use it in GitHub Desktop.
Forensic USB utility
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* USB Forenic Analyzer | |
* Written by @userlandkernel | |
* Powered by the free and opensource libusb (https://libusb.org) | |
*/ | |
#include <stdio.h> | |
#include <stdint.h> | |
#include <stdbool.h> | |
#include <stdlib.h> | |
#include <string.h> | |
#include <unistd.h> | |
#include <dlfcn.h> | |
#include <fcntl.h> | |
#include <sys/mman.h> | |
#include <sys/time.h> | |
#include <libusb-1.0/libusb.h> | |
libusb_context* ctx = NULL; | |
libusb_device **devices = NULL; | |
ssize_t count = 0; | |
const char* libusb_class_string(enum libusb_class_code code){ | |
switch(code) { | |
case LIBUSB_CLASS_PER_INTERFACE: | |
return "Interface Specific"; | |
case LIBUSB_CLASS_AUDIO: | |
return "Audio"; | |
case LIBUSB_CLASS_COMM: | |
return "Communcation"; | |
case LIBUSB_CLASS_HID: | |
return "Human Interface Device"; | |
case LIBUSB_CLASS_PHYSICAL: | |
return "Physical"; | |
case LIBUSB_CLASS_PRINTER: | |
return "Printer"; | |
case LIBUSB_CLASS_PTP: | |
return "PTP"; | |
case LIBUSB_CLASS_MASS_STORAGE: | |
return "Mass Storage"; | |
case LIBUSB_CLASS_DATA: | |
return "Data"; | |
case LIBUSB_CLASS_SMART_CARD: | |
return "Smart card"; | |
case LIBUSB_CLASS_CONTENT_SECURITY: | |
return "Content Security"; | |
case LIBUSB_CLASS_VIDEO: | |
return "Video"; | |
case LIBUSB_CLASS_PERSONAL_HEALTHCARE: | |
return "Personal Healthcare"; | |
case LIBUSB_CLASS_DIAGNOSTIC_DEVICE: | |
return "Diagnostic device"; | |
case LIBUSB_CLASS_WIRELESS: | |
return "Wireless class"; | |
case LIBUSB_CLASS_APPLICATION: | |
return "Application class"; | |
case LIBUSB_CLASS_VENDOR_SPEC: | |
return "Vendor specific"; | |
default: | |
return "Unknown class"; | |
} | |
} | |
const char* libusb_desc_type_string(enum libusb_descriptor_type type) { | |
switch(type) { | |
case LIBUSB_DT_DEVICE: | |
return "Device"; | |
case LIBUSB_DT_CONFIG: | |
return "Configuration"; | |
case LIBUSB_DT_STRING: | |
return "String"; | |
case LIBUSB_DT_INTERFACE: | |
return "Interface"; | |
case LIBUSB_DT_ENDPOINT: | |
return "Endpoint"; | |
case LIBUSB_DT_BOS: | |
return "BOS"; | |
case LIBUSB_DT_DEVICE_CAPABILITY: | |
return "Device Capability"; | |
case LIBUSB_DT_HID: | |
return "HID"; | |
case LIBUSB_DT_REPORT: | |
return "HID report"; | |
case LIBUSB_DT_PHYSICAL: | |
return "Physical"; | |
case LIBUSB_DT_HUB: | |
return "Hub"; | |
case LIBUSB_DT_SUPERSPEED_HUB: | |
return "SuperSpeed Hub"; | |
case LIBUSB_DT_SS_ENDPOINT_COMPANION: | |
return "SuperSpeed Endpoint Companion"; | |
default: | |
return "Unknown descriptor"; | |
} | |
} | |
void init(void) { | |
// Initialize libusb | |
libusb_init(&ctx); | |
// Retrieve attached devices | |
count = libusb_get_device_list(ctx, &devices); | |
} | |
void terminate(void) { | |
if(devices) | |
libusb_free_device_list(devices, count); | |
libusb_exit(ctx); | |
} | |
void hr(void) { | |
for(int i = 0; i < 80; i++) { | |
putchar('-'); | |
} | |
putchar('\n'); | |
} | |
libusb_device* find(uint16_t vid, uint16_t pid) { | |
// Go over all devices | |
for(int i = 0; i < count; i++) { | |
libusb_device* dev = devices[i]; | |
// Retrieve descriptor | |
struct libusb_device_descriptor desc = {0}; | |
libusb_get_device_descriptor(dev, &desc); | |
if(desc.idVendor == vid && desc.idProduct == pid) | |
return dev; | |
} | |
return NULL; | |
} | |
int main(int argc, char *argv[]){ | |
init(); | |
if(argc <= 2) { | |
printf("Usage: %s [vid] [pid]\n\tTip: Consider running lsusb to find devices to analyze\n\n", argv[0]); | |
return 1; | |
} | |
uint16_t vid = strtol(argv[1], NULL, 16); | |
uint16_t pid = strtol(argv[2], NULL, 16); | |
libusb_device* iphone = find(vid, pid); | |
if(!iphone) { | |
printf(" Could not find the device, are you sure it's attached to the BUS?\n"); | |
return 1; | |
} | |
uint64_t bus = libusb_get_bus_number(iphone); | |
uint64_t address = libusb_get_device_address(iphone); | |
printf("\n"); | |
hr(); | |
printf(" USB FORENISCS BY @userlandkernel. Compiled on %s %s\n", __DATE__, __TIME__); | |
hr(); | |
printf("\n"); | |
printf(" Bus: %#lx\n", bus); | |
printf(" Address: %#lx\n", address); | |
struct libusb_device_descriptor desc = {0}; | |
libusb_get_device_descriptor(iphone, &desc); | |
printf("\n"); | |
printf(" Descriptor size: %d bytes\n", desc.bLength); | |
printf(" Descriptor type: %s\n", libusb_desc_type_string(desc.bDescriptorType)); | |
printf(" USB Release: %#x\n", desc.bcdUSB); | |
printf("\n"); | |
printf(" VID / PID: %04x:%04x\n", desc.idVendor, desc.idProduct); | |
printf(" Device class: %s\n", libusb_class_string(desc.bDeviceClass)); | |
printf(" Device sub-class: %s\n", libusb_class_string(desc.bDeviceSubClass)); | |
printf(" Device protocol: %#x\n", desc.bDeviceProtocol); | |
printf(" Device Release: %#x\n", desc.bcdDevice); | |
printf(" Max packet size EP0: %d\n", desc.bMaxPacketSize0); | |
printf(" Number of configurations: %d\n", desc.bNumConfigurations); | |
printf("\n"); | |
libusb_device_handle* handle = NULL; | |
if( libusb_open(iphone, &handle) != LIBUSB_SUCCESS ) { | |
perror("Failed to open device"); | |
return 1; | |
} | |
unsigned char string[256]; | |
if(libusb_get_string_descriptor_ascii(handle, desc.iManufacturer, string, sizeof(string))) { | |
printf("\tManufacturer: %s\n", (char*)string); | |
} | |
if(libusb_get_string_descriptor_ascii(handle, desc.iProduct, string, sizeof(string))) { | |
printf("\tProduct: %s\n", (char*)string); | |
} | |
if(libusb_get_string_descriptor_ascii(handle, desc.iSerialNumber, string, sizeof(string))) { | |
printf("\tSerial Number: %s\n", (char*)string); | |
} | |
printf("\n"); | |
// Print Configurations | |
for(int i = 0; i < desc.bNumConfigurations; i++) { | |
struct libusb_config_descriptor* config = NULL; | |
if( libusb_get_config_descriptor(iphone, i, &config) != LIBUSB_SUCCESS) { | |
perror(" Couldn't retrieve configuration descriptor.\n"); | |
continue; | |
} | |
printf(" Configuration #%d\n", i+1); | |
hr(); | |
printf("\tTotal length: %u", config->wTotalLength); | |
printf("\tInterface count: %u\n", config->bNumInterfaces); | |
printf("\tConfiguration value: %u\n", config->bConfigurationValue); | |
printf("\tConfiguration index: %u\n", config->iConfiguration); | |
printf("\tAttributes: %02xh\n", config->bmAttributes); | |
printf("\tMax. power: %u\n\n", config->MaxPower); | |
// Print interfaces | |
for(int j = 0; j < config->bNumInterfaces; j++) { | |
const struct libusb_interface *iface = &config->interface[j]; | |
printf("\tInterface #%d\n", j+1); | |
printf("\n"); | |
// Print settings | |
for(int k = 0; k < iface->num_altsetting; k++) { | |
const struct libusb_interface_descriptor *ifdesc = &iface->altsetting[k]; | |
printf("\t\tSetting #%d\n", k+1); | |
printf("\t\t\tInterface number: %u\n", ifdesc->bInterfaceNumber); | |
printf("\t\t\tAlternate setting: %u\n", ifdesc->bAlternateSetting); | |
printf("\t\t\tEndpoint count: %u\n", ifdesc->bNumEndpoints); | |
printf("\t\t\tInterface class: %s\n", libusb_class_string(ifdesc->bInterfaceClass)); | |
printf("\t\t\tInterface sub-class: %s\n", libusb_class_string(ifdesc->bInterfaceSubClass)); | |
printf("\t\t\tInterface protocol: %#x\n", ifdesc->bInterfaceProtocol); | |
printf("\t\t\tInterface index: %d\n\n", ifdesc->iInterface); | |
printf("\n"); | |
// Print endpoints | |
for(int l = 0; l < ifdesc->bNumEndpoints; l++) { | |
const struct libusb_endpoint_descriptor* ep = &ifdesc->endpoint[l]; | |
printf("\t\t\tEndpoint %#02x\n", l); | |
printf("\t\t\t\tEndpoint Address: %#02x\n", ep->bEndpointAddress); | |
printf("\t\t\t\tAttributes: %#02x\n", ep->bmAttributes); | |
printf("\t\t\t\tMax. packetsize: %u\n", ep->wMaxPacketSize); | |
printf("\t\t\t\tInterval: %u\n", ep->bInterval); | |
printf("\t\t\t\tRefresh: %u\n", ep->bRefresh); | |
printf("\t\t\t\tSync. Address: %u\n", ep->bSynchAddress); | |
for(int k = 0; k < ep->extra_length; k++){ | |
if( ep->extra[i + 1] == LIBUSB_DT_SS_ENDPOINT_COMPANION ) { | |
printf("\t\t\t\tHAS_ENDPOINTCOMPANION!\n"); | |
} | |
} | |
printf("\n"); | |
} | |
} | |
printf("\n"); | |
} | |
if(config) | |
libusb_free_config_descriptor(config); | |
} | |
terminate(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment