From 5d0ec740a030de67142bd74f3fbb68e9a142cc54 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 12 Jun 2023 16:04:32 +0800 Subject: [PATCH 01/77] chore: change all #import's to #include's --- src/drivers/hal/hal.c | 2 +- src/drivers/mipi/mipi.c | 2 +- src/drivers/plat/s5l8960.c | 2 +- src/drivers/plat/s8000.c | 2 +- src/drivers/plat/s8001.c | 2 +- src/drivers/plat/s8003.c | 2 +- src/drivers/plat/t7000.c | 2 +- src/drivers/plat/t7001.c | 2 +- src/drivers/plat/t8010.c | 2 +- src/drivers/plat/t8011.c | 2 +- src/drivers/plat/t8012.c | 2 +- src/drivers/plat/t8015.c | 2 +- src/drivers/tz/tz.c | 2 +- src/kernel/pongo.h | 4 ++-- 14 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/drivers/hal/hal.c b/src/drivers/hal/hal.c index f3f83d31..cd909b56 100644 --- a/src/drivers/hal/hal.c +++ b/src/drivers/hal/hal.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include struct hal_device _gRootDevice = { .name = "root" }; diff --git a/src/drivers/mipi/mipi.c b/src/drivers/mipi/mipi.c index 481b8ffd..7d1646a4 100644 --- a/src/drivers/mipi/mipi.c +++ b/src/drivers/mipi/mipi.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static uint64_t gmipi_reg; diff --git a/src/drivers/plat/s5l8960.c b/src/drivers/plat/s5l8960.c index e3bc2835..ca3805f1 100644 --- a/src/drivers/plat/s5l8960.c +++ b/src/drivers/plat/s5l8960.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static bool s5l8960_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { if (device->cpid == 0x8960) { diff --git a/src/drivers/plat/s8000.c b/src/drivers/plat/s8000.c index 6067acc2..47cec279 100644 --- a/src/drivers/plat/s8000.c +++ b/src/drivers/plat/s8000.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static bool s8000_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { if (device->cpid == 0x8000) { diff --git a/src/drivers/plat/s8001.c b/src/drivers/plat/s8001.c index 38c89d0f..cb3f3001 100644 --- a/src/drivers/plat/s8001.c +++ b/src/drivers/plat/s8001.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static bool s8001_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { if (device->cpid == 0x8001) { diff --git a/src/drivers/plat/s8003.c b/src/drivers/plat/s8003.c index 2c364737..9c7e376a 100644 --- a/src/drivers/plat/s8003.c +++ b/src/drivers/plat/s8003.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static bool s8003_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { if (device->cpid == 0x8003) { diff --git a/src/drivers/plat/t7000.c b/src/drivers/plat/t7000.c index 41f99223..e45dc2a7 100644 --- a/src/drivers/plat/t7000.c +++ b/src/drivers/plat/t7000.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static bool t7000_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { if (device->cpid == 0x7000) { diff --git a/src/drivers/plat/t7001.c b/src/drivers/plat/t7001.c index 940123ca..5818104e 100644 --- a/src/drivers/plat/t7001.c +++ b/src/drivers/plat/t7001.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static bool t7001_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { if (device->cpid == 0x7001) { diff --git a/src/drivers/plat/t8010.c b/src/drivers/plat/t8010.c index b3a68243..556b7b20 100644 --- a/src/drivers/plat/t8010.c +++ b/src/drivers/plat/t8010.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static bool t8010_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { if (device->cpid == 0x8010) { diff --git a/src/drivers/plat/t8011.c b/src/drivers/plat/t8011.c index ae087a52..89c2f708 100644 --- a/src/drivers/plat/t8011.c +++ b/src/drivers/plat/t8011.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static bool t8011_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { if (device->cpid == 0x8011) { diff --git a/src/drivers/plat/t8012.c b/src/drivers/plat/t8012.c index 913c2243..e3744870 100644 --- a/src/drivers/plat/t8012.c +++ b/src/drivers/plat/t8012.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static bool t8012_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { if (device->cpid == 0x8012) { diff --git a/src/drivers/plat/t8015.c b/src/drivers/plat/t8015.c index 08cc6f89..1dbbc8c3 100644 --- a/src/drivers/plat/t8015.c +++ b/src/drivers/plat/t8015.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include static bool t8015_probe(struct hal_platform_driver* device_driver, struct hal_platform* device) { if (device->cpid == 0x8015) { diff --git a/src/drivers/tz/tz.c b/src/drivers/tz/tz.c index ee57af7d..9de77463 100644 --- a/src/drivers/tz/tz.c +++ b/src/drivers/tz/tz.c @@ -24,7 +24,7 @@ * SOFTWARE. * */ -#import +#include volatile uint32_t *gTZRegbase; diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index 786297e7..0edfd10c 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -190,8 +190,8 @@ typedef enum { } vm_protect_t; #ifdef PONGO_PRIVATE -#import "vfs.h" -#import "task.h" +#include "vfs.h" +#include "task.h" #else struct proc; struct task; From fa27a131d681b85ab4435428ee34dfa8fda784c8 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 12 Jun 2023 16:37:45 +0800 Subject: [PATCH 02/77] chore: Use -Wno-strict-prototypes --- Makefile | 2 +- include/paleinfo.h | 62 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 include/paleinfo.h diff --git a/Makefile b/Makefile index 3193858f..fe7416b0 100644 --- a/Makefile +++ b/Makefile @@ -105,7 +105,7 @@ endif # General options EMBEDDED_LD_FLAGS ?= -nostdlib -Wl,-dead_strip -Wl,-Z $(EMBEDDED_LDFLAGS) -EMBEDDED_CC_FLAGS ?= --target=arm64-apple-ios12.0 -std=gnu17 -Wall -Wstrict-prototypes -Werror=incompatible-function-pointer-types -flto -ffreestanding -nostdlibinc -fno-blocks -U__nonnull -DTARGET_OS_OSX=0 -DTARGET_OS_MACCATALYST=0 -D_GNU_SOURCE -D__DYNAMIC_REENT__ -DDER_TAG_SIZE=8 -I$(LIB)/include $(EMBEDDED_LD_FLAGS) $(EMBEDDED_CFLAGS) +EMBEDDED_CC_FLAGS ?= --target=arm64-apple-ios12.0 -std=gnu17 -Wall -Wstrict-prototypes -Werror=incompatible-function-pointer-types -flto -ffreestanding -nostdlibinc -fno-blocks -U__nonnull -DTARGET_OS_OSX=0 -DTARGET_OS_MACCATALYST=0 -D_GNU_SOURCE -D__DYNAMIC_REENT__ -DDER_TAG_SIZE=8 -Wno-strict-prototypes -I$(LIB)/include $(EMBEDDED_LD_FLAGS) $(EMBEDDED_CFLAGS) ifdef DEV_BUILD EMBEDDED_CC_FLAGS += -DDEV_BUILD diff --git a/include/paleinfo.h b/include/paleinfo.h new file mode 100644 index 00000000..cf35ee07 --- /dev/null +++ b/include/paleinfo.h @@ -0,0 +1,62 @@ +/* + * jbinit - https://github.com/palera1n/jbinit + * + * This file is part of jbinit + * + * SPDX-License-Identifier: MIT + */ + +#ifndef PALEINFO_H +#define PALEINFO_H + +#include + +#define PALEINFO_VERSION 2U +typedef uint64_t palerain_option_t; + +// unified palera1n options +#define palerain_option_rootful (1ULL << 0) /* rootful jailbreak */ +#define palerain_option_rootless (1ULL << 1) /* rootless jailbreak */ +#define palerain_option_setup_rootful (1ULL << 2) /* create fakefs */ +// #define palerain_option_setup_rootful_forced (1ULL << 3) /* create fakefs over an existing one */ +#define palerain_option_setup_partial_root (1ULL << 4) /* fakefs creating should be partial */ +#define palerain_option_checkrain_is_clone (1ULL << 5) /* supplied checkra1n is checkra1n clone */ +#define palerain_option_rootless_livefs (1ULL << 6) /* mount root livefs on rootless */ +// #define palerain_option_no_ssv (1ULL << 7) /* no signed system volume */ +// #define palerain_option_force_fakefs (1ULL << 8) /* force fakefs, even without SSV */ +#define palerain_option_clean_fakefs (1ULL << 9) /* clean fakefs, but does not delete it */ +#define palerain_option_tui (1ULL << 10) /* terminal user interface */ +// #define palerain_option_gui (1ULL << 11) /* graphical user interface*/ +#define palerain_option_dfuhelper_only (1ULL << 12) /* dfuhelper only */ +#define palerain_option_pongo_exit (1ULL << 13) /* boot to clean pongo shell */ +#define palerain_option_demote (1ULL << 14) /* Demote effective production fuse status */ +#define palerain_option_pongo_full (1ULL << 15) /* Boot to pongo with default images and options */ +#define palerain_option_palerain_version (1ULL << 16) /* Print version */ +#define palerain_option_exit_recovery (1ULL << 17) /* Exit recovery mode */ +#define palerain_option_reboot_device (1ULL << 18) /* Reboot device in normal mode */ +#define palerain_option_enter_recovery (1ULL << 19) /* Enter recovery mode */ +#define palerain_option_device_info (1ULL << 20) /* Print device info */ +#define palerain_option_no_colors (1ULL << 21) /* no colors */ +#define palerain_option_bind_mount (1ULL << 22) /* bind mounts should be used (always true iOS 15+)*/ +#define palerain_option_overlay (1ULL << 23) /* there is an overlay (should always be true) */ +#define palerain_option_force_revert (1ULL << 24) /* Unjailbreak */ +#define palerain_option_safemode (1ULL << 25) /* Enter safe mode */ +#define palerain_option_verbose_boot (1ULL << 26) /* verbose boot */ + +#define palerain_option_flower_chain (1ULL << 61) /* Flower chain */ +#define palerain_option_test1 (1ULL << 62) /* Developer test option 1 */ +#define palerain_option_test2 (1ULL << 63) /* Developer test option 2 */ + +#define PALEINFO_MAGIC 'PLSH' + +/* paleinfo version 2, appended to ramdisk */ +struct paleinfo { + uint32_t magic; /* 'PLSH' */ + uint32_t version; /* 2 */ + uint64_t kbase; /* kernel base */ + uint64_t kslide; /* kernel slide */ + uint64_t flags; /* unified palera1n flags */ + char rootdev[0x10]; /* ex. disk0s1s8 */ +}__attribute__((packed)); + +#endif From a156feead9f47b2748d1152c4ca43c7089570565 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 12 Jun 2023 16:49:02 +0800 Subject: [PATCH 03/77] kpf: replace kerninfo and other flags with paleinfo paleinfo is palera1n's version kerninfo, with support for additional things such as rootful with fakefs. --- checkra1n/kpf/bindfs.c | 9 +-- checkra1n/kpf/developer_mode.c | 2 +- checkra1n/kpf/kpf.h | 11 ++-- checkra1n/kpf/launch_constraints.c | 2 +- checkra1n/kpf/mach_port.c | 4 +- checkra1n/kpf/main.c | 72 +++++++++++---------- checkra1n/kpf/nvram.c | 2 +- checkra1n/kpf/overlay.c | 9 +-- checkra1n/kpf/ramdisk.c | 88 ++++++++++++++++++++----- checkra1n/kpf/trustcache.c | 2 +- include/kerninfo.h | 100 ----------------------------- include/paleinfo.h | 65 ++++++++++--------- src/kernel/pongo.h | 4 +- 13 files changed, 169 insertions(+), 201 deletions(-) delete mode 100644 include/kerninfo.h diff --git a/checkra1n/kpf/bindfs.c b/checkra1n/kpf/bindfs.c index ff99313a..7632fb2d 100644 --- a/checkra1n/kpf/bindfs.c +++ b/checkra1n/kpf/bindfs.c @@ -26,7 +26,7 @@ */ #include "kpf.h" -#include +#include #include #include #include @@ -255,7 +255,7 @@ static void kpf_bindfs_patches(xnu_pf_patchset_t *xnu_text_exec_patchset) } } -static void kpf_bindfs_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, checkrain_option_t kpf_flags, checkrain_option_t checkra1n_flags) +static void kpf_bindfs_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, palerain_option_t palera1n_flags) { const char rootvp_string[] = "rootvp not authenticated after mounting"; const char *rootvp_string_match = memmem(cstring->cacheable_base, cstring->size, rootvp_string, sizeof(rootvp_string) - 1); // don't match null byte @@ -271,10 +271,11 @@ static void kpf_bindfs_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, do_bind_mounts = rootvp_string_match != NULL; } -static void kpf_bindfs_finish(struct mach_header_64 *hdr, checkrain_option_t *checkra1n_flags) +static void kpf_bindfs_finish(struct mach_header_64 *hdr, palerain_option_t *palera1n_flags) { // Signal to ramdisk whether we can have union mounts - checkrain_set_option(*checkra1n_flags, checkrain_option_bind_mount, do_bind_mounts); + if (do_bind_mounts) + *palera1n_flags |= palerain_option_bind_mount; } static uint32_t kpf_bindfs_size(void) diff --git a/checkra1n/kpf/developer_mode.c b/checkra1n/kpf/developer_mode.c index 55429007..663a30d1 100644 --- a/checkra1n/kpf/developer_mode.c +++ b/checkra1n/kpf/developer_mode.c @@ -124,7 +124,7 @@ static void kpf_developer_mode_patch(xnu_pf_patchset_t *amfi_text_exec_patchset) xnu_pf_maskmatch(amfi_text_exec_patchset, "developer_mode", matches, masks, sizeof(matches)/sizeof(uint64_t), true, (void*)kpf_developer_mode_callback); } -static void kpf_developer_mode_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, checkrain_option_t kpf_flags, checkrain_option_t checkra1n_flags) +static void kpf_developer_mode_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, palerain_option_t palera1n_flags) { struct mach_header_64 *amfi = xnu_pf_get_kext_header(hdr, "com.apple.driver.AppleMobileFileIntegrity"); xnu_pf_range_t *amfi_cstring = xnu_pf_section(amfi, "__TEXT", "__cstring"); diff --git a/checkra1n/kpf/kpf.h b/checkra1n/kpf/kpf.h index 38754eb6..cb144bfa 100644 --- a/checkra1n/kpf/kpf.h +++ b/checkra1n/kpf/kpf.h @@ -59,16 +59,17 @@ typedef const struct void (*patch)(xnu_pf_patchset_t *patchset); // NULL = end of list } kpf_patch_t; -// Order of invocations: init, shc_size, patches, shc_emit, finish, bootprep. -// All of init, finish and bootprep may be NULL independently. +// Order of invocations: pre_init, init, shc_size, patches, shc_emit, finish, bootprep. +// All of pre_init, init, finish and bootprep may be NULL independently. // shc_size and shc_emit must either both be NULL or non-NULL. // shc_size returns the maximum number of instructions to be emitted. // shc_emit returns the actual number of instructions that were emitted. typedef const struct { - void (*init)(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, checkrain_option_t kpf_flags, checkrain_option_t checkra1n_flags); // Flags are input only - void (*finish)(struct mach_header_64 *hdr, checkrain_option_t *checkra1n_flags); // Flags are to be treated as output only - void (*bootprep)(struct mach_header_64 *hdr, checkrain_option_t checkra1n_flags); // Flags are input only + void (*pre_init)(); // this is ran when the kpf module is first loaded + void (*init)(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, palerain_option_t palera1n_flags); // Flags are input only + void (*finish)(struct mach_header_64 *hdr, palerain_option_t *palera1n_flags); // Flags are to be treated as output only + void (*bootprep)(struct mach_header_64 *hdr, palerain_option_t palera1n_flags); // Flags are input only uint32_t (*shc_size)(void); uint32_t (*shc_emit)(uint32_t *shellcode_area); kpf_patch_t patches[]; diff --git a/checkra1n/kpf/launch_constraints.c b/checkra1n/kpf/launch_constraints.c index bdb253c1..609a81b5 100644 --- a/checkra1n/kpf/launch_constraints.c +++ b/checkra1n/kpf/launch_constraints.c @@ -94,7 +94,7 @@ static void kpf_launch_constraints_patch(xnu_pf_patchset_t *patchset) xnu_pf_maskmatch(patchset, "launch_constraints", matches, masks, sizeof(matches)/sizeof(uint64_t), true, (void*)kpf_launch_constraints_callback); } -static void kpf_launch_constraints_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, checkrain_option_t kpf_flags, checkrain_option_t checkra1n_flags) +static void kpf_launch_constraints_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, palerain_option_t palera1n_flags) { const char constraints_string[] = "mac_proc_check_launch_constraints"; const char *constraints_string_match = memmem(cstring->cacheable_base, cstring->size, constraints_string, sizeof(constraints_string)); diff --git a/checkra1n/kpf/mach_port.c b/checkra1n/kpf/mach_port.c index 4a3aa536..1134ceac 100644 --- a/checkra1n/kpf/mach_port.c +++ b/checkra1n/kpf/mach_port.c @@ -500,7 +500,7 @@ static void kpf_task_conversion_eval_patch(xnu_pf_patchset_t *xnu_text_exec_patc xnu_pf_maskmatch(xnu_text_exec_patchset, "task_conversion_eval", matches_imm, masks_imm, sizeof(matches_imm)/sizeof(uint64_t), false, (void*)kpf_task_conversion_eval_callback_imm); } -static void kpf_mach_port_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, checkrain_option_t kpf_flags, checkrain_option_t checkra1n_flags) +static void kpf_mach_port_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, palerain_option_t palera1n_flags) { const char kmap_port_string[] = "userspace has control access to a"; // iOS 14 had broken panic strings const char *kmap_port_string_match = memmem(cstring->cacheable_base, cstring->size, kmap_port_string, sizeof(kmap_port_string) - 1); // don't match null byte @@ -525,7 +525,7 @@ static void kpf_mach_port_patches(xnu_pf_patchset_t *xnu_text_exec_patchset) kpf_task_conversion_eval_patch(xnu_text_exec_patchset); } -static void kpf_mach_port_finish(struct mach_header_64 *hdr, checkrain_option_t *checkra1n_flags) +static void kpf_mach_port_finish(struct mach_header_64 *hdr, palerain_option_t *palera1n_flags) { if(need_convert_port_to_map_patch && !found_convert_port_to_map) { diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index a9fc73be..fe4e927b 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -31,7 +31,7 @@ #include #include #include -#include +#include #include #include #include @@ -1501,7 +1501,22 @@ static int kpf_compare_patches(const void *a, const void *b) return (int)one->granule - (int)two->granule; } -static checkrain_option_t kpf_flags, checkra1n_flags; +static palerain_option_t palera1n_flags; + +kpf_component_t* const kpf_components[] = { + &kpf_bindfs, + &kpf_developer_mode, + &kpf_dyld, + &kpf_launch_constraints, + &kpf_mach_port, + &kpf_nvram, + &kpf_shellcode, + &kpf_overlay, + &kpf_ramdisk, + &kpf_trustcache, + &kpf_vfs, + &kpf_vm_prot, +}; static void kpf_cmd(const char *cmd, char *args) { @@ -1515,22 +1530,6 @@ static void kpf_cmd(const char *cmd, char *args) uint64_t tick_0 = get_ticks(); uint64_t tick_1; - kpf_component_t* const kpf_components[] = - { - &kpf_bindfs, - &kpf_developer_mode, - &kpf_dyld, - &kpf_launch_constraints, - &kpf_mach_port, - &kpf_nvram, - &kpf_shellcode, - &kpf_overlay, - &kpf_ramdisk, - &kpf_trustcache, - &kpf_vfs, - &kpf_vm_prot, - }; - size_t npatches = 0; for(size_t i = 0; i < sizeof(kpf_components)/sizeof(kpf_components[0]); ++i) { @@ -1610,7 +1609,7 @@ static void kpf_cmd(const char *cmd, char *args) kpf_component_t *component = kpf_components[i]; if(component->init) { - component->init(hdr, text_cstring_range, kpf_flags, checkra1n_flags); + component->init(hdr, text_cstring_range, palera1n_flags); } } @@ -1885,7 +1884,7 @@ static void kpf_cmd(const char *cmd, char *args) { if(kpf_components[i]->finish) { - kpf_components[i]->finish(hdr, &checkra1n_flags); + kpf_components[i]->finish(hdr, &palera1n_flags); } } @@ -1893,11 +1892,11 @@ static void kpf_cmd(const char *cmd, char *args) { if(kpf_components[i]->bootprep) { - kpf_components[i]->bootprep(hdr, checkra1n_flags); + kpf_components[i]->bootprep(hdr, palera1n_flags); } } - if(checkrain_option_enabled(kpf_flags, checkrain_option_verbose_boot)) + if(palera1n_flags & palerain_option_verbose_boot) { gBootArgs->Video.v_display = 0; } @@ -1906,28 +1905,23 @@ static void kpf_cmd(const char *cmd, char *args) printf("KPF: Applied patchset in %llu ms\n", (tick_1 - tick_0) / TICKS_IN_1MS); } -static void set_flags(char *args, uint32_t *flags, const char *name) +static void set_flags(char *args, palerain_option_t *flags, const char *name) { if(args[0] != '\0') { - uint32_t val = strtoul(args, NULL, 16); - printf("Setting %s to 0x%08x\n", name, val); + palerain_option_t val = strtoul(args, NULL, 16); + printf("Setting %s to 0x%016llx\n", name, val); *flags = val; } else { - printf("%s: 0x%08x\n", name, *flags); + printf("%s: 0x%016llx\n", name, *flags); } } -static void checkra1n_flags_cmd(const char *cmd, char *args) +static void palera1n_flags_cmd(const char *cmd, char *args) { - set_flags(args, &checkra1n_flags, "checkra1n_flags"); -} - -static void kpf_flags_cmd(const char *cmd, char *args) -{ - set_flags(args, &kpf_flags, "kpf_flags"); + set_flags(args, &palera1n_flags, "palera1n_flags"); } void module_entry(void) @@ -1955,9 +1949,17 @@ void module_entry(void) puts("# Cellebrite (ih8sn0w, cjori, ronyrus et al.)"); puts("#=================="); + for(size_t i = 0; i < sizeof(kpf_components)/sizeof(kpf_components[0]); ++i) + { + kpf_component_t *component = kpf_components[i]; + if(component->pre_init) + { + component->pre_init(); + } + } + preboot_hook = kpf_cmd; - command_register("checkra1n_flags", "set flags for checkra1n userland", checkra1n_flags_cmd); - command_register("kpf_flags", "set flags for kernel patchfinder", kpf_flags_cmd); + command_register("palera1n_flags", "set flags for checkra1n userland", palera1n_flags_cmd); command_register("kpf", "running checkra1n-kpf without booting (use bootux afterwards)", kpf_cmd); command_register("overlay", "loads an overlay disk image", kpf_overlay_cmd); } diff --git a/checkra1n/kpf/nvram.c b/checkra1n/kpf/nvram.c index 759a03f9..15be499a 100644 --- a/checkra1n/kpf/nvram.c +++ b/checkra1n/kpf/nvram.c @@ -271,7 +271,7 @@ static void kpf_nvram_patches(xnu_pf_patchset_t *xnu_text_exec_patchset) xnu_pf_maskmatch(xnu_text_exec_patchset, "nvram_unlock", matches4, masks4, sizeof(matches4)/sizeof(uint64_t), false, (void*)kpf_nvram_table_callback); } -static void kpf_nvram_finish(struct mach_header_64 *hdr, checkrain_option_t *checkra1n_flags) +static void kpf_nvram_finish(struct mach_header_64 *hdr, palerain_option_t *palera1n_flags) { #ifdef DEV_BUILD // Treat this patch as optional in release diff --git a/checkra1n/kpf/overlay.c b/checkra1n/kpf/overlay.c index 7edf5e6a..1fde0783 100644 --- a/checkra1n/kpf/overlay.c +++ b/checkra1n/kpf/overlay.c @@ -26,7 +26,7 @@ */ #include "kpf.h" -#include +#include #include #include #include @@ -159,7 +159,7 @@ static void kpf_overlay_kdi_patches(xnu_pf_patchset_t *kdi_text_exec_patchset) } } -static void kpf_overlay_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, checkrain_option_t kpf_flags, checkrain_option_t checkra1n_flags) +static void kpf_overlay_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, palerain_option_t palera1n_flags) { did_run = true; @@ -173,9 +173,10 @@ static void kpf_overlay_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring do_shellcode = overlay_size > 0; } -static void kpf_overlay_finish(struct mach_header_64 *hdr, checkrain_option_t *checkra1n_flags) +static void kpf_overlay_finish(struct mach_header_64 *hdr, palerain_option_t *palera1n_flags) { - checkrain_set_option(*checkra1n_flags, checkrain_option_overlay, do_shellcode); + if (do_shellcode) + *palera1n_flags |= palerain_option_overlay; } static uint32_t kpf_overlay_size(void) diff --git a/checkra1n/kpf/ramdisk.c b/checkra1n/kpf/ramdisk.c index 43d6f93c..30fafa7d 100644 --- a/checkra1n/kpf/ramdisk.c +++ b/checkra1n/kpf/ramdisk.c @@ -26,7 +26,7 @@ */ #include "kpf.h" -#include +#include #include #include #include @@ -70,7 +70,7 @@ static void kpf_rootdev_patch(xnu_pf_patchset_t *xnu_text_exec_patchset) // A ton of kexts check for "rd=md*" and "rootdev=md*" in order to determine whether we're restoring. // We previously tried to patch all of those, but that is really tedious to do, and it's basically // impossible to determine whether you found all instances. - // What we do now is just change the place that actually boots off the ramdisk from "rootdev" to "nootdev", + // What we do now is just change the place that actually boots off the ramdisk from "rootdev" to "spartan", // and then patch the boot-args string to reflect that. // // Because codegen orders function args differently across versions and may or may not inline stuff, @@ -98,7 +98,54 @@ static void kpf_ramdisk_patches(xnu_pf_patchset_t *xnu_text_exec_patchset) } } -static void kpf_ramdisk_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, checkrain_option_t kpf_flags, checkrain_option_t checkra1n_flags) +static char rootdev[16] = { '\0' }; +static uint32_t partid = 1; + +static void kpf_ramdisk_rootdev_cmd(const char *cmd, char *args) { + // newfs: newfs_apfs -A -D -o role=r -v Xystem /dev/disk1 + + size_t root_matching_len = 0; + dt_node_t* chosen = dt_find(gDeviceTree, "chosen"); + if (!chosen) panic("invalid devicetree: no device!"); + uint32_t* root_matching = dt_prop(chosen, "root-matching", &root_matching_len); + if (!root_matching) panic("invalid devicetree: no prop!"); + + char str[0x100]; // max size = 0x100 + memset(&str, 0x0, 0x100); + + if (args[0] != '\0') { + snprintf(str, 0x100, "IOProviderClassIOServiceBSD Name%s", args); + snprintf(rootdev, 16, "%s", args); + + memset(root_matching, 0x0, 0x100); + memcpy(root_matching, str, 0x100); + printf("set new entry: %016llx: BSD Name: %s\n", (uint64_t)root_matching, args); + } else { + size_t max_fs_entries_len = 0; + dt_node_t* fstab = dt_find(gDeviceTree, "fstab"); + if (!fstab) panic("invalid devicetree: no fstab!"); + uint32_t* max_fs_entries = dt_prop(fstab, "max_fs_entries", &max_fs_entries_len); + if (!max_fs_entries) panic("invalid devicetree: no prop!"); + uint32_t* patch = (uint32_t*)max_fs_entries; + printf("fstab max_fs_entries: %016llx: %08x\n", (uint64_t)max_fs_entries, patch[0]); + dt_node_t* baseband = dt_find(gDeviceTree, "baseband"); + + if (baseband) partid = patch[0] + 1U; + else partid = patch[0]; + if (socnum == 0x7000 || socnum == 0x7001) partid--; + + snprintf(str, 0x100, "IOProviderClassIOMediaIOPropertyMatchPartition ID%u", partid); + memset(root_matching, 0x0, 0x100); + memcpy(root_matching, str, 0x100); + printf("set new entry: %016llx: Partition ID: %u\n", (uint64_t)root_matching, partid); + } +} + +static void kpf_ramdisk_pre_init(void) { + command_register("rootfs", "set rootfs in dt and paleinfo", kpf_ramdisk_rootdev_cmd); +} + +static void kpf_ramdisk_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, palerain_option_t palera1n_flags) { char *bootargs = (char*)((uintptr_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView); rootdev_bootarg = strstr(bootargs, "rootdev="); @@ -106,6 +153,13 @@ static void kpf_ramdisk_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring { rootdev_bootarg = NULL; } + const char cryptex_string[] = "/private/preboot/Cryptexes"; + const char *cryptex_string_match = memmem(cstring->cacheable_base, cstring->size, cryptex_string, sizeof(cryptex_string)); + if (rootdev[0] == '\0') { + if (cryptex_string_match != NULL) snprintf(rootdev, 16, "disk1s%u", partid); + else snprintf(rootdev, 16, "disk0s1s%u", partid); + } + #ifdef DEV_BUILD have_ramdisk = true; #else @@ -113,34 +167,37 @@ static void kpf_ramdisk_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring #endif } -static void kpf_ramdisk_bootprep(struct mach_header_64 *hdr, checkrain_option_t checkra1n_flags) +static void kpf_ramdisk_bootprep(struct mach_header_64 *hdr, palerain_option_t palera1n_flags) { if(rootdev_bootarg) { - rootdev_bootarg[0] = 'n'; // rootdev -> nootdev + memcpy(rootdev_bootarg, "spartan", 7); // rootdev -> spartan } if(ramdisk_size) { - puts("KPF: Found ramdisk, appending kerninfo"); + puts("KPF: Found ramdisk, appending paleinfo"); uint64_t slide = xnu_slide_value(hdr); - ramdisk_buf = realloc(ramdisk_buf, ramdisk_size + sizeof(struct kerninfo)); + ramdisk_buf = realloc(ramdisk_buf, ramdisk_size + 0x10000); if(!ramdisk_buf) { - panic("Failed to reallocate ramdisk with kerninfo"); + panic("Failed to reallocate ramdisk with paleinfo"); } - *(struct kerninfo*)(ramdisk_buf + ramdisk_size) = (struct kerninfo) + struct paleinfo* pinfo_p = (struct paleinfo*)(ramdisk_buf + ramdisk_size); + *pinfo_p = (struct paleinfo) { - .size = sizeof(struct kerninfo), - .base = slide + 0xfffffff007004000, - .slide = slide, - .flags = checkra1n_flags, + .magic = 'PLSH', + .version = 2, + .kbase = slide + 0xfffffff007004000, + .kslide = slide, + .flags = palera1n_flags, }; + snprintf(pinfo_p->rootdev, 16, "%s", rootdev); *(uint32_t*)(ramdisk_buf) = ramdisk_size; - ramdisk_size += sizeof(struct kerninfo); + ramdisk_size += 0x10000; } } @@ -162,7 +219,7 @@ static uint32_t kpf_ramdisk_emit(uint32_t *shellcode_area) // We emit a new string because it's possible that strings have // been merged with kexts, and we don't wanna patch those. - const char str[] = "nootdev"; + const char str[] = "spartan"; memcpy(shellcode_area, str, sizeof(str)); uint64_t shellcode_addr = xnu_ptr_to_va(shellcode_area); @@ -181,6 +238,7 @@ static uint32_t kpf_ramdisk_emit(uint32_t *shellcode_area) kpf_component_t kpf_ramdisk = { + .pre_init = kpf_ramdisk_pre_init, .init = kpf_ramdisk_init, .bootprep = kpf_ramdisk_bootprep, .shc_size = kpf_ramdisk_size, diff --git a/checkra1n/kpf/trustcache.c b/checkra1n/kpf/trustcache.c index 987d57b7..d19141db 100644 --- a/checkra1n/kpf/trustcache.c +++ b/checkra1n/kpf/trustcache.c @@ -162,7 +162,7 @@ static void kpf_trustcache_patches(xnu_pf_patchset_t *amfi_text_exec_patchset) xnu_pf_maskmatch(amfi_text_exec_patchset, "trustcache", matches_new, masks_new, sizeof(matches_new)/sizeof(uint64_t), false, (void*)kpf_trustcache_new_callback); } -static void kpf_trustcache_finish(struct mach_header_64 *hdr, checkrain_option_t *checkra1n_flags) +static void kpf_trustcache_finish(struct mach_header_64 *hdr, palerain_option_t *palera1n_flags) { if(!found_trustcache) { diff --git a/include/kerninfo.h b/include/kerninfo.h deleted file mode 100644 index cd9bb85b..00000000 --- a/include/kerninfo.h +++ /dev/null @@ -1,100 +0,0 @@ -/* - * pongoOS - https://checkra.in - * - * Copyright (C) 2019-2023 checkra1n team - * - * This file is part of pongoOS. - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * - */ -#ifndef _KERNINFO_H -#define _KERNINFO_H - -#include -#include -#include - -#define MAX_BOOTARGS_LEN 256 - -#define checkrain_option_none 0x00000000 -#define checkrain_option_all 0x7fffffff -#define checkrain_option_failure 0x80000000 - -// Host options -#define checkrain_option_verbose_logging (1 << 0) -#define checkrain_option_demote (1 << 1) -#define checkrain_option_early_exit (1 << 2) -#define checkrain_option_quick_mode (1 << 3) -#define checkrain_option_pongo_shell (1 << 4) -#define checkrain_option_pongo_full (1 << 5) - -// KPF options -#define checkrain_option_verbose_boot (1 << 0) - -// Global options -#define checkrain_option_safemode (1 << 0) -#define checkrain_option_bind_mount (1 << 1) -#define checkrain_option_overlay (1 << 2) -#define checkrain_option_force_revert (1 << 7) /* keep this at 7 */ - -typedef uint32_t checkrain_option_t, *checkrain_option_p; - -typedef enum { - jailbreak_capability_tfp0 = 1 << 0, - jailbreak_capability_userspace_reboot = 1 << 1, - jailbreak_capability_dyld_ignore_os = 1 << 2, // TODO: This needs a better name -} jailbreak_capability_t, *jailbreak_capability_p; - -#define DEFAULT_CAPABILITIES (jailbreak_capability_tfp0|jailbreak_capability_userspace_reboot) -struct kerninfo { - uint64_t size; - uint64_t base; - uint64_t slide; - checkrain_option_t flags; -}; -struct kpfinfo { - struct kerninfo k; - checkrain_option_t kpf_flags; - char bootargs[MAX_BOOTARGS_LEN]; -}; - -#define checkrain_set_option(options, option, enabled) do { \ - if (enabled) \ - options = (checkrain_option_t)((options) | option); \ - else \ - options = (checkrain_option_t)((options) & ~option); \ -} while (0); - -static inline bool checkrain_option_enabled(checkrain_option_t flags, checkrain_option_t opt) -{ - if(flags == checkrain_option_failure) - { - switch(opt) - { - case checkrain_option_safemode: - return true; - default: - return false; - } - } - return (flags & opt) != 0; -} - -#endif diff --git a/include/paleinfo.h b/include/paleinfo.h index cf35ee07..e8a77bd3 100644 --- a/include/paleinfo.h +++ b/include/paleinfo.h @@ -15,37 +15,40 @@ typedef uint64_t palerain_option_t; // unified palera1n options -#define palerain_option_rootful (1ULL << 0) /* rootful jailbreak */ -#define palerain_option_rootless (1ULL << 1) /* rootless jailbreak */ -#define palerain_option_setup_rootful (1ULL << 2) /* create fakefs */ -// #define palerain_option_setup_rootful_forced (1ULL << 3) /* create fakefs over an existing one */ -#define palerain_option_setup_partial_root (1ULL << 4) /* fakefs creating should be partial */ -#define palerain_option_checkrain_is_clone (1ULL << 5) /* supplied checkra1n is checkra1n clone */ -#define palerain_option_rootless_livefs (1ULL << 6) /* mount root livefs on rootless */ -// #define palerain_option_no_ssv (1ULL << 7) /* no signed system volume */ -// #define palerain_option_force_fakefs (1ULL << 8) /* force fakefs, even without SSV */ -#define palerain_option_clean_fakefs (1ULL << 9) /* clean fakefs, but does not delete it */ -#define palerain_option_tui (1ULL << 10) /* terminal user interface */ -// #define palerain_option_gui (1ULL << 11) /* graphical user interface*/ -#define palerain_option_dfuhelper_only (1ULL << 12) /* dfuhelper only */ -#define palerain_option_pongo_exit (1ULL << 13) /* boot to clean pongo shell */ -#define palerain_option_demote (1ULL << 14) /* Demote effective production fuse status */ -#define palerain_option_pongo_full (1ULL << 15) /* Boot to pongo with default images and options */ -#define palerain_option_palerain_version (1ULL << 16) /* Print version */ -#define palerain_option_exit_recovery (1ULL << 17) /* Exit recovery mode */ -#define palerain_option_reboot_device (1ULL << 18) /* Reboot device in normal mode */ -#define palerain_option_enter_recovery (1ULL << 19) /* Enter recovery mode */ -#define palerain_option_device_info (1ULL << 20) /* Print device info */ -#define palerain_option_no_colors (1ULL << 21) /* no colors */ -#define palerain_option_bind_mount (1ULL << 22) /* bind mounts should be used (always true iOS 15+)*/ -#define palerain_option_overlay (1ULL << 23) /* there is an overlay (should always be true) */ -#define palerain_option_force_revert (1ULL << 24) /* Unjailbreak */ -#define palerain_option_safemode (1ULL << 25) /* Enter safe mode */ -#define palerain_option_verbose_boot (1ULL << 26) /* verbose boot */ - -#define palerain_option_flower_chain (1ULL << 61) /* Flower chain */ -#define palerain_option_test1 (1ULL << 62) /* Developer test option 1 */ -#define palerain_option_test2 (1ULL << 63) /* Developer test option 2 */ +#define palerain_option_rootful (UINT64_C(1) << 0) /* rootful jailbreak */ +#define palerain_option_rootless (UINT64_C(1) << 1) /* rootless jailbreak */ +#define palerain_option_setup_rootful (UINT64_C(1) << 2) /* create fakefs */ +/* reserved */ +#define palerain_option_setup_partial_root (UINT64_C(1) << 4) /* fakefs creating should be partial */ +#define palerain_option_checkrain_is_clone (UINT64_C(1) << 5) /* supplied checkra1n is checkra1n clone */ +#define palerain_option_rootless_livefs (UINT64_C(1) << 6) /* mount root livefs on rootless */ +// #define palerain_option_no_ssv (UINT64_C(1) << 7) /* no signed system volume */ +// #define palerain_option_force_fakefs (UINT64_C(1) << 8) /* force fakefs, even without SSV */ +#define palerain_option_clean_fakefs (UINT64_C(1) << 9) /* clean fakefs, but does not delete it */ +#define palerain_option_tui (UINT64_C(1) << 10) /* terminal user interface */ +// #define palerain_option_gui (UINT64_C(1) << 11) /* graphical user interface*/ +#define palerain_option_dfuhelper_only (UINT64_C(1) << 12) /* dfuhelper only */ +#define palerain_option_pongo_exit (UINT64_C(1) << 13) /* boot to clean pongo shell */ +#define palerain_option_demote (UINT64_C(1) << 14) /* Demote effective production fuse status */ +#define palerain_option_pongo_full (UINT64_C(1) << 15) /* Boot to pongo with default images and options */ +#define palerain_option_palerain_version (UINT64_C(1) << 16) /* Print version */ +#define palerain_option_exit_recovery (UINT64_C(1) << 17) /* Exit recovery mode */ +#define palerain_option_reboot_device (UINT64_C(1) << 18) /* Reboot device in normal mode */ +#define palerain_option_enter_recovery (UINT64_C(1) << 19) /* Enter recovery mode */ +#define palerain_option_device_info (UINT64_C(1) << 20) /* Print device info */ +#define palerain_option_no_colors (UINT64_C(1) << 21) /* no colors */ +#define palerain_option_bind_mount (UINT64_C(1) << 22) /* bind mounts should be used (always true iOS 15+)*/ +#define palerain_option_overlay (UINT64_C(1) << 23) /* there is an overlay (should always be true) */ +#define palerain_option_force_revert (UINT64_C(1) << 24) /* Unjailbreak */ +#define palerain_option_safemode (UINT64_C(1) << 25) /* Enter safe mode */ +#define palerain_option_verbose_boot (UINT64_C(1) << 26) /* verbose boot */ + +#define palerain_option_jbinit_log_to_file (UINT64_C(1) << 50) /* make ramdisk log to file (jbinit2) */ +#define palerain_option_setup_rootful_forced (UINT64_C(1) << 51) /* create fakefs over an existing one (jbinit2) */ + +#define palerain_option_flower_chain (UINT64_C(1) << 61) /* Flower chain */ +#define palerain_option_test1 (UINT64_C(1) << 62) /* Developer test option 1 */ +#define palerain_option_test2 (UINT64_C(1) << 63) /* Developer test option 2 */ #define PALEINFO_MAGIC 'PLSH' diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index 0edfd10c..6ecde290 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -29,10 +29,12 @@ #include #include #include +#include #include #include +#include #include -#include +#include #ifdef PONGO_PRIVATE #include "framebuffer/fb.h" From ed9ab07f45d7c25308f1ce8555f3bab41c7fcf33 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sat, 8 Jul 2023 03:47:13 +0800 Subject: [PATCH 04/77] kpf: jbinit2 compatibility --- checkra1n/kpf/ramdisk.c | 54 +++++++++++++++++--- include/paleinfo_legacy.h | 101 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 include/paleinfo_legacy.h diff --git a/checkra1n/kpf/ramdisk.c b/checkra1n/kpf/ramdisk.c index 30fafa7d..5a3e350b 100644 --- a/checkra1n/kpf/ramdisk.c +++ b/checkra1n/kpf/ramdisk.c @@ -33,6 +33,7 @@ #include #include #include +#include static bool have_ramdisk = false; static char *rootdev_bootarg = NULL; @@ -167,6 +168,8 @@ static void kpf_ramdisk_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring #endif } +#define PINFO2PINFO1_MAP(name) { palerain_option_ ## name , palerain1_option_ ## name } + static void kpf_ramdisk_bootprep(struct mach_header_64 *hdr, palerain_option_t palera1n_flags) { if(rootdev_bootarg) @@ -185,16 +188,51 @@ static void kpf_ramdisk_bootprep(struct mach_header_64 *hdr, palerain_option_t p panic("Failed to reallocate ramdisk with paleinfo"); } - struct paleinfo* pinfo_p = (struct paleinfo*)(ramdisk_buf + ramdisk_size); - *pinfo_p = (struct paleinfo) + struct new_old_info_mapping pkinfo_mapping[] = { + { palerain_option_bind_mount, checkrain_option_bind_mount }, + { palerain_option_overlay, checkrain_option_overlay }, + { palerain_option_safemode, checkrain_option_safemode }, + { palerain_option_force_revert, checkrain_option_force_revert }, + { 0ULL, 0U } + }; + + struct new_old_info_mapping pinfo2pinfo1_mapping[] = { + PINFO2PINFO1_MAP(rootful), + PINFO2PINFO1_MAP(setup_rootful), + PINFO2PINFO1_MAP(rootless_livefs), + PINFO2PINFO1_MAP(setup_partial_root), + PINFO2PINFO1_MAP(jbinit_log_to_file), + PINFO2PINFO1_MAP(clean_fakefs), + { 0ULL, 0U } + }; + + uint32_t checkra1n_flags = 0; + for (uint8_t i = 0; pkinfo_mapping[i].old_info != 0U; i++) { + if (palera1n_flags & pkinfo_mapping[i].new_info) + checkra1n_flags |= pkinfo_mapping[i].old_info; + } + + uint32_t palera1n1_flags = 0; + for (uint8_t i = 0; pinfo2pinfo1_mapping[i].old_info != 0U; i++) { + if (palera1n_flags & pinfo2pinfo1_mapping[i].new_info) + palera1n1_flags |= pinfo2pinfo1_mapping[i].old_info; + } + + *(struct kerninfo*)(ramdisk_buf + ramdisk_size) = (struct kerninfo) { - .magic = 'PLSH', - .version = 2, - .kbase = slide + 0xfffffff007004000, - .kslide = slide, - .flags = palera1n_flags, + .size = sizeof(struct kerninfo), + .base = slide + 0xfffffff007004000, + .slide = slide, + .flags = checkra1n_flags, + }; + + struct paleinfo1* pinfo1_p = (struct paleinfo1*)(ramdisk_buf + ramdisk_size+ 0x1000); + *pinfo1_p = (struct paleinfo1){ + .magic = PALEINFO_MAGIC, + .version = 1, + .flags = palera1n1_flags, }; - snprintf(pinfo_p->rootdev, 16, "%s", rootdev); + snprintf(pinfo1_p->rootdev, 16, "%s", rootdev); *(uint32_t*)(ramdisk_buf) = ramdisk_size; ramdisk_size += 0x10000; diff --git a/include/paleinfo_legacy.h b/include/paleinfo_legacy.h new file mode 100644 index 00000000..996189ef --- /dev/null +++ b/include/paleinfo_legacy.h @@ -0,0 +1,101 @@ +#ifndef PALEINFO_LEGACY_H +#define PALEINFO_LEGACY_H + +#include +#include +#include + +#define MAX_BOOTARGS_LEN 256 + +#define checkrain_option_none 0x00000000 +#define checkrain_option_all 0x7fffffff +#define checkrain_option_failure 0x80000000 + +// Host options +#define checkrain_option_verbose_logging (1 << 0) +#define checkrain_option_demote (1 << 1) +#define checkrain_option_early_exit (1 << 2) +#define checkrain_option_quick_mode (1 << 3) +#define checkrain_option_pongo_shell (1 << 4) +#define checkrain_option_pongo_full (1 << 5) + +// KPF options +#define checkrain_option_verbose_boot (1 << 0) + +// Global options +#define checkrain_option_safemode (1 << 0) +#define checkrain_option_bind_mount (1 << 1) +#define checkrain_option_overlay (1 << 2) +#define checkrain_option_force_revert (1 << 7) /* keep this at 7 */ + +// palera1n options +#define palerain1_option_rootful (1 << 0) /* rootful jailbreak */ +#define palerain1_option_jbinit_log_to_file (1 << 1) /* log to /cores/jbinit.log */ +#define palerain1_option_setup_rootful (1 << 2) /* create fakefs */ +//#define palerain1_option_setup_rootful_forced (1 << 3) /* create fakefs over an existing one */ +#define palerain1_option_setup_partial_root (1 << 4) /* fakefs creating should be partial */ +// #define palerain1_option_checkrain_is_clone (1 << 5) /* supplied checkra1n is checkra1n clone */ +#define palerain1_option_rootless_livefs (1 << 6) /* mount root livefs on rootless */ +/* reserved values */ +// #define palerain1_option_no_ssv (1 << 7) /* no signed system volume */ +// #define palerain1_option_force_fakefs (1 << 8) /* force fakefs, even without SSV */ +// #define palerain1_option_rootless (1 << 9) /* rootless jailbreak */ +#define palerain1_option_clean_fakefs (1 << 10) /* clean fakefs, but does not delete it */ + +#define PALEINFO_MAGIC 'PLSH' + +typedef uint32_t checkrain_option_t, *checkrain_option_p; + +typedef enum { + jailbreak_capability_tfp0 = 1 << 0, + jailbreak_capability_userspace_reboot = 1 << 1, + jailbreak_capability_dyld_ignore_os = 1 << 2, // TODO: This needs a better name +} jailbreak_capability_t, *jailbreak_capability_p; + +#define DEFAULT_CAPABILITIES (jailbreak_capability_tfp0|jailbreak_capability_userspace_reboot) +struct kerninfo { + uint64_t size; + uint64_t base; + uint64_t slide; + checkrain_option_t flags; +}; +struct paleinfo1 { + uint32_t magic; // 'PLSH' / 0x504c5348 + uint32_t version; // 1 + checkrain_option_t flags; + char rootdev[0x10]; +}; +struct kpfinfo { + struct kerninfo k; + checkrain_option_t kpf_flags; + char bootargs[MAX_BOOTARGS_LEN]; +}; + +struct new_old_info_mapping { + uint64_t new_info; + uint32_t old_info; +}; + +#define checkrain_set_option(options, option, enabled) do { \ + if (enabled) \ + options = (checkrain_option_t)(options | option); \ + else \ + options = (checkrain_option_t)(options & ~option); \ +} while (0); + +static inline bool checkrain_option_enabled(checkrain_option_t flags, checkrain_option_t opt) +{ + if(flags == checkrain_option_failure) + { + switch(opt) + { + case checkrain_option_safemode: + return true; + default: + return false; + } + } + return (flags & opt) != 0; +} + +#endif From c1eb64836c6c598633b65fbd91886741fc0d38d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=3D=3FUTF-8=3Fq=3F=3DE3=3D81=3DAD=3DE3=3D82=3D80=3DE3=3D81?= =?UTF-8?q?=3D84=3F=3D?= <69592455+kok3shidoll@users.noreply.github.com> Date: Mon, 12 Jun 2023 16:55:14 +0800 Subject: [PATCH 05/77] kpf: fix mac_mount on iOS 16.4+ unlike checkra1n, this patch is always required on palera1n --- checkra1n/kpf/main.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index fe4e927b..209ae45d 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -159,7 +159,7 @@ static void kpf_kernel_version_init(xnu_pf_range_t *text_const_range) // Imports from shellcode.S extern uint32_t sandbox_shellcode[], sandbox_shellcode_setuid_patch[], sandbox_shellcode_ptrs[], sandbox_shellcode_end[]; -bool kpf_has_done_mac_mount; +bool kpf_has_done_mac_mount = false; bool kpf_mac_mount_callback(struct xnu_pf_patch* patch, uint32_t* opcode_stream) { puts("KPF: Found mac_mount"); uint32_t* mac_mount = &opcode_stream[0]; @@ -201,6 +201,7 @@ void kpf_mac_mount_patch(xnu_pf_patchset_t* xnu_text_exec_patchset) { // After that we search for a ldrb w8, [x8, 0x71] and replace it with a movz x8, 0 // at 0x70 there are the flags and MNT_ROOTFS is 0x00004000 -> 0x4000 >> 8 -> 0x40 -> bit 6 -> the check is right below // that way we can also perform operations on the rootfs + // r2: /x e92f1f32 uint64_t matches[] = { 0x321f2fe9, // orr w9, wzr, 0x1ffe }; @@ -208,7 +209,11 @@ void kpf_mac_mount_patch(xnu_pf_patchset_t* xnu_text_exec_patchset) { 0xFFFFFFFF, }; xnu_pf_maskmatch(xnu_text_exec_patchset, "mac_mount_patch1", matches, masks, sizeof(matches)/sizeof(uint64_t), false, (void*)kpf_mac_mount_callback); - matches[0] = 0x5283ffc9; // movz w9, 0x1ffe + + // ios 16.4 changed the codegen, so we match both + // r2: /x c9ff8312:ffffff3f + matches[0] = 0x1283ffc9; // movz w/x9, 0x1ffe/-0x1fff + masks[0] = 0x3fffffff; xnu_pf_maskmatch(xnu_text_exec_patchset, "mac_mount_patch2", matches, masks, sizeof(matches)/sizeof(uint64_t), false, (void*)kpf_mac_mount_callback); } @@ -1773,7 +1778,7 @@ static void kpf_cmd(const char *cmd, char *args) if (!found_vm_fault_enter) panic("no vm_fault_enter"); if (!found_vm_map_protect) panic("Missing patch: vm_map_protect"); if (!vfs_context_current) panic("Missing patch: vfs_context_current"); - if (!rootvp_string_match && !kpf_has_done_mac_mount) panic("Missing patch: mac_mount"); + if (!kpf_has_done_mac_mount) panic("Missing patch: mac_mount"); uint32_t delta = (&shellcode_area[1]) - amfi_ret; delta &= 0x03ffffff; From d83496959b8806c72fe80465987e93ab8b314e2a Mon Sep 17 00:00:00 2001 From: Tom E Date: Mon, 12 Jun 2023 17:15:35 +0800 Subject: [PATCH 06/77] kpf: add rootful APFS patches Co-authored-by: =?UTF-8?q?=E3=81=AD=E3=82=80=E3=81=84?= <69592455+kok3shidoll@users.noreply.github.com> --- checkra1n/kpf/main.c | 207 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 204 insertions(+), 3 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 209ae45d..b8ffbe1d 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -37,6 +37,7 @@ #include uint32_t offsetof_p_flags; +static palerain_option_t palera1n_flags; #if 0 // AES, sigh @@ -934,6 +935,175 @@ bool kpf_apfs_patches_mount(struct xnu_pf_patch* patch, uint32_t* opcode_stream) *f_apfs_privcheck = 0xeb00001f; // cmp x0, x0 return true; } + +#if 0 +bool kpf_apfs_seal_broken(struct xnu_pf_patch* patch, uint32_t* opcode_stream) { + puts("KPF: Found root seal broken"); + + opcode_stream[3] = NOP; + + return true; +} + +bool personalized_hash_patched = false; +bool kpf_personalized_root_hash(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { + // ios 16.4 broke this a lot, so we're just gonna find the string and do stuff with that + printf("KPF: found kpf_apfs_personalized_hash\n"); + + uint32_t* cbz1 = find_prev_insn(opcode_stream, 0x10, 0x34000000, 0x7e000000); + + if (!cbz1) { + printf("kpf_apfs_personalized_hash: failed to find first cbz\n"); + return false; + } + + uint32_t* cbz_fail = find_prev_insn(cbz1 + 1, 0x50, 0x34000000, 0x7e000000); + + if (!cbz_fail) { + printf("kpf_apfs_personalized_hash: failed to find fail cbz\n"); + return false; + } + + uint64_t addr_fail = xnu_ptr_to_va(cbz_fail) + (sxt32(cbz_fail[0] >> 5, 19) << 2); + + uint32_t *fail_stream = xnu_va_to_ptr(addr_fail); + + uint32_t *success_stream = opcode_stream; + uint32_t *temp_stream = opcode_stream; + + for (int i = 0; i < 0x500; i++) { + if ((temp_stream[0] & 0x9f000000) == 0x90000000 && // adrp + (temp_stream[1] & 0xff800000) == 0x91000000) { // add + const char *str = get_string(temp_stream); + if (strcmp(str, "%s:%d: %s successfully validated on-disk root hash\n") == 0) { + success_stream = find_prev_insn(temp_stream, 0x10, 0x35000000, 0x7f000000); + + if (success_stream) { + success_stream++; + } else { + success_stream = find_prev_insn(temp_stream, 0x10, 0xf90003e0, 0xffc003e0); // str x*, [sp, #0x*] + + if (!success_stream) { + DEVLOG("kpf_apfs_personalized_hash: failed to find start of block"); + } + } + + break; + } + } + + temp_stream++; + } + + if (!success_stream) { + printf("kpf_apfs_personalized_hash: failed to find success!\n"); + return false; + } + + uint64_t addr_success = xnu_ptr_to_va(success_stream); + + DEVLOG("addrs: success is 0x%llx, fail is 0x%llx, target is 0x%llx", addr_success, xnu_ptr_to_va(cbz_fail), addr_fail); + + uint32_t branch_success = 0x14000000 | (((addr_success - addr_fail) >> 2) & 0x03ffffff); + + DEVLOG("branch is 0x%x (BE)", branch_success); + + fail_stream[0] = branch_success; + + personalized_hash_patched = true; + + return true; +} + +bool kpf_apfs_auth_required(struct xnu_pf_patch* patch, uint32_t* opcode_stream) { + printf("KPF: Found root authentication required\n"); + + uint32_t* func_start = find_prev_insn(opcode_stream, 0x50, 0xa98003e0, 0xffc003e0); //stp x*, x*, [sp, -0x*]! + + if (!func_start) { + func_start = find_prev_insn(opcode_stream, 0x50, 0xd10000ff, 0xffc003ff); // sub sp, sp, 0x* + + if (!func_start) { + printf("root authentication: failed to find stack marker!\n"); + return false; + } + } + + func_start[0] = 0xd2800000; + func_start[1] = RET; + + return true; +} +#endif + +bool kpf_apfs_vfsop_mount(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { + if (!opcode_stream) { + printf("Missing patch: apfs_vfsop_mount\n"); + return false; + } + uint32_t *tbnz = find_prev_insn(opcode_stream, 2, 0x37700000, 0xfff8001f); // tbnz w0, 0xe, * + if (!tbnz) { + return false; + } + + *tbnz = 0x52800000; /* mov w0, 0 */ + + printf("KPF: found apfs_vfsop_mount\n"); + + return true; +} + +#if 0 +bool handled_eval_rootauth = false; +bool kpf_apfs_rootauth(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { + handled_eval_rootauth = true; + + opcode_stream[0] = NOP; + opcode_stream[1] = 0x52800000; /* mov w0, 0 */ + + printf("KPF: found handle_eval_rootauth\n"); + return true; +} + +bool kpf_apfs_rootauth_new(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { + handled_eval_rootauth = true; + + uint32_t orig_register = (opcode_stream[1] & 0x1f); + opcode_stream[0] = NOP; + opcode_stream[1] = 0x52800000 | orig_register; /* mov wN, 0 */ + + uint32_t *ret_stream = follow_call(opcode_stream + 2); + + if (!ret_stream) { + printf("KPF: failed to follow branch\n"); + return false; + } + + uint32_t *mov = ret_stream; + while (true) { + mov = find_next_insn(mov, 0x10, 0xaa0003e0, 0xffe0ffff); // mov x0, xN + + if (!mov) { + printf("KPF: failed to find mov\n"); + return false; + } + + uint32_t mov_register = (mov[0] >> 16) & 0x1f; + + if (mov_register == orig_register) { + break; + } + + mov++; + } + + mov[0] = 0xd2800000; /* mov x0, 0 */ + + printf("KPF: found handle_eval_rootauth\n"); + return true; +} +#endif + void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { // there is a check in the apfs mount function that makes sure that the kernel task is calling this function (current_task() == kernel_task) // we also want to call it so we patch that check out @@ -952,7 +1122,7 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { // 0xfffffff00692e6a8 080140f9 ldr x8, [x8] // 0xfffffff00692e6ac 1f0008eb cmp x0, x8 <- cmp (patches to cmp x0, x0) // r2 cmd: - // /x 0000003908011b3200000039000000b9:000000ffffffffff000000ff000000ff + // /x 0000403908011b3200000039000000b9:0000c0bfffffffff0000c0bf000000ff uint64_t matches[] = { 0x39400000, // ldr{b|h} w*, [x*] 0x321b0108, // orr w8, w8, 0x20 @@ -992,6 +1162,39 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { }; xnu_pf_maskmatch(patchset, "apfs_patch_rename", i_matches, i_masks, sizeof(i_matches)/sizeof(uint64_t), true, (void*)kpf_apfs_patches_rename); } + + // if(palera1n_flags & palerain_option_rootful) + { + // This patch is not required on rootless, but it is nice to have as still as some + // actions over SSH would not be possible without it. + // when mounting an apfs volume, there is a check to make sure the volume is not read/write + // we just nop the check out + // example from iPad 6 16.1.1: + // 0xfffffff0064023a8 e8b340b9 ldr w8, [sp, 0xb0] ; 5 + // 0xfffffff0064023ac 08791f12 and w8, w8, 0xfffffffe + // 0xfffffff0064023b0 e8b300b9 str w8, [sp, 0xb0] + // r2: /x a00340b900781f12a00300b9:a003feff00fcffffa003c0ff + uint64_t remount_matches[] = { + 0xb94003a0, // ldr x*, [x29/sp, *] + 0x121f7800, // and w*, w*, 0xfffffffe + 0xb90003a0, // str x*, [x29/sp, *] + }; + + uint64_t remount_masks[] = { + 0xfffe03a0, + 0xfffffc00, + 0xffc003a0, + }; + + xnu_pf_maskmatch(patchset, + "apfs_vfsop_mount", remount_matches, remount_masks, sizeof(remount_masks) / sizeof(uint64_t), + !have_union +#ifndef DEV_BUILD + && (palera1n_flags & palerain_option_rootful) != 0 +#endif + ,(void *)kpf_apfs_vfsop_mount); + + } } static uint32_t* amfi_ret; bool kpf_amfi_execve_tail(struct xnu_pf_patch* patch, uint32_t* opcode_stream) { @@ -1506,8 +1709,6 @@ static int kpf_compare_patches(const void *a, const void *b) return (int)one->granule - (int)two->granule; } -static palerain_option_t palera1n_flags; - kpf_component_t* const kpf_components[] = { &kpf_bindfs, &kpf_developer_mode, From 7ae51b59553b31ab43176797a894b51ba1f64aab Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 12 Jun 2023 17:21:36 +0800 Subject: [PATCH 07/77] kpf: shellcode: dyld: change patched dyld path to /cores/dyld --- checkra1n/kpf/shellcode.S | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkra1n/kpf/shellcode.S b/checkra1n/kpf/shellcode.S index 3d4aa3e0..aaa7622a 100644 --- a/checkra1n/kpf/shellcode.S +++ b/checkra1n/kpf/shellcode.S @@ -194,7 +194,7 @@ L_dyld_shc_epilog: ldp x29, x30, [sp], 0x20 ret L_alt_dyld_path: - .asciz "/fs/gen/dyld" + .asciz "/cores/dyld" L_dyld_path: .asciz "/usr/lib/dyld" .align 2 From 349cc795ae9fdd187459ec1d4da15d578bc82fbc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=3D=3FUTF-8=3Fq=3F=3DE3=3D81=3DAD=3DE3=3D82=3D80=3DE3=3D81?= =?UTF-8?q?=3D84=3F=3D?= <69592455+kok3shidoll@users.noreply.github.com> Date: Mon, 12 Jun 2023 17:31:46 +0800 Subject: [PATCH 08/77] Add proc_selfname patch this is needed to fix the IDSBlastDoorService crash loop since 16.2 --- checkra1n/kpf/kpf.h | 1 + checkra1n/kpf/main.c | 1 + checkra1n/kpf/proc_selfname.c | 178 +++++++++++++++++++++++++++ checkra1n/kpf/shellcode.S | 225 ++++++++++++++++++++++------------ 4 files changed, 330 insertions(+), 75 deletions(-) create mode 100644 checkra1n/kpf/proc_selfname.c diff --git a/checkra1n/kpf/kpf.h b/checkra1n/kpf/kpf.h index cb144bfa..5d7c514d 100644 --- a/checkra1n/kpf/kpf.h +++ b/checkra1n/kpf/kpf.h @@ -123,6 +123,7 @@ extern kpf_component_t kpf_ramdisk; extern kpf_component_t kpf_trustcache; extern kpf_component_t kpf_vfs; extern kpf_component_t kpf_vm_prot; +extern kpf_component_t kpf_proc_selfname; /********** ********** ********** ********** ********** Exports ********** ********** ********** ********** **********/ diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index b8ffbe1d..12e588d4 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1722,6 +1722,7 @@ kpf_component_t* const kpf_components[] = { &kpf_trustcache, &kpf_vfs, &kpf_vm_prot, + &kpf_proc_selfname }; static void kpf_cmd(const char *cmd, char *args) diff --git a/checkra1n/kpf/proc_selfname.c b/checkra1n/kpf/proc_selfname.c new file mode 100644 index 00000000..2994dc15 --- /dev/null +++ b/checkra1n/kpf/proc_selfname.c @@ -0,0 +1,178 @@ +/* + * pongoOS - https://checkra.in + * + * Copyright (C) 2023 checkra1n team + * + * This file is part of pongoOS. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + * + */ + +#include "kpf.h" +#include +#include +#include +#include + +static bool need_proc_selfname_patch = false; +static uint32_t* proc_selfname = NULL; + +static bool kpf_proc_selfname_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) +{ + if(proc_selfname) + { + DEVLOG("proc_selfname_callback: already ran, skipping..."); + return false; + } + + // Most reliable marker of a stack frame seems to be "add x29, sp, 0x...". + // And this function is HUGE, hence up to 2k insn. + uint32_t *frame = find_prev_insn(opcode_stream, 2000, 0x910003fd, 0xff8003ff); + if(!frame) return false; + + // Now find the insn that decrements sp. This can be either + // "stp ..., ..., [sp, -0x...]!" or "sub sp, sp, 0x...". + // Match top bit of imm on purpose, since we only want negative offsets. + uint32_t *start = find_prev_insn(frame, 10, 0xa9a003e0, 0xffe003e0); + if(!start) start = find_prev_insn(frame, 10, 0xd10003ff, 0xff8003ff); + if(!start) return false; + + puts("KPF: Found proc_selfname"); + proc_selfname = start; +#ifdef DEV_BUILD + printf("proc_selfname 0x%016llx\n", xnu_ptr_to_va(proc_selfname)); +#endif + return true; +} + +static void kpf_proc_selfname_patch(xnu_pf_patchset_t *patchset) +{ + // the IDSBlastDoorService process since 16.2 does not seem to like vnode_check_open being hooked. + // so I will tentatively only do a normal check when this process is detected... + // we need to run proc_selfname and look for this function to get the process name. + // ... + // fffffff0076117cc ldr x8, [x0, #0x10] + // fffffff0076117d0 cbz x8, loc_fffffff0076117ec + // fffffff0076117d4 add x1, x8, #0x381 ; argument "src" for method _strlcpy + // fffffff0076117d8 sxtw x2, w20 ; argument "size" for method _strlcpy + // fffffff0076117dc mov x0, x19 ; argument "dst" for method _strlcpy + // fffffff0076117e0 ldp fp, lr, [sp, #0x10] + // fffffff0076117e4 ldp x20, x19, [sp], #0x20 + // fffffff0076117e8 b _strlcpy + // fffffff0076117ec adrp x8, #0xfffffff007195000 + // fffffff0076117f0 ldr x8, [x8, #0x10] ; _kernproc + // fffffff0076117f4 cbnz x8, loc_fffffff0076117d4 + + uint64_t matches[] = { + 0xf9400000, // ldr xN, [xM, ...] + 0xb4000000, // cbz x*, ... + 0x91000001, // add x1, xn, #imm + 0x93407c02, // sxtw x2, wy + 0xaa0003e0, // mov x0, xN + 0x00000000, // ldp + 0x00000000, // ldp + 0x14000000, // b 0x... + 0x90000000, // adrp + 0xf9400000, // ldr xN, [xM, ...] + 0xb5000000, // cbnz x*, 0x... + }; + + uint64_t masks[] = { + 0xffc00000, // ldr xN, [xM, ...] + 0xff000000, // cbz x*, ... + 0xff00000f, // add xn, xn, #imm + 0xffff7c0f, // sxtw x2, wy + 0xffe0ffff, // mov x0, xn + 0x00000000, // ldp + 0x00000000, // ldp + 0xfc000000, // b 0x... + 0x9f000000, // adrp + 0xffc00000, // ldr xN, [xM, ...] + 0xff000000, // cbnz x*, 0x... + }; + + xnu_pf_maskmatch(patchset, "proc_selfname", matches, masks, sizeof(masks)/sizeof(uint64_t), false, (void*)kpf_proc_selfname_callback); + + uint64_t i_matches[] = { + 0xf9400000, // ldr xN, [xM, ...] + 0xb4000000, // cbz x*, ... + 0x91000001, // add x1, xn, #imm + 0x93407c02, // sxtw x2, wy + 0xaa0003e0, // mov x0, xN + 0x92800003, // mov x3, #-1 + 0x00000000, // ldp + 0x00000000, // ldp + 0x14000000, // b 0x... + 0x90000000, // adrp + 0xf9400000, // ldr xN, [xM, ...] + 0xb5000000, // cbnz x*, 0x... + }; + + uint64_t i_masks[] = { + 0xffc00000, // ldr xN, [xM, ...] + 0xff000000, // cbz x*, ... + 0xff00000f, // add xn, xn, #imm + 0xffff7c0f, // sxtw x2, wy + 0xffe0ffff, // mov x0, xn + 0xffffffff, // mov x3, #-1 + 0x00000000, // ldp + 0x00000000, // ldp + 0xfc000000, // b 0x... + 0x9f000000, // adrp + 0xffc00000, // ldr xN, [xM, ...] + 0xff000000, // cbnz x*, 0x... + }; + + xnu_pf_maskmatch(patchset, "proc_selfname", i_matches, i_masks, sizeof(i_masks)/sizeof(uint64_t), false, (void*)kpf_proc_selfname_callback); +} + +static void kpf_proc_selfname_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, palerain_option_t palera1n_flags) +{ + const char cryptex_string[] = "/private/preboot/Cryptexes"; + const char *cryptex_string_match = memmem(cstring->cacheable_base, cstring->size, cryptex_string, sizeof(cryptex_string)); + +#ifdef DEV_BUILD + // 16.0 beta 1 onwards + if((cryptex_string_match != NULL) != (gKernelVersion.darwinMajor >= 22)) + { + panic("Cryptex presence doesn't match expected Darwin version"); + } +#endif + + need_proc_selfname_patch = cryptex_string_match != NULL; +} + +static void kpf_proc_selfname_patches(xnu_pf_patchset_t *amfi_text_exec_patchset) +{ + if(need_proc_selfname_patch) // iOS 16+ only + { + kpf_proc_selfname_patch(amfi_text_exec_patchset); + } +} + +kpf_component_t kpf_proc_selfname = +{ + .init = kpf_proc_selfname_init, + .patches = + { + { NULL, "__TEXT_EXEC", "__text", XNU_PF_ACCESS_32BIT, kpf_proc_selfname_patches }, + {}, + }, +}; diff --git a/checkra1n/kpf/shellcode.S b/checkra1n/kpf/shellcode.S index aaa7622a..fbf49c40 100644 --- a/checkra1n/kpf/shellcode.S +++ b/checkra1n/kpf/shellcode.S @@ -29,45 +29,50 @@ .globl _sandbox_shellcode_end .globl _sandbox_shellcode_setuid_patch .globl _dyld_hook_shellcode + +.globl _vnode_check_open_shc +.globl _vnode_check_open_shc_ptr +.globl _vnode_check_open_shc_end + .align 2 _sandbox_shellcode: -b sandbox_shellcode_m -b amfi_execve_hook -b pre_execve_hook + b sandbox_shellcode_m + b amfi_execve_hook + b pre_execve_hook vnode_getpath: -mov x19, x0 -nop -mov x0, x19 -ret + mov x19, x0 + nop + mov x0, x19 + ret sandbox_shellcode_m: // deny .fsevent accesses -mov x6, x30 -mov x4, x19 -mov x5, x0 -mov x0, x1 -cbz x0, nopath -bl vnode_getpath -cbz x0, nopath -ldr x7, [x0] -adr x0, pattern -ldr x8, [x0] -mov x0, xzr -cmp x8, x7 -b.ne nomatch + mov x6, x30 + mov x4, x19 + mov x5, x0 + mov x0, x1 + cbz x0, nopath + bl vnode_getpath + cbz x0, nopath + ldr x7, [x0] + adr x0, pattern + ldr x8, [x0] + mov x0, xzr + cmp x8, x7 + b.ne nomatch mov x0, #1 nomatch: nopath: -mov x19, x4 -br x6 + mov x19, x4 + br x6 amfi_execve_hook: // you can't kill me :P (makes sure amfi doesn't try to kill our binaries) -ldr x0, [sp, #8] // cs_flags -ldr w1, [x0] -orr w1, w1, #0x04000000 // CS_PLATFORM_BINARY -orr w1, w1, #0x000f // CS_VALID | CS_ADHOC | CS_GET_TASK_ALLOW | CS_INSTALLER -and w1, w1, #(~0x3f00) // clearing CS_HARD | CS_KILL | CS_CHECK_EXPIRATION | CS_RESTRICT | CS_ENFORCEMENT | CS_REQUIRE_LV -//and w1, w1, #(~0x00000000) -str w1, [x0] -mov x0, xzr -ret + ldr x0, [sp, #8] // cs_flags + ldr w1, [x0] + orr w1, w1, #0x04000000 // CS_PLATFORM_BINARY + orr w1, w1, #0x000f // CS_VALID | CS_ADHOC | CS_GET_TASK_ALLOW | CS_INSTALLER + and w1, w1, #(~0x3f00) // clearing CS_HARD | CS_KILL | CS_CHECK_EXPIRATION | CS_RESTRICT | CS_ENFORCEMENT | CS_REQUIRE_LV + //and w1, w1, #(~0x00000000) + str w1, [x0] + mov x0, xzr + ret // call signature //int mpo_cred_label_update_execve_t( // kauth_cred_t old_cred, @@ -86,55 +91,55 @@ ret // ); // setuid patch pre_execve_hook: -cbz x3, pre_execve_hook$orig -sub sp, sp, #0x400 -stp x29, x30, [sp] -stp x0, x1, [sp, #0x10] -stp x2, x3, [sp, #0x20] -stp x4, x5, [sp, #0x30] -stp x6, x7, [sp, #0x40] -ldr x16, vfs -blr x16 // getting current vfs context -mov x2, x0 -ldr x0, [sp, #0x28] -add x1, sp, #0x80 -mov w8, #0x380 -stp xzr, x8, [x1] -stp xzr, xzr, [x1, 0x10] -ldr x16, vnode // getting vnode attributes -blr x16 -cbnz x0, pre_execve_hook$orig$epilog // failed so we just jump out -mov w2, #0 -ldr w8, [sp, #0xcc] // va_mode -tbz w8, #11, pre_execve_hook$orig$gid -ldr w8, [sp, #0xc4] // va_uid -ldr x0, [sp, #0x18] // this is new_cred->uid -str w8, [x0, #0x18] -mov w2, #1 // Mark this as having been setuid or setgid + cbz x3, pre_execve_hook$orig + sub sp, sp, #0x400 + stp x29, x30, [sp] + stp x0, x1, [sp, #0x10] + stp x2, x3, [sp, #0x20] + stp x4, x5, [sp, #0x30] + stp x6, x7, [sp, #0x40] + ldr x16, vfs + blr x16 // getting current vfs context + mov x2, x0 + ldr x0, [sp, #0x28] + add x1, sp, #0x80 + mov w8, #0x380 + stp xzr, x8, [x1] + stp xzr, xzr, [x1, 0x10] + ldr x16, vnode // getting vnode attributes + blr x16 + cbnz x0, pre_execve_hook$orig$epilog // failed so we just jump out + mov w2, #0 + ldr w8, [sp, #0xcc] // va_mode + tbz w8, #11, pre_execve_hook$orig$gid + ldr w8, [sp, #0xc4] // va_uid + ldr x0, [sp, #0x18] // this is new_cred->uid + str w8, [x0, #0x18] + mov w2, #1 // Mark this as having been setuid or setgid pre_execve_hook$orig$gid: -ldr w8, [sp, #0xcc] -tbz w8, #10, pre_execve_hook$orig$p_flags -mov w2, #1 -ldr w8, [sp, #0xc8] -ldr x0, [sp, #0x18] -str w8, [x0, #0x28] + ldr w8, [sp, #0xcc] + tbz w8, #10, pre_execve_hook$orig$p_flags + mov w2, #1 + ldr w8, [sp, #0xc8] + ldr x0, [sp, #0x18] + str w8, [x0, #0x28] pre_execve_hook$orig$p_flags: -cbz w2, pre_execve_hook$orig$epilog // didn't change UID or GID -ldr x0, [sp, #0x20] + cbz w2, pre_execve_hook$orig$epilog // didn't change UID or GID + ldr x0, [sp, #0x20] _sandbox_shellcode_setuid_patch: -ldr w8, [x0, #0] // Gets replaced with real offset by kpf -orr w8, w8, #0x100 // Add P_SUGID -str w8, [x0, #0] // Gets replaced with real offset by kpf + ldr w8, [x0, #0] // Gets replaced with real offset by kpf + orr w8, w8, #0x100 // Add P_SUGID + str w8, [x0, #0] // Gets replaced with real offset by kpf pre_execve_hook$orig$epilog: -ldp x0, x1, [sp, #0x10] -ldp x2, x3, [sp, #0x20] -ldp x4, x5, [sp, #0x30] -ldp x6, x7, [sp, #0x40] -ldp x29, x30, [sp] -add sp, sp, #0x400 + ldp x0, x1, [sp, #0x10] + ldp x2, x3, [sp, #0x20] + ldp x4, x5, [sp, #0x30] + ldp x6, x7, [sp, #0x40] + ldp x29, x30, [sp] + add sp, sp, #0x400 pre_execve_hook$orig: -ldr x16, orig -br x16 + ldr x16, orig + br x16 .align 3 _sandbox_shellcode_ptrs: @@ -150,10 +155,80 @@ vnode_put: .quad 0x4141414141414140 pattern: .quad 0x746E65766573662E // .fsevent + +.align 2 +_vnode_check_open_shc: +vnode_check_open_hook: + sub sp, sp, #0x50 + stp x22, x21, [sp, #0x20] + stp x20, x19, [sp, #0x30] + stp x29, x30, [sp, #0x40] + add x29, sp, #0x40 + mov x19, x3 + mov x20, x2 + mov x21, x1 + mov x22, x0 + add x0, sp, #0xc + mov w1, #0x14 + ldr x8, proc_selfname // get proc name + blr x8 + + ldp w8, w9, [sp, #0xc] // check if procname is 'IDSBlastDoorService' or not. + ldp w10, w11, [sp, #0x14] + ldr w12, [sp, #0x1c] + mov w13, #0x4449 + movk w13, #0x4253, lsl #16 // 'IDSB' + cmp w8, w13 + mov w8, #0x616c + movk w8, #0x7473, lsl #16 // 'last' + ccmp w9, w8, #0x0, eq + mov w8, #0x6f44 + movk w8, #0x726f, lsl #16 // 'Door' + ccmp w10, w8, #0x0, eq + mov w8, #0x6553 + movk w8, #0x7672, lsl #16 // 'Serv' + ccmp w11, w8, #0x0, eq + mov w8, #0x6369 + movk w8, #0x65, lsl #16 // 'ice\x00' + ccmp w12, w8, #0x0, eq + b.eq vnode_check_open_shc$orig // go to normal checks. + +vnode_check_open_shc$shellcode: // go to sandbox_shellcode_m and make sure deny .fsevent accesses + mov x0, x22 + mov x1, x21 + mov x2, x20 + mov x3, x19 + ldp x29, x30, [sp, #0x40] + ldp x20, x19, [sp, #0x30] + ldp x22, x21, [sp, #0x20] + add sp, sp, #0x50 + b sandbox_shellcode_m + +vnode_check_open_shc$orig: + mov x0, x22 + mov x1, x21 + mov x2, x20 + mov x3, x19 + ldp x29, x30, [sp, #0x40] + ldp x20, x19, [sp, #0x30] + ldp x22, x21, [sp, #0x20] + add sp, sp, #0x50 + ldr x8, vnode_check_open_orig + br x8 + +_vnode_check_open_shc_ptr: +proc_selfname: +.quad 0x5151515151515151 + +vnode_check_open_orig: +.quad 0x5252525252525252 + _sandbox_shellcode_end: + + // Function logic // const char* dyld_hook(void) // { From 75e917836d80d572a4f0b5a0289af4090d48b584 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=3D=3FUTF-8=3Fq=3F=3DE3=3D81=3DAD=3DE3=3D82=3D80=3DE3=3D81?= =?UTF-8?q?=3D84=3F=3D?= <69592455+kok3shidoll@users.noreply.github.com> Date: Mon, 12 Jun 2023 17:40:03 +0800 Subject: [PATCH 09/77] feat: checkra1n pride --- src/drivers/framebuffer/fb.c | 60 +++++++++++++++++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/src/drivers/framebuffer/fb.c b/src/drivers/framebuffer/fb.c index 976ec096..b4785136 100644 --- a/src/drivers/framebuffer/fb.c +++ b/src/drivers/framebuffer/fb.c @@ -210,6 +210,56 @@ void screen_invert() { uint32_t gLogoBitmap[32] = { 0x0, 0xa00, 0x400, 0x5540, 0x7fc0, 0x3f80, 0x3f80, 0x1f00, 0x1f00, 0x1f00, 0x3f80, 0xffe0, 0x3f80, 0x3f80, 0x3f83, 0x103f9f, 0x18103ffb, 0xe3fffd5, 0x1beabfab, 0x480d7fd5, 0xf80abfab, 0x480d7fd5, 0x1beabfab, 0xe3fffd5, 0x18107ffb, 0x107fdf, 0x7fc3, 0xffe0, 0xffe0, 0xffe0, 0x1fff0, 0x1fff0 }; +int isARGB8888() { + return gWidth == gRowPixels; +} + +// wat?! +uint32_t convert_to_ARGB2101010(uint32_t color) +{ + uint16_t red = ((color >> 16) & 0xff) << 2; + uint16_t green = ((color >> 8) & 0xff) << 2; + uint16_t blue = ((color ) & 0xff) << 2; + return red << 20 | green << 10 | blue; +} + +void fbinfo() { + printf("gRowPixels : %ld\n", gBootArgs->Video.v_rowBytes >> 2); + printf("gWidth : %ld\n", gBootArgs->Video.v_width); + printf("gHeight : %ld\n", gBootArgs->Video.v_height); + printf("fbbase : %016llx\n", gBootArgs->Video.v_baseAddr); + printf("fbsize : %016llx\n", (gBootArgs->Video.v_height) * (gBootArgs->Video.v_rowBytes >> 2) * 4); +} + +uint32_t nextColor(uint32_t color) +{ + uint8_t r = (color >> 16) & 0xff; + uint8_t g = (color >> 8) & 0xff; + uint8_t b = (color ) & 0xff; + if((r != 0xff) && (b == 0x0)) + { + color += (1 << 16); + goto end; + } + if((r == 0xff) && (b != 0xff)) + { + color += 1; + goto end; + } + if((r != 0x0) && (b == 0xff)) + { + color -= (1 << 16); + goto end; + } + if((r == 0x0) && (b != 0x0)) + { + color -= 1; + goto end; + } +end: + return color; +} + void screen_init() { gRowPixels = gBootArgs->Video.v_rowBytes >> 2; uint16_t width = gWidth = gBootArgs->Video.v_width; @@ -244,16 +294,23 @@ void screen_init() { uint32_t logo_x_begin = (gRowPixels / 2) - (16 * logo_scaler_factor); uint32_t logo_y_begin = (height / 2) - (16 * logo_scaler_factor); + uint32_t mask = 0; + uint32_t color = 0xff0000; + for (uint32_t y = 0; y < (32 * logo_scaler_factor); ++y) { uint32_t b = gLogoBitmap[y / logo_scaler_factor]; for (uint32_t x = 0; x < (32 * logo_scaler_factor); ++x) { uint32_t ind = logo_x_begin + x + ((logo_y_begin + y) * gRowPixels); uint32_t curcolor = gFramebuffer[ind]; if (b & (1 << (x / logo_scaler_factor))) { - curcolor ^= 0xFFFFFFFF; + mask = isARGB8888() ? color : convert_to_ARGB2101010(color); + mask ^= 0xFFFFFFFF; + curcolor ^= mask; } gFramebuffer[ind] = curcolor; } + for(int i=0; i<(32 / logo_scaler_factor); i++) + color = nextColor(color); } memcpy(gFramebufferCopy, gFramebuffer, fbsize); @@ -262,5 +319,6 @@ void screen_init() { cache_clean(gFramebuffer, gHeight * gRowPixels * 4); command_register("fbclear", "clears the framebuffer output (minus banner)", screen_clear_all); command_register("fbinvert", "inverts framebuffer contents", screen_invert); + command_register("fbinfo", "show framebuffer info", fbinfo); scale_factor = 1; } From da64c80ccc5cb395d7e380180854a72df334f44d Mon Sep 17 00:00:00 2001 From: Tom E Date: Mon, 12 Jun 2023 17:42:28 +0800 Subject: [PATCH 10/77] chore: fix GitHub Actions --- .github/workflows/ci.yml | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f984c228..8763e968 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: CI +name: Build KPF on: # Trigger on all pushes and pull requests @@ -40,13 +40,16 @@ jobs: git reset --hard origin/$(git branch --show-current) git submodule update --recursive --remote - name: Compile - run: EMBEDDED_CC='clang-10' EMBEDDED_AR='llvm-ar-10' EMBEDDED_RANLIB='llvm-ranlib-10' make all - - name: Archive - uses: actions/upload-artifact@v2 + run: | + EMBEDDED_CC='clang-10' EMBEDDED_AR='llvm-ar-10' EMBEDDED_RANLIB='llvm-ranlib-10' DEV_BUILD=1 make build/checkra1n-kpf-pongo -j$(nproc) + - name: Upload artifact + uses: wangyucode/sftp-upload-action@v1.4.8 with: - name: PongoOS - path: | - build/checkra1n-kpf-pongo - build/Pongo - build/Pongo.bin - build/PongoConsolidated.bin + host: ${{ secrets.NICKCHAN_FTP_HOST }} + port: ${{ secrets.NICKCHAN_FTP_PORT }} + username: palera1n + privateKey: ${{ secrets.NICKCHAN_FTP_KEY }} + forceUpload: true + dryRun: false + localDir: 'build' + remoteDir: '/palera1n/artifacts/kpf' From 4878939863bf89354422e0893e7064e93767af0f Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sat, 8 Jul 2023 19:38:58 +0800 Subject: [PATCH 11/77] actions: fix sftp authentication --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8763e968..b4662fb0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -48,7 +48,7 @@ jobs: host: ${{ secrets.NICKCHAN_FTP_HOST }} port: ${{ secrets.NICKCHAN_FTP_PORT }} username: palera1n - privateKey: ${{ secrets.NICKCHAN_FTP_KEY }} + password: ${{ secrets.NICKCHAN_FTP_PASS }} forceUpload: true dryRun: false localDir: 'build' From b52ef78e6edd5e35efacef10a4f1dda839572457 Mon Sep 17 00:00:00 2001 From: samara <97859147+ssalggnikool@users.noreply.github.com> Date: Mon, 17 Jul 2023 14:32:53 -0700 Subject: [PATCH 12/77] ci: remove DEV_BUILD=1 --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b4662fb0..1250ca05 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: git submodule update --recursive --remote - name: Compile run: | - EMBEDDED_CC='clang-10' EMBEDDED_AR='llvm-ar-10' EMBEDDED_RANLIB='llvm-ranlib-10' DEV_BUILD=1 make build/checkra1n-kpf-pongo -j$(nproc) + EMBEDDED_CC='clang-10' EMBEDDED_AR='llvm-ar-10' EMBEDDED_RANLIB='llvm-ranlib-10' make build/checkra1n-kpf-pongo -j$(nproc) - name: Upload artifact uses: wangyucode/sftp-upload-action@v1.4.8 with: From 0556e90f05f36365f3af8853a5cee405ee248412 Mon Sep 17 00:00:00 2001 From: kok3shidoll <69592455+kok3shidoll@users.noreply.github.com> Date: Tue, 18 Jul 2023 06:54:58 +0900 Subject: [PATCH 13/77] fixed problem with apfs_vfsop_mount patch not working on ios 17. but we are not have rootful for ios 17, so there is no point in updating this patch. --- checkra1n/kpf-test/main.c | 5 +++++ checkra1n/kpf/main.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/checkra1n/kpf-test/main.c b/checkra1n/kpf-test/main.c index 105975d5..7fb0f828 100644 --- a/checkra1n/kpf-test/main.c +++ b/checkra1n/kpf-test/main.c @@ -48,6 +48,9 @@ # include #endif +#include +extern palerain_option_t palera1n_flags; + #define SWAP32(x) (((x & 0xff000000) >> 24) | ((x & 0xff0000) >> 8) | ((x & 0xff00) << 8) | ((x & 0xff) << 24)) #define MACH_MAGIC MH_MAGIC_64 @@ -417,6 +420,8 @@ static void __attribute__((noreturn)) process_kernel(int fd) printf("Kernel at 0x%llx, entry at 0x%llx", (uint64_t)mem, (uint64_t)gEntryPoint); module_entry(); + // jsut for testing + palera1n_flags |= palerain_option_rootful; preboot_hook(); exit(0); diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 12e588d4..fd32cec2 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -37,7 +37,7 @@ #include uint32_t offsetof_p_flags; -static palerain_option_t palera1n_flags; +palerain_option_t palera1n_flags; #if 0 // AES, sigh @@ -1163,8 +1163,13 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { xnu_pf_maskmatch(patchset, "apfs_patch_rename", i_matches, i_masks, sizeof(i_matches)/sizeof(uint64_t), true, (void*)kpf_apfs_patches_rename); } - // if(palera1n_flags & palerain_option_rootful) - { + if( +#ifdef DEV_BUILD + gKernelVersion.darwinMajor <= 22 && // this patch is not used on ios 17. +#endif + palera1n_flags & palerain_option_rootful // this patch is not required on rootless + ) + { // This patch is not required on rootless, but it is nice to have as still as some // actions over SSH would not be possible without it. // when mounting an apfs volume, there is a check to make sure the volume is not read/write From 0a5369086136ad73839c9f8d65fd08af44183ba0 Mon Sep 17 00:00:00 2001 From: Samara Date: Mon, 17 Jul 2023 15:10:38 -0700 Subject: [PATCH 14/77] ci: compile newest pongo in actions --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1250ca05..8a07fe1b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,7 @@ jobs: git submodule update --recursive --remote - name: Compile run: | - EMBEDDED_CC='clang-10' EMBEDDED_AR='llvm-ar-10' EMBEDDED_RANLIB='llvm-ranlib-10' make build/checkra1n-kpf-pongo -j$(nproc) + EMBEDDED_CC='clang-10' EMBEDDED_AR='llvm-ar-10' EMBEDDED_RANLIB='llvm-ranlib-10' make build/checkra1n-kpf-pongo build/Pongo.bin -j$(nproc) - name: Upload artifact uses: wangyucode/sftp-upload-action@v1.4.8 with: From 69050ac638c304425c0f41c031e5778748f232b3 Mon Sep 17 00:00:00 2001 From: Samara Date: Mon, 17 Jul 2023 15:33:32 -0700 Subject: [PATCH 15/77] ci: move to macos (I hate linux) --- .github/workflows/ci.yml | 40 ++++++++++++++++------------------------ 1 file changed, 16 insertions(+), 24 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8a07fe1b..1164e115 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,4 +1,4 @@ -name: Build KPF +name: Build KPF & Pongo on: # Trigger on all pushes and pull requests @@ -10,38 +10,30 @@ on: jobs: build: - runs-on: ubuntu-20.04 + runs-on: macos-latest steps: - - name: Install toolchain - run: | - echo 'deb https://assets.checkra.in/debian /' | sudo tee /etc/apt/sources.list.d/checkra1n.list - sudo apt-key adv --fetch-keys https://assets.checkra.in/debian/archive.key - sudo apt-get update - sudo apt-get install -y ld64 cctools-strip - - name: Voodoo magic - id: voodoo - uses: actions/cache@v2 - with: - key: ${{ github.event_name }}-${{ github.ref }}-${{ github.run_id }} - restore-keys: | - push-${{ github.ref }}- - push- - path: | - ** - name: Checkout repository - if: steps.voodoo.outputs.cache-hit != 'true' uses: actions/checkout@v2 with: - submodules: true + fetch-depth: 0 + - name: Update repository - if: steps.voodoo.outputs.cache-hit == 'true' run: | + git submodule update --init --recursive git fetch --all git reset --hard origin/$(git branch --show-current) git submodule update --recursive --remote - - name: Compile + + - name: Compile KPF and Pongo run: | - EMBEDDED_CC='clang-10' EMBEDDED_AR='llvm-ar-10' EMBEDDED_RANLIB='llvm-ranlib-10' make build/checkra1n-kpf-pongo build/Pongo.bin -j$(nproc) + make + + - name: Prepare upload directory + run: | + mkdir upload + mv build/Pongo.bin upload/ + mv build/checkra1n-kpf-pongo upload/ + - name: Upload artifact uses: wangyucode/sftp-upload-action@v1.4.8 with: @@ -51,5 +43,5 @@ jobs: password: ${{ secrets.NICKCHAN_FTP_PASS }} forceUpload: true dryRun: false - localDir: 'build' + localDir: 'upload' remoteDir: '/palera1n/artifacts/kpf' From 481ce2c2e17b37af2de9d11d5a384d959582ac09 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Wed, 26 Jul 2023 03:48:57 +0800 Subject: [PATCH 16/77] Mark apfs_vfsop_mount as not required on xnu 10002 and run it always --- checkra1n/kpf-test/Makefile | 2 +- checkra1n/kpf-test/main.c | 2 -- checkra1n/kpf/main.c | 22 +++++++++++++++++++--- 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/checkra1n/kpf-test/Makefile b/checkra1n/kpf-test/Makefile index 0cb805c9..c9e4163c 100644 --- a/checkra1n/kpf-test/Makefile +++ b/checkra1n/kpf-test/Makefile @@ -15,7 +15,7 @@ RA1N := $(ROOT)/checkra1n/kpf KPF_H := $(wildcard $(RA1N)/*.h) $(wildcard $(INC)/*.h) $(wildcard $(SRC)/kernel/*.h) $(wildcard $(SRC)/drivers/*.h) KPF_C := main.c $(wildcard $(RA1N)/*.c) $(wildcard $(RA1N)/*.S) $(SRC)/drivers/xnu/xnu.c $(SRC)/drivers/xnu/xnu.S KPF_LD_FLAGS := -Wl,-fatal_warnings -Wl,-dead_strip $(KPF_LDFLAGS) -KPF_CC_FLAGS := -std=gnu17 -Wall -Wstrict-prototypes -Werror=incompatible-function-pointer-types -O3 -flto -I$(INC) -I$(SRC)/kernel -I$(SRC)/drivers -DCHECKRA1N_VERSION='"x.y.z"' -Diprintf=printf -Dpanic=realpanic \ +KPF_CC_FLAGS := -std=gnu17 -Wall -Wno-strict-prototypes -Werror=incompatible-function-pointer-types -O3 -flto -I$(INC) -I$(SRC)/kernel -I$(SRC)/drivers -DCHECKRA1N_VERSION='"x.y.z"' -Diprintf=printf -Dpanic=realpanic \ '-Djit_set_exec(m)=void pthread_jit_write_protect_np(int); pthread_jit_write_protect_np(m)' -DOVERRIDE_CACHEABLE_VIEW=0x800000000ULL -DDEV_BUILD -D_GNU_SOURCE $(KPF_CFLAGS) $(KPF_LD_FLAGS) ifeq ($(HOST_OS),Darwin) diff --git a/checkra1n/kpf-test/main.c b/checkra1n/kpf-test/main.c index 7fb0f828..8fedc6aa 100644 --- a/checkra1n/kpf-test/main.c +++ b/checkra1n/kpf-test/main.c @@ -420,8 +420,6 @@ static void __attribute__((noreturn)) process_kernel(int fd) printf("Kernel at 0x%llx, entry at 0x%llx", (uint64_t)mem, (uint64_t)gEntryPoint); module_entry(); - // jsut for testing - palera1n_flags |= palerain_option_rootful; preboot_hook(); exit(0); diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index fd32cec2..29f419f5 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1036,6 +1036,7 @@ bool kpf_apfs_auth_required(struct xnu_pf_patch* patch, uint32_t* opcode_stream) } #endif +bool has_found_apfs_vfsop_mount = false; bool kpf_apfs_vfsop_mount(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { if (!opcode_stream) { printf("Missing patch: apfs_vfsop_mount\n"); @@ -1047,6 +1048,7 @@ bool kpf_apfs_vfsop_mount(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { } *tbnz = 0x52800000; /* mov w0, 0 */ + has_found_apfs_vfsop_mount = true; printf("KPF: found apfs_vfsop_mount\n"); @@ -1163,12 +1165,11 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { xnu_pf_maskmatch(patchset, "apfs_patch_rename", i_matches, i_masks, sizeof(i_matches)/sizeof(uint64_t), true, (void*)kpf_apfs_patches_rename); } +#if !__STDC_HOSTED__ if( -#ifdef DEV_BUILD - gKernelVersion.darwinMajor <= 22 && // this patch is not used on ios 17. -#endif palera1n_flags & palerain_option_rootful // this patch is not required on rootless ) +#endif { // This patch is not required on rootless, but it is nice to have as still as some // actions over SSH would not be possible without it. @@ -1196,6 +1197,9 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { !have_union #ifndef DEV_BUILD && (palera1n_flags & palerain_option_rootful) != 0 +#endif +#if __STDC_HOSTED__ + && gKernelVersion.darwinMajor <= 22 // this patch is not used on ios 17. #endif ,(void *)kpf_apfs_vfsop_mount); @@ -1986,6 +1990,18 @@ static void kpf_cmd(const char *cmd, char *args) if (!found_vm_map_protect) panic("Missing patch: vm_map_protect"); if (!vfs_context_current) panic("Missing patch: vfs_context_current"); if (!kpf_has_done_mac_mount) panic("Missing patch: mac_mount"); + if (!has_found_apfs_vfsop_mount && rootvp_string_match != NULL) { +#if __STDC_HOSTED__ + if (gKernelVersion.darwinMajor <= 22) { + puts("Missing patch: apfs_vfsop_mount"); + } else +#endif + if (palera1n_flags & palerain_option_rootful) { + panic("Missing patch: apfs_vfsop_mount"); + } else { + puts("Missing patch: apfs_vfsop_mount"); + } + } uint32_t delta = (&shellcode_area[1]) - amfi_ret; delta &= 0x03ffffff; From 1b310885b495bd7f748baef7d6f92bba61446c87 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Wed, 26 Jul 2023 04:08:56 +0800 Subject: [PATCH 17/77] Always run apfs_vfsop_mount on non-test DEV_BUILD's --- checkra1n/kpf/main.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 29f419f5..995d1d30 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1165,15 +1165,14 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { xnu_pf_maskmatch(patchset, "apfs_patch_rename", i_matches, i_masks, sizeof(i_matches)/sizeof(uint64_t), true, (void*)kpf_apfs_patches_rename); } -#if !__STDC_HOSTED__ +#ifndef DEV_BUILD if( palera1n_flags & palerain_option_rootful // this patch is not required on rootless ) #endif { - // This patch is not required on rootless, but it is nice to have as still as some - // actions over SSH would not be possible without it. - // when mounting an apfs volume, there is a check to make sure the volume is not read/write + // when mounting an apfs volume, there is a check to make sure the volume is + // not both root volume and read/write // we just nop the check out // example from iPad 6 16.1.1: // 0xfffffff0064023a8 e8b340b9 ldr w8, [sp, 0xb0] ; 5 @@ -1195,11 +1194,10 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { xnu_pf_maskmatch(patchset, "apfs_vfsop_mount", remount_matches, remount_masks, sizeof(remount_masks) / sizeof(uint64_t), !have_union -#ifndef DEV_BUILD - && (palera1n_flags & palerain_option_rootful) != 0 -#endif -#if __STDC_HOSTED__ +#ifdef DEV_BUILD && gKernelVersion.darwinMajor <= 22 // this patch is not used on ios 17. +#else + && (palera1n_flags & palerain_option_rootful) != 0 #endif ,(void *)kpf_apfs_vfsop_mount); From df604e41fc7e3345cf33a315ba6cef28a97a4b02 Mon Sep 17 00:00:00 2001 From: kok3shidoll <69592455+kok3shidoll@users.noreply.github.com> Date: Fri, 28 Jul 2023 03:11:09 +0900 Subject: [PATCH 18/77] ci: have different artifacts per branch --- .github/workflows/ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1164e115..758461be 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -34,6 +34,10 @@ jobs: mv build/Pongo.bin upload/ mv build/checkra1n-kpf-pongo upload/ + - name: Get branch name + id: branch-name + uses: tj-actions/branch-names@v7 + - name: Upload artifact uses: wangyucode/sftp-upload-action@v1.4.8 with: @@ -44,4 +48,4 @@ jobs: forceUpload: true dryRun: false localDir: 'upload' - remoteDir: '/palera1n/artifacts/kpf' + remoteDir: "/palera1n/artifacts/kpf/${{ steps.branch-name.outputs.ref_branch || github.ref }}" From 11be43e163641f0d5a1ccd2f6d41bb494ce445fa Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 28 Jul 2023 02:30:03 +0800 Subject: [PATCH 19/77] kpf-test for linux arm64 --- checkra1n/kpf-test/.gitignore | 3 + checkra1n/kpf-test/Makefile | 17 ++- checkra1n/kpf-test/include/mach-o/loader.h | 146 +++++++++++++++++++++ checkra1n/kpf-test/main.c | 35 ++++- checkra1n/kpf/bindfs.c | 2 +- checkra1n/kpf/dyld.c | 2 +- checkra1n/kpf/kpf.h | 2 +- checkra1n/kpf/main.c | 32 ++--- checkra1n/kpf/nvram.c | 2 +- checkra1n/kpf/overlay.c | 2 +- checkra1n/kpf/proc_selfname.c | 2 +- checkra1n/kpf/ramdisk.c | 6 +- checkra1n/kpf/vm_prot.c | 2 +- checkra1n/unit-test/tfp0.c | 4 +- checkra1n/unit-test/vm_map_protect.c | 2 +- checkra1n/unit-test/vm_map_protect_dsc.c | 6 +- example/include/pongo.h | 1 + src/drivers/framebuffer/fb.c | 4 +- src/drivers/recfg/recfg_soc.c | 14 +- src/drivers/tz/tz.c | 8 +- src/drivers/usb/synopsys_otg.c | 2 +- src/drivers/xnu/xnu.c | 18 +-- src/dynamic/modload.c | 2 +- src/dynamic/modload_macho.c | 8 +- src/kernel/legacy.c | 2 +- src/kernel/lowlevel.c | 16 +-- src/kernel/mm.c | 42 +++--- src/kernel/panic.c | 4 +- src/kernel/pongo.h | 1 + src/kernel/task.c | 2 +- src/modules/linux/linux.c | 10 +- src/shell/main.c | 4 +- tools/vmacho.c | 8 +- 33 files changed, 303 insertions(+), 108 deletions(-) create mode 100644 checkra1n/kpf-test/include/mach-o/loader.h diff --git a/checkra1n/kpf-test/.gitignore b/checkra1n/kpf-test/.gitignore index 6f4d40fd..21c23794 100644 --- a/checkra1n/kpf-test/.gitignore +++ b/checkra1n/kpf-test/.gitignore @@ -1,2 +1,5 @@ /kpf-test.ios /kpf-test.macos +/kpf-test.linux +shellcode_S_linux.S +xnu_S_linux.S diff --git a/checkra1n/kpf-test/Makefile b/checkra1n/kpf-test/Makefile index c9e4163c..8e73f0b1 100644 --- a/checkra1n/kpf-test/Makefile +++ b/checkra1n/kpf-test/Makefile @@ -17,6 +17,9 @@ KPF_C := main.c $(wildcard $(RA1N)/*.c) $(wildcard $(RA1N)/*.S KPF_LD_FLAGS := -Wl,-fatal_warnings -Wl,-dead_strip $(KPF_LDFLAGS) KPF_CC_FLAGS := -std=gnu17 -Wall -Wno-strict-prototypes -Werror=incompatible-function-pointer-types -O3 -flto -I$(INC) -I$(SRC)/kernel -I$(SRC)/drivers -DCHECKRA1N_VERSION='"x.y.z"' -Diprintf=printf -Dpanic=realpanic \ '-Djit_set_exec(m)=void pthread_jit_write_protect_np(int); pthread_jit_write_protect_np(m)' -DOVERRIDE_CACHEABLE_VIEW=0x800000000ULL -DDEV_BUILD -D_GNU_SOURCE $(KPF_CFLAGS) $(KPF_LD_FLAGS) +KPF_LD_FLAGS_LINUX := +KPF_CC_FLAGS_LINUX := -std=gnu17 -Wall -Wno-strict-prototypes -O3 -flto -I$(INC) -I$(SRC)/kernel -I$(SRC)/drivers -DCHECKRA1N_VERSION='"x.y.z"' -Diprintf=printf -Dpanic=realpanic \ + -DOVERRIDE_CACHEABLE_VIEW=0x800000000ULL '-Djit_set_exec(m)=void pthread_jit_write_protect_np(int);' -DDEV_BUILD -D_GNU_SOURCE -Iinclude $(KPF_CFLAGS) $(KPF_LD_FLAGS_LINUX) ifeq ($(HOST_OS),Darwin) IOS_CC ?= xcrun -sdk iphoneos clang --target=arm64-apple-ios7.0 @@ -26,6 +29,7 @@ else ifeq ($(HOST_OS),Linux) # TODO: macOS target IOS_CC ?= arm64-apple-ios12.0.0-clang -arch arm64 + LINUX_CC ?= clang SIGN ?= ldid -Sent.plist endif endif @@ -42,5 +46,16 @@ kpf-test.ios: Makefile $(KPF_C) $(KPF_H) kpf-test.macos: Makefile $(KPF_C) $(KPF_H) $(MACOS_CC) -o $@ $(KPF_C) $(KPF_CC_FLAGS) +shellcode_S_linux.S: $(RA1N)/shellcode.S Makefile + sed -e 's/_pf_jit/pf_jit/g' -e 's/_dyld_shc/dyld_shc/g' -e 's/_sandbox/sandbox/g' \ + -e 's/_fsctl_shc/fsctl_shc/g' -e 's/_kdi_shc/kdi_shc/g' -e 's/_nvram_shc/nvram_shc/g' $< > $@ + +xnu_S_linux.S: $(SRC)/drivers/xnu/xnu.S Makefile + sed -e 's/_pf_jit/pf_jit/g' $< > $@ + +kpf-test.linux: Makefile $(KPF_C) $(KPF_H) shellcode_S_linux.S xnu_S_linux.S + $(LINUX_CC) -o $@ main.c -g $(wildcard $(RA1N)/*.c) $(SRC)/drivers/xnu/xnu.c shellcode_S_linux.S xnu_S_linux.S $(KPF_CC_FLAGS_LINUX) + clean: - rm -f kpf-test.ios kpf-test.macos + rm -f kpf-test.ios kpf-test.macos kpf-test.linux + rm -f shellcode_S_linux.S xnu_S_linux.S diff --git a/checkra1n/kpf-test/include/mach-o/loader.h b/checkra1n/kpf-test/include/mach-o/loader.h new file mode 100644 index 00000000..dc8a9b6c --- /dev/null +++ b/checkra1n/kpf-test/include/mach-o/loader.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 1999-2010 Apple Inc. All Rights Reserved. + * + * @APPLE_LICENSE_HEADER_START@ + * + * This file contains Original Code and/or Modifications of Original Code + * as defined in and that are subject to the Apple Public Source License + * Version 2.0 (the 'License'). You may not use this file except in + * compliance with the License. Please obtain a copy of the License at + * http://www.opensource.apple.com/apsl/ and read it before using this + * file. + * + * The Original Code and all software distributed under the License are + * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER + * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, + * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. + * Please see the License for the specific language governing rights and + * limitations under the License. + * + * @APPLE_LICENSE_HEADER_END@ + */ +/* Mach-O declarations for non-Apple targets */ +#ifndef __APPLE__ +#ifndef _LOADER_H_ +#define _LOADER_H_ + +#include +typedef int32_t integer_t; + +// +typedef integer_t cpu_type_t; +typedef integer_t cpu_subtype_t; +#define CPU_ARCH_ABI64 0x01000000 /* 64 bit ABI */ +#define CPU_TYPE_ARM ((cpu_type_t) 12) +#define CPU_TYPE_ARM64 (CPU_TYPE_ARM | CPU_ARCH_ABI64) +#define ARM_THREAD_STATE64 6 + +#define _STRUCT_ARM_THREAD_STATE64 struct __darwin_arm_thread_state64 +_STRUCT_ARM_THREAD_STATE64 +{ + uint64_t __x[29]; /* General purpose registers x0-x28 */ + uint64_t __fp; /* Frame pointer x29 */ + uint64_t __lr; /* Link register x30 */ + uint64_t __sp; /* Stack pointer x31 */ + uint64_t __pc; /* Program counter */ + uint32_t __cpsr; /* Current program status register */ +}; + +// +typedef int vm_prot_t; + +// +#define FAT_MAGIC 0xcafebabe +#define FAT_CIGAM 0xbebafeca /* NXSwapLong(FAT_MAGIC) */ +struct fat_header { + uint32_t magic; /* FAT_MAGIC */ + uint32_t nfat_arch; /* number of structs that follow */ +}; + +struct fat_arch { + cpu_type_t cputype; /* cpu specifier (int) */ + cpu_subtype_t cpusubtype; /* machine specifier (int) */ + uint32_t offset; /* file offset to this object file */ + uint32_t size; /* size of this object file */ + uint32_t align; /* alignment as a power of 2 */ +}; + +// Everything below is from +#define MH_MAGIC_64 0xfeedfacf +#define SG_NORELOC 0x4 +#define LC_REQ_DYLD 0x80000000 +#define LC_RPATH (0x1c | LC_REQ_DYLD) /* runpath additions */ +#define LC_BUILD_VERSION 0x32 /* build for platform min OS version */ +#define LC_SEGMENT_64 0x19 + +#define PLATFORM_MACOS 1 +#define PLATFORM_IOS 2 +#define PLATFORM_TVOS 3 +#define PLATFORM_WATCHOS 4 +#define PLATFORM_BRIDGEOS 5 +#define PLATFORM_MACCATALYST 6 +#define PLATFORM_IOSSIMULATOR 7 +#define PLATFORM_TVOSSIMULATOR 8 +#define PLATFORM_WATCHOSSIMULATOR 9 +#define PLATFORM_DRIVERKIT 10 + +#define LC_UNIXTHREAD 0x5 /* unix thread (includes a stack) */ + +struct mach_header_64 { + uint32_t magic; /* mach magic number identifier */ + cpu_type_t cputype; /* cpu specifier */ + cpu_subtype_t cpusubtype; /* machine specifier */ + uint32_t filetype; /* type of file */ + uint32_t ncmds; /* number of load commands */ + uint32_t sizeofcmds; /* the size of all the load commands */ + uint32_t flags; /* flags */ + uint32_t reserved; /* reserved */ +}; + +struct segment_command_64 { /* for 64-bit architectures */ + uint32_t cmd; /* LC_SEGMENT_64 */ + uint32_t cmdsize; /* includes sizeof section_64 structs */ + char segname[16]; /* segment name */ + uint64_t vmaddr; /* memory address of this segment */ + uint64_t vmsize; /* memory size of this segment */ + uint64_t fileoff; /* file offset of this segment */ + uint64_t filesize; /* amount to map from the file */ + vm_prot_t maxprot; /* maximum VM protection */ + vm_prot_t initprot; /* initial VM protection */ + uint32_t nsects; /* number of sections in segment */ + uint32_t flags; /* flags */ +}; + +struct build_version_command { + uint32_t cmd; /* LC_BUILD_VERSION */ + uint32_t cmdsize; /* sizeof(struct build_version_command) plus */ + /* ntools * sizeof(struct build_tool_version) */ + uint32_t platform; /* platform */ + uint32_t minos; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ + uint32_t sdk; /* X.Y.Z is encoded in nibbles xxxx.yy.zz */ + uint32_t ntools; /* number of tool entries following this */ +}; + +struct load_command { + uint32_t cmd; /* type of load command */ + uint32_t cmdsize; /* total size of command in bytes */ +}; + +struct section_64 { /* for 64-bit architectures */ + char sectname[16]; /* name of this section */ + char segname[16]; /* segment this section goes in */ + uint64_t addr; /* memory address of this section */ + uint64_t size; /* size in bytes of this section */ + uint32_t offset; /* file offset of this section */ + uint32_t align; /* section alignment (power of 2) */ + uint32_t reloff; /* file offset of relocation entries */ + uint32_t nreloc; /* number of relocation entries */ + uint32_t flags; /* flags (section type and attributes)*/ + uint32_t reserved1; /* reserved (for offset or index) */ + uint32_t reserved2; /* reserved (for count or sizeof) */ + uint32_t reserved3; /* reserved */ +}; + +#endif +#endif diff --git a/checkra1n/kpf-test/main.c b/checkra1n/kpf-test/main.c index 8fedc6aa..29dfd518 100644 --- a/checkra1n/kpf-test/main.c +++ b/checkra1n/kpf-test/main.c @@ -24,7 +24,12 @@ * SOFTWARE. * */ +#define _DEFAULT_SOURCE #undef panic +#ifndef __APPLE__ +#include "./mach-o/loader.h" +#include +#endif #include #include #include @@ -35,15 +40,18 @@ #include #include #include +#include #include #include #include #include +#ifdef __APPLE__ #include #include #include #include #include +#endif #if TARGET_OS_OSX # include #endif @@ -95,7 +103,11 @@ typedef struct boot_args }; } __attribute__((packed)) boot_args; +#ifdef __APPLE__ extern kern_return_t mach_vm_protect(vm_map_t task, mach_vm_address_t addr, mach_vm_size_t size, boolean_t set_max, vm_prot_t prot); +#else +void sys_icache_invalidate(void* a, size_t b) {} +#endif extern void module_entry(void); extern void (*preboot_hook)(void); @@ -109,7 +121,11 @@ void realpanic(const char *str, ...) vasprintf(&ptr, str, va); va_end(va); +#ifdef __APPLE__ panic(ptr); +#else + abort(); +#endif } void *ramdisk_buf = NULL; @@ -127,7 +143,14 @@ static struct { uint64_t get_ticks(void) { +#ifdef __APPLE__ return __builtin_arm_rsr64("cntpct_el0"); +#else + struct timespec spec; + + clock_gettime(CLOCK_REALTIME, &spec); + return (uint64_t)((spec.tv_sec*1000+spec.tv_nsec/1e6)*24000); +#endif } void command_register(const char* name, const char* desc, void (*cb)(const char* cmd, char* args)) @@ -152,7 +175,7 @@ void invalidate_icache(void) } } -#if !TARGET_OS_OSX +#if !TARGET_OS_OSX && defined(__APPLE__) void pthread_jit_write_protect_np(int exec) { for(uint32_t i = 0; i < NUM_JIT; ++i) @@ -168,6 +191,8 @@ void pthread_jit_write_protect_np(int exec) } } } +#elif !defined(__APPLE__) +void pthread_jit_write_protect_np(int exec) {} #endif void* jit_alloc(size_t count, size_t size) @@ -180,7 +205,11 @@ void* jit_alloc(size_t count, size_t size) exit(-1); } - int prot = PROT_READ | PROT_WRITE; +#if defined(__APPLE__) + int prot = PROT_READ | PROT_WRITE | PROT_EXEC; +#else + int prot = PROT_READ | PROT_WRITE | PROT_EXEC; +#endif int flags = MAP_ANON | MAP_PRIVATE; #if TARGET_OS_OSX prot |= PROT_EXEC; @@ -417,7 +446,7 @@ static void __attribute__((noreturn)) process_kernel(int fd) gBootArgs = &BootArgs; gEntryPoint = (void*)((uintptr_t)mem + (entry - lowest)); - printf("Kernel at 0x%llx, entry at 0x%llx", (uint64_t)mem, (uint64_t)gEntryPoint); + printf("Kernel at 0x%" PRIx64 ", entry at 0x%" PRIx64 "", (uint64_t)mem, (uint64_t)gEntryPoint); module_entry(); preboot_hook(); diff --git a/checkra1n/kpf/bindfs.c b/checkra1n/kpf/bindfs.c index 7632fb2d..e950e728 100644 --- a/checkra1n/kpf/bindfs.c +++ b/checkra1n/kpf/bindfs.c @@ -318,7 +318,7 @@ static uint32_t kpf_bindfs_emit(uint32_t *shellcode_area) patch_off > 0x7fffffcLL || patch_off < -0x8000000LL ) { - panic("fsctl_patch jump too far: 0x%llx/0x%llx/0x%llx/0x%llx/0x%llx", open_off, close_off, bl_off, b_off, patch_off); + panic("fsctl_patch jump too far: 0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "", open_off, close_off, bl_off, b_off, patch_off); } memcpy(shellcode_area, fsctl_shc, (uintptr_t)fsctl_shc_end - (uintptr_t)fsctl_shc); diff --git a/checkra1n/kpf/dyld.c b/checkra1n/kpf/dyld.c index f2625125..713dc160 100644 --- a/checkra1n/kpf/dyld.c +++ b/checkra1n/kpf/dyld.c @@ -198,7 +198,7 @@ static uint32_t kpf_dyld_emit(uint32_t *shellcode_area) int64_t patch_off = shellcode_addr - patchpoint_addr; if(ctx_off > 0x7fffffcLL || ctx_off < -0x8000000LL || lookup_off > 0x7fffffcLL || lookup_off < -0x8000000LL || put_off > 0x7fffffcLL || put_off < -0x8000000LL || patch_off > 0x7fffffcLL || patch_off < -0x8000000LL) { - panic("kpf_dyld: jump too far: 0x%llx/0x%llx/0x%llx/0x%llx", ctx_off, lookup_off, put_off, patch_off); + panic("kpf_dyld: jump too far: 0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "", ctx_off, lookup_off, put_off, patch_off); } memcpy(shellcode_area, dyld_shc, (uintptr_t)dyld_shc_end - (uintptr_t)dyld_shc); diff --git a/checkra1n/kpf/kpf.h b/checkra1n/kpf/kpf.h index 5d7c514d..e9c1cf50 100644 --- a/checkra1n/kpf/kpf.h +++ b/checkra1n/kpf/kpf.h @@ -38,7 +38,7 @@ #ifdef DEV_BUILD # define DEVLOG(msg, ...) do { printf(msg "\n", ##__VA_ARGS__); } while(0) -# define panic_at(addr, msg, ...) do { panic(msg " (0x%llx)", ##__VA_ARGS__, xnu_ptr_to_va((addr))); } while(0) +# define panic_at(addr, msg, ...) do { panic(msg " (0x%" PRIx64 ")", ##__VA_ARGS__, xnu_ptr_to_va((addr))); } while(0) #else # define DEVLOG(msg, ...) do {} while (0) # define panic_at(addr, msg, ...) do { (void)(addr); panic(msg, ##__VA_ARGS__); } while (0) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 995d1d30..f95d3009 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -108,7 +108,7 @@ uint32_t* follow_call(uint32_t *from) uint32_t op = *from; if((op & 0x7c000000) != 0x14000000) { - DEVLOG("follow_call 0x%llx is not B or BL", xnu_ptr_to_va(from)); + DEVLOG("follow_call 0x%" PRIx64 " is not B or BL", xnu_ptr_to_va(from)); return NULL; } uint32_t *target = from + sxt32(op, 26); @@ -123,7 +123,7 @@ uint32_t* follow_call(uint32_t *from) uint64_t ptr = *(uint64_t*)(page + ((((uint64_t)target[1] >> 10) & 0xfffULL) << 3)); target = xnu_va_to_ptr(kext_rebase_va(ptr)); } - DEVLOG("followed call from 0x%llx to 0x%llx", xnu_ptr_to_va(from), xnu_ptr_to_va(target)); + DEVLOG("followed call from 0x%" PRIx64 " to 0x%" PRIx64 "", xnu_ptr_to_va(from), xnu_ptr_to_va(target)); return target; } @@ -253,13 +253,13 @@ bool kpf_mac_dounmount_callback(struct xnu_pf_patch* patch, uint32_t* opcode_str (mov[-2]&0xFFE0FFFF) == 0xAA0003E0 && // MOV X0, Xn (mov[-1]&0xFC000000) == 0x94000000) { // BL vnode_getparent #if DEBUG_DOUNMOUNT - DEVLOG("Dounmount match for call to vnode_getparent at 0x%llx", xnu_rebase_va(xnu_ptr_to_va(opcode_stream))); + DEVLOG("Dounmount match for call to vnode_getparent at 0x%" PRIx64 "", xnu_rebase_va(xnu_ptr_to_va(opcode_stream))); #endif parent_rn = *mov&0x1f; } #if DEBUG_DOUNMOUNT - DEVLOG("Dounmount tenative match at 0x%llx", xnu_rebase_va(xnu_ptr_to_va(opcode_stream))); + DEVLOG("Dounmount tenative match at 0x%" PRIx64 "", xnu_rebase_va(xnu_ptr_to_va(opcode_stream))); #endif // Check that we have code to release parent_vnode below @@ -271,7 +271,7 @@ bool kpf_mac_dounmount_callback(struct xnu_pf_patch* patch, uint32_t* opcode_str return false; } #if DEBUG_DOUNMOUNT - DEVLOG("Dounmount testing parent lock at 0x%llx", xnu_rebase_va(xnu_ptr_to_va(parent_lock))); + DEVLOG("Dounmount testing parent lock at 0x%" PRIx64 "", xnu_rebase_va(xnu_ptr_to_va(parent_lock))); #endif uint32_t* call; @@ -403,7 +403,7 @@ static bool kpf_vm_map_protect_branch_short(struct xnu_pf_patch *patch, uint32_t static bool kpf_vm_map_protect_inline(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { - DEVLOG("vm_map_protect candidate at 0x%llx", xnu_ptr_to_va(opcode_stream)); + DEVLOG("vm_map_protect candidate at 0x%" PRIx64 "", xnu_ptr_to_va(opcode_stream)); // Match all possible combo and adjust index to the "csel" uint32_t idx = 2; @@ -578,7 +578,7 @@ bool vm_fault_enter_callback(struct xnu_pf_patch* patch, uint32_t* opcode_stream DEVLOG("vm_fault_enter_callback: already ran, skipping..."); return false; } - DEVLOG("Trying vm_fault_enter at 0x%llx", xnu_ptr_to_va(opcode_stream)); + DEVLOG("Trying vm_fault_enter at 0x%" PRIx64 "", xnu_ptr_to_va(opcode_stream)); // Should be followed by a TB(N)Z Wx, #2 shortly if (!find_next_insn(opcode_stream, 0x18, 0x36100000, 0xFEF80000)) { // Wrong place... @@ -613,7 +613,7 @@ bool vm_fault_enter_callback14(struct xnu_pf_patch* patch, uint32_t* opcode_stre DEVLOG("vm_fault_enter_callback: already ran, skipping..."); return false; } - DEVLOG("Trying vm_fault_enter at 0x%llx", xnu_ptr_to_va(opcode_stream)); + DEVLOG("Trying vm_fault_enter at 0x%" PRIx64 "", xnu_ptr_to_va(opcode_stream)); // r2 /x // Make sure this was preceded by a "tbz w[16-31], 2, ..." that jumps to the code we're currently looking at uint32_t *tbz = find_prev_insn(opcode_stream, 0x18, 0x36100010, 0xfff80010); @@ -757,7 +757,7 @@ bool vnode_lookup_callback(struct xnu_pf_patch* patch, uint32_t* opcode_stream) (try[1]&0xFC000000) != 0x94000000 || // BL _sfree (try[3]&0xFF000000) != 0xB4000000 || // CBZ (try[4]&0xFC000000) != 0x94000000 ) { // BL _vnode_put - DEVLOG("Failed match of vnode_lookup code at 0x%llx", kext_rebase_va(xnu_ptr_to_va(opcode_stream))); + DEVLOG("Failed match of vnode_lookup code at 0x%" PRIx64 "", kext_rebase_va(xnu_ptr_to_va(opcode_stream))); return false; } puts("KPF: Found vnode_lookup"); @@ -1002,7 +1002,7 @@ bool kpf_personalized_root_hash(struct xnu_pf_patch *patch, uint32_t *opcode_str uint64_t addr_success = xnu_ptr_to_va(success_stream); - DEVLOG("addrs: success is 0x%llx, fail is 0x%llx, target is 0x%llx", addr_success, xnu_ptr_to_va(cbz_fail), addr_fail); + DEVLOG("addrs: success is 0x%" PRIx64 ", fail is 0x%" PRIx64 ", target is 0x%" PRIx64 "", addr_success, xnu_ptr_to_va(cbz_fail), addr_fail); uint32_t branch_success = 0x14000000 | (((addr_success - addr_fail) >> 2) & 0x03ffffff); @@ -1231,7 +1231,7 @@ bool kpf_amfi_sha1(struct xnu_pf_patch* patch, uint32_t* opcode_stream) { } void kpf_find_offset_p_flags(uint32_t *proc_issetugid) { - DEVLOG("Found kpf_find_offset_p_flags 0x%llx", xnu_ptr_to_va(proc_issetugid)); + DEVLOG("Found kpf_find_offset_p_flags 0x%" PRIx64 "", xnu_ptr_to_va(proc_issetugid)); if (!proc_issetugid) { panic("kpf_find_offset_p_flags called with no argument"); } @@ -1980,9 +1980,9 @@ static void kpf_cmd(const char *cmd, char *args) if (!has_found_sbops) panic("no sbops?"); if (!amfi_ret) panic("no amfi_ret?"); if (!vnode_lookup) panic("no vnode_lookup?"); - DEVLOG("Found vnode_lookup: 0x%llx", xnu_rebase_va(xnu_ptr_to_va(vnode_lookup))); + DEVLOG("Found vnode_lookup: 0x%" PRIx64 "", xnu_rebase_va(xnu_ptr_to_va(vnode_lookup))); if (!vnode_put) panic("no vnode_put?"); - DEVLOG("Found vnode_put: 0x%llx", xnu_rebase_va(xnu_ptr_to_va(vnode_put))); + DEVLOG("Found vnode_put: 0x%" PRIx64 "", xnu_rebase_va(xnu_ptr_to_va(vnode_put))); if (offsetof_p_flags == -1) panic("no p_flags?"); if (!found_vm_fault_enter) panic("no vm_fault_enter"); if (!found_vm_map_protect) panic("Missing patch: vm_map_protect"); @@ -2128,7 +2128,7 @@ static void kpf_cmd(const char *cmd, char *args) } tick_1 = get_ticks(); - printf("KPF: Applied patchset in %llu ms\n", (tick_1 - tick_0) / TICKS_IN_1MS); + printf("KPF: Applied patchset in %" PRIu64 " ms\n", (tick_1 - tick_0) / TICKS_IN_1MS); } static void set_flags(char *args, palerain_option_t *flags, const char *name) @@ -2136,12 +2136,12 @@ static void set_flags(char *args, palerain_option_t *flags, const char *name) if(args[0] != '\0') { palerain_option_t val = strtoul(args, NULL, 16); - printf("Setting %s to 0x%016llx\n", name, val); + printf("Setting %s to 0x%016" PRIx64 "\n", name, val); *flags = val; } else { - printf("%s: 0x%016llx\n", name, *flags); + printf("%s: 0x%016" PRIx64 "\n", name, *flags); } } diff --git a/checkra1n/kpf/nvram.c b/checkra1n/kpf/nvram.c index 15be499a..1846c7ff 100644 --- a/checkra1n/kpf/nvram.c +++ b/checkra1n/kpf/nvram.c @@ -299,7 +299,7 @@ static uint32_t kpf_nvram_emit(uint32_t *shellcode_area) int64_t nvram_off = nvram_patch_to - nvram_patch_from; if(nvram_off > 0x7fffffcLL || nvram_off < -0x8000000LL) { - panic("kpf_nvram_unlock: jump too far: 0x%llx", nvram_off); + panic("kpf_nvram_unlock: jump too far: 0x%" PRIx64 "", nvram_off); } memcpy(shellcode_area, nvram_shc, (uintptr_t)nvram_shc_end - (uintptr_t)nvram_shc); diff --git a/checkra1n/kpf/overlay.c b/checkra1n/kpf/overlay.c index 1fde0783..5d872127 100644 --- a/checkra1n/kpf/overlay.c +++ b/checkra1n/kpf/overlay.c @@ -222,7 +222,7 @@ static uint32_t kpf_overlay_emit(uint32_t *shellcode_area) int64_t patch_off = shellcode_addr - patchpoint_addr; if(orig_off > 0x7fffffcLL || orig_off < -0x8000000LL || new_off > 0x7fffffcLL || new_off < -0x8000000LL || patch_off > 0x7fffffcLL || patch_off < -0x8000000LL) { - panic("kdi_patch jump too far: 0x%llx/0x%llx/0x%llx", orig_off, new_off, patch_off); + panic("kdi_patch jump too far: 0x%" PRIx64 "/0x%" PRIx64 "/0x%" PRIx64 "", orig_off, new_off, patch_off); } memcpy(shellcode_area, kdi_shc, (uintptr_t)kdi_shc_end - (uintptr_t)kdi_shc); diff --git a/checkra1n/kpf/proc_selfname.c b/checkra1n/kpf/proc_selfname.c index 2994dc15..1772440f 100644 --- a/checkra1n/kpf/proc_selfname.c +++ b/checkra1n/kpf/proc_selfname.c @@ -57,7 +57,7 @@ static bool kpf_proc_selfname_callback(struct xnu_pf_patch *patch, uint32_t *opc puts("KPF: Found proc_selfname"); proc_selfname = start; #ifdef DEV_BUILD - printf("proc_selfname 0x%016llx\n", xnu_ptr_to_va(proc_selfname)); + printf("proc_selfname 0x%016" PRIx64 "\n", xnu_ptr_to_va(proc_selfname)); #endif return true; } diff --git a/checkra1n/kpf/ramdisk.c b/checkra1n/kpf/ramdisk.c index 5a3e350b..1bf9fd28 100644 --- a/checkra1n/kpf/ramdisk.c +++ b/checkra1n/kpf/ramdisk.c @@ -120,7 +120,7 @@ static void kpf_ramdisk_rootdev_cmd(const char *cmd, char *args) { memset(root_matching, 0x0, 0x100); memcpy(root_matching, str, 0x100); - printf("set new entry: %016llx: BSD Name: %s\n", (uint64_t)root_matching, args); + printf("set new entry: %016" PRIx64 ": BSD Name: %s\n", (uint64_t)root_matching, args); } else { size_t max_fs_entries_len = 0; dt_node_t* fstab = dt_find(gDeviceTree, "fstab"); @@ -128,7 +128,7 @@ static void kpf_ramdisk_rootdev_cmd(const char *cmd, char *args) { uint32_t* max_fs_entries = dt_prop(fstab, "max_fs_entries", &max_fs_entries_len); if (!max_fs_entries) panic("invalid devicetree: no prop!"); uint32_t* patch = (uint32_t*)max_fs_entries; - printf("fstab max_fs_entries: %016llx: %08x\n", (uint64_t)max_fs_entries, patch[0]); + printf("fstab max_fs_entries: %016" PRIx64 ": %08x\n", (uint64_t)max_fs_entries, patch[0]); dt_node_t* baseband = dt_find(gDeviceTree, "baseband"); if (baseband) partid = patch[0] + 1U; @@ -138,7 +138,7 @@ static void kpf_ramdisk_rootdev_cmd(const char *cmd, char *args) { snprintf(str, 0x100, "IOProviderClassIOMediaIOPropertyMatchPartition ID%u", partid); memset(root_matching, 0x0, 0x100); memcpy(root_matching, str, 0x100); - printf("set new entry: %016llx: Partition ID: %u\n", (uint64_t)root_matching, partid); + printf("set new entry: %016" PRIx64 ": Partition ID: %u\n", (uint64_t)root_matching, partid); } } diff --git a/checkra1n/kpf/vm_prot.c b/checkra1n/kpf/vm_prot.c index ca655c47..d225d1a3 100644 --- a/checkra1n/kpf/vm_prot.c +++ b/checkra1n/kpf/vm_prot.c @@ -79,7 +79,7 @@ static bool kpf_aprr_callback(struct xnu_pf_patch *patch, uint32_t *opcode_strea ) ) { - DEVLOG("Ignoring APRR load from thread state at 0x%llx", xnu_ptr_to_va(opcode_stream)); + DEVLOG("Ignoring APRR load from thread state at 0x%" PRIx64 "", xnu_ptr_to_va(opcode_stream)); return false; } // 2. Immediates of two forms: diff --git a/checkra1n/unit-test/tfp0.c b/checkra1n/unit-test/tfp0.c index 211b5c2e..fc9c3e5b 100644 --- a/checkra1n/unit-test/tfp0.c +++ b/checkra1n/unit-test/tfp0.c @@ -51,7 +51,7 @@ int main(void) } ret = mach_vm_allocate(tfp0, &page, 0x4000, VM_FLAGS_ANYWHERE); - printf("mach_vm_allocate: 0x%llx, %s\n", page, mach_error_string(ret)); + printf("mach_vm_allocate: 0x%" PRIx64 ", %s\n", page, mach_error_string(ret)); if(ret != KERN_SUCCESS || page == 0) { goto out; @@ -74,7 +74,7 @@ int main(void) goto out; } - printf("Data: 0x%016llx 0x%016llx\n", check[0], check[1]); + printf("Data: 0x%016" PRIx64 " 0x%016" PRIx64 "\n", check[0], check[1]); if(check[0] != data[0] || check[1] != data[1]) { goto out; diff --git a/checkra1n/unit-test/vm_map_protect.c b/checkra1n/unit-test/vm_map_protect.c index 0a8e1e43..d41086c8 100644 --- a/checkra1n/unit-test/vm_map_protect.c +++ b/checkra1n/unit-test/vm_map_protect.c @@ -67,7 +67,7 @@ int main(void) if(addr_check != addr || size_check != 0x4000) { printf("Bad addr/size returned from mach_vm_region_recurse!\n"); - printf("Want 0x%llx/0x%llx, have 0x%llx/0x%llx\n", addr, 0x4000ULL, addr_check, size_check); + printf("Want 0x%" PRIx64 "/0x%" PRIx64 ", have 0x%" PRIx64 "/0x%" PRIx64 "\n", addr, 0x4000ULL, addr_check, size_check); return -1; } diff --git a/checkra1n/unit-test/vm_map_protect_dsc.c b/checkra1n/unit-test/vm_map_protect_dsc.c index 78ee4eed..ebf0d17f 100644 --- a/checkra1n/unit-test/vm_map_protect_dsc.c +++ b/checkra1n/unit-test/vm_map_protect_dsc.c @@ -60,7 +60,7 @@ static int require_prot(mach_vm_address_t addr, mach_vm_size_t size, vm_prot_t p if(addr_check != (addr & ~0x3fffULL) || size_check != ((size + 0x3fffULL) & ~0x3fffULL)) { printf("Bad addr/size returned from mach_vm_region_recurse!\n"); - printf("Want 0x%llx/0x%llx, have 0x%llx/0x%llx\n", addr, size, addr_check, size_check); + printf("Want 0x%" PRIx64 "/0x%" PRIx64 ", have 0x%" PRIx64 "/0x%" PRIx64 "\n", addr, size, addr_check, size_check); return -1; } @@ -83,14 +83,14 @@ static int require_prot(mach_vm_address_t addr, mach_vm_size_t size, vm_prot_t p int main(void) { void *libxpc = dlopen("/usr/lib/system/libxpc.dylib", RTLD_LAZY); - printf("dlopen: 0x%llx\n", (uint64_t)libxpc); + printf("dlopen: 0x%" PRIx64 "\n", (uint64_t)libxpc); if(!libxpc) { return -1; } void *test_sym = dlsym(libxpc, "xpc_test_symbols_exported"); - printf("dlsym: 0x%llx\n", (uint64_t)test_sym); + printf("dlsym: 0x%" PRIx64 "\n", (uint64_t)test_sym); if(!test_sym) { return -1; diff --git a/example/include/pongo.h b/example/include/pongo.h index 7446912c..2ef036e1 100644 --- a/example/include/pongo.h +++ b/example/include/pongo.h @@ -28,6 +28,7 @@ #include #include #include +#include #define DT_KEY_LEN 0x20 #define BOOT_LINE_LENGTH_iOS12 0x100 diff --git a/src/drivers/framebuffer/fb.c b/src/drivers/framebuffer/fb.c index b4785136..651d0979 100644 --- a/src/drivers/framebuffer/fb.c +++ b/src/drivers/framebuffer/fb.c @@ -227,8 +227,8 @@ void fbinfo() { printf("gRowPixels : %ld\n", gBootArgs->Video.v_rowBytes >> 2); printf("gWidth : %ld\n", gBootArgs->Video.v_width); printf("gHeight : %ld\n", gBootArgs->Video.v_height); - printf("fbbase : %016llx\n", gBootArgs->Video.v_baseAddr); - printf("fbsize : %016llx\n", (gBootArgs->Video.v_height) * (gBootArgs->Video.v_rowBytes >> 2) * 4); + printf("fbbase : %016" PRIx64 "\n", gBootArgs->Video.v_baseAddr); + printf("fbsize : %016" PRIx64 "\n", (gBootArgs->Video.v_height) * (gBootArgs->Video.v_rowBytes >> 2) * 4); } uint32_t nextColor(uint32_t color) diff --git a/src/drivers/recfg/recfg_soc.c b/src/drivers/recfg/recfg_soc.c index 9e56cca5..693e65b0 100644 --- a/src/drivers/recfg/recfg_soc.c +++ b/src/drivers/recfg/recfg_soc.c @@ -422,8 +422,8 @@ static int recfg_read32_cb(void *a, uint64_t *addr, uint32_t *mask, uint32_t *da static int recfg_read64_cb(void *a, uint64_t *addr, uint64_t *mask, uint64_t *data, bool *retry, uint8_t *recnt) { - if(*retry) iprintf(" rd64 0x%09llx & 0x%016llx == 0x%016llx, retry = %d\n", *addr, *mask, *data, *recnt); - else iprintf(" rd64 0x%09llx & 0x%016llx == 0x%016llx\n", *addr, *mask, *data); + if(*retry) iprintf(" rd64 0x%09llx & 0x%016" PRIx64 " == 0x%016" PRIx64 ", retry = %d\n", *addr, *mask, *data, *recnt); + else iprintf(" rd64 0x%09llx & 0x%016" PRIx64 " == 0x%016" PRIx64 "\n", *addr, *mask, *data); return kRecfgSuccess; } @@ -435,7 +435,7 @@ static int recfg_write32_cb(void *a, uint64_t *addr, uint32_t *data) static int recfg_write64_cb(void *a, uint64_t *addr, uint64_t *data) { - iprintf(" wr64 0x%llx = 0x%016llx\n", *addr, *data); + iprintf(" wr64 0x%" PRIx64 " = 0x%016" PRIx64 "\n", *addr, *data); return kRecfgSuccess; } @@ -450,15 +450,15 @@ static void recfg_cmd_dump(const char *cmd, char *args) uint32_t lock_val = *gCFG->aop_sram_lock_range; uint64_t lock_from = sram_base + ((lock_val & 0xffff) << 6); uint64_t lock_to = sram_base + (((lock_val >> 16) & 0xffff) << 6) + 0x40; - iprintf("CFG table: 0x%llx (%s)\n", cfg_base, cfg_locked ? "locked" : "unlocked"); - iprintf("SRAM base: 0x%llx (%s)\n", sram_base, sram_locked ? "locked" : "unlocked"); + iprintf("CFG table: 0x%" PRIx64 " (%s)\n", cfg_base, cfg_locked ? "locked" : "unlocked"); + iprintf("SRAM base: 0x%" PRIx64 " (%s)\n", sram_base, sram_locked ? "locked" : "unlocked"); if(lock_to <= lock_from) { iprintf("SRAM lock range: none (%s)\n", sram_locked ? "locked" : "unlocked"); } else { - iprintf("SRAM lock range: 0x%llx-0x%llx (%s)\n", lock_from, lock_to, sram_locked ? "locked" : "unlocked"); + iprintf("SRAM lock range: 0x%" PRIx64 "-0x%" PRIx64 " (%s)\n", lock_from, lock_to, sram_locked ? "locked" : "unlocked"); } recfg_cb_t cb = { @@ -475,7 +475,7 @@ static void recfg_cmd_dump(const char *cmd, char *args) uint64_t seq_base = (uint64_t)table[i] << 4; size_t seq_size = sram_end - seq_base; seq_size = recfg_map(seq_base, seq_size); - iprintf("Recfg seq %lu: 0x%llx\n", i, seq_base); + iprintf("Recfg seq %lu: 0x%" PRIx64 "\n", i, seq_base); if(recfg_check((void*)seq_base, seq_size, NULL, true) == kRecfgSuccess) { diff --git a/src/drivers/tz/tz.c b/src/drivers/tz/tz.c index 9de77463..87514d58 100644 --- a/src/drivers/tz/tz.c +++ b/src/drivers/tz/tz.c @@ -55,12 +55,12 @@ static void tz_command(const char* cmd, char* args) { real[2] = ( (uint64_t)raw[2] << shift) + 0x800000000ULL; real[3] = (((uint64_t)raw[3] + 1) << shift) + 0x800000000ULL; iprintf("TZ0 (%s):\n" - " base: %x (%llx)\n" - " end: %x (%llx)\n" + " base: %x (%" PRIx64 ")\n" + " end: %x (%" PRIx64 ")\n" "\n" "TZ1 (%s):\n" - " base: %x (%llx)\n" - " end: %x (%llx)\n" + " base: %x (%" PRIx64 ")\n" + " end: %x (%" PRIx64 ")\n" "\n", gTZRegbase[4] ? "locked" : "unlocked", raw[0], real[0], diff --git a/src/drivers/usb/synopsys_otg.c b/src/drivers/usb/synopsys_otg.c index eca13a01..ca7398e2 100644 --- a/src/drivers/usb/synopsys_otg.c +++ b/src/drivers/usb/synopsys_otg.c @@ -1864,7 +1864,7 @@ void usb_init(void) { dt_node_t *chosen = dt_get("/chosen"); char *srnm = NULL; - asprintf(&srnm, "CPID:%04X BDID:%02X ECID:%016llX SRTG:[%s]", socnum, dt_node_u32(chosen, "board-id", 0), dt_node_u64(chosen, "unique-chip-id", 0), "PongoOS-" PONGO_VERSION); + asprintf(&srnm, "CPID:%04X BDID:%02X ECID:%016" PRIx64 " SRTG:[%s]", socnum, dt_node_u32(chosen, "board-id", 0), dt_node_u64(chosen, "unique-chip-id", 0), "PongoOS-" PONGO_VERSION); string_descriptors[iSerialNumber] = srnm; gSynopsysOTGBase = 0; diff --git a/src/drivers/xnu/xnu.c b/src/drivers/xnu/xnu.c index eb78c7a0..c9755b66 100644 --- a/src/drivers/xnu/xnu.c +++ b/src/drivers/xnu/xnu.c @@ -122,18 +122,18 @@ void log_bootargs(const char *cmd, char *args) iprintf("gBootArgs:\n" "\tRevision: 0x%x\n" "\tVersion: 0x%x\n" - "\tvirtBase: 0x%llx\n" - "\tphysBase 0x%llx\n" - "\tmemSize: 0x%llx\n" - "\ttopOfKernelData: 0x%llx\n" + "\tvirtBase: 0x%" PRIx64 "\n" + "\tphysBase 0x%" PRIx64 "\n" + "\tmemSize: 0x%" PRIx64 "\n" + "\ttopOfKernelData: 0x%" PRIx64 "\n" "\tmachineType: 0x%x\n" - "\tdeviceTreeP: 0x%llx\n" + "\tdeviceTreeP: 0x%" PRIx64 "\n" "\tdeviceTreeLength: 0x%x\n" "\tCommandLine: 0x%s\n" - "\tbootFlags (<=iOS12): 0x%llx\n" - "\tmemSizeActual (<=iOS12): 0x%llx\n" - "\tbootFlags (>=iOS13): 0x%llx\n" - "\tmemSizeActual (>=iOS13): 0x%llx\n", + "\tbootFlags (<=iOS12): 0x%" PRIx64 "\n" + "\tmemSizeActual (<=iOS12): 0x%" PRIx64 "\n" + "\tbootFlags (>=iOS13): 0x%" PRIx64 "\n" + "\tmemSizeActual (>=iOS13): 0x%" PRIx64 "\n", cBootArgs->Revision, cBootArgs->Version, cBootArgs->virtBase, diff --git a/src/dynamic/modload.c b/src/dynamic/modload.c index e551bf99..4caa03ef 100644 --- a/src/dynamic/modload.c +++ b/src/dynamic/modload.c @@ -745,7 +745,7 @@ struct pongo_module_info* pongo_module_create(uint32_t segmentCount) { void pongo_module_print_list() { struct pongo_module_info* cur = head; while (cur) { - iprintf(" | %26s @ 0x%llx->0x%llx\n", cur->name, cur->vm_base, cur->vm_end); + iprintf(" | %26s @ 0x%" PRIx64 "->0x%" PRIx64 "\n", cur->name, cur->vm_base, cur->vm_end); for (uint32_t i = 0; i < cur->segcount; i++) { iprintf(" |---> %22s @ 0x%08llx, size 0x%06llx (%s%s%s)\n", cur->segments[i].name, cur->vm_base + cur->segments[i].vm_addr, cur->segments[i].vm_size, cur->segments[i].prot & PROT_READ ? "r" : "-", cur->segments[i].prot & PROT_WRITE ? "w" : "-", cur->segments[i].prot & PROT_EXEC ? "x" : "-"); } diff --git a/src/dynamic/modload_macho.c b/src/dynamic/modload_macho.c index 2b3753c9..d4739b59 100644 --- a/src/dynamic/modload_macho.c +++ b/src/dynamic/modload_macho.c @@ -53,7 +53,7 @@ void modload_cmd() { if (lc->cmd == LC_SEGMENT_64) { segmentCount++; struct segment_command_64 * sg = (struct segment_command_64*) lc; - //iprintf("found %s, vmaddr %llx, vmsz %llx, fileoff %llx, filesize %llx\n", sg->segname, sg->vmaddr, sg->vmsize, sg->fileoff, sg->filesize); + //iprintf("found %s, vmaddr %" PRIx64 ", vmsz %" PRIx64 ", fileoff %" PRIx64 ", filesize %" PRIx64 "\n", sg->segname, sg->vmaddr, sg->vmsize, sg->fileoff, sg->filesize); if (sg->vmaddr < base_vmaddr) base_vmaddr = sg->vmaddr; if (sg->fileoff + sg->filesize > filesz_expected) filesz_expected = sg->fileoff + sg->filesize; @@ -67,7 +67,7 @@ void modload_cmd() { lc = (struct load_command*)(((char*)lc) + lc->cmdsize); } vmsz_needed -= base_vmaddr; - //iprintf("need %llx, got %llx\n", filesz_expected, loader_xfer_recv_count); + //iprintf("need %" PRIx64 ", got %" PRIx64 "\n", filesz_expected, loader_xfer_recv_count); if (!(filesz_expected > loader_xfer_recv_count)) { uint64_t entrypoint = 0; uint8_t * allocto = alloc_contig((vmsz_needed + 0x3FFF) & ~0x3FFF); @@ -77,7 +77,7 @@ void modload_cmd() { module->vm_end = vma_base + vmsz_needed; uint32_t segmentIndex = 0; - //iprintf("need vm %llx, got %p, base %llx\n", vmsz_needed, allocto, base_vmaddr); + //iprintf("need vm %" PRIx64 ", got %p, base %" PRIx64 "\n", vmsz_needed, allocto, base_vmaddr); struct load_command* lc = (struct load_command*) (mh + 1); for (int i=0; incmds; i++) { if (lc->cmd == LC_SEGMENT_64) { @@ -98,7 +98,7 @@ void modload_cmd() { info->prot = prots; for (uint32_t page = 0; page < sg->vmsize; page += PAGE_SIZE) { - //fiprintf(stderr, "mapping %llx (%llx, %llx), %x\n", vma_base + page + sg->vmaddr - base_vmaddr, sg->vmaddr, sg->vmsize, prots); + //fiprintf(stderr, "mapping %" PRIx64 " (%" PRIx64 ", %" PRIx64 "), %x\n", vma_base + page + sg->vmaddr - base_vmaddr, sg->vmaddr, sg->vmsize, prots); uint64_t ppage = vatophys((uint64_t)(allocto + page + sg->vmaddr - base_vmaddr)); vm_space_map_page_physical_prot(&kernel_vm_space, vma_base + page + sg->vmaddr - base_vmaddr, ppage, prots | PROT_KERN_ONLY); } diff --git a/src/kernel/legacy.c b/src/kernel/legacy.c index 8343e169..e4dfbe06 100644 --- a/src/kernel/legacy.c +++ b/src/kernel/legacy.c @@ -30,7 +30,7 @@ void print_register(uint64_t value) { - iprintf("0x%016llx\n", value); + iprintf("0x%016" PRIx64 "\n", value); } void command_puts(const char* c) diff --git a/src/kernel/lowlevel.c b/src/kernel/lowlevel.c index 696a8ca7..863553dd 100644 --- a/src/kernel/lowlevel.c +++ b/src/kernel/lowlevel.c @@ -287,7 +287,7 @@ volatile char is_in_exception; void print_state(uint64_t* state) { task_critical_enter(); for (int i=0; i<31; i++) { - fiprintf(stderr, "X%d: %s0x%016llx ", i, i < 10 ? " " : "", state[i]); + fiprintf(stderr, "X%d: %s0x%016" PRIx64 " ", i, i < 10 ? " " : "", state[i]); if (i == 30) break; if ((i & 1) == 1) { if ((i & 3) == 3) { @@ -298,12 +298,12 @@ void print_state(uint64_t* state) { } } } - fiprintf(stderr, "SP: 0x%016llx\n", state[0x118/8]); - fiprintf(stderr, "ESR: 0x%016llx ", state[0xf8/8]); - fiprintf(stderr, "ELR: 0x%016llx ", state[0x100/8]); + fiprintf(stderr, "SP: 0x%016" PRIx64 "\n", state[0x118/8]); + fiprintf(stderr, "ESR: 0x%016" PRIx64 " ", state[0xf8/8]); + fiprintf(stderr, "ELR: 0x%016" PRIx64 " ", state[0x100/8]); fflush(stderr); screen_putc('\n'); // avoid word wrap on screen - fiprintf(stderr, "FAR: 0x%016llx ", state[0x108/8]); + fiprintf(stderr, "FAR: 0x%016" PRIx64 " ", state[0x108/8]); fiprintf(stderr, "CPSR: 0x%08llx\n", state[0x110/8]); struct task *t = task_current(); @@ -313,15 +313,15 @@ void print_state(uint64_t* state) { fiprintf(stderr, "skipping call stack due to fault in critical section\n"); } else { fiprintf(stderr, "Call stack:\n"); - fiprintf(stderr, " registers: fp 0x%016llx, lr 0x%016llx\n", state[29], state[30]); + fiprintf(stderr, " registers: fp 0x%016" PRIx64 ", lr 0x%016" PRIx64 "\n", state[29], state[30]); int depth = 0; uint64_t fpcopy[2]; for(uint64_t *fp = (uint64_t*)state[29]; fp; fp = (uint64_t*)fpcopy[0]) { if (memcpy_trap(fpcopy, fp, 0x10) == 0x10) { - fiprintf(stderr, "0x%016llx: fp 0x%016llx, lr 0x%016llx\n", ((uint64_t)fp), fpcopy[0], fpcopy[1]); + fiprintf(stderr, "0x%016" PRIx64 ": fp 0x%016" PRIx64 ", lr 0x%016" PRIx64 "\n", ((uint64_t)fp), fpcopy[0], fpcopy[1]); } else { - fiprintf(stderr, "couldn't access frame at %016llx, stopping here..,\n", (uint64_t)fp); + fiprintf(stderr, "couldn't access frame at %016" PRIx64 ", stopping here..,\n", (uint64_t)fp); break; } depth++; diff --git a/src/kernel/mm.c b/src/kernel/mm.c index 740e9bee..64a912b9 100644 --- a/src/kernel/mm.c +++ b/src/kernel/mm.c @@ -108,7 +108,7 @@ void map_range_map(uint64_t* tt0, uint64_t va, uint64_t pa, uint64_t size, uint6 uint64_t pgsz = 1ULL << (tt_bits + 3ULL); if((va & (pgsz - 1ULL)) || (pa & (pgsz - 1ULL)) || (size & (pgsz - 1ULL)) || size < pgsz || (va + size < va) || (pa + size < pa)) { - panic("map_range: called with bad arguments (0x%llx, 0x%llx, 0x%llx, ...)", va, pa, size); + panic("map_range: called with bad arguments (0x%" PRIx64 ", 0x%" PRIx64 ", 0x%" PRIx64 ", ...)", va, pa, size); } union tte tte; @@ -497,7 +497,7 @@ err_t vm_space_map_page_physical_prot(struct vm_space* vmspace, uint64_t vaddr, if (vaddr & 0x7000000000000000) { if ((physical & 0x3fff) && !(prot & PROT_PAGING_INFO)) { - panic("passed unaligned PA %llx to vm_space_map_page_physical_prot", physical); + panic("passed unaligned PA %" PRIx64 " to vm_space_map_page_physical_prot", physical); } map_range_map((uint64_t*)vmspace->ttbr1, vaddr, prot & PROT_PAGING_INFO ? 0 : physical, 0x4000, prot & PROT_DEVICE ? 3 : 2, prot & PROT_DEVICE ? 0 : 1, 1, prot & PROT_PAGING_INFO ? physical : 0, prot & (PROT_READ|PROT_WRITE|PROT_EXEC|PROT_KERN_ONLY|PROT_PAGING_INFO), true); if (!(prot & PROT_PAGING_INFO)) @@ -533,7 +533,7 @@ uint64_t asid_alloc() { if (!is_alloc) { asid_table[i>>3] |= (1 << (i&0x7)); enable_interrupts(); - //fiprintf(stderr, "allocating asid: %llx\n", ((uint64_t) i) << 48ULL); + //fiprintf(stderr, "allocating asid: %" PRIx64 "\n", ((uint64_t) i) << 48ULL); return ((uint64_t) i) << 48ULL; } @@ -548,7 +548,7 @@ void asid_free(uint64_t asid) { bool is_alloc = !!(asid_table[index>>3] & (1 << (index&0x7))); if (!is_alloc) panic("ASID was not allocated?!"); #if DEBUG_REFCOUNT - fiprintf(stderr, "freeing asid: %llx\n", asid); + fiprintf(stderr, "freeing asid: %" PRIx64 "\n", asid); #endif asid_table[index >> 3] &= ~(1 << (index&0x7)); asm volatile("ISB"); @@ -615,16 +615,16 @@ uint64_t free_pages = 0; uint64_t wired_pages = 0; uint32_t phys_get_entry(uint64_t pa) { pa -= gBootArgs->physBase; - if (pa & 0x3fff) panic("phys_get_entry only works with aligned PAs (pa: %llx)", pa); + if (pa & 0x3fff) panic("phys_get_entry only works with aligned PAs (pa: %" PRIx64 ")", pa); pa >>= 14; - if (pa > ppages) panic("OOB phys_get_entry: 0x%llx", pa << 14ULL); + if (pa > ppages) panic("OOB phys_get_entry: 0x%" PRIx64 "", pa << 14ULL); return ppage_list[pa]; } void phys_set_entry(uint64_t pa, uint32_t val) { pa -= gBootArgs->physBase; - if (pa & 0x3fff) panic("phys_get_entry only works with aligned PAs (pa: %llx)", pa); + if (pa & 0x3fff) panic("phys_get_entry only works with aligned PAs (pa: %" PRIx64 ")", pa); pa >>= 14; - if (pa > ppages) panic("OOB phys_set_entry: 0x%llx", pa << 14ULL); + if (pa > ppages) panic("OOB phys_set_entry: 0x%" PRIx64 "", pa << 14ULL); ppage_list[pa] = val; } uint64_t pa_head; @@ -642,21 +642,21 @@ void phys_unlink_contiguous(uint64_t pa, uint64_t size) { disable_interrupts(); for (uint64_t i=pa; i < pa+fpages; i++) { - if (i > ppages) panic("OOB phys_unlink_contiguous: 0x%llx", i << 14ULL); + if (i > ppages) panic("OOB phys_unlink_contiguous: 0x%" PRIx64 "", i << 14ULL); uint64_t* pa_v = phystokv((i << 14ULL) + gBootArgs->physBase); - if ((phys_get_entry((i << 14ULL) + gBootArgs->physBase) & PAGE_REFBITS) != PAGE_FREE) panic("phys_unlink_contiguous: ppage (pa: %llx) is not free!", (i << 14ULL) + gBootArgs->physBase); + if ((phys_get_entry((i << 14ULL) + gBootArgs->physBase) & PAGE_REFBITS) != PAGE_FREE) panic("phys_unlink_contiguous: ppage (pa: %" PRIx64 ") is not free!", (i << 14ULL) + gBootArgs->physBase); uint64_t pa_next = pa_v[0]; uint64_t pa_prev = pa_v[1]; if (pa_next) { - if ((phys_get_entry(pa_next) & PAGE_REFBITS) != PAGE_FREE) panic("phys_unlink_contiguous: ppage (next: %llx) is not free!", pa_next); + if ((phys_get_entry(pa_next) & PAGE_REFBITS) != PAGE_FREE) panic("phys_unlink_contiguous: ppage (next: %" PRIx64 ") is not free!", pa_next); uint64_t* pa_next_v = phystokv(pa_next); pa_next_v[1] = pa_prev; // unlink } if (pa_prev) { - if ((phys_get_entry(pa_prev) & PAGE_REFBITS) != PAGE_FREE) panic("phys_unlink_contiguous: ppage (prev: %llx) is not free!", pa_prev); + if ((phys_get_entry(pa_prev) & PAGE_REFBITS) != PAGE_FREE) panic("phys_unlink_contiguous: ppage (prev: %" PRIx64 ") is not free!", pa_prev); uint64_t* pa_prev_v = phystokv(pa_prev); pa_prev_v[0] = pa_next; } else { @@ -669,13 +669,13 @@ void mark_phys_wired(uint64_t pa, uint64_t size) { pa -= gBootArgs->physBase; uint64_t fpages = size >> 14; - if (pa & 0x3fff) panic("mark_phys_wired only works with aligned PAs (pa: %llx)", pa); + if (pa & 0x3fff) panic("mark_phys_wired only works with aligned PAs (pa: %" PRIx64 ")", pa); pa >>= 14; disable_interrupts(); for (uint64_t i=pa; i < pa+fpages; i++) { - if ((phys_get_entry((i << 14ULL) + gBootArgs->physBase) & PAGE_REFBITS) != PAGE_FREE) panic("mark_phys_wired: ppage (pa: %llx) is not free!", (i << 14ULL) + gBootArgs->physBase); - if (i > ppages) panic("OOB mark_phys_wired: 0x%llx", i << 14ULL); + if ((phys_get_entry((i << 14ULL) + gBootArgs->physBase) & PAGE_REFBITS) != PAGE_FREE) panic("mark_phys_wired: ppage (pa: %" PRIx64 ") is not free!", (i << 14ULL) + gBootArgs->physBase); + if (i > ppages) panic("OOB mark_phys_wired: 0x%" PRIx64 "", i << 14ULL); ppage_list[i] = (ppage_list[i] & ~PAGE_REFBITS) | PAGE_WIRED; free_pages--; wired_pages++; @@ -725,7 +725,7 @@ void phys_force_free(uint64_t pa, uint64_t size) { disable_interrupts(); for (uint64_t i=pa; i < pa+fpages; i++) { - if (i > ppages) panic("OOB phys_force_free: 0x%llx", i << 14ULL); + if (i > ppages) panic("OOB phys_force_free: 0x%" PRIx64 "", i << 14ULL); if ((ppage_list[i] & PAGE_REFBITS) == PAGE_WIRED) { wired_pages--; } @@ -747,7 +747,7 @@ void phys_reference(uint64_t pa, uint64_t size) { disable_interrupts(); for (uint64_t i=pa; i < pa+fpages; i++) { - if (i > ppages) panic("OOB phys_reference: 0x%llx", i << 14ULL); + if (i > ppages) panic("OOB phys_reference: 0x%" PRIx64 "", i << 14ULL); if ((ppage_list[i] & PAGE_REFBITS) != PAGE_WIRED) { if ((ppage_list[i] & PAGE_REFBITS) == PAGE_FREE) { free_pages--; @@ -763,18 +763,18 @@ void phys_dereference(uint64_t pa, uint64_t size) { pa -= gBootArgs->physBase; uint64_t fpages = size >> 14ULL; - if (pa & 0x3fff) panic("phys_dereference only works with aligned PAs (was passed %llx)", pa + gBootArgs->physBase); + if (pa & 0x3fff) panic("phys_dereference only works with aligned PAs (was passed %" PRIx64 ")", pa + gBootArgs->physBase); pa >>= 14ULL; disable_interrupts(); for (uint64_t i=pa; i < pa+fpages; i++) { - if (i > ppages) panic("OOB phys_dereference: 0x%llx", i << 14ULL); + if (i > ppages) panic("OOB phys_dereference: 0x%" PRIx64 "", i << 14ULL); if ((ppage_list[i] & PAGE_REFBITS) != PAGE_FREE) { ppage_list[i] = (ppage_list[i] & ~PAGE_REFBITS) | ((ppage_list[i] - 1) & PAGE_REFBITS); if ((ppage_list[i] & PAGE_REFBITS) == PAGE_FREE) { phys_page_was_freed((i << 14ULL) + gBootArgs->physBase); } - } else panic("phys_dereference called on PAGE_FREE page @ 0x%llx", i << 14ULL); + } else panic("phys_dereference called on PAGE_FREE page @ 0x%" PRIx64 "", i << 14ULL); } enable_interrupts(); } @@ -956,7 +956,7 @@ bool vm_fault(struct vm_space* vmspace, uint64_t vma, vm_protect_t fault_prot) { if (tte.valid == 0 && tte.table == 1) { tte.table = 0; if (tte.u64 == PAGING_INFO_ALLOC_ON_FAULT_MAGIC) { - //fiprintf(stderr, "should allocate physical for %llx\n", vma); + //fiprintf(stderr, "should allocate physical for %" PRIx64 "\n", vma); paging_requests++; vm_space_map_page_physical_prot(vmspace, vma & ~0x3fff, ppage_alloc(), PROT_READ|PROT_WRITE); enable_interrupts(); diff --git a/src/kernel/panic.c b/src/kernel/panic.c index 55807c9f..71f8b1bc 100644 --- a/src/kernel/panic.c +++ b/src/kernel/panic.c @@ -63,9 +63,9 @@ void panic(const char* str, ...) { for(uint64_t *fp = __builtin_frame_address(0); fp; fp = (uint64_t*)fpcopy[0]) { if (memcpy_trap(fpcopy, fp, 0x10) == 0x10) { - iprintf("0x%016llx: fp 0x%016llx, lr 0x%016llx\n", ((uint64_t)fp), fpcopy[0], fpcopy[1]); + iprintf("0x%016" PRIx64 ": fp 0x%016" PRIx64 ", lr 0x%016" PRIx64 "\n", ((uint64_t)fp), fpcopy[0], fpcopy[1]); } else { - iprintf("couldn't access frame at %016llx, stopping here..,\n", (uint64_t)fp); + iprintf("couldn't access frame at %016" PRIx64 ", stopping here..,\n", (uint64_t)fp); break; } depth++; diff --git a/src/kernel/pongo.h b/src/kernel/pongo.h index 6ecde290..a853ca74 100644 --- a/src/kernel/pongo.h +++ b/src/kernel/pongo.h @@ -35,6 +35,7 @@ #include #include #include +#include #ifdef PONGO_PRIVATE #include "framebuffer/fb.h" diff --git a/src/kernel/task.c b/src/kernel/task.c index c3f0f97a..614958fc 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -198,7 +198,7 @@ retry:; for(int i = 0; i < ntasks; ++i) { task_info_t *t = &tasks_copy[i]; - iprintf(" | %7s | task %d | runcnt = %llx | flags = %s, %s\n", t->name[0] ? t->name : "unknown", t->pid, t->runcnt, t->flags & TASK_PREEMPT ? "preempt" : "coop", t->flags & TASK_LINKED ? "run" : "wait"); + iprintf(" | %7s | task %d | runcnt = %" PRIx64 " | flags = %s, %s\n", t->name[0] ? t->name : "unknown", t->pid, t->runcnt, t->flags & TASK_PREEMPT ? "preempt" : "coop", t->flags & TASK_LINKED ? "run" : "wait"); } iprintf("=+= IRQ Handlers ===\n"); for(int i = 0; i < nirq; ++i) diff --git a/src/modules/linux/linux.c b/src/modules/linux/linux.c index 27d096de..351b91c7 100644 --- a/src/modules/linux/linux.c +++ b/src/modules/linux/linux.c @@ -70,7 +70,7 @@ void linux_dtree_init(void) /* Alias */ node = fdt_add_subnode(fdt, 0, "/aliases"); char serials[64]; - siprintf(serials, "/soc/serial@%llx", ((uint64_t)dt_get_u32_prop("uart0", "reg")) + gIOBase); + siprintf(serials, "/soc/serial@%" PRIx64 "", ((uint64_t)dt_get_u32_prop("uart0", "reg")) + gIOBase); fdt_appendprop_string(fdt, node, "serial0", serials); /* CPU */ @@ -117,7 +117,7 @@ void linux_dtree_init(void) fdt_appendprop(fdt, node, "ranges", "", 0); /* Interrupt controller: Apple AIC */ - siprintf(fdt_nodename, "/interrupt-controller@%llx", (uint64_t)dt_get_u32_prop("aic", "reg") + gIOBase); + siprintf(fdt_nodename, "/interrupt-controller@%" PRIx64 "", (uint64_t)dt_get_u32_prop("aic", "reg") + gIOBase); node1 = fdt_add_subnode(fdt, node, fdt_nodename); fdt_appendprop_string(fdt, node1, "name", "interrupt_controller"); fdt_appendprop_string(fdt, node1, "device_type", "interrupt_controller"); @@ -131,7 +131,7 @@ void linux_dtree_init(void) fdt_appendprop(fdt, node1, "interrupt-controller", "", 0); /* UART */ - siprintf(fdt_nodename, "/serial@%llx", (uint64_t)dt_get_u32_prop("uart0", "reg") + gIOBase); + siprintf(fdt_nodename, "/serial@%" PRIx64 "", (uint64_t)dt_get_u32_prop("uart0", "reg") + gIOBase); node1 = fdt_add_subnode(fdt, node, fdt_nodename); fdt_appendprop_string(fdt, node1, "compatible", "hx,uart"); fdt_appendprop_addrrange(fdt, 0, node1, "reg", @@ -156,7 +156,7 @@ void linux_dtree_init(void) fdt_appendprop(fdt, node, "ranges", "", 0); uint64_t nomap_area = 0x800000000 + gBootArgs->memSize - 0x02000000; - siprintf(fdt_nodename, "/fw_area@%llx", nomap_area); + siprintf(fdt_nodename, "/fw_area@%" PRIx64 "", nomap_area); node1 = fdt_add_subnode(fdt, node, fdt_nodename); fdt_appendprop_addrrange(fdt, 0, node1, "reg", nomap_area, 0x04000000); fdt_appendprop(fdt, node1, "no-map", "", 0); @@ -172,7 +172,7 @@ void linux_dtree_late(void) fdt_appendprop(fdt, node, "ranges", "", 0); char cmdline[256]; - siprintf(cmdline, "debug earlycon=hx_uart,0x%llx console=tty0 console=ttyHX0", ((uint64_t)dt_get_u32_prop("uart0", "reg")) + gIOBase); + siprintf(cmdline, "debug earlycon=hx_uart,0x%" PRIx64 " console=tty0 console=ttyHX0", ((uint64_t)dt_get_u32_prop("uart0", "reg")) + gIOBase); fdt_appendprop_string(fdt, node, "bootargs", cmdline); /* simplefb dart-apcie3*/ diff --git a/src/shell/main.c b/src/shell/main.c index edecf838..326c43ce 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -153,7 +153,7 @@ void peek_cmd(const char* cmd, char* args) { uint64_t addr = strtoull(args, NULL, 16); uint32_t rv = *((uint32_t*)addr); - iprintf("0x%llx: %x (%x %x %x %x)\n", (uint64_t)addr, rv, rv&0xff, (rv>>8)&0xff, (rv>>16)&0xff, (rv>>24)&0xff); + iprintf("0x%" PRIx64 ": %x (%x %x %x %x)\n", (uint64_t)addr, rv, rv&0xff, (rv>>8)&0xff, (rv>>16)&0xff, (rv>>24)&0xff); } void poke_cmd(const char* cmd, char* args) { if (! *args) { @@ -167,7 +167,7 @@ void poke_cmd(const char* cmd, char* args) { } uint64_t addr = strtoull(args, NULL, 16); uint32_t value = strtoul(arg1, NULL, 16); - iprintf("writing %x @ 0x%llx\n", value, addr); + iprintf("writing %x @ 0x%" PRIx64 "\n", value, addr); *((uint32_t*)addr) = value; } diff --git a/tools/vmacho.c b/tools/vmacho.c index f685c3fb..05beb6fa 100644 --- a/tools/vmacho.c +++ b/tools/vmacho.c @@ -471,7 +471,7 @@ int main(int argc, const char **argv) { if((uintptr_t)cmd + sizeof(*cmd) > (uintptr_t)end || (uintptr_t)cmd + cmd->cmdsize > (uintptr_t)end || (uintptr_t)cmd + cmd->cmdsize < (uintptr_t)cmd) { - LOG("Bad LC: 0x%llx", (unsigned long long)((uintptr_t)cmd - ufile)); + LOG("Bad LC: 0x%" PRIx64 "", (unsigned long long)((uintptr_t)cmd - ufile)); goto out; } @@ -505,7 +505,7 @@ int main(int argc, const char **argv) uint64_t off = fileoff + size; if(off > flen || off < fileoff) { - LOG("Bad segment: 0x%llx", (unsigned long long)((uintptr_t)cmd - ufile)); + LOG("Bad segment: 0x%" PRIx64 "", (unsigned long long)((uintptr_t)cmd - ufile)); goto out; } @@ -522,7 +522,7 @@ int main(int argc, const char **argv) } if(highest < lowest) { - LOG("Bad memory layout, lowest: 0x%llx, highest: 0x%llx", (unsigned long long)lowest, (unsigned long long)highest); + LOG("Bad memory layout, lowest: 0x%" PRIx64 ", highest: 0x%" PRIx64 "", (unsigned long long)lowest, (unsigned long long)highest); goto out; } mlen = (size_t)(highest - lowest); @@ -609,7 +609,7 @@ int main(int argc, const char **argv) } fflush(outfile); // In case of stdout - LOG("Done, base address: 0x%llx", (unsigned long long)lowest); + LOG("Done, base address: 0x%" PRIx64 "", (unsigned long long)lowest); retval = 0; out:; From 6e67b7295a45bdc65ffd9e3d5f274294d25200ec Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 28 Jul 2023 02:36:36 +0800 Subject: [PATCH 20/77] vmacho.c should include inttypes.h --- tools/vmacho.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/vmacho.c b/tools/vmacho.c index 05beb6fa..376e59df 100644 --- a/tools/vmacho.c +++ b/tools/vmacho.c @@ -31,6 +31,7 @@ #include // fopen, fclose, ftell, fseek, fflush, fprintf, stdin, stdout, stderr #include // malloc, free #include // memset, strcmp, strerror +#include // PRI* #define LOG(str, ...) do { fprintf(stderr, str "\n", ##__VA_ARGS__); } while(0) From d19792ce8d31384c5d20841be66a2dee025bdd24 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 28 Jul 2023 03:17:15 +0800 Subject: [PATCH 21/77] actions: compile kpf-test.linux --- .github/workflows/ci.yml | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 758461be..54dd3bf3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,3 +49,24 @@ jobs: dryRun: false localDir: 'upload' remoteDir: "/palera1n/artifacts/kpf/${{ steps.branch-name.outputs.ref_branch || github.ref }}" + + test: + runs-on: ubuntu-22.04 + container: + image: debian:stable + steps: + - name: Install packages + run: | + dpkg --add-architecture arm64 + apt-get update + apt-get -y --allow-downgrades dist-upgrade + apt-get install -y build-essential git libc6:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld + + - name: Checkout repository + uses: actions/checkout@v2 + with: + fetch-depth: 0 + + - name: Compile KPF test + run: + make -C checkra1n/kpf-test KPF_CFLAGS="-target aarch64-linux-gnu -L/usr/aarch64-linux-gnu/lib -I/usr/aarch64-linux-gnu/include -L/usr/lib/gcc-cross/aarch64-linux-gnu/*" kpf-test.linux From 9e757f3a1904eaa33952351155a416f7c1840ea2 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 28 Jul 2023 04:30:07 +0800 Subject: [PATCH 22/77] actions: Actually test KPF --- .github/workflows/ci.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 54dd3bf3..fdaffe78 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: dpkg --add-architecture arm64 apt-get update apt-get -y --allow-downgrades dist-upgrade - apt-get install -y build-essential git libc6:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld + apt-get install -y build-essential git libc6:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld xz-utils curl - name: Checkout repository uses: actions/checkout@v2 @@ -70,3 +70,14 @@ jobs: - name: Compile KPF test run: make -C checkra1n/kpf-test KPF_CFLAGS="-target aarch64-linux-gnu -L/usr/aarch64-linux-gnu/lib -I/usr/aarch64-linux-gnu/include -L/usr/lib/gcc-cross/aarch64-linux-gnu/*" kpf-test.linux + + - name: Get kernels + run: | + curl -LOu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.xz + xz -cdT 0 kc.tar.xz | tar -x + + - name: Test KPF + run: | + for k in ./kernel/xnu-*; do + qemu-aarch64 ./checkra1n/kpf-test/kpf-test.linux "${k}"; + done From ae7d6d698292f91f8aeb29e8ef8bc6f722379887 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 28 Jul 2023 05:09:39 +0800 Subject: [PATCH 23/77] kpf-test: Make panic work properly on linux --- .github/workflows/ci.yml | 3 ++- checkra1n/kpf-test/main.c | 10 +++++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fdaffe78..088894a2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: dpkg --add-architecture arm64 apt-get update apt-get -y --allow-downgrades dist-upgrade - apt-get install -y build-essential git libc6:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld xz-utils curl + apt-get install -y build-essential git libc6:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld curl xz-utils - name: Checkout repository uses: actions/checkout@v2 @@ -79,5 +79,6 @@ jobs: - name: Test KPF run: | for k in ./kernel/xnu-*; do + echo "${k}"; qemu-aarch64 ./checkra1n/kpf-test/kpf-test.linux "${k}"; done diff --git a/checkra1n/kpf-test/main.c b/checkra1n/kpf-test/main.c index 29dfd518..56331497 100644 --- a/checkra1n/kpf-test/main.c +++ b/checkra1n/kpf-test/main.c @@ -114,16 +114,20 @@ extern void (*preboot_hook)(void); void realpanic(const char *str, ...) { - char *ptr = NULL; va_list va; +#ifdef __APPLE__ + char *ptr = NULL; va_start(va, str); vasprintf(&ptr, str, va); va_end(va); - -#ifdef __APPLE__ panic(ptr); #else + printf("panic: "); + va_start(va, str); + vprintf(str, va); + va_end(va); + printf("\n"); abort(); #endif } From 07ce18ddc1446effb6f75076d1ce7b963594b0af Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Tue, 5 Sep 2023 18:14:50 +0800 Subject: [PATCH 24/77] kpf: shellcode: set CS_DEBUGGED DolphiniOS do not like it if it is not set --- checkra1n/kpf/shellcode.S | 1 + 1 file changed, 1 insertion(+) diff --git a/checkra1n/kpf/shellcode.S b/checkra1n/kpf/shellcode.S index fbf49c40..66174afb 100644 --- a/checkra1n/kpf/shellcode.S +++ b/checkra1n/kpf/shellcode.S @@ -67,6 +67,7 @@ amfi_execve_hook: // you can't kill me :P (makes sure amfi doesn't try to kill o ldr x0, [sp, #8] // cs_flags ldr w1, [x0] orr w1, w1, #0x04000000 // CS_PLATFORM_BINARY + orr w1, w1, #0x10000000 // CS_DEBUGGED orr w1, w1, #0x000f // CS_VALID | CS_ADHOC | CS_GET_TASK_ALLOW | CS_INSTALLER and w1, w1, #(~0x3f00) // clearing CS_HARD | CS_KILL | CS_CHECK_EXPIRATION | CS_RESTRICT | CS_ENFORCEMENT | CS_REQUIRE_LV //and w1, w1, #(~0x00000000) From 0922d9547e4e7860dd3bd8a6a25b73063fe9ce40 Mon Sep 17 00:00:00 2001 From: Siguza Date: Wed, 6 Sep 2023 03:02:40 +0200 Subject: [PATCH 25/77] Fix APFS mount patch stuff --- checkra1n/kpf/main.c | 40 +++++++++++++++++++++++++++++----------- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index f95d3009..3e4fc3d8 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -924,15 +924,31 @@ bool kpf_apfs_patches_rename(struct xnu_pf_patch* patch, uint32_t* opcode_stream return true; } -bool kpf_apfs_patches_mount(struct xnu_pf_patch* patch, uint32_t* opcode_stream) { +bool kpf_apfs_patches_mount(struct xnu_pf_patch* patch, uint32_t* opcode_stream) +{ + uint32_t adrp = opcode_stream[0], + add = opcode_stream[1]; + const char *str = (const char *)(((uint64_t)(opcode_stream) & ~0xfffULL) + adrp_off(adrp) + ((add >> 10) & 0xfff)); + if(strcmp(str, "%s:%d: not allowed to mount as root\n") != 0) + { + return false; + } + + static bool has_found_f_apfs_privcheck = false; + if(has_found_f_apfs_privcheck) + { + panic("f_apfs_privcheck found twice!"); + } + // cmp x0, x8 - uint32_t* f_apfs_privcheck = find_next_insn(opcode_stream, 0x10, 0xeb08001f, 0xFFFFFFFF); + uint32_t* f_apfs_privcheck = find_prev_insn(opcode_stream, 0x10, 0xeb08001f, 0xFFFFFFFF); if (!f_apfs_privcheck) { DEVLOG("kpf_apfs_patches_mount: failed to find f_apfs_privcheck"); return false; } puts("KPF: Found APFS mount"); *f_apfs_privcheck = 0xeb00001f; // cmp x0, x0 + has_found_f_apfs_privcheck = true; return true; } @@ -1124,18 +1140,20 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { // 0xfffffff00692e6a8 080140f9 ldr x8, [x8] // 0xfffffff00692e6ac 1f0008eb cmp x0, x8 <- cmp (patches to cmp x0, x0) // r2 cmd: - // /x 0000403908011b3200000039000000b9:0000c0bfffffffff0000c0bf000000ff + // /x 0000009000000091000000942000001200000014:1f00009fff03c0ff000000fc20fc7f9f000000fc uint64_t matches[] = { - 0x39400000, // ldr{b|h} w*, [x*] - 0x321b0108, // orr w8, w8, 0x20 - 0x39000000, // str{b|h} w*, [x*] - 0xb9000000 // str w*, [x*] + 0x90000000, // adrp x0, "%s:%d: not allowed to mount as root\n"@PAGE + 0x91000000, // add x0, x0, "%s:%d: not allowed to mount as root\n"@PAGEOFF + 0x94000000, // bl _panic + 0x12000020, // mov w*, #1 // orr w*, wzr, #1 + 0x14000000, // b ? }; uint64_t masks[] = { - 0xbfc00000, - 0xffffffff, - 0xbfc00000, - 0xff000000, + 0x9f00001f, + 0xffc003ff, + 0xfc000000, + 0x9f7ffc20, + 0xfc000000, }; xnu_pf_maskmatch(patchset, "apfs_patch_mount", matches, masks, sizeof(matches)/sizeof(uint64_t), true, (void*)kpf_apfs_patches_mount); if(have_union) From bd39bbe25a90f6d6151f25f7acc5345c161fd63e Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Thu, 7 Sep 2023 03:26:43 +0800 Subject: [PATCH 26/77] fix remount root patch --- checkra1n/kpf/main.c | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 3e4fc3d8..a0ccb7ce 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1054,16 +1054,21 @@ bool kpf_apfs_auth_required(struct xnu_pf_patch* patch, uint32_t* opcode_stream) bool has_found_apfs_vfsop_mount = false; bool kpf_apfs_vfsop_mount(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { - if (!opcode_stream) { - printf("Missing patch: apfs_vfsop_mount\n"); - return false; - } - uint32_t *tbnz = find_prev_insn(opcode_stream, 2, 0x37700000, 0xfff8001f); // tbnz w0, 0xe, * - if (!tbnz) { + uint32_t tbnz_offset = (opcode_stream[1] >> 5) & 0x3fff; + uint32_t *tbnz_stream = opcode_stream + 1 + tbnz_offset; + uint32_t *adrp = find_next_insn(tbnz_stream, 10, 0x90000000, 0x9f00001f); // adrp + if (!adrp) { return false; } + if ((adrp[1] & 0xff80001f) != 0x91000000) return false; + uint64_t page = ((uint64_t)adrp & ~0xfffULL) + adrp_off(adrp[0]); + uint32_t off = (adrp[1] >> 10) & 0xfff; + const char *str = (const char*)(page + off); + if (strcmp(str, "%s:%d: %s Updating mount to read/write mode is not allowed\n") != 0) { + return false; + } - *tbnz = 0x52800000; /* mov w0, 0 */ + opcode_stream[1] = 0x52800000; /* mov w0, 0 */ has_found_apfs_vfsop_mount = true; printf("KPF: found apfs_vfsop_mount\n"); @@ -1198,15 +1203,13 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { // 0xfffffff0064023b0 e8b300b9 str w8, [sp, 0xb0] // r2: /x a00340b900781f12a00300b9:a003feff00fcffffa003c0ff uint64_t remount_matches[] = { - 0xb94003a0, // ldr x*, [x29/sp, *] - 0x121f7800, // and w*, w*, 0xfffffffe - 0xb90003a0, // str x*, [x29/sp, *] + 0x94000000, // bl + 0x37700000 // tbnz w0, 0xe, * }; uint64_t remount_masks[] = { - 0xfffe03a0, - 0xfffffc00, - 0xffc003a0, + 0xfc000000, + 0xfff8001f }; xnu_pf_maskmatch(patchset, From 473225d66652616ad88bcb94994089219fb5d7d6 Mon Sep 17 00:00:00 2001 From: Siguza Date: Tue, 10 Oct 2023 07:51:48 +0200 Subject: [PATCH 27/77] Fix tvOS 17.x / audioOS 17.x / bridgeOS 8.x KPF --- checkra1n/kpf/main.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index a0ccb7ce..6fb88478 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1364,7 +1364,7 @@ bool kpf_amfi_mac_syscall(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { bool kpf_amfi_mac_syscall_low(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { // Unlike the other matches, the case we want is *not* the fallthrough one here. // So we need to follow the b.eq for 0x5a here. - return kpf_amfi_mac_syscall(patch, opcode_stream + 3 + sxt32(opcode_stream[3] >> 5, 19)); // uint32 takes care of << 2 + return kpf_amfi_mac_syscall(patch, opcode_stream + 1 + sxt32(opcode_stream[1] >> 5, 19)); // uint32 takes care of << 2 } void kpf_amfi_kext_patches(xnu_pf_patchset_t* patchset) { // this patch helps us find the return of the amfi function so that we can jump into shellcode from there and modify the cs flags @@ -1523,18 +1523,14 @@ void kpf_amfi_kext_patches(xnu_pf_patchset_t* patchset) { // tvOS/audioOS 16 and bridgeOS 7 apparently got some cases removed, so their codegen looks different again. // - // 0xfffffff008b0ad48 3f780171 cmp w1, 0x5e - // 0xfffffff008b0ad4c cc030054 b.gt 0xfffffff008b0adc4 // 0xfffffff008b0ad50 3f680171 cmp w1, 0x5a // 0xfffffff008b0ad54 40060054 b.eq 0xfffffff008b0ae1c // 0xfffffff008b0ad58 3f6c0171 cmp w1, 0x5b // 0xfffffff008b0ad5c 210e0054 b.ne 0xfffffff008b0af20 // // r2: - // /x 3f7801710c0000543f680171000000543f6c017101000054:ffffffff1f0000ffffffffff1f0000ffffffffff1f0000ff + // /x 3f680171000000543f6c017101000054:ffffffff1f0000ffffffffff1f0000ff uint64_t iiii_matches[] = { - 0x7101783f, // cmp w1, 0x5e - 0x5400000c, // b.gt 0x7101683f, // cmp w1, 0x5a 0x54000000, // b.eq 0x71016c3f, // cmp w1, 0x5b @@ -1545,8 +1541,6 @@ void kpf_amfi_kext_patches(xnu_pf_patchset_t* patchset) { 0xff00001f, 0xffffffff, 0xff00001f, - 0xffffffff, - 0xff00001f, }; xnu_pf_maskmatch(patchset, "amfi_mac_syscall_low", iiii_matches, iiii_masks, sizeof(iiii_matches)/sizeof(uint64_t), false, (void*)kpf_amfi_mac_syscall_low); } From 73c5fa9311a1207d4a727beda763bcd483c966bf Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Thu, 26 Oct 2023 14:50:26 +0800 Subject: [PATCH 28/77] kpf-test: test everything even if some failed --- .github/workflows/ci.yml | 5 +---- checkra1n/kpf-test/main.c | 1 + 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 088894a2..88b6587d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -78,7 +78,4 @@ jobs: - name: Test KPF run: | - for k in ./kernel/xnu-*; do - echo "${k}"; - qemu-aarch64 ./checkra1n/kpf-test/kpf-test.linux "${k}"; - done + qemu-aarch64 ./checkra1n/kpf-test/kpf-test.linux -n kernel; diff --git a/checkra1n/kpf-test/main.c b/checkra1n/kpf-test/main.c index 56331497..b5c2e68d 100644 --- a/checkra1n/kpf-test/main.c +++ b/checkra1n/kpf-test/main.c @@ -128,6 +128,7 @@ void realpanic(const char *str, ...) vprintf(str, va); va_end(va); printf("\n"); + fflush(stdout); abort(); #endif } From b3ea8a5286d2d6e61dafa754673083eaeeb2243e Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Thu, 26 Oct 2023 18:49:47 +0800 Subject: [PATCH 29/77] ci: switch to zstd compression --- .github/workflows/ci.yml | 7 +++---- checkra1n/kpf-test/main.c | 7 ++++++- checkra1n/kpf/main.c | 14 +++++++++++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 88b6587d..552436c5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: dpkg --add-architecture arm64 apt-get update apt-get -y --allow-downgrades dist-upgrade - apt-get install -y build-essential git libc6:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld curl xz-utils + apt-get install -y build-essential git libc6:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld curl zstd - name: Checkout repository uses: actions/checkout@v2 @@ -73,9 +73,8 @@ jobs: - name: Get kernels run: | - curl -LOu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.xz - xz -cdT 0 kc.tar.xz | tar -x + curl -Lu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.zst | zstd -cdT0 | tar -x - name: Test KPF run: | - qemu-aarch64 ./checkra1n/kpf-test/kpf-test.linux -n kernel; + qemu-aarch64 ./checkra1n/kpf-test/kpf-test.linux -n kernel2; diff --git a/checkra1n/kpf-test/main.c b/checkra1n/kpf-test/main.c index b5c2e68d..c31c3592 100644 --- a/checkra1n/kpf-test/main.c +++ b/checkra1n/kpf-test/main.c @@ -565,6 +565,8 @@ static int wait_for_child(child_t *children, size_t *num_bad, child_t **slot) return -1; } +bool test_force_rootful = 0; + int main(int argc, const char **argv) { int aoff = 1; @@ -588,6 +590,9 @@ int main(int argc, const char **argv) case 'v': ++verbose; break; + case 'f': + test_force_rootful = 1; + break; default: fprintf(stderr, "Bad arg: -%c\n", c); return -1; @@ -596,7 +601,7 @@ int main(int argc, const char **argv) } if(argc - aoff != 1) { - fprintf(stderr, "Usage: %s [-nqv] [file | dir]\n", argv[0]); + fprintf(stderr, "Usage: %s [-nqvf] [file | dir]\n", argv[0]); return -1; } int fd = open(argv[aoff], O_RDONLY); diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 6fb88478..1e4542e9 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -39,6 +39,10 @@ uint32_t offsetof_p_flags; palerain_option_t palera1n_flags; +#if __STDC_HOSTED__ +extern bool test_force_rootful; +#endif + #if 0 // AES, sigh else if((fetch & 0xfffffc00) == 0x510fa000 && (apfs_privcheck[i+1] & 0xfffffc1f) == 0x7100081f && (apfs_privcheck[i+2] & 0xff00001f) == 0x54000003) { @@ -1215,8 +1219,12 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { xnu_pf_maskmatch(patchset, "apfs_vfsop_mount", remount_matches, remount_masks, sizeof(remount_masks) / sizeof(uint64_t), !have_union -#ifdef DEV_BUILD - && gKernelVersion.darwinMajor <= 22 // this patch is not used on ios 17. +#if DEV_BUILD + && (gKernelVersion.darwinMajor <= 22 +#if __STDC_HOSTED__ + || test_force_rootful +#endif + ) // this patch is not used on ios 17. #else && (palera1n_flags & palerain_option_rootful) != 0 #endif @@ -2005,7 +2013,7 @@ static void kpf_cmd(const char *cmd, char *args) if (!kpf_has_done_mac_mount) panic("Missing patch: mac_mount"); if (!has_found_apfs_vfsop_mount && rootvp_string_match != NULL) { #if __STDC_HOSTED__ - if (gKernelVersion.darwinMajor <= 22) { + if (gKernelVersion.darwinMajor <= 22 || test_force_rootful) { puts("Missing patch: apfs_vfsop_mount"); } else #endif From a46f5deb6e872c8bdb5f2af528a0815c3677de18 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Thu, 26 Oct 2023 19:17:47 +0800 Subject: [PATCH 30/77] kpf-test: exit(6) on linux instead of abort --- checkra1n/kpf-test/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkra1n/kpf-test/main.c b/checkra1n/kpf-test/main.c index c31c3592..73632a16 100644 --- a/checkra1n/kpf-test/main.c +++ b/checkra1n/kpf-test/main.c @@ -129,7 +129,7 @@ void realpanic(const char *str, ...) va_end(va); printf("\n"); fflush(stdout); - abort(); + exit(6); #endif } From 2e69146f5bbf6c71bd56551b66003b2920190372 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 27 Oct 2023 21:11:56 +0800 Subject: [PATCH 31/77] kpf: fix detecting kernel version on some kernels --- checkra1n/kpf/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 1e4542e9..e348d3fa 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -135,11 +135,13 @@ uint32_t* follow_call(uint32_t *from) struct kernel_version gKernelVersion; static void kpf_kernel_version_init(xnu_pf_range_t *text_const_range) { - const char kernelVersionStringMarker[] = "@(#)VERSION: Darwin Kernel Version "; + const char* kernelVersionStringMarker = "@(#)VERSION: Darwin Kernel Version "; const char *kernelVersionString = memmem(text_const_range->cacheable_base, text_const_range->size, kernelVersionStringMarker, strlen(kernelVersionStringMarker)); if(kernelVersionString == NULL) { - panic("No kernel version string found"); + kernelVersionStringMarker = "Darwin Kernel Version "; + kernelVersionString = memmem(text_const_range->cacheable_base, text_const_range->size, kernelVersionStringMarker, strlen(kernelVersionStringMarker)); + if(kernelVersionString == NULL) panic("No kernel version string found"); } const char *start = kernelVersionString + strlen(kernelVersionStringMarker); char *end = NULL; From 9fc14fe04e27bd09120ca33d382a34ab7128202a Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 30 Oct 2023 00:42:18 +0800 Subject: [PATCH 32/77] kpf: fix apfs_vfsop_mount patch on iOS 15.0b1-15.0b4 --- checkra1n/kpf/main.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index e348d3fa..cc47917f 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1062,7 +1062,7 @@ bool has_found_apfs_vfsop_mount = false; bool kpf_apfs_vfsop_mount(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { uint32_t tbnz_offset = (opcode_stream[1] >> 5) & 0x3fff; uint32_t *tbnz_stream = opcode_stream + 1 + tbnz_offset; - uint32_t *adrp = find_next_insn(tbnz_stream, 10, 0x90000000, 0x9f00001f); // adrp + uint32_t *adrp = find_next_insn(tbnz_stream, 20, 0x90000000, 0x9f00001f); // adrp if (!adrp) { return false; } @@ -1070,7 +1070,9 @@ bool kpf_apfs_vfsop_mount(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { uint64_t page = ((uint64_t)adrp & ~0xfffULL) + adrp_off(adrp[0]); uint32_t off = (adrp[1] >> 10) & 0xfff; const char *str = (const char*)(page + off); - if (strcmp(str, "%s:%d: %s Updating mount to read/write mode is not allowed\n") != 0) { + if ( + strcmp(str, "%s:%d: %s Updating mount to read/write mode is not allowed\n") /* iOS 15.0b5+ */ + && strcmp(str, "%s:%d: %ss%d:%.0lld Updating mount to read/write mode is not allowed\n")) /* iOS 15.0b1-b4 */ { return false; } From 7d27b7ecc1dbe0f836f41b2e85fcae517437a95b Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 30 Oct 2023 02:38:00 +0800 Subject: [PATCH 33/77] kpf: use strstr for apfs_vfsop_mount --- checkra1n/kpf/main.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index cc47917f..29ce888c 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1070,11 +1070,9 @@ bool kpf_apfs_vfsop_mount(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { uint64_t page = ((uint64_t)adrp & ~0xfffULL) + adrp_off(adrp[0]); uint32_t off = (adrp[1] >> 10) & 0xfff; const char *str = (const char*)(page + off); - if ( - strcmp(str, "%s:%d: %s Updating mount to read/write mode is not allowed\n") /* iOS 15.0b5+ */ - && strcmp(str, "%s:%d: %ss%d:%.0lld Updating mount to read/write mode is not allowed\n")) /* iOS 15.0b1-b4 */ { - return false; - } + if (!strstr(str, "Updating mount to read/write mode is not allowed\n")) { + return false; + } opcode_stream[1] = 0x52800000; /* mov w0, 0 */ has_found_apfs_vfsop_mount = true; From efd954fb3b7ae3936abba13ecc2fe80649ec0684 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 18 Aug 2023 03:32:38 +0800 Subject: [PATCH 34/77] Revert "kpf: jbinit2 compatibility" This reverts commit ed9ab07f45d7c25308f1ce8555f3bab41c7fcf33. --- checkra1n/kpf/ramdisk.c | 54 +++----------------- include/paleinfo_legacy.h | 101 -------------------------------------- 2 files changed, 8 insertions(+), 147 deletions(-) delete mode 100644 include/paleinfo_legacy.h diff --git a/checkra1n/kpf/ramdisk.c b/checkra1n/kpf/ramdisk.c index 1bf9fd28..de4b7429 100644 --- a/checkra1n/kpf/ramdisk.c +++ b/checkra1n/kpf/ramdisk.c @@ -33,7 +33,6 @@ #include #include #include -#include static bool have_ramdisk = false; static char *rootdev_bootarg = NULL; @@ -168,8 +167,6 @@ static void kpf_ramdisk_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring #endif } -#define PINFO2PINFO1_MAP(name) { palerain_option_ ## name , palerain1_option_ ## name } - static void kpf_ramdisk_bootprep(struct mach_header_64 *hdr, palerain_option_t palera1n_flags) { if(rootdev_bootarg) @@ -188,51 +185,16 @@ static void kpf_ramdisk_bootprep(struct mach_header_64 *hdr, palerain_option_t p panic("Failed to reallocate ramdisk with paleinfo"); } - struct new_old_info_mapping pkinfo_mapping[] = { - { palerain_option_bind_mount, checkrain_option_bind_mount }, - { palerain_option_overlay, checkrain_option_overlay }, - { palerain_option_safemode, checkrain_option_safemode }, - { palerain_option_force_revert, checkrain_option_force_revert }, - { 0ULL, 0U } - }; - - struct new_old_info_mapping pinfo2pinfo1_mapping[] = { - PINFO2PINFO1_MAP(rootful), - PINFO2PINFO1_MAP(setup_rootful), - PINFO2PINFO1_MAP(rootless_livefs), - PINFO2PINFO1_MAP(setup_partial_root), - PINFO2PINFO1_MAP(jbinit_log_to_file), - PINFO2PINFO1_MAP(clean_fakefs), - { 0ULL, 0U } - }; - - uint32_t checkra1n_flags = 0; - for (uint8_t i = 0; pkinfo_mapping[i].old_info != 0U; i++) { - if (palera1n_flags & pkinfo_mapping[i].new_info) - checkra1n_flags |= pkinfo_mapping[i].old_info; - } - - uint32_t palera1n1_flags = 0; - for (uint8_t i = 0; pinfo2pinfo1_mapping[i].old_info != 0U; i++) { - if (palera1n_flags & pinfo2pinfo1_mapping[i].new_info) - palera1n1_flags |= pinfo2pinfo1_mapping[i].old_info; - } - - *(struct kerninfo*)(ramdisk_buf + ramdisk_size) = (struct kerninfo) + struct paleinfo* pinfo_p = (struct paleinfo*)(ramdisk_buf + ramdisk_size); + *pinfo_p = (struct paleinfo) { - .size = sizeof(struct kerninfo), - .base = slide + 0xfffffff007004000, - .slide = slide, - .flags = checkra1n_flags, - }; - - struct paleinfo1* pinfo1_p = (struct paleinfo1*)(ramdisk_buf + ramdisk_size+ 0x1000); - *pinfo1_p = (struct paleinfo1){ - .magic = PALEINFO_MAGIC, - .version = 1, - .flags = palera1n1_flags, + .magic = 'PLSH', + .version = 2, + .kbase = slide + 0xfffffff007004000, + .kslide = slide, + .flags = palera1n_flags, }; - snprintf(pinfo1_p->rootdev, 16, "%s", rootdev); + snprintf(pinfo_p->rootdev, 16, "%s", rootdev); *(uint32_t*)(ramdisk_buf) = ramdisk_size; ramdisk_size += 0x10000; diff --git a/include/paleinfo_legacy.h b/include/paleinfo_legacy.h deleted file mode 100644 index 996189ef..00000000 --- a/include/paleinfo_legacy.h +++ /dev/null @@ -1,101 +0,0 @@ -#ifndef PALEINFO_LEGACY_H -#define PALEINFO_LEGACY_H - -#include -#include -#include - -#define MAX_BOOTARGS_LEN 256 - -#define checkrain_option_none 0x00000000 -#define checkrain_option_all 0x7fffffff -#define checkrain_option_failure 0x80000000 - -// Host options -#define checkrain_option_verbose_logging (1 << 0) -#define checkrain_option_demote (1 << 1) -#define checkrain_option_early_exit (1 << 2) -#define checkrain_option_quick_mode (1 << 3) -#define checkrain_option_pongo_shell (1 << 4) -#define checkrain_option_pongo_full (1 << 5) - -// KPF options -#define checkrain_option_verbose_boot (1 << 0) - -// Global options -#define checkrain_option_safemode (1 << 0) -#define checkrain_option_bind_mount (1 << 1) -#define checkrain_option_overlay (1 << 2) -#define checkrain_option_force_revert (1 << 7) /* keep this at 7 */ - -// palera1n options -#define palerain1_option_rootful (1 << 0) /* rootful jailbreak */ -#define palerain1_option_jbinit_log_to_file (1 << 1) /* log to /cores/jbinit.log */ -#define palerain1_option_setup_rootful (1 << 2) /* create fakefs */ -//#define palerain1_option_setup_rootful_forced (1 << 3) /* create fakefs over an existing one */ -#define palerain1_option_setup_partial_root (1 << 4) /* fakefs creating should be partial */ -// #define palerain1_option_checkrain_is_clone (1 << 5) /* supplied checkra1n is checkra1n clone */ -#define palerain1_option_rootless_livefs (1 << 6) /* mount root livefs on rootless */ -/* reserved values */ -// #define palerain1_option_no_ssv (1 << 7) /* no signed system volume */ -// #define palerain1_option_force_fakefs (1 << 8) /* force fakefs, even without SSV */ -// #define palerain1_option_rootless (1 << 9) /* rootless jailbreak */ -#define palerain1_option_clean_fakefs (1 << 10) /* clean fakefs, but does not delete it */ - -#define PALEINFO_MAGIC 'PLSH' - -typedef uint32_t checkrain_option_t, *checkrain_option_p; - -typedef enum { - jailbreak_capability_tfp0 = 1 << 0, - jailbreak_capability_userspace_reboot = 1 << 1, - jailbreak_capability_dyld_ignore_os = 1 << 2, // TODO: This needs a better name -} jailbreak_capability_t, *jailbreak_capability_p; - -#define DEFAULT_CAPABILITIES (jailbreak_capability_tfp0|jailbreak_capability_userspace_reboot) -struct kerninfo { - uint64_t size; - uint64_t base; - uint64_t slide; - checkrain_option_t flags; -}; -struct paleinfo1 { - uint32_t magic; // 'PLSH' / 0x504c5348 - uint32_t version; // 1 - checkrain_option_t flags; - char rootdev[0x10]; -}; -struct kpfinfo { - struct kerninfo k; - checkrain_option_t kpf_flags; - char bootargs[MAX_BOOTARGS_LEN]; -}; - -struct new_old_info_mapping { - uint64_t new_info; - uint32_t old_info; -}; - -#define checkrain_set_option(options, option, enabled) do { \ - if (enabled) \ - options = (checkrain_option_t)(options | option); \ - else \ - options = (checkrain_option_t)(options & ~option); \ -} while (0); - -static inline bool checkrain_option_enabled(checkrain_option_t flags, checkrain_option_t opt) -{ - if(flags == checkrain_option_failure) - { - switch(opt) - { - case checkrain_option_safemode: - return true; - default: - return false; - } - } - return (flags & opt) != 0; -} - -#endif From 18e48e2e387b84138aa0fd39c347cbdecee9999d Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 18 Aug 2023 03:37:51 +0800 Subject: [PATCH 35/77] choose rootful or rootless based on ssv --- checkra1n/kpf/main.c | 21 +++++++++----- include/paleinfo.h | 69 +++++++++++++++++++++----------------------- 2 files changed, 47 insertions(+), 43 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 29ce888c..14548934 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1826,21 +1826,18 @@ static void kpf_cmd(const char *cmd, char *args) xnu_pf_patchset_t* apfs_patchset = xnu_pf_patchset_create(XNU_PF_ACCESS_32BIT); struct mach_header_64* apfs_header = xnu_pf_get_kext_header(hdr, "com.apple.filesystems.apfs"); xnu_pf_range_t* apfs_text_exec_range = xnu_pf_section(apfs_header, "__TEXT_EXEC", "__text"); - //xnu_pf_range_t* apfs_text_cstring_range = xnu_pf_section(apfs_header, "__TEXT", "__cstring"); + xnu_pf_range_t* apfs_text_cstring_range = xnu_pf_section(apfs_header, "__TEXT", "__cstring"); const char rootvp_string[] = "rootvp not authenticated after mounting"; const char *rootvp_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, rootvp_string, sizeof(rootvp_string) - 1); -#if 0 + const char livefs_string[] = "Rooting from the live fs of a sealed volume is not allowed on a RELEASE build"; const char *livefs_string_match = apfs_text_cstring_range ? memmem(apfs_text_cstring_range->cacheable_base, apfs_text_cstring_range->size, livefs_string, sizeof(livefs_string) - 1) : NULL; if(!livefs_string_match) livefs_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, livefs_string, sizeof(livefs_string) - 1); -#endif #ifdef DEV_BUILD -#if 0 // 15.0 beta 1 onwards, but only iOS/iPadOS if((livefs_string_match != NULL) != (gKernelVersion.darwinMajor >= 21 && xnu_platform() == PLATFORM_IOS)) panic("livefs panic doesn't match expected Darwin version"); -#endif #endif for(size_t i = 0; i < sizeof(kpf_components)/sizeof(kpf_components[0]); ++i) @@ -1911,12 +1908,22 @@ static void kpf_cmd(const char *cmd, char *args) } kpf_apfs_patches(apfs_patchset, rootvp_string_match == NULL); -#if 0 + if(livefs_string_match) { + palera1n_flags |= palerain_option_ssv; +#if 0 kpf_root_livefs_patch(apfs_patchset); - } #endif + } + if (!(palera1n_flags & palerain_option_rootful) && !(palera1n_flags & palerain_option_rootless)) { + if (livefs_string_match) { + palera1n_flags |= palerain_option_rootless; + } else { + palera1n_flags |= palerain_option_rootful; + } + } + xnu_pf_emit(apfs_patchset); xnu_pf_apply(apfs_text_exec_range, apfs_patchset); xnu_pf_patchset_destroy(apfs_patchset); diff --git a/include/paleinfo.h b/include/paleinfo.h index e8a77bd3..50af4b04 100644 --- a/include/paleinfo.h +++ b/include/paleinfo.h @@ -1,7 +1,7 @@ /* - * jbinit - https://github.com/palera1n/jbinit + * plooshInit - https://github.com/plooshi/plooshInit * - * This file is part of jbinit + * This file is part of plooshInit * * SPDX-License-Identifier: MIT */ @@ -15,40 +15,37 @@ typedef uint64_t palerain_option_t; // unified palera1n options -#define palerain_option_rootful (UINT64_C(1) << 0) /* rootful jailbreak */ -#define palerain_option_rootless (UINT64_C(1) << 1) /* rootless jailbreak */ -#define palerain_option_setup_rootful (UINT64_C(1) << 2) /* create fakefs */ -/* reserved */ -#define palerain_option_setup_partial_root (UINT64_C(1) << 4) /* fakefs creating should be partial */ -#define palerain_option_checkrain_is_clone (UINT64_C(1) << 5) /* supplied checkra1n is checkra1n clone */ -#define palerain_option_rootless_livefs (UINT64_C(1) << 6) /* mount root livefs on rootless */ -// #define palerain_option_no_ssv (UINT64_C(1) << 7) /* no signed system volume */ -// #define palerain_option_force_fakefs (UINT64_C(1) << 8) /* force fakefs, even without SSV */ -#define palerain_option_clean_fakefs (UINT64_C(1) << 9) /* clean fakefs, but does not delete it */ -#define palerain_option_tui (UINT64_C(1) << 10) /* terminal user interface */ -// #define palerain_option_gui (UINT64_C(1) << 11) /* graphical user interface*/ -#define palerain_option_dfuhelper_only (UINT64_C(1) << 12) /* dfuhelper only */ -#define palerain_option_pongo_exit (UINT64_C(1) << 13) /* boot to clean pongo shell */ -#define palerain_option_demote (UINT64_C(1) << 14) /* Demote effective production fuse status */ -#define palerain_option_pongo_full (UINT64_C(1) << 15) /* Boot to pongo with default images and options */ -#define palerain_option_palerain_version (UINT64_C(1) << 16) /* Print version */ -#define palerain_option_exit_recovery (UINT64_C(1) << 17) /* Exit recovery mode */ -#define palerain_option_reboot_device (UINT64_C(1) << 18) /* Reboot device in normal mode */ -#define palerain_option_enter_recovery (UINT64_C(1) << 19) /* Enter recovery mode */ -#define palerain_option_device_info (UINT64_C(1) << 20) /* Print device info */ -#define palerain_option_no_colors (UINT64_C(1) << 21) /* no colors */ -#define palerain_option_bind_mount (UINT64_C(1) << 22) /* bind mounts should be used (always true iOS 15+)*/ -#define palerain_option_overlay (UINT64_C(1) << 23) /* there is an overlay (should always be true) */ -#define palerain_option_force_revert (UINT64_C(1) << 24) /* Unjailbreak */ -#define palerain_option_safemode (UINT64_C(1) << 25) /* Enter safe mode */ -#define palerain_option_verbose_boot (UINT64_C(1) << 26) /* verbose boot */ - -#define palerain_option_jbinit_log_to_file (UINT64_C(1) << 50) /* make ramdisk log to file (jbinit2) */ -#define palerain_option_setup_rootful_forced (UINT64_C(1) << 51) /* create fakefs over an existing one (jbinit2) */ - -#define palerain_option_flower_chain (UINT64_C(1) << 61) /* Flower chain */ -#define palerain_option_test1 (UINT64_C(1) << 62) /* Developer test option 1 */ -#define palerain_option_test2 (UINT64_C(1) << 63) /* Developer test option 2 */ +#define palerain_option_rootful (1ULL << 0) /* rootful jailbreak */ +#define palerain_option_rootless (1ULL << 1) /* rootless jailbreak */ +#define palerain_option_setup_rootful (1ULL << 2) /* create fakefs */ +// (1ULL << 3) /* Deprecated and removed */ +#define palerain_option_setup_partial_root (1ULL << 4) /* fakefs creating should be partial */ +#define palerain_option_checkrain_is_clone (1ULL << 5) /* supplied checkra1n is checkra1n clone */ +#define palerain_option_rootless_livefs (1ULL << 6) /* mount root livefs on rootless */ +#define palerain_option_ssv (1ULL << 7) /* has signed system volume */ +// (1ULL << 8) /* reserved */ +#define palerain_option_clean_fakefs (1ULL << 9) /* clean fakefs, but does not delete it */ +#define palerain_option_tui (1ULL << 10) /* terminal user interface */ +// #define palerain_option_gui (1ULL << 11) /* graphical user interface*/ +#define palerain_option_dfuhelper_only (1ULL << 12) /* dfuhelper only */ +#define palerain_option_pongo_exit (1ULL << 13) /* boot to clean pongo shell */ +#define palerain_option_demote (1ULL << 14) /* Demote effective production fuse status */ +#define palerain_option_pongo_full (1ULL << 15) /* Boot to pongo with default images and options */ +#define palerain_option_palerain_version (1ULL << 16) /* Print version */ +#define palerain_option_exit_recovery (1ULL << 17) /* Exit recovery mode */ +#define palerain_option_reboot_device (1ULL << 18) /* Reboot device in normal mode */ +#define palerain_option_enter_recovery (1ULL << 19) /* Enter recovery mode */ +#define palerain_option_device_info (1ULL << 20) /* Print device info */ +#define palerain_option_no_colors (1ULL << 21) /* no colors */ +#define palerain_option_bind_mount (1ULL << 22) /* bind mounts should be used (always true iOS 15+)*/ +#define palerain_option_overlay (1ULL << 23) /* there is an overlay (should always be true) */ +#define palerain_option_force_revert (1ULL << 24) /* Unjailbreak */ +#define palerain_option_safemode (1ULL << 25) /* Enter safe mode */ +#define palerain_option_verbose_boot (1ULL << 26) /* verbose boot */ + +#define palerain_option_flower_chain (1ULL << 61) /* Flower chain */ +#define palerain_option_test1 (1ULL << 62) /* Developer test option 1 */ +#define palerain_option_test2 (1ULL << 63) /* Developer test option 2 */ #define PALEINFO_MAGIC 'PLSH' From b8e3bb832d38381b8d3d840e3aa2cc6a2d80eac5 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 18 Aug 2023 03:58:55 +0800 Subject: [PATCH 36/77] use UINT64_C --- include/paleinfo.h | 62 +++++++++++++++++++++++----------------------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/include/paleinfo.h b/include/paleinfo.h index 50af4b04..2e17ae90 100644 --- a/include/paleinfo.h +++ b/include/paleinfo.h @@ -15,37 +15,37 @@ typedef uint64_t palerain_option_t; // unified palera1n options -#define palerain_option_rootful (1ULL << 0) /* rootful jailbreak */ -#define palerain_option_rootless (1ULL << 1) /* rootless jailbreak */ -#define palerain_option_setup_rootful (1ULL << 2) /* create fakefs */ -// (1ULL << 3) /* Deprecated and removed */ -#define palerain_option_setup_partial_root (1ULL << 4) /* fakefs creating should be partial */ -#define palerain_option_checkrain_is_clone (1ULL << 5) /* supplied checkra1n is checkra1n clone */ -#define palerain_option_rootless_livefs (1ULL << 6) /* mount root livefs on rootless */ -#define palerain_option_ssv (1ULL << 7) /* has signed system volume */ -// (1ULL << 8) /* reserved */ -#define palerain_option_clean_fakefs (1ULL << 9) /* clean fakefs, but does not delete it */ -#define palerain_option_tui (1ULL << 10) /* terminal user interface */ -// #define palerain_option_gui (1ULL << 11) /* graphical user interface*/ -#define palerain_option_dfuhelper_only (1ULL << 12) /* dfuhelper only */ -#define palerain_option_pongo_exit (1ULL << 13) /* boot to clean pongo shell */ -#define palerain_option_demote (1ULL << 14) /* Demote effective production fuse status */ -#define palerain_option_pongo_full (1ULL << 15) /* Boot to pongo with default images and options */ -#define palerain_option_palerain_version (1ULL << 16) /* Print version */ -#define palerain_option_exit_recovery (1ULL << 17) /* Exit recovery mode */ -#define palerain_option_reboot_device (1ULL << 18) /* Reboot device in normal mode */ -#define palerain_option_enter_recovery (1ULL << 19) /* Enter recovery mode */ -#define palerain_option_device_info (1ULL << 20) /* Print device info */ -#define palerain_option_no_colors (1ULL << 21) /* no colors */ -#define palerain_option_bind_mount (1ULL << 22) /* bind mounts should be used (always true iOS 15+)*/ -#define palerain_option_overlay (1ULL << 23) /* there is an overlay (should always be true) */ -#define palerain_option_force_revert (1ULL << 24) /* Unjailbreak */ -#define palerain_option_safemode (1ULL << 25) /* Enter safe mode */ -#define palerain_option_verbose_boot (1ULL << 26) /* verbose boot */ - -#define palerain_option_flower_chain (1ULL << 61) /* Flower chain */ -#define palerain_option_test1 (1ULL << 62) /* Developer test option 1 */ -#define palerain_option_test2 (1ULL << 63) /* Developer test option 2 */ +#define palerain_option_rootful (UINT64_C(1) << 0) /* rootful jailbreak */ +#define palerain_option_rootless (UINT64_C(1) << 1) /* rootless jailbreak */ +#define palerain_option_setup_rootful (UINT64_C(1) << 2) /* create fakefs */ +// (UINT64_C(1) << 3) /* Deprecated and removed */ +#define palerain_option_setup_partial_root (UINT64_C(1) << 4) /* fakefs creating should be partial */ +#define palerain_option_checkrain_is_clone (UINT64_C(1) << 5) /* supplied checkra1n is checkra1n clone */ +#define palerain_option_rootless_livefs (UINT64_C(1) << 6) /* mount root livefs on rootless */ +#define palerain_option_ssv (UINT64_C(1) << 7) /* has signed system volume */ +// (UINT64_C(1) << 8) /* reserved */ +#define palerain_option_clean_fakefs (UINT64_C(1) << 9) /* clean fakefs, but does not delete it */ +#define palerain_option_tui (UINT64_C(1) << 10) /* terminal user interface */ +// #define palerain_option_gui (UINT64_C(1) << 11) /* graphical user interface*/ +#define palerain_option_dfuhelper_only (UINT64_C(1) << 12) /* dfuhelper only */ +#define palerain_option_pongo_exit (UINT64_C(1) << 13) /* boot to clean pongo shell */ +#define palerain_option_demote (UINT64_C(1) << 14) /* Demote effective production fuse status */ +#define palerain_option_pongo_full (UINT64_C(1) << 15) /* Boot to pongo with default images and options */ +#define palerain_option_palerain_version (UINT64_C(1) << 16) /* Print version */ +#define palerain_option_exit_recovery (UINT64_C(1) << 17) /* Exit recovery mode */ +#define palerain_option_reboot_device (UINT64_C(1) << 18) /* Reboot device in normal mode */ +#define palerain_option_enter_recovery (UINT64_C(1) << 19) /* Enter recovery mode */ +#define palerain_option_device_info (UINT64_C(1) << 20) /* Print device info */ +#define palerain_option_no_colors (UINT64_C(1) << 21) /* no colors */ +#define palerain_option_bind_mount (UINT64_C(1) << 22) /* bind mounts should be used (always true iOS 15+)*/ +#define palerain_option_overlay (UINT64_C(1) << 23) /* there is an overlay (should always be true) */ +#define palerain_option_force_revert (UINT64_C(1) << 24) /* Unjailbreak */ +#define palerain_option_safemode (UINT64_C(1) << 25) /* Enter safe mode */ +#define palerain_option_verbose_boot (UINT64_C(1) << 26) /* verbose boot */ + +#define palerain_option_flower_chain (UINT64_C(1) << 61) /* Flower chain */ +#define palerain_option_test1 (UINT64_C(1) << 62) /* Developer test option 1 */ +#define palerain_option_test2 (UINT64_C(1) << 63) /* Developer test option 2 */ #define PALEINFO_MAGIC 'PLSH' From d66964d54953140997a31cb1d0ca44a56ed9977d Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 30 Oct 2023 16:17:35 +0800 Subject: [PATCH 37/77] support LZMA compressed ramdisk --- include/paleinfo.h | 8 ++++++-- src/shell/main.c | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 40 insertions(+), 8 deletions(-) diff --git a/include/paleinfo.h b/include/paleinfo.h index 2e17ae90..6414c9c0 100644 --- a/include/paleinfo.h +++ b/include/paleinfo.h @@ -1,7 +1,7 @@ /* - * plooshInit - https://github.com/plooshi/plooshInit + * jbinit - https://github.com/palera1n/jbinit * - * This file is part of plooshInit + * This file is part of jbinit * * SPDX-License-Identifier: MIT */ @@ -42,6 +42,9 @@ typedef uint64_t palerain_option_t; #define palerain_option_force_revert (UINT64_C(1) << 24) /* Unjailbreak */ #define palerain_option_safemode (UINT64_C(1) << 25) /* Enter safe mode */ #define palerain_option_verbose_boot (UINT64_C(1) << 26) /* verbose boot */ +// #define palerain_option_sf_ssh (UINT64_C(1) << 27) /* safe mode with bootstrap ssh */ +// #define palerain_option_sf_launchdaemons (UINT64_C(1) << 28) /* safe mode with launchdaemons */ +// #define palerain_option_emerg_mode (UINT64_C(1) << 28) /* emergency mode (early boot usb shell) */ #define palerain_option_flower_chain (UINT64_C(1) << 61) /* Flower chain */ #define palerain_option_test1 (UINT64_C(1) << 62) /* Developer test option 1 */ @@ -57,6 +60,7 @@ struct paleinfo { uint64_t kslide; /* kernel slide */ uint64_t flags; /* unified palera1n flags */ char rootdev[0x10]; /* ex. disk0s1s8 */ + /* int8_t loglevel; */ }__attribute__((packed)); #endif diff --git a/src/shell/main.c b/src/shell/main.c index 326c43ce..f0be91e3 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -25,6 +25,15 @@ * */ #include +#include + +int _isatty(int a) { + return 0; +} + +int __chkstk_darwin() { + return 0; +} extern volatile char gBootFlag; @@ -56,16 +65,35 @@ uint32_t ramdisk_size; */ -void ramdisk_cmd() { +void ramdisk_cmd(const char* cmd, char* args) { if (!loader_xfer_recv_count) { iprintf("please upload a ramdisk before issuing this command\n"); return; } - if (ramdisk_buf) free(ramdisk_buf); - ramdisk_buf = malloc(loader_xfer_recv_count); - if (!ramdisk_buf) panic("couldn't reserve heap for ramdisk"); - ramdisk_size = loader_xfer_recv_count; - memcpy(ramdisk_buf, loader_xfer_recv_data, ramdisk_size); + if (args[0] != '\0') { + size_t tmp_ramdisk_size; + if ((tmp_ramdisk_size = (int)strtoul(args, NULL, 0)) != 0) { + printf("args: %s, tmp_ramdisk_size: %u\n", args, tmp_ramdisk_size); + if (ramdisk_buf) free(ramdisk_buf); + ramdisk_buf = malloc(tmp_ramdisk_size); + if (!ramdisk_buf) panic("couldn't reserve heap for ramdisk"); + int lzma_result = unlzma_decompress(ramdisk_buf, &tmp_ramdisk_size, loader_xfer_recv_data, loader_xfer_recv_count); + if (lzma_result != SZ_OK) { + printf("ramdisk decompression failed\n"); + return; + } + ramdisk_size = (uint32_t)tmp_ramdisk_size; + } else { + printf("ramdisk usage: ramdisk [uncompressed size if compressed]\n"); + return; + } + } else { + if (ramdisk_buf) free(ramdisk_buf); + ramdisk_buf = malloc(loader_xfer_recv_count); + if (!ramdisk_buf) panic("couldn't reserve heap for ramdisk"); + ramdisk_size = loader_xfer_recv_count; + memcpy(ramdisk_buf, loader_xfer_recv_data, ramdisk_size); + } loader_xfer_recv_count = 0; } From 983748a1eb04aa78d831c4ead183c348151ef194 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 30 Oct 2023 17:35:37 +0800 Subject: [PATCH 38/77] support LZMA compressed ramdisk --- src/shell/main.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/shell/main.c b/src/shell/main.c index f0be91e3..0f7cba1f 100644 --- a/src/shell/main.c +++ b/src/shell/main.c @@ -27,14 +27,6 @@ #include #include -int _isatty(int a) { - return 0; -} - -int __chkstk_darwin() { - return 0; -} - extern volatile char gBootFlag; From b8fb5fe3fe05320e71d4fa96266dae693fd0ca3b Mon Sep 17 00:00:00 2001 From: kok3shidoll <69592455+kok3shidoll@users.noreply.github.com> Date: Wed, 1 Nov 2023 04:12:09 +0900 Subject: [PATCH 39/77] md0 on /cores --- checkra1n/kpf/main.c | 199 ++++++++++++++++++++++++++++++++++++++ checkra1n/kpf/shellcode.S | 137 +++++++++++++++++++++++++- 2 files changed, 334 insertions(+), 2 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 14548934..17c429e3 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -165,7 +165,9 @@ static void kpf_kernel_version_init(xnu_pf_range_t *text_const_range) // Imports from shellcode.S extern uint32_t sandbox_shellcode[], sandbox_shellcode_setuid_patch[], sandbox_shellcode_ptrs[], sandbox_shellcode_end[]; +extern uint32_t launchd_execve_hook[], launchd_execve_hook_ptr[], launchd_execve_hook_offset[]; +uint32_t* _mac_mount = NULL; bool kpf_has_done_mac_mount = false; bool kpf_mac_mount_callback(struct xnu_pf_patch* patch, uint32_t* opcode_stream) { puts("KPF: Found mac_mount"); @@ -195,6 +197,22 @@ bool kpf_mac_mount_callback(struct xnu_pf_patch* patch, uint32_t* opcode_stream) // replace with a mov x8, xzr // this will bypass the (vp->v_mount->mnt_flag & MNT_ROOTFS) check mac_mount_1[0] = 0xaa1f03e8; + + // Most reliable marker of a stack frame seems to be "add x29, sp, 0x...". + // And this function is HUGE, hence up to 2k insn. + uint32_t *frame = find_prev_insn(mac_mount_1, 2000, 0x910003fd, 0xff8003ff); + if(!frame) return false; + + // Now find the insn that decrements sp. This can be either + // "stp ..., ..., [sp, -0x...]!" or "sub sp, sp, 0x...". + // Match top bit of imm on purpose, since we only want negative offsets. + uint32_t *start = find_prev_insn(frame, 10, 0xa9a003e0, 0xffe003e0); + if(!start) start = find_prev_insn(frame, 10, 0xd10003ff, 0xff8003ff); + if(!start) return false; + + _mac_mount = start; + puts("KPF: Found mac_mount top"); + kpf_has_done_mac_mount = true; xnu_pf_disable_patch(patch); puts("KPF: Found mac_mount"); @@ -1674,6 +1692,155 @@ void kpf_root_livefs_patch(xnu_pf_patchset_t* patchset) { } #endif +uint32_t* mdevremoveall = NULL; +uint32_t* mac_execve = NULL; +uint32_t* mac_execve_hook = NULL; +uint32_t* copyout = NULL; +uint32_t* mach_vm_allocate_kernel = NULL; +uint32_t current_map_off = -1; +uint32_t vm_map_page_size_off = -1; + +bool IOSecureBSDRoot_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) +{ + // Prevent ramdisk from being cleaned even when booted without rootdev="md0" + if(mdevremoveall) + { + DEVLOG("IOSecureBSDRoot_callback: already ran, skipping..."); + return false; + } + puts("KPF: Found mdevremoveall"); + DEVLOG("Found mdevremoveall 0x%llx", xnu_rebase_va(xnu_ptr_to_va(opcode_stream)) + 4*4); + + uint32_t insn = opcode_stream[4]; + int32_t off = sxt32(insn >> 5, 19); + opcode_stream[4] = 0x14000000 | (uint32_t)off; + mdevremoveall = opcode_stream; + return true; +} + +bool load_init_program_at_path_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) +{ + puts("KPF: Found load_init_program_at_path"); + opcode_stream += 4; + mac_execve = follow_call(opcode_stream); + mac_execve_hook = opcode_stream; + puts("KPF: Found mac_execve"); + + uint32_t* prebl = find_prev_insn(opcode_stream, 0x80, 0x52800302, 0xffffffff); + uint32_t* bl = find_next_insn(prebl, 10, 0x94000000, 0xfc000000); // bl + + copyout = follow_call(bl); + puts("KPF: Found copyout"); + + // Most reliable marker of a stack frame seems to be "add x29, sp, 0x...". + // And this function is HUGE, hence up to 2k insn. + uint32_t *frame = find_prev_insn(opcode_stream, 2000, 0x910003fd, 0xff8003ff); + if(!frame) return false; + + // Now find the insn that decrements sp. This can be either + // "stp ..., ..., [sp, -0x...]!" or "sub sp, sp, 0x...". + // Match top bit of imm on purpose, since we only want negative offsets. + uint32_t *start = find_prev_insn(frame, 10, 0xa9a003e0, 0xffe003e0); + if(!start) start = find_prev_insn(frame, 10, 0xd10003ff, 0xff8003ff); + if(!start) return false; + + + /* xxx */ + uint32_t *tpidr_el1 = find_next_insn(start, 0x20, 0xd538d080, 0xffffff80); // search mrs xN, tpidr_el1 + if(!tpidr_el1) return false; + uint32_t reg = tpidr_el1[0] & 0x1f; + + uint32_t *ldr = find_next_insn(tpidr_el1, 10, 0xf9400000 | (reg << 5), 0xffc000e0 | (reg << 5)); // search ldr xM, [xN, #xxx] + if(!ldr) return false; + current_map_off = ((ldr[0] >> 10) & 0xfff) << 3; + printf("KPF: Found current_map_offset at 0x%x\n", current_map_off); + + reg = ldr[0] & 0x1f; + + uint32_t *ldrh = find_next_insn(ldr, 10, 0x79400000 | (reg << 5), 0xffc000e0 | (reg << 5)); + if(ldrh) + { + // 1st: search ldrh + vm_map_page_size_off = ((ldrh[0] >> 11) & 0x7FF) << 2; + printf("KPF: Found vm_map_page_size offset at 0x%x\n", vm_map_page_size_off); + } + else + { + // 2nd: xnu-8019: search add + uint32_t *add = find_next_insn(ldr, 10, 0x91000000 | (reg << 5), 0xffc000e0 | (reg << 5)); + if(!add) return false; + vm_map_page_size_off = (add[0] >> 10) & 0xfff; + printf("KPF: Found vm_map_page_size offset at 0x%x\n", vm_map_page_size_off); + } + + bl = NULL; + for(int i = 0; i < 0x80; i++) + { + if(start[i] == 0x52800023 && + start[i + 1] == 0x52800004) + { + bl = find_next_insn(start + i, 10, 0x94000000, 0xfc000000); // bl + if(bl) break; + } + } + if(!bl) return false; + + mach_vm_allocate_kernel = follow_call(bl); + puts("KPF: Found mach_vm_allocate_kernel"); + + + return true; +} + +void kpf_md0oncores_patch(xnu_pf_patchset_t* patchset) +{ + uint64_t matches[] = + { + 0xd63f0100, // blr x8 + 0x52805828, // mov w8, #0x2c1 + 0x72bc0008, // movk w8, #0xe000, lsl #16 + 0x6b08001f, // cmp wN, w8 + 0x54000001, // b.ne 0x... + }; + uint64_t masks[] = + { + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xfffffc1f, + 0xff00001f, + }; + xnu_pf_maskmatch(patchset, "IOSecureBSDRoot", matches, masks, sizeof(masks)/sizeof(uint64_t), true, (void*)IOSecureBSDRoot_callback); + + /* i7 15.7.6 + * fffffff0075cd178 stp x21, x23, [sp, #0x38] + * fffffff0075cd17c stp xzr, xzr, [sp, #0x48] + * fffffff0075cd180 add x1, sp, #0x38 + * fffffff0075cd184 mov x0, x19 + * fffffff0075cd188 bl __mac_execve + * fffffff0075cd18c cbnz w0, loc_fffffff0075cd1c4 + */ + uint64_t i_matches[] = + { + 0xa903dff5, // stp x21, x23, [sp, #0x38] + 0xa904ffff, // stp xzr, xzr, [sp, #0x48] + 0x9100e3e1, // add x1, sp, #0x38 + 0xaa1303e0, // mov x0, x19 + 0x94000000, // bl __mac_execve + 0x35000000, // cbnz wN, ... + }; + uint64_t i_masks[] = + { + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xfc000000, + 0xff000000, + }; + xnu_pf_maskmatch(patchset, "load_init_program_at_path", i_matches, i_masks, sizeof(i_masks)/sizeof(uint64_t), true, (void*)load_init_program_at_path_callback); +} + static uint32_t shellcode_count; static uint32_t *shellcode_area; @@ -1999,6 +2166,7 @@ static void kpf_cmd(const char *cmd, char *args) kpf_find_shellcode_funcs(xnu_text_exec_patchset); if(rootvp_string_match) // Union mounts no longer work { + kpf_md0oncores_patch(xnu_text_exec_patchset); kpf_vnop_rootvp_auth_patch(xnu_text_exec_patchset); } @@ -2116,6 +2284,37 @@ static void kpf_cmd(const char *cmd, char *args) uint32_t* repatch_vnode_shellcode = &shellcode_area[4]; *repatch_vnode_shellcode = repatch_ldr_x19_vnode_pathoff; + if(rootvp_string_match) + { + if (!mdevremoveall) panic("no mdevremoveall"); + if (!mac_execve) panic("no mac_execve"); + if (!mac_execve_hook) panic("no mac_execve_hook"); + if (!copyout) panic("no copyout"); + if (!mach_vm_allocate_kernel) panic("no mach_vm_allocate_kernel"); + if (current_map_off == -1 || vm_map_page_size_off == -1) panic("no offsets"); + + uint64_t* repatch_launchd_execve_hook_ptrs = (uint64_t*)(launchd_execve_hook_ptr - shellcode_from + shellcode_to); + uint32_t* repatch_launchd_execve_hook = (uint32_t*)(launchd_execve_hook - shellcode_from + shellcode_to); + uint32_t* repatch_launchd_execve_hook_offset = (uint32_t*)(launchd_execve_hook_offset - shellcode_from + shellcode_to); + + if (repatch_launchd_execve_hook_ptrs[0] != 0x4141414141414141) { + panic("Shellcode corruption"); + } + + repatch_launchd_execve_hook_ptrs[0] = xnu_ptr_to_va(mac_execve); + repatch_launchd_execve_hook_ptrs[1] = xnu_ptr_to_va(_mac_mount); + repatch_launchd_execve_hook_ptrs[2] = xnu_ptr_to_va(mach_vm_allocate_kernel); + repatch_launchd_execve_hook_ptrs[3] = xnu_ptr_to_va(copyout); + + repatch_launchd_execve_hook_offset[0] |= ((current_map_off >> 3) & 0xfff) << 10; + repatch_launchd_execve_hook_offset[2] |= ((vm_map_page_size_off >> 2) & 0x7ff) << 11; + + uint32_t delta = (&repatch_launchd_execve_hook[0]) - mac_execve_hook; + delta &= 0x03ffffff; + delta |= 0x94000000; + *mac_execve_hook = delta; + } + if(!rootvp_string_match) // Only use underlying fs on union mounts { char *snapshotString = (char*)memmem((unsigned char *)text_cstring_range->cacheable_base, text_cstring_range->size, (uint8_t *)"com.apple.os.update-", strlen("com.apple.os.update-")); diff --git a/checkra1n/kpf/shellcode.S b/checkra1n/kpf/shellcode.S index 66174afb..e11b337b 100644 --- a/checkra1n/kpf/shellcode.S +++ b/checkra1n/kpf/shellcode.S @@ -217,13 +217,146 @@ vnode_check_open_shc$orig: ldr x8, vnode_check_open_orig br x8 +.align 3 _vnode_check_open_shc_ptr: proc_selfname: .quad 0x5151515151515151 - vnode_check_open_orig: .quad 0x5252525252525252 +.align 2 +.globl _launchd_execve_hook +.globl _launchd_execve_hook_ptr +.globl _launchd_execve_hook_end +.globl _launchd_execve_hook_offset +_launchd_execve_hook: +b launchd_execve_hook$start + +launchd_execve_hook$start: +sub sp, sp, #0xa0 +stp x26, x25, [sp, #0x50] +stp x24, x23, [sp, #0x60] +stp x22, x21, [sp, #0x70] +stp x20, x19, [sp, #0x80] +stp x29, x30, [sp, #0x90] +add x29, sp, #0x90 +mov x19, x2 +mov x20, x1 +mov x21, x0 +stur wzr, [x29, #-0x44] +str xzr, [sp, #0x40] + +mrs x8, tpidr_el1 +_launchd_execve_hook_offset: +ldr x0, [x8, #0x0] // Gets replaced with real offset by kpf +cbz x0, launchd_execve_hook$current_map$zero +launchd_execve_hook$current_map$notzero: +ldrh w8, [x0, #0x0] // Gets replaced with real offset by kpf +b launchd_execve_hook$get_map_page_size +launchd_execve_hook$current_map$zero: +mov w8, #0xe // 16k page +launchd_execve_hook$get_map_page_size: +mov w1, #0x1 +lsl w2, w1, w8 // map_page_size + +add x1, sp, #0x40 // &scratch_addr +mov w3, #0x1 // VM_FLAGS_ANYWHERE +mov x4, #0x0 // VM_KERN_MEMORY_NONE +ldr x8, mach_vm_allocate_kernel +blr x8 + +ldr x22, [sp, #0x40] +adr x0, fstype // 'hfs' +mov x1, x22 // scratch_addr +mov w2, #0x4 // len +ldr x8, copyout +blr x8 +cbnz w0, launchd_execve_hook$panik_1 + +ldr x8, [sp, #0x40] +add x23, x8, #0x8 // align +str x23, [sp, #0x40] +adr x0, mountpoint // '/cores' +mov x1, x23 // scratch_addr +mov w2, #0x7 // len +ldr x8, copyout +blr x8 +cbnz w0, launchd_execve_hook$panik_1 + +ldr x8, [sp, #0x40] +add x24, x8, #0x8 // align +str x24, [sp, #0x40] +adr x0, devfs_path // '/dev/md0' +mov x1, x24 // scratch_addr +mov w2, #0x9 // len +ldr x8, copyout +blr x8 +cbnz w0, launchd_execve_hook$panik_1 + +ldr x8, [sp, #0x40] +add x1, x8, #0x10 // align +str x1, [sp, #0x40] // scratch_addr +stp x24, xzr, [sp, #0x8] +add x0, sp, #0x8 // argv64bit +mov w2, #0x8 // sizeof(uint64_t) +ldr x8, copyout +blr x8 +cbnz w0, launchd_execve_hook$panik_1 + +stp x22, x23, [sp, #0x18] +ldr x8, [sp, #0x40] +stp xzr, x8, [sp, #0x28] +str xzr, [sp, #0x38] +mov x0, x21 // proc +add x1, sp, #0x18 // &muap +sub x2, x29, #0x44 // retval +ldr x8, mac_mount // call mac_mount +blr x8 +cbnz w0, launchd_execve_hook$panik_2 + +launchd_execve_hook$orig: +mov x0, x21 +mov x1, x20 +mov x2, x19 +ldr x8, mac_execve +blr x8 +launchd_execve_hook$ret: +ldp x29, x30, [sp, #0x90] +ldp x20, x19, [sp, #0x80] +ldp x22, x21, [sp, #0x70] +ldp x24, x23, [sp, #0x60] +ldp x26, x25, [sp, #0x50] +add sp, sp, #0xa0 +ret + +launchd_execve_hook$panik_1: +b launchd_execve_hook$orig // copyout failed +launchd_execve_hook$panik_2: +b launchd_execve_hook$orig // mac_mount failed + +.align 3 +_launchd_execve_hook_ptr: +mac_execve: +.quad 0x4141414141414141 +mac_mount: +.quad 0x4242424242424242 +mach_vm_allocate_kernel: +.quad 0x4343434343434343 +copyout: +.quad 0x4444444444444444 + +.align 2 +devfs_path: +.asciz "/dev/md0" +.align 2 +fstype: +.asciz "hfs" +.align 2 +mountpoint: +.asciz "/cores" + +.align 2 +_launchd_execve_hook_end: _sandbox_shellcode_end: @@ -270,7 +403,7 @@ L_dyld_shc_epilog: ldp x29, x30, [sp], 0x20 ret L_alt_dyld_path: - .asciz "/cores/dyld" + .asciz "/cores/usr/lib/dyld" L_dyld_path: .asciz "/usr/lib/dyld" .align 2 From 161504e8ec22841ba422ad5046b493dbccb18628 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Wed, 1 Nov 2023 03:36:21 +0800 Subject: [PATCH 40/77] kpf-test: sed _launchd_execve_hook on linux --- checkra1n/kpf-test/Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/checkra1n/kpf-test/Makefile b/checkra1n/kpf-test/Makefile index 8e73f0b1..c3728897 100644 --- a/checkra1n/kpf-test/Makefile +++ b/checkra1n/kpf-test/Makefile @@ -48,7 +48,8 @@ kpf-test.macos: Makefile $(KPF_C) $(KPF_H) shellcode_S_linux.S: $(RA1N)/shellcode.S Makefile sed -e 's/_pf_jit/pf_jit/g' -e 's/_dyld_shc/dyld_shc/g' -e 's/_sandbox/sandbox/g' \ - -e 's/_fsctl_shc/fsctl_shc/g' -e 's/_kdi_shc/kdi_shc/g' -e 's/_nvram_shc/nvram_shc/g' $< > $@ + -e 's/_fsctl_shc/fsctl_shc/g' -e 's/_kdi_shc/kdi_shc/g' -e 's/_nvram_shc/nvram_shc/g' \ + -e 's/_launchd_execve_hook/launchd_execve_hook/g' $< > $@ xnu_S_linux.S: $(SRC)/drivers/xnu/xnu.S Makefile sed -e 's/_pf_jit/pf_jit/g' $< > $@ From d344c9eb48c07473b7a73a332417e533fb51b2d5 Mon Sep 17 00:00:00 2001 From: kok3shidoll <69592455+kok3shidoll@users.noreply.github.com> Date: Wed, 1 Nov 2023 05:01:17 +0900 Subject: [PATCH 41/77] just for xnu-7938 --- checkra1n/kpf/main.c | 33 ++++++++++++++++++++++++++++++--- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 17c429e3..d06dd3c9 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1721,13 +1721,16 @@ bool IOSecureBSDRoot_callback(struct xnu_pf_patch *patch, uint32_t *opcode_strea bool load_init_program_at_path_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { puts("KPF: Found load_init_program_at_path"); - opcode_stream += 4; + uint32_t* bl = find_next_insn(opcode_stream, 8, 0x94000000, 0xfc000000); + if(!bl) return false; + opcode_stream = bl; + mac_execve = follow_call(opcode_stream); mac_execve_hook = opcode_stream; puts("KPF: Found mac_execve"); uint32_t* prebl = find_prev_insn(opcode_stream, 0x80, 0x52800302, 0xffffffff); - uint32_t* bl = find_next_insn(prebl, 10, 0x94000000, 0xfc000000); // bl + bl = find_next_insn(prebl, 10, 0x94000000, 0xfc000000); // bl copyout = follow_call(bl); puts("KPF: Found copyout"); @@ -1838,7 +1841,31 @@ void kpf_md0oncores_patch(xnu_pf_patchset_t* patchset) 0xfc000000, 0xff000000, }; - xnu_pf_maskmatch(patchset, "load_init_program_at_path", i_matches, i_masks, sizeof(i_masks)/sizeof(uint64_t), true, (void*)load_init_program_at_path_callback); + xnu_pf_maskmatch(patchset, "load_init_program_at_path", i_matches, i_masks, sizeof(i_masks)/sizeof(uint64_t), false, (void*)load_init_program_at_path_callback); + + // just for xnu-7938 + uint64_t ii_matches[] = + { + 0xa904dff5, // stp x21, x23, [sp, #0x48] + 0xa905ffff, // stp xzr, xzr, [sp, #0x58] + 0x910123e1, // add x1, sp, #0x48 + 0x910103e2, // add x2, sp, #0x40 + 0xaa1303e0, // mov x0, x19 + 0x94000000, // bl __mac_execve + 0x35000000, // cbnz wN, ... + }; + uint64_t ii_masks[] = + { + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xfc000000, + 0xff000000, + }; + xnu_pf_maskmatch(patchset, "load_init_program_at_path", ii_matches, ii_masks, sizeof(ii_masks)/sizeof(uint64_t), false, (void*)load_init_program_at_path_callback); + } static uint32_t shellcode_count; From 98e3908353e39f101b90deb27386ea5f2d9171fb Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Wed, 1 Nov 2023 19:05:55 +0800 Subject: [PATCH 42/77] kpf: plooshInit support --- checkra1n/kpf/main.c | 6 +++++- checkra1n/kpf/ramdisk.c | 3 ++- checkra1n/kpf/shellcode.S | 2 +- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index d06dd3c9..47c70979 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -37,7 +37,7 @@ #include uint32_t offsetof_p_flags; -palerain_option_t palera1n_flags; +palerain_option_t palera1n_flags = 0; #if __STDC_HOSTED__ extern bool test_force_rootful; @@ -2352,6 +2352,10 @@ static void kpf_cmd(const char *cmd, char *args) puts("KPF: Disabled snapshot temporarily"); } + char *launchdString = (char*)memmem((unsigned char *)text_cstring_range->cacheable_base, text_cstring_range->size, (uint8_t *)"/sbin/launchd", sizeof("/sbin/launchd")); + if (!launchdString) panic("no launchd string"); + snprintf(launchdString, sizeof("/sbin/launchd"), "/cores/ploosh"); + // TODO: tmp shellcode_area = shellcode_to; diff --git a/checkra1n/kpf/ramdisk.c b/checkra1n/kpf/ramdisk.c index de4b7429..43866b8c 100644 --- a/checkra1n/kpf/ramdisk.c +++ b/checkra1n/kpf/ramdisk.c @@ -101,6 +101,7 @@ static void kpf_ramdisk_patches(xnu_pf_patchset_t *xnu_text_exec_patchset) static char rootdev[16] = { '\0' }; static uint32_t partid = 1; +extern palerain_option_t palera1n_flags; static void kpf_ramdisk_rootdev_cmd(const char *cmd, char *args) { // newfs: newfs_apfs -A -D -o role=r -v Xystem /dev/disk1 @@ -134,7 +135,7 @@ static void kpf_ramdisk_rootdev_cmd(const char *cmd, char *args) { else partid = patch[0]; if (socnum == 0x7000 || socnum == 0x7001) partid--; - snprintf(str, 0x100, "IOProviderClassIOMediaIOPropertyMatchPartition ID%u", partid); + snprintf(str, 0x100, "IOProviderClassIOMediaIOPropertyMatchPartition ID%u", palera1n_flags & palerain_option_setup_rootful ? 1 : partid); memset(root_matching, 0x0, 0x100); memcpy(root_matching, str, 0x100); printf("set new entry: %016" PRIx64 ": Partition ID: %u\n", (uint64_t)root_matching, partid); diff --git a/checkra1n/kpf/shellcode.S b/checkra1n/kpf/shellcode.S index e11b337b..bb77cd4b 100644 --- a/checkra1n/kpf/shellcode.S +++ b/checkra1n/kpf/shellcode.S @@ -403,7 +403,7 @@ L_dyld_shc_epilog: ldp x29, x30, [sp], 0x20 ret L_alt_dyld_path: - .asciz "/cores/usr/lib/dyld" + .asciz "/cores/dyld" L_dyld_path: .asciz "/usr/lib/dyld" .align 2 From e8e363a14f3b8bb3aec5d968bc15da557d5d61ec Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Thu, 2 Nov 2023 02:19:59 +0800 Subject: [PATCH 43/77] kpf: BSD Name based rooting --- checkra1n/kpf/ramdisk.c | 93 ++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 53 deletions(-) diff --git a/checkra1n/kpf/ramdisk.c b/checkra1n/kpf/ramdisk.c index 43866b8c..f9a2675e 100644 --- a/checkra1n/kpf/ramdisk.c +++ b/checkra1n/kpf/ramdisk.c @@ -98,54 +98,10 @@ static void kpf_ramdisk_patches(xnu_pf_patchset_t *xnu_text_exec_patchset) } } -static char rootdev[16] = { '\0' }; -static uint32_t partid = 1; extern palerain_option_t palera1n_flags; -static void kpf_ramdisk_rootdev_cmd(const char *cmd, char *args) { - // newfs: newfs_apfs -A -D -o role=r -v Xystem /dev/disk1 - - size_t root_matching_len = 0; - dt_node_t* chosen = dt_find(gDeviceTree, "chosen"); - if (!chosen) panic("invalid devicetree: no device!"); - uint32_t* root_matching = dt_prop(chosen, "root-matching", &root_matching_len); - if (!root_matching) panic("invalid devicetree: no prop!"); - - char str[0x100]; // max size = 0x100 - memset(&str, 0x0, 0x100); - - if (args[0] != '\0') { - snprintf(str, 0x100, "IOProviderClassIOServiceBSD Name%s", args); - snprintf(rootdev, 16, "%s", args); - - memset(root_matching, 0x0, 0x100); - memcpy(root_matching, str, 0x100); - printf("set new entry: %016" PRIx64 ": BSD Name: %s\n", (uint64_t)root_matching, args); - } else { - size_t max_fs_entries_len = 0; - dt_node_t* fstab = dt_find(gDeviceTree, "fstab"); - if (!fstab) panic("invalid devicetree: no fstab!"); - uint32_t* max_fs_entries = dt_prop(fstab, "max_fs_entries", &max_fs_entries_len); - if (!max_fs_entries) panic("invalid devicetree: no prop!"); - uint32_t* patch = (uint32_t*)max_fs_entries; - printf("fstab max_fs_entries: %016" PRIx64 ": %08x\n", (uint64_t)max_fs_entries, patch[0]); - dt_node_t* baseband = dt_find(gDeviceTree, "baseband"); - - if (baseband) partid = patch[0] + 1U; - else partid = patch[0]; - if (socnum == 0x7000 || socnum == 0x7001) partid--; - - snprintf(str, 0x100, "IOProviderClassIOMediaIOPropertyMatchPartition ID%u", palera1n_flags & palerain_option_setup_rootful ? 1 : partid); - memset(root_matching, 0x0, 0x100); - memcpy(root_matching, str, 0x100); - printf("set new entry: %016" PRIx64 ": Partition ID: %u\n", (uint64_t)root_matching, partid); - } -} - -static void kpf_ramdisk_pre_init(void) { - command_register("rootfs", "set rootfs in dt and paleinfo", kpf_ramdisk_rootdev_cmd); -} +static bool gHasConstriants = false; static void kpf_ramdisk_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring, palerain_option_t palera1n_flags) { char *bootargs = (char*)((uintptr_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView); @@ -154,12 +110,10 @@ static void kpf_ramdisk_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring { rootdev_bootarg = NULL; } - const char cryptex_string[] = "/private/preboot/Cryptexes"; - const char *cryptex_string_match = memmem(cstring->cacheable_base, cstring->size, cryptex_string, sizeof(cryptex_string)); - if (rootdev[0] == '\0') { - if (cryptex_string_match != NULL) snprintf(rootdev, 16, "disk1s%u", partid); - else snprintf(rootdev, 16, "disk0s1s%u", partid); - } + + const char constraints_string[] = "mac_proc_check_launch_constraints"; + const char *constraints_string_match = memmem(cstring->cacheable_base, cstring->size, constraints_string, sizeof(constraints_string)); + gHasConstriants = (constraints_string_match != NULL); #ifdef DEV_BUILD have_ramdisk = true; @@ -175,6 +129,40 @@ static void kpf_ramdisk_bootprep(struct mach_header_64 *hdr, palerain_option_t p memcpy(rootdev_bootarg, "spartan", 7); // rootdev -> spartan } + char BSDName[16]; + uint32_t partid = 1; + /* have SSV and rootful but not setup rootful */ + if ((palera1n_flags & (palerain_option_rootful | palerain_option_ssv)) == (palerain_option_rootful | palerain_option_ssv)) { + dt_node_t* fstab = dt_find(gDeviceTree, "fstab"); + if (!fstab) panic("invalid devicetree: no fstab!"); /* iOS 12 and below should not have SSV */ + size_t max_fs_entries_len = 0; + size_t root_matching_len = 0; + uint32_t* max_fs_entries = dt_prop(fstab, "max_fs_entries", &max_fs_entries_len); + if (!max_fs_entries) panic("invalid devicetree: no prop!"); + uint32_t* patch = (uint32_t*)max_fs_entries; + printf("fstab max_fs_entries: %016" PRIx64 ": %08x\n", (uint64_t)max_fs_entries, patch[0]); + dt_node_t* baseband = dt_find(gDeviceTree, "baseband"); + if (baseband) partid = patch[0] + 1U; + else partid = patch[0]; + if (socnum == 0x7000 || socnum == 0x7001) partid--; + dt_node_t* chosen = dt_find(gDeviceTree, "chosen"); + if (!chosen) panic("invalid devicetree: no device!"); + char* root_matching = dt_prop(chosen, "root-matching", &root_matching_len); + if (!root_matching) panic("invalid devicetree: no prop!"); + snprintf(BSDName, 16, "%s%" PRIu32, gHasConstriants ? "disk1s" : "disk0s1s", partid); + if ((palera1n_flags & palerain_option_setup_rootful) == 0) + snprintf(root_matching, root_matching_len, + "IOProviderClassIOServiceBSD Name%s", + BSDName); + else + printf("KPF: rooting from original rootfs for fakefs setup\n"); + printf("KPF: root BSD Name: %s\n", BSDName); + printf("KPF: root_matching (raw): %s\n", root_matching); + } else { + snprintf(BSDName, 16, "%s%" PRIu32, gHasConstriants ? "disk1s" : "disk0s1s", partid); + printf("KPF: root BSD Name: %s\n", BSDName); + } + if(ramdisk_size) { puts("KPF: Found ramdisk, appending paleinfo"); @@ -195,7 +183,7 @@ static void kpf_ramdisk_bootprep(struct mach_header_64 *hdr, palerain_option_t p .kslide = slide, .flags = palera1n_flags, }; - snprintf(pinfo_p->rootdev, 16, "%s", rootdev); + snprintf(pinfo_p->rootdev, 16, "%s", BSDName); *(uint32_t*)(ramdisk_buf) = ramdisk_size; ramdisk_size += 0x10000; @@ -239,7 +227,6 @@ static uint32_t kpf_ramdisk_emit(uint32_t *shellcode_area) kpf_component_t kpf_ramdisk = { - .pre_init = kpf_ramdisk_pre_init, .init = kpf_ramdisk_init, .bootprep = kpf_ramdisk_bootprep, .shc_size = kpf_ramdisk_size, From 220159d49214642f5254344271d535f7646d96cb Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Thu, 2 Nov 2023 02:25:47 +0800 Subject: [PATCH 44/77] usbloader: Compressed module support --- checkra1n/kpf/main.c | 6 +++++- checkra1n/kpf/ramdisk.c | 11 +++++++--- checkra1n/kpf/shellcode.S | 4 +--- src/dynamic/modload_macho.c | 42 +++++++++++++++++++++++++++++-------- 4 files changed, 47 insertions(+), 16 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 47c70979..a21584b4 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1709,7 +1709,7 @@ bool IOSecureBSDRoot_callback(struct xnu_pf_patch *patch, uint32_t *opcode_strea return false; } puts("KPF: Found mdevremoveall"); - DEVLOG("Found mdevremoveall 0x%llx", xnu_rebase_va(xnu_ptr_to_va(opcode_stream)) + 4*4); + DEVLOG("Found mdevremoveall 0x%" PRIx64, xnu_rebase_va(xnu_ptr_to_va(opcode_stream)) + 4*4); uint32_t insn = opcode_stream[4]; int32_t off = sxt32(insn >> 5, 19); @@ -2034,6 +2034,10 @@ static void kpf_cmd(const char *cmd, char *args) if((livefs_string_match != NULL) != (gKernelVersion.darwinMajor >= 21 && xnu_platform() == PLATFORM_IOS)) panic("livefs panic doesn't match expected Darwin version"); #endif + if (!rootvp_string_match) { + strncat((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), " rootdev=md0", 0x270); + } + for(size_t i = 0; i < sizeof(kpf_components)/sizeof(kpf_components[0]); ++i) { kpf_component_t *component = kpf_components[i]; diff --git a/checkra1n/kpf/ramdisk.c b/checkra1n/kpf/ramdisk.c index f9a2675e..323191b9 100644 --- a/checkra1n/kpf/ramdisk.c +++ b/checkra1n/kpf/ramdisk.c @@ -110,7 +110,7 @@ static void kpf_ramdisk_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring { rootdev_bootarg = NULL; } - + const char constraints_string[] = "mac_proc_check_launch_constraints"; const char *constraints_string_match = memmem(cstring->cacheable_base, cstring->size, constraints_string, sizeof(constraints_string)); gHasConstriants = (constraints_string_match != NULL); @@ -124,11 +124,15 @@ static void kpf_ramdisk_init(struct mach_header_64 *hdr, xnu_pf_range_t *cstring static void kpf_ramdisk_bootprep(struct mach_header_64 *hdr, palerain_option_t palera1n_flags) { + if(rootdev_bootarg) { memcpy(rootdev_bootarg, "spartan", 7); // rootdev -> spartan } +#if __STDC_HOSTED__ + char BSDName[16] = "disk0s1s1"; +#else char BSDName[16]; uint32_t partid = 1; /* have SSV and rootful but not setup rootful */ @@ -150,18 +154,19 @@ static void kpf_ramdisk_bootprep(struct mach_header_64 *hdr, palerain_option_t p char* root_matching = dt_prop(chosen, "root-matching", &root_matching_len); if (!root_matching) panic("invalid devicetree: no prop!"); snprintf(BSDName, 16, "%s%" PRIu32, gHasConstriants ? "disk1s" : "disk0s1s", partid); - if ((palera1n_flags & palerain_option_setup_rootful) == 0) + if ((palera1n_flags & (palerain_option_setup_rootful | palerain_option_force_revert)) == 0) snprintf(root_matching, root_matching_len, "IOProviderClassIOServiceBSD Name%s", BSDName); else - printf("KPF: rooting from original rootfs for fakefs setup\n"); + printf("KPF: rooting from original rootfs for fakefs setup or force revert\n"); printf("KPF: root BSD Name: %s\n", BSDName); printf("KPF: root_matching (raw): %s\n", root_matching); } else { snprintf(BSDName, 16, "%s%" PRIu32, gHasConstriants ? "disk1s" : "disk0s1s", partid); printf("KPF: root BSD Name: %s\n", BSDName); } +#endif if(ramdisk_size) { diff --git a/checkra1n/kpf/shellcode.S b/checkra1n/kpf/shellcode.S index bb77cd4b..c3488951 100644 --- a/checkra1n/kpf/shellcode.S +++ b/checkra1n/kpf/shellcode.S @@ -403,7 +403,7 @@ L_dyld_shc_epilog: ldp x29, x30, [sp], 0x20 ret L_alt_dyld_path: - .asciz "/cores/dyld" + .asciz "/cores/usr/lib/dyld" L_dyld_path: .asciz "/usr/lib/dyld" .align 2 @@ -482,8 +482,6 @@ L_kdi_shc_ramfile: .align 2 _kdi_shc_end: - - .globl _fsctl_shc .globl _fsctl_shc_vnode_open .globl _fsctl_shc_stolen_slowpath diff --git a/src/dynamic/modload_macho.c b/src/dynamic/modload_macho.c index d4739b59..935d08e7 100644 --- a/src/dynamic/modload_macho.c +++ b/src/dynamic/modload_macho.c @@ -28,17 +28,18 @@ #include #include #include +#include // to replace with dlsym perhaps later on void* resolve_symbol(const char* name); void link_exports(struct pongo_exports* export); -void modload_cmd() { +bool modload_buf(char* buf, uint32_t bufsz) { iprintf("[modload_macho:i] Attempting to load a module\n"); - if (loader_xfer_recv_count >= 0x4000) { - //iprintf("enough bytes! %x\n", loader_xfer_recv_count); - struct mach_header_64* mh = (void*) loader_xfer_recv_data; + if (bufsz >= 0x4000) { + //iprintf("enough bytes! %x\n", bufsz); + struct mach_header_64* mh = (void*) buf; struct load_command* lc = (struct load_command*) (mh + 1); if (mh->magic == MH_MAGIC_64) { //puts("it's a mach-o!"); @@ -67,8 +68,8 @@ void modload_cmd() { lc = (struct load_command*)(((char*)lc) + lc->cmdsize); } vmsz_needed -= base_vmaddr; - //iprintf("need %" PRIx64 ", got %" PRIx64 "\n", filesz_expected, loader_xfer_recv_count); - if (!(filesz_expected > loader_xfer_recv_count)) { + //iprintf("need %" PRIx64 ", got %" PRIx64 "\n", filesz_expected, bufsz); + if (!(filesz_expected > bufsz)) { uint64_t entrypoint = 0; uint8_t * allocto = alloc_contig((vmsz_needed + 0x3FFF) & ~0x3FFF); uint64_t vma_base = linear_kvm_alloc(vmsz_needed); @@ -88,7 +89,7 @@ void modload_cmd() { info->vm_size = sg->vmsize; memset(allocto + sg->vmaddr - base_vmaddr, 0, sg->vmsize); - memcpy(allocto + sg->vmaddr - base_vmaddr, loader_xfer_recv_data + sg->fileoff, sg->filesize); + memcpy(allocto + sg->vmaddr - base_vmaddr, buf + sg->fileoff, sg->filesize); vm_protect_t prots = 0; prots |= sg->initprot & VM_PROT_READ ? PROT_READ : 0; @@ -146,7 +147,7 @@ void modload_cmd() { void* symbol_value = resolve_symbol(name); if (symbol_value == 0) { puts("[modload_macho:!] load module: linking failed"); - return; + return false; } // Find the offset of the relocation pointer in the virtually mapped Mach-O and // replace it with the resolved address of the symbol. r_address is the offset from @@ -179,9 +180,32 @@ void modload_cmd() { module->name = strdup(modname ? *modname ? *modname : "" : ""); module->exports = exports; ((void (*)())entrypoint)(); + return true; } else puts ("[modload_macho:!] load module: truncated load"); } else puts("[modload_macho:!] load module: need dylib"); } else puts("[modload_macho:!] load module: not mach-o"); } else puts("[modload_macho:!] load module: short read"); - loader_xfer_recv_count = 0; + return false; +} + +void modload_cmd(char* cmd, char* args) { + if (args[0] != '\0') { + size_t module_size; + if ((module_size = (int)strtoul(args, NULL, 0)) != 0) { + printf("args: %s, module_size: %zu\n", args, module_size); + void* module_buf = malloc(module_size); + if (!module_buf) panic("couldn't reserve heap for module"); + int lzma_result = unlzma_decompress(module_buf, &module_size, loader_xfer_recv_data, loader_xfer_recv_count); + if (lzma_result == SZ_OK) { + modload_buf(module_buf, (uint32_t)module_size); + free(module_buf); + } else printf("module decompression failed\n"); + } else { + printf("modload usage: modload [uncompressed size if compressed]\n"); + return; + } + } else { + modload_buf(loader_xfer_recv_data, loader_xfer_recv_count); + } + loader_xfer_recv_size = 0; } From 11bb55f42b7628e4f5a47358f82947b0ef36e5ce Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 8 Jan 2024 20:19:47 +0800 Subject: [PATCH 45/77] kpf: Fix certain app store apps crashing on 17.2+ --- .github/workflows/ci.yml | 2 +- checkra1n/kpf-test/Makefile | 2 +- checkra1n/kpf/main.c | 28 +++++++++++++++++++++++++++- 3 files changed, 29 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 552436c5..7eb6d8da 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -60,7 +60,7 @@ jobs: dpkg --add-architecture arm64 apt-get update apt-get -y --allow-downgrades dist-upgrade - apt-get install -y build-essential git libc6:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld curl zstd + apt-get install -y build-essential git libc6:arm64 libbsd0:arm64 libbsd-dev:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld curl zstd - name: Checkout repository uses: actions/checkout@v2 diff --git a/checkra1n/kpf-test/Makefile b/checkra1n/kpf-test/Makefile index c3728897..c657b1fc 100644 --- a/checkra1n/kpf-test/Makefile +++ b/checkra1n/kpf-test/Makefile @@ -55,7 +55,7 @@ xnu_S_linux.S: $(SRC)/drivers/xnu/xnu.S Makefile sed -e 's/_pf_jit/pf_jit/g' $< > $@ kpf-test.linux: Makefile $(KPF_C) $(KPF_H) shellcode_S_linux.S xnu_S_linux.S - $(LINUX_CC) -o $@ main.c -g $(wildcard $(RA1N)/*.c) $(SRC)/drivers/xnu/xnu.c shellcode_S_linux.S xnu_S_linux.S $(KPF_CC_FLAGS_LINUX) + $(LINUX_CC) -o $@ main.c -lbsd -g $(wildcard $(RA1N)/*.c) $(SRC)/drivers/xnu/xnu.c shellcode_S_linux.S xnu_S_linux.S $(KPF_CC_FLAGS_LINUX) clean: rm -f kpf-test.ios kpf-test.macos kpf-test.linux diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index a21584b4..e74f6f7e 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -41,6 +41,10 @@ palerain_option_t palera1n_flags = 0; #if __STDC_HOSTED__ extern bool test_force_rootful; + +#if __has_include() +#include +#endif #endif #if 0 @@ -2035,8 +2039,30 @@ static void kpf_cmd(const char *cmd, char *args) #endif if (!rootvp_string_match) { - strncat((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), " rootdev=md0", 0x270); + strlcat((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), " rootdev=md0", 0x270); + } + + xnu_pf_range_t* bootdata_range = xnu_pf_section(hdr, "__BOOTDATA", "__init"); + + if (bootdata_range) { + const char thid_should_crash_string[] = "thid_should_crash"; + const char *thid_should_crash_string_match = memmem(bootdata_range->cacheable_base, bootdata_range->size, thid_should_crash_string, sizeof(thid_should_crash_string) - 1); + +#ifdef DEV_BUILD + // 17.0 beta 1 onwards + if((thid_should_crash_string_match != NULL) != (gKernelVersion.darwinMajor >= 23)) panic("thid_should_crash string doesn't match expected Darwin version"); +#endif + + if (thid_should_crash_string_match && !strstr((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), "thid_should_crash=")) + { + strlcat((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), " thid_should_crash=0", 0x270); + } } +#ifdef DEV_BUILD + else if (gKernelVersion.darwinMajor > 19) { + panic("__BOOTDATA __init existence does not match expected Darwin version"); + } +#endif for(size_t i = 0; i < sizeof(kpf_components)/sizeof(kpf_components[0]); ++i) { From 0b4dc731c94c5274e786440e26fae44176f788cc Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 26 Jan 2024 02:46:37 +0800 Subject: [PATCH 46/77] kpf: fix thid_should_crash string match on xnu-10063 --- checkra1n/kpf/main.c | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index e74f6f7e..33efd1e5 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1232,12 +1232,12 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { // r2: /x a00340b900781f12a00300b9:a003feff00fcffffa003c0ff uint64_t remount_matches[] = { 0x94000000, // bl - 0x37700000 // tbnz w0, 0xe, * + 0x37700000, // tbnz w0, 0xe, * }; uint64_t remount_masks[] = { 0xfc000000, - 0xfff8001f + 0xfff8001f, }; xnu_pf_maskmatch(patchset, @@ -2043,16 +2043,31 @@ static void kpf_cmd(const char *cmd, char *args) } xnu_pf_range_t* bootdata_range = xnu_pf_section(hdr, "__BOOTDATA", "__init"); + xnu_pf_range_t* const_klddata_range = xnu_pf_section(hdr, "__KLDDATA", "__const"); + +#ifdef DEV_BUILD + if (gKernelVersion.darwinMajor >= 20 != (const_klddata_range != NULL)) { + panic("__KLDDATA __const existence does not match expected Darwin version"); + } +#endif if (bootdata_range) { const char thid_should_crash_string[] = "thid_should_crash"; const char *thid_should_crash_string_match = memmem(bootdata_range->cacheable_base, bootdata_range->size, thid_should_crash_string, sizeof(thid_should_crash_string) - 1); + #ifdef DEV_BUILD - // 17.0 beta 1 onwards - if((thid_should_crash_string_match != NULL) != (gKernelVersion.darwinMajor >= 23)) panic("thid_should_crash string doesn't match expected Darwin version"); + // 17.0 beta 1 - 17.3 + if((thid_should_crash_string_match != NULL) != gKernelVersion.xnuMajor >= 10002 && gKernelVersion.xnuMajor < 10063) panic("thid_should_crash string doesn't match expected Darwin version"); #endif + if (!thid_should_crash_string_match && const_klddata_range) { + thid_should_crash_string_match = memmem(const_klddata_range->cacheable_base, const_klddata_range->size, thid_should_crash_string, sizeof(thid_should_crash_string) - 1); + } + + // 17.4 beta 1 onwards + if((thid_should_crash_string_match != NULL) != gKernelVersion.xnuMajor >= 10063) panic("thid_should_crash string doesn't match expected Darwin version"); + if (thid_should_crash_string_match && !strstr((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), "thid_should_crash=")) { strlcat((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), " thid_should_crash=0", 0x270); From d3ac5712049fe107717fcda0da52add33d461abc Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 26 Jan 2024 03:16:00 +0800 Subject: [PATCH 47/77] kpf: fix finding mac_execve on xnu-10063 --- checkra1n/kpf/main.c | 39 ++++++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 9 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 33efd1e5..6202682e 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1843,7 +1843,7 @@ void kpf_md0oncores_patch(xnu_pf_patchset_t* patchset) 0xffffffff, 0xffffffff, 0xfc000000, - 0xff000000, + 0xff00001f, }; xnu_pf_maskmatch(patchset, "load_init_program_at_path", i_matches, i_masks, sizeof(i_masks)/sizeof(uint64_t), false, (void*)load_init_program_at_path_callback); @@ -1866,10 +1866,31 @@ void kpf_md0oncores_patch(xnu_pf_patchset_t* patchset) 0xffffffff, 0xffffffff, 0xfc000000, - 0xff000000, + 0xff00001f, }; xnu_pf_maskmatch(patchset, "load_init_program_at_path", ii_matches, ii_masks, sizeof(ii_masks)/sizeof(uint64_t), false, (void*)load_init_program_at_path_callback); + // xnu-10063 + uint64_t iii_matches[] = { + 0xa903dbf5, // stp x21, x22, [sp, #0x38] + 0xa904ffff, // stp xzr, xzr, [sp, #0x48] + 0x9100e3e1, // add x1, sp, #0x38 + 0xaa1303e0, // mov x0, x19 + 0x94000000, // bl __mac_execve + 0x35000000, // cbnz w0, ... + }; + + uint64_t iii_masks[] = + { + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xffffffff, + 0xfc000000, + 0xff00001f, + }; + xnu_pf_maskmatch(patchset, "load_init_program_at_path", iii_matches, iii_masks, sizeof(iii_matches)/sizeof(uint64_t), false, (void*)load_init_program_at_path_callback); + } static uint32_t shellcode_count; @@ -2043,11 +2064,11 @@ static void kpf_cmd(const char *cmd, char *args) } xnu_pf_range_t* bootdata_range = xnu_pf_section(hdr, "__BOOTDATA", "__init"); +#ifdef DEV_BUILD xnu_pf_range_t* const_klddata_range = xnu_pf_section(hdr, "__KLDDATA", "__const"); -#ifdef DEV_BUILD - if (gKernelVersion.darwinMajor >= 20 != (const_klddata_range != NULL)) { - panic("__KLDDATA __const existence does not match expected Darwin version"); + if (gKernelVersion.xnuMajor >= 7195 != (const_klddata_range != NULL)) { + if (gKernelVersion.xnuMajor == 7195 && gKernelVersion.darwinMinor > 4) panic("__KLDDATA __const existence does not match expected Darwin version"); } #endif @@ -2059,15 +2080,15 @@ static void kpf_cmd(const char *cmd, char *args) #ifdef DEV_BUILD // 17.0 beta 1 - 17.3 if((thid_should_crash_string_match != NULL) != gKernelVersion.xnuMajor >= 10002 && gKernelVersion.xnuMajor < 10063) panic("thid_should_crash string doesn't match expected Darwin version"); -#endif - if (!thid_should_crash_string_match && const_klddata_range) { + + if (const_klddata_range) { thid_should_crash_string_match = memmem(const_klddata_range->cacheable_base, const_klddata_range->size, thid_should_crash_string, sizeof(thid_should_crash_string) - 1); } // 17.4 beta 1 onwards - if((thid_should_crash_string_match != NULL) != gKernelVersion.xnuMajor >= 10063) panic("thid_should_crash string doesn't match expected Darwin version"); - + if(const_klddata_range && ((thid_should_crash_string_match != NULL) != gKernelVersion.xnuMajor >= 10063)) panic("thid_should_crash string doesn't match expected Darwin version"); +#endif if (thid_should_crash_string_match && !strstr((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), "thid_should_crash=")) { strlcat((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), " thid_should_crash=0", 0x270); From c16ade52a9240d469e4022dd9f29cb5d1f1e9054 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 26 Jan 2024 05:17:59 +0800 Subject: [PATCH 48/77] kpf-test: should panic on missing apfs_vfsop_mount (ios 15-16) --- checkra1n/kpf/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 6202682e..55ab75c6 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -2284,7 +2284,7 @@ static void kpf_cmd(const char *cmd, char *args) if (!has_found_apfs_vfsop_mount && rootvp_string_match != NULL) { #if __STDC_HOSTED__ if (gKernelVersion.darwinMajor <= 22 || test_force_rootful) { - puts("Missing patch: apfs_vfsop_mount"); + panic("Missing patch: apfs_vfsop_mount"); } else #endif if (palera1n_flags & palerain_option_rootful) { From d93a0fb8aa95e48771e727578124ccead9150282 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 26 Jan 2024 06:29:32 +0800 Subject: [PATCH 49/77] kpf: apply thid_should_crash correctly on xnu-10063 --- checkra1n/kpf/main.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 55ab75c6..d16f8169 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -2064,9 +2064,9 @@ static void kpf_cmd(const char *cmd, char *args) } xnu_pf_range_t* bootdata_range = xnu_pf_section(hdr, "__BOOTDATA", "__init"); -#ifdef DEV_BUILD xnu_pf_range_t* const_klddata_range = xnu_pf_section(hdr, "__KLDDATA", "__const"); +#ifdef DEV_BUILD if (gKernelVersion.xnuMajor >= 7195 != (const_klddata_range != NULL)) { if (gKernelVersion.xnuMajor == 7195 && gKernelVersion.darwinMinor > 4) panic("__KLDDATA __const existence does not match expected Darwin version"); } @@ -2080,12 +2080,13 @@ static void kpf_cmd(const char *cmd, char *args) #ifdef DEV_BUILD // 17.0 beta 1 - 17.3 if((thid_should_crash_string_match != NULL) != gKernelVersion.xnuMajor >= 10002 && gKernelVersion.xnuMajor < 10063) panic("thid_should_crash string doesn't match expected Darwin version"); - +#endif if (const_klddata_range) { thid_should_crash_string_match = memmem(const_klddata_range->cacheable_base, const_klddata_range->size, thid_should_crash_string, sizeof(thid_should_crash_string) - 1); } +#ifdef DEV_BUILD // 17.4 beta 1 onwards if(const_klddata_range && ((thid_should_crash_string_match != NULL) != gKernelVersion.xnuMajor >= 10063)) panic("thid_should_crash string doesn't match expected Darwin version"); #endif From 67910fb9214118882090062772c5da2dcb52550c Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 29 Jan 2024 02:16:51 +0800 Subject: [PATCH 50/77] kpf: fix nvram_unlock on xnu-10063 (#179) --- checkra1n/kpf/nvram.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/checkra1n/kpf/nvram.c b/checkra1n/kpf/nvram.c index 1846c7ff..520707d9 100644 --- a/checkra1n/kpf/nvram.c +++ b/checkra1n/kpf/nvram.c @@ -1,4 +1,4 @@ -/* +m/* * pongoOS - https://checkra.in * * Copyright (C) 2019-2023 checkra1n team @@ -241,17 +241,17 @@ static void kpf_nvram_patches(xnu_pf_patchset_t *xnu_text_exec_patchset) // 0xfffffff0077addec 9a0640f9 ldr x26, [x20, 8] <- this loads the flags / permissions // // Shortly afterwards, there is a "tbnz w26, 2", which checks for the kernel-only bit. We just get rid of that. - // /x 1000009094e210910000009000000091e10310aa0000009460000034000e41f880ffffb5100640f9:1000009f1002c0ff1f00009fff03c0fffffff0ff000000fcffffffff1ffeffffffffffff10feffff + // /x 10000090100200910000009000000091e10310aa0000009460000034000c40f880ffffb5100640f9:1000009f1002c0ff1f00009fff03c0fffffff0ff000000fcffffffff1f0ce0ffffffffff10feffff uint64_t matches4[] = { 0x90000010, // adrp xN, 0x... - 0x91000210, // add xN, xN, 0x438 + 0x91000210, // add xN, xN, 0x... 0x90000000, // adrp x0, 0x... - 0x91000000, // add x0, x0, 0x32b + 0x91000000, // add x0, x0, 0x... 0xaa1003e1, // mov x1, x{16-31} 0x94000000, // bl sym._strcmp 0x34000060, // cbz w0, .+12 - 0xf8410e00, // ldr x0, [xN, 0x10]! + 0xf8400c00, // ldr x0, [xN, ...]! 0xb5ffff80, // cbnz x0, .-16 0xf9400610, // ldr x{16-31}, [xN, 8] }; @@ -264,7 +264,7 @@ static void kpf_nvram_patches(xnu_pf_patchset_t *xnu_text_exec_patchset) 0xfff0ffff, 0xfc000000, 0xffffffff, - 0xfffffe1f, + 0xffe00c1f, 0xffffffff, 0xfffffe10, }; From 609957bdec2753200d27020f5bdd69291e3b4269 Mon Sep 17 00:00:00 2001 From: Siguza Date: Sun, 28 Jan 2024 21:28:39 +0100 Subject: [PATCH 51/77] Sigh --- checkra1n/kpf/nvram.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkra1n/kpf/nvram.c b/checkra1n/kpf/nvram.c index 520707d9..3bb35d76 100644 --- a/checkra1n/kpf/nvram.c +++ b/checkra1n/kpf/nvram.c @@ -1,4 +1,4 @@ -m/* +/* * pongoOS - https://checkra.in * * Copyright (C) 2019-2023 checkra1n team From e37120cdf13304b38a1b0be6ad4b3a4f30d8b36c Mon Sep 17 00:00:00 2001 From: kok3shidoll <69592455+kok3shidoll@users.noreply.github.com> Date: Wed, 31 Jan 2024 12:03:12 +0900 Subject: [PATCH 52/77] fixed find copyout --- checkra1n/kpf/main.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index d16f8169..6205123f 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1733,11 +1733,11 @@ bool load_init_program_at_path_callback(struct xnu_pf_patch *patch, uint32_t *op mac_execve_hook = opcode_stream; puts("KPF: Found mac_execve"); - uint32_t* prebl = find_prev_insn(opcode_stream, 0x80, 0x52800302, 0xffffffff); - bl = find_next_insn(prebl, 10, 0x94000000, 0xfc000000); // bl - - copyout = follow_call(bl); - puts("KPF: Found copyout"); + //uint32_t* prebl = find_prev_insn(opcode_stream, 0x80, 0x52800302, 0xffffffff); + //bl = find_next_insn(prebl, 10, 0x94000000, 0xfc000000); // bl + // + //copyout = follow_call(bl); + //puts("KPF: Found copyout"); // Most reliable marker of a stack frame seems to be "add x29, sp, 0x...". // And this function is HUGE, hence up to 2k insn. @@ -1751,6 +1751,34 @@ bool load_init_program_at_path_callback(struct xnu_pf_patch *patch, uint32_t *op if(!start) start = find_prev_insn(frame, 10, 0xd10003ff, 0xff8003ff); if(!start) return false; + uint32_t* match = opcode_stream; + + while(1) { + if( + ((match[0] & 0xfff0ffff) == 0xaa1003e0) && // mov x0, x{16-30} + ((match[1] & 0xfc000000) == 0x94000000) && // bl _strlen + ((match[2] & 0xfffffff0) == 0x91000410) && // add x{16-30}, x0, #1 + ((match[3] & 0xfffffe1f) == 0xf100121f) && // cmp x{16-30}, #4 + ((match[4] & 0xff000000) == 0x54000000) && // b.hs + ((match[5] & 0x9f000000) == 0x90000000) && // adrp + ((match[6] & 0xff000000) == 0x91000000) && // add + ((match[7] & 0xfff0ffff) == 0xaa1003e1) && // mov x1, x{16-30} + ((match[8] & 0xfff0ffff) == 0xaa1003e2) && // mov x2, x{16-30} + ((match[9] & 0xfc000000) == 0x94000000) // bl _copyout + ) + { + // found + match += 9; + copyout = follow_call(match); + puts("KPF: Found copyout"); + break; + } + match--; + if(match == start) { + panic("copyout not found"); + return false; + } + } /* xxx */ uint32_t *tpidr_el1 = find_next_insn(start, 0x20, 0xd538d080, 0xffffff80); // search mrs xN, tpidr_el1 From 8f3dd365de7bd23564275c3fba03b1b8f6b07015 Mon Sep 17 00:00:00 2001 From: opa334 Date: Thu, 15 Feb 2024 16:38:27 +0100 Subject: [PATCH 53/77] kpf: Add patch to disable Protobox on iOS 16+ --- checkra1n/kpf/main.c | 47 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 6205123f..f63fe5dd 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -796,6 +796,27 @@ bool vnode_lookup_callback(struct xnu_pf_patch* patch, uint32_t* opcode_stream) return true; } +bool kpf_protobox_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) +{ + uint32_t adrp1 = opcode_stream[0], + add1 = opcode_stream[1]; + const char *str1 = (const char *)(((uint64_t)(opcode_stream) & ~0xfffULL) + adrp_off(adrp1) + ((add1 >> 10) & 0xfff)); + + uint32_t adrp2 = opcode_stream[4], + add2 = opcode_stream[5]; + const char *str2 = (const char *)(((uint64_t)(opcode_stream) & ~0xfffULL) + adrp_off(adrp2) + ((add2 >> 10) & 0xfff)); + + if (!strcmp(str1, "Restore") && !strcmp(str2, "Darwin")) { + // Make protobox think this device is in "Restore" mode + // This will disable protobox + opcode_stream[2] = 0xD2800020; // mov x0, #1 + printf("KPF: Found and patched protobox check @ 0x%llx\n", xnu_ptr_to_va(opcode_stream)); + return true; + } + + return false; +} + void kpf_find_shellcode_funcs(xnu_pf_patchset_t* xnu_text_exec_patchset) { // to find this with r2 run: // /x 00008192007fbef2:00ffffff00ffffff @@ -1601,6 +1622,32 @@ void kpf_sandbox_kext_patches(xnu_pf_patchset_t* patchset) { 0xFF000000 }; xnu_pf_maskmatch(patchset, "vnode_lookup", matches, masks, sizeof(masks)/sizeof(uint64_t), true, (void*)vnode_lookup_callback); + + // Protobox on is an additional sandbox mechanism in iOS 16+ that introduces syscall masks, which is used to have syscall whitelists on some system processes + // When injecting into them or using something like Frida, it can prevent certain functionality + // Additionally it makes these processes crash on sandbox violations, meaning that calling even something simple like mach_thread_self in watchdogd will crash the process + // We disable it by making the code that enables it think the device is in Restore mode, as this check involves calling is_release_type with a string it's easy to find + uint64_t protobox_matches[] = { + 0x90000000, // adrp x0, "Restore"@PAGE + 0x91000000, // add x0, "Restore"@PAGEOFF + 0x94000000, // bl _is_release_type + 0x37000000, // tbnz w0, #0, ??? + 0x90000000, // adrp x0, "Darwin"@PAGE + 0x91000000, // add x0, "Darwin"@PAGEOFF + 0x94000000, // bl _is_release_type + 0x36000000, // tb(n)z w0, #0, ??? + }; + uint64_t protobox_masks[] = { + 0x9f00001f, + 0xff8003ff, + 0xfc000000, + 0xff00001f, + 0x9f00001f, + 0xff8003ff, + 0xfc000000, + 0xfe00001f, + }; + xnu_pf_maskmatch(patchset, "protobox", protobox_matches, protobox_masks, sizeof(protobox_masks)/sizeof(uint64_t), false, (void *)kpf_protobox_callback); } bool vnop_rootvp_auth_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { From 383ea2a879f56689cc672c171c36f915e46c2eae Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 16 Feb 2024 11:35:16 +0800 Subject: [PATCH 54/77] kpf: Add patch to disable Protobox on iOS 16+ This patch disables Protobox, which was introduced in iOS 16 and adds syscall masks (whitelists) to certain system daemons. It also includes a mechanism that makes certain processes crash on sandbox violations, amongst other things. Co-authored-by: opa334 --- checkra1n/kpf/main.c | 51 ++++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 23 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index f63fe5dd..f5746bb3 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1598,7 +1598,7 @@ void kpf_amfi_kext_patches(xnu_pf_patchset_t* patchset) { xnu_pf_maskmatch(patchset, "amfi_mac_syscall_low", iiii_matches, iiii_masks, sizeof(iiii_matches)/sizeof(uint64_t), false, (void*)kpf_amfi_mac_syscall_low); } -void kpf_sandbox_kext_patches(xnu_pf_patchset_t* patchset) { +void kpf_sandbox_kext_patches(xnu_pf_patchset_t* patchset, const char* constraints_string_match) { uint64_t matches[] = { 0x35000000, // CBNZ 0x94000000, // BL _vfs_context_current @@ -1627,27 +1627,29 @@ void kpf_sandbox_kext_patches(xnu_pf_patchset_t* patchset) { // When injecting into them or using something like Frida, it can prevent certain functionality // Additionally it makes these processes crash on sandbox violations, meaning that calling even something simple like mach_thread_self in watchdogd will crash the process // We disable it by making the code that enables it think the device is in Restore mode, as this check involves calling is_release_type with a string it's easy to find - uint64_t protobox_matches[] = { - 0x90000000, // adrp x0, "Restore"@PAGE - 0x91000000, // add x0, "Restore"@PAGEOFF - 0x94000000, // bl _is_release_type - 0x37000000, // tbnz w0, #0, ??? - 0x90000000, // adrp x0, "Darwin"@PAGE - 0x91000000, // add x0, "Darwin"@PAGEOFF - 0x94000000, // bl _is_release_type - 0x36000000, // tb(n)z w0, #0, ??? - }; - uint64_t protobox_masks[] = { - 0x9f00001f, - 0xff8003ff, - 0xfc000000, - 0xff00001f, - 0x9f00001f, - 0xff8003ff, - 0xfc000000, - 0xfe00001f, - }; - xnu_pf_maskmatch(patchset, "protobox", protobox_matches, protobox_masks, sizeof(protobox_masks)/sizeof(uint64_t), false, (void *)kpf_protobox_callback); + if (constraints_string_match && xnu_platform() != PLATFORM_BRIDGEOS) { + uint64_t protobox_matches[] = { + 0x90000000, // adrp x0, "Restore"@PAGE + 0x91000000, // add x0, "Restore"@PAGEOFF + 0x94000000, // bl _is_release_type + 0x37000000, // tbnz w0, #0, ??? + 0x90000000, // adrp x0, "Darwin"@PAGE + 0x91000000, // add x0, "Darwin"@PAGEOFF + 0x94000000, // bl _is_release_type + 0x36000000, // tb(n)z w0, #0, ??? + }; + uint64_t protobox_masks[] = { + 0x9f00001f, + 0xff8003ff, + 0xfc000000, + 0xff00001f, + 0x9f00001f, + 0xff8003ff, + 0xfc000000, + 0xfe00001f, + }; + xnu_pf_maskmatch(patchset, "protobox", protobox_matches, protobox_masks, sizeof(protobox_masks)/sizeof(uint64_t), true, (void *)kpf_protobox_callback); + } } bool vnop_rootvp_auth_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { @@ -2129,6 +2131,9 @@ static void kpf_cmd(const char *cmd, char *args) const char *livefs_string_match = apfs_text_cstring_range ? memmem(apfs_text_cstring_range->cacheable_base, apfs_text_cstring_range->size, livefs_string, sizeof(livefs_string) - 1) : NULL; if(!livefs_string_match) livefs_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, livefs_string, sizeof(livefs_string) - 1); + const char constraints_string[] = "mac_proc_check_launch_constraints"; + const char *constraints_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, constraints_string, sizeof(constraints_string)); + #ifdef DEV_BUILD // 15.0 beta 1 onwards, but only iOS/iPadOS if((livefs_string_match != NULL) != (gKernelVersion.darwinMajor >= 21 && xnu_platform() == PLATFORM_IOS)) panic("livefs panic doesn't match expected Darwin version"); @@ -2275,7 +2280,7 @@ static void kpf_cmd(const char *cmd, char *args) xnu_pf_patchset_t* sandbox_patchset = xnu_pf_patchset_create(XNU_PF_ACCESS_32BIT); struct mach_header_64* sandbox_header = xnu_pf_get_kext_header(hdr, "com.apple.security.sandbox"); xnu_pf_range_t* sandbox_text_exec_range = xnu_pf_section(sandbox_header, "__TEXT_EXEC", "__text"); - kpf_sandbox_kext_patches(sandbox_patchset); + kpf_sandbox_kext_patches(sandbox_patchset, constraints_string_match); xnu_pf_emit(sandbox_patchset); xnu_pf_apply(sandbox_text_exec_range, sandbox_patchset); xnu_pf_patchset_destroy(sandbox_patchset); From 5f7c911c12676e38a0d47a820d1be62db7bb8c4c Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 16 Feb 2024 11:50:31 +0800 Subject: [PATCH 55/77] actions: Delete /usr/share/dotnet --- .github/workflows/ci.yml | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7eb6d8da..144e516f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -54,6 +54,10 @@ jobs: runs-on: ubuntu-22.04 container: image: debian:stable + volumes: + - /:/mnt + options: --privileged + steps: - name: Install packages run: | @@ -66,15 +70,19 @@ jobs: uses: actions/checkout@v2 with: fetch-depth: 0 - + - name: Compile KPF test run: make -C checkra1n/kpf-test KPF_CFLAGS="-target aarch64-linux-gnu -L/usr/aarch64-linux-gnu/lib -I/usr/aarch64-linux-gnu/include -L/usr/lib/gcc-cross/aarch64-linux-gnu/*" kpf-test.linux + - name: Free up space + run: + rm -rf /mnt/usr/share/dotnet /mnt/usr/local/lib/android /mnt/opt/ghc /mnt/opt/hostedtoolcache/CodeQL + - name: Get kernels run: | curl -Lu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.zst | zstd -cdT0 | tar -x - + - name: Test KPF run: | qemu-aarch64 ./checkra1n/kpf-test/kpf-test.linux -n kernel2; From 6fb9cfb845c247a2ea853802d5af9b75a601f5a2 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 16 Feb 2024 16:50:52 +0800 Subject: [PATCH 56/77] fixed find copyout for real --- checkra1n/kpf/main.c | 37 ++++++++++++++++++++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index f5746bb3..eb97b9a8 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1799,7 +1799,8 @@ bool load_init_program_at_path_callback(struct xnu_pf_patch *patch, uint32_t *op uint32_t *start = find_prev_insn(frame, 10, 0xa9a003e0, 0xffe003e0); if(!start) start = find_prev_insn(frame, 10, 0xd10003ff, 0xff8003ff); if(!start) return false; - + +#if 0 uint32_t* match = opcode_stream; while(1) { @@ -1828,6 +1829,7 @@ bool load_init_program_at_path_callback(struct xnu_pf_patch *patch, uint32_t *op return false; } } +#endif /* xxx */ uint32_t *tpidr_el1 = find_next_insn(start, 0x20, 0xd538d080, 0xffffff80); // search mrs xN, tpidr_el1 @@ -1876,6 +1878,19 @@ bool load_init_program_at_path_callback(struct xnu_pf_patch *patch, uint32_t *op return true; } +bool copyout_callsites_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { + uint32_t* candidate = follow_call(&opcode_stream[1]); + if (!copyout) { + copyout = candidate; + puts("KPF: Found copyout"); + return true; + } + if (candidate != copyout) { + panic("KPF: Found multiple copyout candidates"); + } + return true; +} + void kpf_md0oncores_patch(xnu_pf_patchset_t* patchset) { uint64_t matches[] = @@ -1968,6 +1983,26 @@ void kpf_md0oncores_patch(xnu_pf_patchset_t* patchset) }; xnu_pf_maskmatch(patchset, "load_init_program_at_path", iii_matches, iii_masks, sizeof(iii_matches)/sizeof(uint64_t), false, (void*)load_init_program_at_path_callback); + // Find callsite(s) of copyout function + // Might match more than once but as long as they point the same address it's fine + // Note: In older iOS versions the cbnz instruction could be cbz, but we don't need it here + // /x 0211805200000094f00300aa00000035:ffffffff000000fcf003ffff000000ff + uint64_t copyout_matches[] = + { + 0x52801102, // mov w2, #0x88 + 0x94000000, // bl copyout + 0xaa0003f0, // mov x{16-31}, x0 + 0x35000000 // cbnz wN, ... + }; + + uint64_t copyout_masks[] = + { + 0xffffffff, + 0xfc000000, + 0xffff03f0, + 0xff000000 + }; + xnu_pf_maskmatch(patchset, "copyout_callsites", copyout_matches, copyout_masks, sizeof(copyout_matches)/sizeof(uint64_t), true, (void*)copyout_callsites_callback); } static uint32_t shellcode_count; From d25d4b8a2aed11551cc80deefd90a9197a70d63a Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 19 Feb 2024 01:01:53 +0800 Subject: [PATCH 57/77] kpf: check protobox existence *properly* --- checkra1n/kpf/main.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index eb97b9a8..30e7c233 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1598,7 +1598,7 @@ void kpf_amfi_kext_patches(xnu_pf_patchset_t* patchset) { xnu_pf_maskmatch(patchset, "amfi_mac_syscall_low", iiii_matches, iiii_masks, sizeof(iiii_matches)/sizeof(uint64_t), false, (void*)kpf_amfi_mac_syscall_low); } -void kpf_sandbox_kext_patches(xnu_pf_patchset_t* patchset, const char* constraints_string_match) { +void kpf_sandbox_kext_patches(xnu_pf_patchset_t* patchset, bool protobox_used) { uint64_t matches[] = { 0x35000000, // CBNZ 0x94000000, // BL _vfs_context_current @@ -1627,7 +1627,7 @@ void kpf_sandbox_kext_patches(xnu_pf_patchset_t* patchset, const char* constrain // When injecting into them or using something like Frida, it can prevent certain functionality // Additionally it makes these processes crash on sandbox violations, meaning that calling even something simple like mach_thread_self in watchdogd will crash the process // We disable it by making the code that enables it think the device is in Restore mode, as this check involves calling is_release_type with a string it's easy to find - if (constraints_string_match && xnu_platform() != PLATFORM_BRIDGEOS) { + if (protobox_used) { uint64_t protobox_matches[] = { 0x90000000, // adrp x0, "Restore"@PAGE 0x91000000, // add x0, "Restore"@PAGEOFF @@ -2166,9 +2166,6 @@ static void kpf_cmd(const char *cmd, char *args) const char *livefs_string_match = apfs_text_cstring_range ? memmem(apfs_text_cstring_range->cacheable_base, apfs_text_cstring_range->size, livefs_string, sizeof(livefs_string) - 1) : NULL; if(!livefs_string_match) livefs_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, livefs_string, sizeof(livefs_string) - 1); - const char constraints_string[] = "mac_proc_check_launch_constraints"; - const char *constraints_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, constraints_string, sizeof(constraints_string)); - #ifdef DEV_BUILD // 15.0 beta 1 onwards, but only iOS/iPadOS if((livefs_string_match != NULL) != (gKernelVersion.darwinMajor >= 21 && xnu_platform() == PLATFORM_IOS)) panic("livefs panic doesn't match expected Darwin version"); @@ -2315,7 +2312,24 @@ static void kpf_cmd(const char *cmd, char *args) xnu_pf_patchset_t* sandbox_patchset = xnu_pf_patchset_create(XNU_PF_ACCESS_32BIT); struct mach_header_64* sandbox_header = xnu_pf_get_kext_header(hdr, "com.apple.security.sandbox"); xnu_pf_range_t* sandbox_text_exec_range = xnu_pf_section(sandbox_header, "__TEXT_EXEC", "__text"); - kpf_sandbox_kext_patches(sandbox_patchset, constraints_string_match); + xnu_pf_range_t* protobox_string_range = xnu_pf_section(sandbox_header, "__TEXT", "__cstring"); + if (!protobox_string_range) protobox_string_range = text_cstring_range; + + const char protobox_string[] = "failed to initialize protobox collection"; + const char *protobox_string_match = memmem(protobox_string_range->cacheable_base, protobox_string_range->size, protobox_string, sizeof(protobox_string) - 1); + +#ifdef DEV_BUILD + // 15.0 beta 3 and later, except bridgeOS + if ((gKernelVersion.xnuMajor >= 8019 && (xnu_platform() != PLATFORM_BRIDGEOS)) != (protobox_string_match != NULL)) { + panic("Protobox string doesn't match expected Darwin version"); + } +#endif + + // 16.0 beta 1 and later + const char constraints_string[] = "mac_proc_check_launch_constraints"; + const char *constraints_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, constraints_string, sizeof(constraints_string)); + + kpf_sandbox_kext_patches(sandbox_patchset, (protobox_string_match != NULL) && (constraints_string_match != NULL)); xnu_pf_emit(sandbox_patchset); xnu_pf_apply(sandbox_text_exec_range, sandbox_patchset); xnu_pf_patchset_destroy(sandbox_patchset); From 6bf3ca85d23a0d2163d516e7fbfa82dcc866fc80 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 19 Feb 2024 10:16:04 +0800 Subject: [PATCH 58/77] Fixed APFS Rename for tvOS 15.0+ --- checkra1n/kpf/main.c | 61 +++++++++++++++++++++++++------------------- 1 file changed, 35 insertions(+), 26 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 30e7c233..3489c272 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -960,6 +960,8 @@ bool mach_traps_alt_callback(struct xnu_pf_patch *patch, uint64_t *mach_traps) bool has_found_sbops = 0; uint64_t* sbops; + +bool found_apfs_rename = false; bool sb_ops_callback(struct xnu_pf_patch* patch, uint64_t* sbops_stream) { puts("KPF: Found sbops"); sbops = sbops_stream; @@ -968,8 +970,25 @@ bool sb_ops_callback(struct xnu_pf_patch* patch, uint64_t* sbops_stream) { return true; } bool kpf_apfs_patches_rename(struct xnu_pf_patch* patch, uint32_t* opcode_stream) { + if ( + (opcode_stream[-1] & 0xfec003a0) != 0xf80003a0 /*st(u)r x*, [x29/sp, *]*/ + && (opcode_stream[-1] & 0xffffffff) != 0xaa0003fc /* mov x28, x0 */ + ) return false; + + if (found_apfs_rename) { + panic("APFS rename: Found twice"); + } + found_apfs_rename = true; puts("KPF: Found APFS rename"); - opcode_stream[3] = NOP; + if ((opcode_stream[2] & 0xff000000) == 0x36000000) { + /* tbz -> b */ + opcode_stream[2] = 0x14000000 | (uint32_t)sxt32(opcode_stream[2] >> 5, 14); + } else if ((opcode_stream[2] & 0xff000000) == 0x37000000) { + /* tbnz -> nop */ + opcode_stream[2] = NOP; + } else { + panic("KPF: unreachable in apfs_patches_rename"); + } return true; } @@ -1176,7 +1195,7 @@ bool kpf_apfs_rootauth_new(struct xnu_pf_patch *patch, uint32_t *opcode_stream) } #endif -void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { +void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_ssv, bool support_rootauth) { // there is a check in the apfs mount function that makes sure that the kernel task is calling this function (current_task() == kernel_task) // we also want to call it so we patch that check out // example from i7 13.3: @@ -1210,7 +1229,7 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { 0xfc000000, }; xnu_pf_maskmatch(patchset, "apfs_patch_mount", matches, masks, sizeof(matches)/sizeof(uint64_t), true, (void*)kpf_apfs_patches_mount); - if(have_union) + if(!have_ssv) { // the rename function will prevent us from renaming a snapshot that's on the rootfs, so we will just patch that check out // example from i7 13.3 @@ -1218,31 +1237,32 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { // 0xfffffff0068f3d5c e01f00f9 str x0, [sp, 0x38] // 0xfffffff0068f3d60 08c44039 ldrb w8, [x0, 0x31] ; [0x31:4]= // 0xfffffff0068f3d64 68043037 tbnz w8, 6, 0xfffffff0068f3df0 <- patch this out - // Since iOS 15, the "str" can also be "stur", so we mask out one of the upper bits to catch both, + // This patch must not be applied to iOS 15+ because it means people can recovery loop their devices by renaming the snapshot + // Since tvOS 15.0, the "str" can also be "stur", so we mask out one of the upper bits to catch both, // and we apply a mask of 0x1d to the base register, to catch exactly x29 and sp. + // Since tvOS 15.4, the first st(u)r instruction can also be mov x28, x0, so we only check it in the callback + // Since tvOS 16.0, the tbnz instruction can also be tbz, which required converting the branch instead of nopping // r2 cmd: - // /x a00300f8a00300f80000403900003037:a003c0fea003c0fe0000feff0000f8ff + // /x a00300f80000403900003037:a003c0fe0000feff0000f8ff uint64_t i_matches[] = { - 0xf80003a0, // st(u)r x*, [x29/sp, *] 0xf80003a0, // st(u)r x*, [x29/sp, *] 0x39400000, // ldrb w*, [x*] - 0x37300000, // tbnz w*, 6, * + 0x36300000, // tb(n)z w*, 6, * }; uint64_t i_masks[] = { - 0xfec003a0, 0xfec003a0, 0xfffe0000, - 0xfff80000, + 0xfef80000, }; xnu_pf_maskmatch(patchset, "apfs_patch_rename", i_matches, i_masks, sizeof(i_matches)/sizeof(uint64_t), true, (void*)kpf_apfs_patches_rename); } -#ifndef DEV_BUILD if( - palera1n_flags & palerain_option_rootful // this patch is not required on rootless - ) + support_rootauth +#ifndef DEV_BUILD + && palera1n_flags & palerain_option_rootful // this patch is not required on rootless #endif - { + ) { // when mounting an apfs volume, there is a check to make sure the volume is // not both root volume and read/write // we just nop the check out @@ -1262,18 +1282,7 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_union) { }; xnu_pf_maskmatch(patchset, - "apfs_vfsop_mount", remount_matches, remount_masks, sizeof(remount_masks) / sizeof(uint64_t), - !have_union -#if DEV_BUILD - && (gKernelVersion.darwinMajor <= 22 -#if __STDC_HOSTED__ - || test_force_rootful -#endif - ) // this patch is not used on ios 17. -#else - && (palera1n_flags & palerain_option_rootful) != 0 -#endif - ,(void *)kpf_apfs_vfsop_mount); + "apfs_vfsop_mount", remount_matches, remount_masks, sizeof(remount_masks) / sizeof(uint64_t), true ,(void *)kpf_apfs_vfsop_mount); } } @@ -2280,7 +2289,7 @@ static void kpf_cmd(const char *cmd, char *args) } } - kpf_apfs_patches(apfs_patchset, rootvp_string_match == NULL); + kpf_apfs_patches(apfs_patchset, livefs_string_match != NULL, rootvp_string_match != NULL); if(livefs_string_match) { From 4255e7fda69248bb716f27dfc88ed7fe56f61f53 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Mon, 19 Feb 2024 10:25:53 +0800 Subject: [PATCH 59/77] If we can remount realfs, disable the snapshot too --- checkra1n/kpf/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 3489c272..7ce966a1 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -2547,7 +2547,7 @@ static void kpf_cmd(const char *cmd, char *args) *mac_execve_hook = delta; } - if(!rootvp_string_match) // Only use underlying fs on union mounts + if(!livefs_string_match) // Only disable snapshot when we can remount realfs { char *snapshotString = (char*)memmem((unsigned char *)text_cstring_range->cacheable_base, text_cstring_range->size, (uint8_t *)"com.apple.os.update-", strlen("com.apple.os.update-")); if (!snapshotString) snapshotString = (char*)memmem((unsigned char *)plk_text_range->cacheable_base, plk_text_range->size, (uint8_t *)"com.apple.os.update-", strlen("com.apple.os.update-")); From 8ce9b6554e0363da2206165baa5ae10cf2fae737 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Tue, 5 Mar 2024 14:03:46 +0800 Subject: [PATCH 60/77] Fix thid_should_crash=0 application --- checkra1n/kpf/main.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 7ce966a1..63487dea 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -2197,23 +2197,18 @@ static void kpf_cmd(const char *cmd, char *args) const char thid_should_crash_string[] = "thid_should_crash"; const char *thid_should_crash_string_match = memmem(bootdata_range->cacheable_base, bootdata_range->size, thid_should_crash_string, sizeof(thid_should_crash_string) - 1); - -#ifdef DEV_BUILD - // 17.0 beta 1 - 17.3 - if((thid_should_crash_string_match != NULL) != gKernelVersion.xnuMajor >= 10002 && gKernelVersion.xnuMajor < 10063) panic("thid_should_crash string doesn't match expected Darwin version"); -#endif - - if (const_klddata_range) { + if (const_klddata_range && !thid_should_crash_string_match) { thid_should_crash_string_match = memmem(const_klddata_range->cacheable_base, const_klddata_range->size, thid_should_crash_string, sizeof(thid_should_crash_string) - 1); } #ifdef DEV_BUILD - // 17.4 beta 1 onwards - if(const_klddata_range && ((thid_should_crash_string_match != NULL) != gKernelVersion.xnuMajor >= 10063)) panic("thid_should_crash string doesn't match expected Darwin version"); + // 17.0 beta 1 onwards + if(((thid_should_crash_string_match != NULL) != gKernelVersion.xnuMajor >= 10002)) panic("thid_should_crash string doesn't match expected Darwin version"); #endif if (thid_should_crash_string_match && !strstr((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), "thid_should_crash=")) { strlcat((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), " thid_should_crash=0", 0x270); + DEVLOG("Applied thid_should_crash=0 boot arg"); } } #ifdef DEV_BUILD From e86577d5d6a093bd4c3b034e0661e46592224ab1 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Tue, 5 Mar 2024 16:06:24 +0800 Subject: [PATCH 61/77] use lrzip because sgp1 downloads are slow --- .github/workflows/ci.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 144e516f..e9025b51 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: dpkg --add-architecture arm64 apt-get update apt-get -y --allow-downgrades dist-upgrade - apt-get install -y build-essential git libc6:arm64 libbsd0:arm64 libbsd-dev:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld curl zstd + apt-get install -y build-essential git libc6:arm64 libbsd0:arm64 libbsd-dev:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld curl - name: Checkout repository uses: actions/checkout@v2 @@ -81,7 +81,9 @@ jobs: - name: Get kernels run: | - curl -Lu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.zst | zstd -cdT0 | tar -x + curl -LO https://github.com/pete4abw/lrzip-next/releases/download/v0.12.6/lrzip-next-static-0.12.6 + chmod +x lrzip-next-static-0.12.6 + curl -Lu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.lrz | ./lrzip-next-static-0.12.6 -d - | tar -x - name: Test KPF run: | From 314c3f73c7f3c8f048ed7d46d675774b28b286e9 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Tue, 5 Mar 2024 16:12:12 +0800 Subject: [PATCH 62/77] Fix protobox patch printf --- .github/workflows/ci.yml | 4 ++-- checkra1n/kpf/main.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e9025b51..cc83f2ad 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,9 +81,9 @@ jobs: - name: Get kernels run: | - curl -LO https://github.com/pete4abw/lrzip-next/releases/download/v0.12.6/lrzip-next-static-0.12.6 + curl -sLO https://github.com/pete4abw/lrzip-next/releases/download/v0.12.6/lrzip-next-static-0.12.6 chmod +x lrzip-next-static-0.12.6 - curl -Lu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.lrz | ./lrzip-next-static-0.12.6 -d - | tar -x + curl -sLu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.lrz | ./lrzip-next-static-0.12.6 -do - | tar -x - name: Test KPF run: | diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 63487dea..8f3b30e1 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -810,7 +810,7 @@ bool kpf_protobox_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) // Make protobox think this device is in "Restore" mode // This will disable protobox opcode_stream[2] = 0xD2800020; // mov x0, #1 - printf("KPF: Found and patched protobox check @ 0x%llx\n", xnu_ptr_to_va(opcode_stream)); + printf("KPF: Found and patched protobox check @ 0x%" PRIx64 "\n", xnu_ptr_to_va(opcode_stream)); return true; } From 776ced38c677575054bb9f89496add05ce754c51 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Wed, 6 Mar 2024 10:54:34 +0800 Subject: [PATCH 63/77] use normal zstd --- .github/workflows/ci.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cc83f2ad..7f2d35c7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: dpkg --add-architecture arm64 apt-get update apt-get -y --allow-downgrades dist-upgrade - apt-get install -y build-essential git libc6:arm64 libbsd0:arm64 libbsd-dev:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld curl + apt-get install -y build-essential git libc6:arm64 libbsd0:arm64 libbsd-dev:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld curl zstd - name: Checkout repository uses: actions/checkout@v2 @@ -81,9 +81,7 @@ jobs: - name: Get kernels run: | - curl -sLO https://github.com/pete4abw/lrzip-next/releases/download/v0.12.6/lrzip-next-static-0.12.6 - chmod +x lrzip-next-static-0.12.6 - curl -sLu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.lrz | ./lrzip-next-static-0.12.6 -do - | tar -x + curl -sLu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.lrz | zstd -cdT0 | tar -x - name: Test KPF run: | From 745e5d022786dd0c3d214fd3efdebc08655b7f2f Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Wed, 6 Mar 2024 12:55:33 +0800 Subject: [PATCH 64/77] Actually use normal zstd --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7f2d35c7..accf755b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -81,7 +81,7 @@ jobs: - name: Get kernels run: | - curl -sLu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.lrz | zstd -cdT0 | tar -x + curl -sLu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.zst | zstd -cdT0 | tar -x - name: Test KPF run: | From 6f40b0ee1ca14dfbb6797db00c903318b121751c Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sat, 23 Mar 2024 11:41:19 +0800 Subject: [PATCH 65/77] Fix 4K md0oncores --- checkra1n/kpf/main.c | 3 ++- checkra1n/kpf/shellcode.S | 7 +++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 8f3b30e1..83e85d7e 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -169,7 +169,7 @@ static void kpf_kernel_version_init(xnu_pf_range_t *text_const_range) // Imports from shellcode.S extern uint32_t sandbox_shellcode[], sandbox_shellcode_setuid_patch[], sandbox_shellcode_ptrs[], sandbox_shellcode_end[]; -extern uint32_t launchd_execve_hook[], launchd_execve_hook_ptr[], launchd_execve_hook_offset[]; +extern uint32_t launchd_execve_hook[], launchd_execve_hook_ptr[], launchd_execve_hook_offset[], launchd_execve_hook_pagesize[]; uint32_t* _mac_mount = NULL; bool kpf_has_done_mac_mount = false; @@ -2536,6 +2536,7 @@ static void kpf_cmd(const char *cmd, char *args) repatch_launchd_execve_hook_offset[0] |= ((current_map_off >> 3) & 0xfff) << 10; repatch_launchd_execve_hook_offset[2] |= ((vm_map_page_size_off >> 2) & 0x7ff) << 11; + if (socnum != 0x8960 && socnum != 0x7000 && socnum != 0x7001) launchd_execve_hook_pagesize[0] = NOP; uint32_t delta = (&repatch_launchd_execve_hook[0]) - mac_execve_hook; delta &= 0x03ffffff; delta |= 0x94000000; diff --git a/checkra1n/kpf/shellcode.S b/checkra1n/kpf/shellcode.S index c3488951..90104ae7 100644 --- a/checkra1n/kpf/shellcode.S +++ b/checkra1n/kpf/shellcode.S @@ -229,6 +229,7 @@ vnode_check_open_orig: .globl _launchd_execve_hook_ptr .globl _launchd_execve_hook_end .globl _launchd_execve_hook_offset +.globl _launchd_execve_hook_pagesize _launchd_execve_hook: b launchd_execve_hook$start @@ -253,8 +254,14 @@ cbz x0, launchd_execve_hook$current_map$zero launchd_execve_hook$current_map$notzero: ldrh w8, [x0, #0x0] // Gets replaced with real offset by kpf b launchd_execve_hook$get_map_page_size +_launchd_execve_hook_pagesize: launchd_execve_hook$current_map$zero: +b launchd_execve_hook$current_map$zero_4k // Replaced with NOP by KPF on 16K +launchd_execve_hook$current_map$zero_16k: mov w8, #0xe // 16k page +b launchd_execve_hook$get_map_page_size +launchd_execve_hook$current_map$zero_4k: +mov w8, #0xc // 4K page launchd_execve_hook$get_map_page_size: mov w1, #0x1 lsl w2, w1, w8 // map_page_size From c93abf8ad7e19e571b54936ceb214dcda29acd2e Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sat, 23 Mar 2024 11:51:37 +0800 Subject: [PATCH 66/77] Define socnum in kpf-test --- checkra1n/kpf-test/main.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/checkra1n/kpf-test/main.c b/checkra1n/kpf-test/main.c index 73632a16..74cb160d 100644 --- a/checkra1n/kpf-test/main.c +++ b/checkra1n/kpf-test/main.c @@ -70,6 +70,8 @@ typedef struct load_command mach_lc_t; typedef struct segment_command_64 mach_seg_t; typedef struct thread_command mach_th_t; +uint32_t socnum = 0x8015; + typedef struct boot_args { uint16_t Revision; From e5f001c4ad0301c9f16dab4e86ebd23a4ea2ba37 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sat, 23 Mar 2024 12:04:48 +0800 Subject: [PATCH 67/77] Remove testing --- .github/workflows/ci.yml | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index accf755b..b36c1e4e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,39 +50,3 @@ jobs: localDir: 'upload' remoteDir: "/palera1n/artifacts/kpf/${{ steps.branch-name.outputs.ref_branch || github.ref }}" - test: - runs-on: ubuntu-22.04 - container: - image: debian:stable - volumes: - - /:/mnt - options: --privileged - - steps: - - name: Install packages - run: | - dpkg --add-architecture arm64 - apt-get update - apt-get -y --allow-downgrades dist-upgrade - apt-get install -y build-essential git libc6:arm64 libbsd0:arm64 libbsd-dev:arm64 gcc-aarch64-linux-gnu libc6-arm64-cross libc6-dev-arm64-cross qemu-user qemu-user-binfmt clang lld curl zstd - - - name: Checkout repository - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - - name: Compile KPF test - run: - make -C checkra1n/kpf-test KPF_CFLAGS="-target aarch64-linux-gnu -L/usr/aarch64-linux-gnu/lib -I/usr/aarch64-linux-gnu/include -L/usr/lib/gcc-cross/aarch64-linux-gnu/*" kpf-test.linux - - - name: Free up space - run: - rm -rf /mnt/usr/share/dotnet /mnt/usr/local/lib/android /mnt/opt/ghc /mnt/opt/hostedtoolcache/CodeQL - - - name: Get kernels - run: | - curl -sLu ${{ secrets.ACTIONS_RESOURCES_LOGIN }} https://static.palera.in/action-resources/kc.tar.zst | zstd -cdT0 | tar -x - - - name: Test KPF - run: | - qemu-aarch64 ./checkra1n/kpf-test/kpf-test.linux -n kernel2; From e8f387580961e5fb8709f674087c8dd7b2085dae Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sat, 23 Mar 2024 12:18:46 +0800 Subject: [PATCH 68/77] fix shellcode patch --- checkra1n/kpf/main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 83e85d7e..fa5b65e1 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -2523,6 +2523,8 @@ static void kpf_cmd(const char *cmd, char *args) uint64_t* repatch_launchd_execve_hook_ptrs = (uint64_t*)(launchd_execve_hook_ptr - shellcode_from + shellcode_to); uint32_t* repatch_launchd_execve_hook = (uint32_t*)(launchd_execve_hook - shellcode_from + shellcode_to); uint32_t* repatch_launchd_execve_hook_offset = (uint32_t*)(launchd_execve_hook_offset - shellcode_from + shellcode_to); + uint32_t* repatch_launchd_execve_hook_pagesize = (uint32_t*)(launchd_execve_hook_pagesize - shellcode_from + shellcode_to); + if (repatch_launchd_execve_hook_ptrs[0] != 0x4141414141414141) { panic("Shellcode corruption"); @@ -2536,7 +2538,7 @@ static void kpf_cmd(const char *cmd, char *args) repatch_launchd_execve_hook_offset[0] |= ((current_map_off >> 3) & 0xfff) << 10; repatch_launchd_execve_hook_offset[2] |= ((vm_map_page_size_off >> 2) & 0x7ff) << 11; - if (socnum != 0x8960 && socnum != 0x7000 && socnum != 0x7001) launchd_execve_hook_pagesize[0] = NOP; + if (socnum != 0x8960 && socnum != 0x7000 && socnum != 0x7001) *repatch_launchd_execve_hook_pagesize = NOP; uint32_t delta = (&repatch_launchd_execve_hook[0]) - mac_execve_hook; delta &= 0x03ffffff; delta |= 0x94000000; From bb6b2e77b19be08d9398edf6c184a0f5a82c23fb Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 29 Mar 2024 00:44:50 +0800 Subject: [PATCH 69/77] Handle force-usbdevice --- checkra1n/kpf/main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index fa5b65e1..6c8d1f2c 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -2143,6 +2143,12 @@ static void kpf_cmd(const char *cmd, char *args) } } + if (dt_node_u32(dt_get("/chosen"), "board-id", 0) == 0x02 && socnum == 0x8011) { + if (!strstr((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), "AppleEmbeddedUSBArbitrator-force-usbdevice=")) { + strlcat((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), " AppleEmbeddedUSBArbitrator-force-usbdevice=1", 0x270); + } + } + qsort(patches, npatches, sizeof(kpf_patch_t*), kpf_compare_patches); xnu_pf_patchset_t* xnu_text_exec_patchset = xnu_pf_patchset_create(XNU_PF_ACCESS_32BIT); From 25a0a4d67d3c4edec07fbab93294feb50713efac Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sun, 31 Mar 2024 00:31:12 +0800 Subject: [PATCH 70/77] md0oncores for xnu-7090, xnu-7195 --- checkra1n/kpf-test/main.c | 9 +++++++++ checkra1n/kpf/main.c | 38 ++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/checkra1n/kpf-test/main.c b/checkra1n/kpf-test/main.c index 74cb160d..1e24853e 100644 --- a/checkra1n/kpf-test/main.c +++ b/checkra1n/kpf-test/main.c @@ -160,6 +160,15 @@ uint64_t get_ticks(void) #endif } +void* dt_get(const char *name) +{ + return NULL; +} + +uint32_t dt_node_u32(void *node, const char *prop, uint32_t idx) { + return 0; +} + void command_register(const char* name, const char* desc, void (*cb)(const char* cmd, char* args)) { // nop diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 6c8d1f2c..e79d318e 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1883,11 +1883,13 @@ bool load_init_program_at_path_callback(struct xnu_pf_patch *patch, uint32_t *op mach_vm_allocate_kernel = follow_call(bl); puts("KPF: Found mach_vm_allocate_kernel"); - return true; } bool copyout_callsites_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { + // Don't match inlined copyout + if (find_prev_insn(opcode_stream-1, 20, 0x52801102, 0xffffffff)) return false; /* mov w2, #0x88 */ + uint32_t* candidate = follow_call(&opcode_stream[1]); if (!copyout) { copyout = candidate; @@ -1948,23 +1950,23 @@ void kpf_md0oncores_patch(xnu_pf_patchset_t* patchset) }; xnu_pf_maskmatch(patchset, "load_init_program_at_path", i_matches, i_masks, sizeof(i_masks)/sizeof(uint64_t), false, (void*)load_init_program_at_path_callback); - // just for xnu-7938 + // xnu-7090 - xnu-7938 uint64_t ii_matches[] = { - 0xa904dff5, // stp x21, x23, [sp, #0x48] - 0xa905ffff, // stp xzr, xzr, [sp, #0x58] - 0x910123e1, // add x1, sp, #0x48 - 0x910103e2, // add x2, sp, #0x40 + 0xa9005ff5, // stp x21, x23, [sp, ...] + 0xa9007fff, // stp xzr, xzr, [sp, ...] + 0x910003e1, // add x1, sp, ... + 0x910003e2, // add x2, sp, ... 0xaa1303e0, // mov x0, x19 0x94000000, // bl __mac_execve - 0x35000000, // cbnz wN, ... + 0x35000000, // cbnz w0, ... }; uint64_t ii_masks[] = { - 0xffffffff, - 0xffffffff, - 0xffffffff, - 0xffffffff, + 0xffc07fff, + 0xffc07fff, + 0xffc003ff, + 0xffc003ff, 0xffffffff, 0xfc000000, 0xff00001f, @@ -2001,7 +2003,7 @@ void kpf_md0oncores_patch(xnu_pf_patchset_t* patchset) 0x52801102, // mov w2, #0x88 0x94000000, // bl copyout 0xaa0003f0, // mov x{16-31}, x0 - 0x35000000 // cbnz wN, ... + 0x34000000 // cb(n)z wN, ... }; uint64_t copyout_masks[] = @@ -2009,7 +2011,7 @@ void kpf_md0oncores_patch(xnu_pf_patchset_t* patchset) 0xffffffff, 0xfc000000, 0xffff03f0, - 0xff000000 + 0xfe000000 }; xnu_pf_maskmatch(patchset, "copyout_callsites", copyout_matches, copyout_masks, sizeof(copyout_matches)/sizeof(uint64_t), true, (void*)copyout_callsites_callback); } @@ -2177,6 +2179,8 @@ static void kpf_cmd(const char *cmd, char *args) const char rootvp_string[] = "rootvp not authenticated after mounting"; const char *rootvp_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, rootvp_string, sizeof(rootvp_string) - 1); + bool has_tmpfs = !!xnu_pf_get_kext_header(hdr, "com.apple.filesystems.tmpfs"); + const char livefs_string[] = "Rooting from the live fs of a sealed volume is not allowed on a RELEASE build"; const char *livefs_string_match = apfs_text_cstring_range ? memmem(apfs_text_cstring_range->cacheable_base, apfs_text_cstring_range->size, livefs_string, sizeof(livefs_string) - 1) : NULL; if(!livefs_string_match) livefs_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, livefs_string, sizeof(livefs_string) - 1); @@ -2186,7 +2190,7 @@ static void kpf_cmd(const char *cmd, char *args) if((livefs_string_match != NULL) != (gKernelVersion.darwinMajor >= 21 && xnu_platform() == PLATFORM_IOS)) panic("livefs panic doesn't match expected Darwin version"); #endif - if (!rootvp_string_match) { + if (!has_tmpfs) { strlcat((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), " rootdev=md0", 0x270); } @@ -2397,9 +2401,11 @@ static void kpf_cmd(const char *cmd, char *args) kpf_vm_map_protect_patch(xnu_text_exec_patchset); kpf_mac_vm_fault_enter_patch(xnu_text_exec_patchset); kpf_find_shellcode_funcs(xnu_text_exec_patchset); - if(rootvp_string_match) // Union mounts no longer work + if(has_tmpfs) { kpf_md0oncores_patch(xnu_text_exec_patchset); + } + if (rootvp_string_match) { // Union mounts no longer work kpf_vnop_rootvp_auth_patch(xnu_text_exec_patchset); } @@ -2517,7 +2523,7 @@ static void kpf_cmd(const char *cmd, char *args) uint32_t* repatch_vnode_shellcode = &shellcode_area[4]; *repatch_vnode_shellcode = repatch_ldr_x19_vnode_pathoff; - if(rootvp_string_match) + if(has_tmpfs) { if (!mdevremoveall) panic("no mdevremoveall"); if (!mac_execve) panic("no mac_execve"); From eaa11a8852cec708b312fff2abdf06d486e49125 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sun, 31 Mar 2024 01:47:59 +0800 Subject: [PATCH 71/77] apply apfs_vfsop_mount on xnu-7195 --- checkra1n/kpf/main.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index e79d318e..8a296809 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1133,12 +1133,12 @@ bool kpf_apfs_vfsop_mount(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { uint32_t off = (adrp[1] >> 10) & 0xfff; const char *str = (const char*)(page + off); if (!strstr(str, "Updating mount to read/write mode is not allowed\n")) { - return false; + return false; } opcode_stream[1] = 0x52800000; /* mov w0, 0 */ has_found_apfs_vfsop_mount = true; - + printf("KPF: found apfs_vfsop_mount\n"); return true; @@ -1195,7 +1195,7 @@ bool kpf_apfs_rootauth_new(struct xnu_pf_patch *patch, uint32_t *opcode_stream) } #endif -void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_ssv, bool support_rootauth) { +void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_ssv, bool has_tmpfs) { // there is a check in the apfs mount function that makes sure that the kernel task is calling this function (current_task() == kernel_task) // we also want to call it so we patch that check out // example from i7 13.3: @@ -1258,7 +1258,7 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_ssv, bool support_r } if( - support_rootauth + has_tmpfs #ifndef DEV_BUILD && palera1n_flags & palerain_option_rootful // this patch is not required on rootless #endif @@ -1273,7 +1273,7 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_ssv, bool support_r // r2: /x a00340b900781f12a00300b9:a003feff00fcffffa003c0ff uint64_t remount_matches[] = { 0x94000000, // bl - 0x37700000, // tbnz w0, 0xe, * + 0x37700000, // tbnz w0, 0xe, * }; uint64_t remount_masks[] = { @@ -2294,7 +2294,7 @@ static void kpf_cmd(const char *cmd, char *args) } } - kpf_apfs_patches(apfs_patchset, livefs_string_match != NULL, rootvp_string_match != NULL); + kpf_apfs_patches(apfs_patchset, livefs_string_match != NULL, has_tmpfs); if(livefs_string_match) { From 4203fea85e50f98dbba7950c18ff2e3105acb530 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sun, 31 Mar 2024 11:35:03 +0800 Subject: [PATCH 72/77] Use the apfs_vfsop_mount string instead of has_tmpfs --- checkra1n/kpf/main.c | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 8a296809..783921f1 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1195,7 +1195,7 @@ bool kpf_apfs_rootauth_new(struct xnu_pf_patch *patch, uint32_t *opcode_stream) } #endif -void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_ssv, bool has_tmpfs) { +void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_ssv, bool apfs_vfsop_mount_string_match) { // there is a check in the apfs mount function that makes sure that the kernel task is calling this function (current_task() == kernel_task) // we also want to call it so we patch that check out // example from i7 13.3: @@ -1258,7 +1258,7 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_ssv, bool has_tmpfs } if( - has_tmpfs + apfs_vfsop_mount_string_match #ifndef DEV_BUILD && palera1n_flags & palerain_option_rootful // this patch is not required on rootless #endif @@ -2179,7 +2179,14 @@ static void kpf_cmd(const char *cmd, char *args) const char rootvp_string[] = "rootvp not authenticated after mounting"; const char *rootvp_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, rootvp_string, sizeof(rootvp_string) - 1); - bool has_tmpfs = !!xnu_pf_get_kext_header(hdr, "com.apple.filesystems.tmpfs"); + const char apfs_vfsop_mount_string[] = "Updating mount to read/write mode is not allowed\n"; + const char *apfs_vfsop_mount_string_match = apfs_text_cstring_range ? memmem(apfs_text_cstring_range->cacheable_base, apfs_text_cstring_range->size, apfs_vfsop_mount_string, sizeof(apfs_vfsop_mount_string) - 1) : NULL; + if(!apfs_vfsop_mount_string_match) apfs_vfsop_mount_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, apfs_vfsop_mount_string, sizeof(apfs_vfsop_mount_string) - 1); + +#ifdef DEV_BUILD + // 14.0 beta 1 onwards + if((apfs_vfsop_mount_string_match != NULL) != (gKernelVersion.darwinMajor >= 20)) panic("apfs_vfsop_mount string doesn't match expected Darwin version"); +#endif const char livefs_string[] = "Rooting from the live fs of a sealed volume is not allowed on a RELEASE build"; const char *livefs_string_match = apfs_text_cstring_range ? memmem(apfs_text_cstring_range->cacheable_base, apfs_text_cstring_range->size, livefs_string, sizeof(livefs_string) - 1) : NULL; @@ -2190,7 +2197,7 @@ static void kpf_cmd(const char *cmd, char *args) if((livefs_string_match != NULL) != (gKernelVersion.darwinMajor >= 21 && xnu_platform() == PLATFORM_IOS)) panic("livefs panic doesn't match expected Darwin version"); #endif - if (!has_tmpfs) { + if (!apfs_vfsop_mount_string_match) { strlcat((char*)((int64_t)gBootArgs->iOS13.CommandLine - 0x800000000 + kCacheableView), " rootdev=md0", 0x270); } @@ -2294,7 +2301,7 @@ static void kpf_cmd(const char *cmd, char *args) } } - kpf_apfs_patches(apfs_patchset, livefs_string_match != NULL, has_tmpfs); + kpf_apfs_patches(apfs_patchset, livefs_string_match != NULL, apfs_vfsop_mount_string_match != NULL); if(livefs_string_match) { @@ -2401,7 +2408,7 @@ static void kpf_cmd(const char *cmd, char *args) kpf_vm_map_protect_patch(xnu_text_exec_patchset); kpf_mac_vm_fault_enter_patch(xnu_text_exec_patchset); kpf_find_shellcode_funcs(xnu_text_exec_patchset); - if(has_tmpfs) + if(apfs_vfsop_mount_string_match) { kpf_md0oncores_patch(xnu_text_exec_patchset); } @@ -2427,12 +2434,9 @@ static void kpf_cmd(const char *cmd, char *args) if (!found_vm_map_protect) panic("Missing patch: vm_map_protect"); if (!vfs_context_current) panic("Missing patch: vfs_context_current"); if (!kpf_has_done_mac_mount) panic("Missing patch: mac_mount"); - if (!has_found_apfs_vfsop_mount && rootvp_string_match != NULL) { -#if __STDC_HOSTED__ - if (gKernelVersion.darwinMajor <= 22 || test_force_rootful) { - panic("Missing patch: apfs_vfsop_mount"); - } else -#endif + + + if (!has_found_apfs_vfsop_mount && apfs_vfsop_mount_string_match != NULL) { if (palera1n_flags & palerain_option_rootful) { panic("Missing patch: apfs_vfsop_mount"); } else { @@ -2523,7 +2527,7 @@ static void kpf_cmd(const char *cmd, char *args) uint32_t* repatch_vnode_shellcode = &shellcode_area[4]; *repatch_vnode_shellcode = repatch_ldr_x19_vnode_pathoff; - if(has_tmpfs) + if(apfs_vfsop_mount_string_match) { if (!mdevremoveall) panic("no mdevremoveall"); if (!mac_execve) panic("no mac_execve"); From a3c128da5b1a7bd3dc602f8c546f14a7c984bd15 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sun, 31 Mar 2024 18:40:16 +0800 Subject: [PATCH 73/77] Generate development PongoOS in actions --- .github/workflows/ci.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b36c1e4e..5d2501d3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -28,12 +28,23 @@ jobs: run: | make - - name: Prepare upload directory + - name: Prepare upload directory run: | mkdir upload mv build/Pongo.bin upload/ mv build/checkra1n-kpf-pongo upload/ + - name: Compile KPF and Pongo Development + run: | + make clean + make DEV_BUILD=1 + + - name: Prepare upload directory Development + run: | + mkdir upload + mv build/Pongo.bin upload/Pongo.bin.development + mv build/checkra1n-kpf-pongo upload/checkra1n-kpf-pongo.development + - name: Get branch name id: branch-name uses: tj-actions/branch-names@v7 From 30d5150ce14b26e4e81862a1a93dac00b558682c Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sun, 31 Mar 2024 18:43:06 +0800 Subject: [PATCH 74/77] Do not mkdir twice --- .github/workflows/ci.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5d2501d3..ea4a4cca 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -41,7 +41,6 @@ jobs: - name: Prepare upload directory Development run: | - mkdir upload mv build/Pongo.bin upload/Pongo.bin.development mv build/checkra1n-kpf-pongo upload/checkra1n-kpf-pongo.development From d48308aa0278ceb0c064d3e6c5fad64b55763b84 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Fri, 5 Apr 2024 23:35:10 +0800 Subject: [PATCH 75/77] Add root on orig-fs patch --- checkra1n/kpf/main.c | 94 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 783921f1..e82fd2e8 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -1144,6 +1144,42 @@ bool kpf_apfs_vfsop_mount(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { return true; } +bool kpf_apfs_root_snapshot_name(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { + const char *str = (const char *)(((uint64_t)(opcode_stream) & ~0xfffULL) + + adrp_off(opcode_stream[0]) + ((opcode_stream[1] >> 10) & 0xfff)); + if (strcmp(str, "0123456789ABCDEF") != 0) return false; + + uint32_t* b_cond = find_next_insn(opcode_stream, 20, 0x54000000, 0xff000000); // b.cond + if (!b_cond) { + panic("kpf_apfs_root_snapshot_name_inlined: failed to find b.cond"); + } + uint32_t* dest_addr = b_cond + 1; + + /* + * addr_reg holds a pointer to a buffer as follows: + * com.apple.os.update- ... to be filled in with hash + * ^ + * pointer in addr_reg + * We seek back to the start of the string, write "orig-fs\x00" + * into it, then skip the loop for filling in the buffer + * character-by-character. + */ + + uint32_t addr_reg = (opcode_stream[9] >> 5) & 0x1f; // strb wN, [addr_reg, xN, lsl] + uint32_t scratch_reg = addr_reg - 1; + uint32_t imm12 = 20; + opcode_stream[0] = 0xd1000000 | imm12 << 10 | addr_reg << 5 | scratch_reg; // sub scratch_reg, addr_reg, #0x14 + opcode_stream[1] = 0x10000080 | addr_reg; // adr addr_reg, #0x10 + opcode_stream[2] = 0xf9400000 | addr_reg << 5 | addr_reg; // ldr addr_reg, [addr_reg] + opcode_stream[3] = 0xf9000000 | addr_reg | scratch_reg << 5; // str addr_reg, [scratch_reg] + opcode_stream[4] = 0x14000000 | ((dest_addr - &opcode_stream[4]) & 0x3fffffff); // b dest_addr + opcode_stream[5] = 0x6769726f; // orig + opcode_stream[6] = 0x0073662d; // -fs\x00 + + printf("KPF: found apfs_root_snapshot_name\n"); + return true; +} + #if 0 bool handled_eval_rootauth = false; bool kpf_apfs_rootauth(struct xnu_pf_patch *patch, uint32_t *opcode_stream) { @@ -1285,6 +1321,64 @@ void kpf_apfs_patches(xnu_pf_patchset_t* patchset, bool have_ssv, bool apfs_vfso "apfs_vfsop_mount", remount_matches, remount_masks, sizeof(remount_masks) / sizeof(uint64_t), true ,(void *)kpf_apfs_vfsop_mount); } + +#if __STDC_HOSTED__ == 0 + if ((palera1n_flags & palerain_option_ssv) == 0 && (palera1n_flags & palerain_option_force_revert)) +#endif + { + // This patch is required because on md0oncores, the rootfs is mounted by the kernel + // However, when force reverting on platforms without SSV we want to mount the snapshot + // of the real filesystem, so as to cleanup uicache properly. Here, we change the + // snapshot that the kernel boots from to orig-fs + // Example from Apple TV HD 17.2: + // 0xfffffff006ae3528 09008052 movz w9, 0 + // 0xfffffff006ae352c 0a0080d2 movz x10, 0 + // 0xfffffff006ae3530 8b520091 add x11, x20, 0x14 + // 0xfffffff006ae3534 ac85ffb0 adrp x12, 0xfffffff005b98000 + // 0xfffffff006ae3538 8c990691 add x12, x12, 0x1a6 + // ┌──> 0xfffffff006ae353c 4dfd41d3 lsr x13, x10, 1 + // ╎ 0xfffffff006ae3540 6d6a6d38 ldrb w13, [x19, x13] ; 0xd4000000da ; 910533066970 + // ╎ 0xfffffff006ae3544 ee03292a mvn w14, w9 + // ╎ 0xfffffff006ae3548 ce017e92 and x14, x14, 4 + // ╎ 0xfffffff006ae354c ad25ce9a lsr x13, x13, x14 + // ╎ 0xfffffff006ae3550 ad0d4092 and x13, x13, 0xf + // ╎ 0xfffffff006ae3554 8d696d38 ldrb w13, [x12, x13] ; 0xd4000000d3 ; 910533066963 + // ╎ 0xfffffff006ae3558 6d692a38 strb w13, [x11, x10] + // ╎ 0xfffffff006ae355c 4a050091 add x10, x10, 1 + // ╎ 0xfffffff006ae3560 29110011 add w9, w9, 4 + // ╎ 0xfffffff006ae3564 1f010aeb cmp x8, x10 + // └──< 0xfffffff006ae3568 a1feff54 b.ne 0xfffffff006ae353c + // r2: /x 000000900000009100fc41d300686038e003202a00001e120024c01a000c00120008603800682038:0000009f0000c0ff00fcffff00fce0ffe0ffe0ff00fc9f7f00fce07f00fc9f7f001ce0ff00fce0ff + // This call is sometimes inlined, hence why the patch is somewhat complicated + uint64_t root_snapshot_matches[] = { + 0x90000000, // adrp xN, ... + 0x91000000, // add xN, xN, ... + 0xd341fc00, // lsr xN, xN, #0x1 + 0x38606800, // ldrb wN, [xN, xN, lsl] + 0x2a2003e0, // mvn xN, xN + 0x121e0000, // and rN, rN, #0x4 + 0x1ac02400, // lsr xN, xN, xN + 0x12000c00, // and rN, rN, #0xf + 0x38600800, // ldrb wN, [xN, xN, ...] + 0x38206800 // strb wN, [xN, xN, lsl] + }; + + uint64_t root_snapshot_masks[] = { + 0x9f000000, + 0xffc00000, + 0xfffffc00, + 0xffe0fc00, + 0xffe0ffe0, + 0x7f9ffc00, + 0x7fe0fc00, + 0x7f9ffc00, + 0xffe01c00, + 0xffe0fc00 + }; + + xnu_pf_maskmatch(patchset, + "apfs_root_snapshot_name", root_snapshot_matches, root_snapshot_masks, sizeof(root_snapshot_matches) / sizeof(uint64_t), true ,(void *)kpf_apfs_root_snapshot_name); + } } static uint32_t* amfi_ret; bool kpf_amfi_execve_tail(struct xnu_pf_patch* patch, uint32_t* opcode_stream) { From 603c88d44b848513a5a51fc0d58c123e25139ff7 Mon Sep 17 00:00:00 2001 From: Nick Chan Date: Sun, 7 Apr 2024 15:57:09 +0800 Subject: [PATCH 76/77] fix rootful 17.4 --- checkra1n/kpf/main.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index e82fd2e8..5b8af465 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -2304,9 +2304,10 @@ static void kpf_cmd(const char *cmd, char *args) } #endif + const char *thid_should_crash_string_match = NULL; if (bootdata_range) { const char thid_should_crash_string[] = "thid_should_crash"; - const char *thid_should_crash_string_match = memmem(bootdata_range->cacheable_base, bootdata_range->size, thid_should_crash_string, sizeof(thid_should_crash_string) - 1); + thid_should_crash_string_match = memmem(bootdata_range->cacheable_base, bootdata_range->size, thid_should_crash_string, sizeof(thid_should_crash_string) - 1); if (const_klddata_range && !thid_should_crash_string_match) { thid_should_crash_string_match = memmem(const_klddata_range->cacheable_base, const_klddata_range->size, thid_should_crash_string, sizeof(thid_should_crash_string) - 1); @@ -2661,6 +2662,22 @@ static void kpf_cmd(const char *cmd, char *args) if (!snapshotString) snapshotString = (char*)memmem((unsigned char *)plk_text_range->cacheable_base, plk_text_range->size, (uint8_t *)"com.apple.os.update-", strlen("com.apple.os.update-")); if (!snapshotString) panic("no snapshot string"); +#if __STDC_HOSTED__ == 0 + if (thid_should_crash_string_match != NULL) { + size_t root_snapshot_name_len = 0; + dt_node_t* chosen = dt_find(gDeviceTree, "chosen"); + if (!chosen) panic("invalid devicetree: no device!"); + char* snapshotString2 = dt_prop(chosen, "root-snapshot-name", &root_snapshot_name_len); + if (!snapshotString2) panic("invalid devicetree: no prop!"); + + if ((palera1n_flags & palerain_option_ssv) == 0 && (palera1n_flags & palerain_option_force_revert)) { + memcpy(snapshotString2, "orig-fs", sizeof("orig-fs")); + } else { + *snapshotString2 = 'x'; + } + } +#endif + *snapshotString = 'x'; puts("KPF: Disabled snapshot temporarily"); } From 96aec00939005596f6f6e9d1f5cdc5ca043d62c8 Mon Sep 17 00:00:00 2001 From: Patrice Blin Date: Wed, 10 Apr 2024 16:56:37 +0200 Subject: [PATCH 77/77] Fix amfi_ret jump offset computing --- checkra1n/kpf/main.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/checkra1n/kpf/main.c b/checkra1n/kpf/main.c index 5b8af465..369a4423 100644 --- a/checkra1n/kpf/main.c +++ b/checkra1n/kpf/main.c @@ -2539,7 +2539,10 @@ static void kpf_cmd(const char *cmd, char *args) } } - uint32_t delta = (&shellcode_area[1]) - amfi_ret; + uint64_t shc_amfi_addr = xnu_ptr_to_va(&shellcode_area[1]); + uint64_t amfi_ret_addr = xnu_ptr_to_va(amfi_ret); + int64_t offset = shc_amfi_addr - amfi_ret_addr; + uint32_t delta = offset >> 2; delta &= 0x03ffffff; delta |= 0x14000000; *amfi_ret = delta;