diff --git a/include/xxd-embedded.h b/include/xxd-embedded.h index e63d671..328b2cc 100644 --- a/include/xxd-embedded.h +++ b/include/xxd-embedded.h @@ -22,7 +22,7 @@ extern uint32_t binpack_dmg_len; extern uint8_t Pongo_bin[]; extern uint32_t Pongo_bin_len; -#if defined(__APPLE__) && (TARGET_OS_IPHONE || defined(DEV_BUILD) || defined(FORCE_HELPER)) +#if defined(__APPLE__) extern uint8_t libcheckra1nhelper_dylib[]; extern uint32_t libcheckra1nhelper_dylib_len; #endif diff --git a/src/Makefile b/src/Makefile index 11ba5f8..b238d7e 100644 --- a/src/Makefile +++ b/src/Makefile @@ -4,6 +4,8 @@ OBJDIR = obj GENDIR = gen RESOURCES_DIR = resources +export RESOURCES_DIR OBJDIR GENDIR + C_SRC = $(wildcard *.c) OBJS = $(patsubst %,$(OBJDIR)/%,$(C_SRC:.c=.c.o)) @@ -23,13 +25,9 @@ ifeq ($(DFUHELPER_AUTO_ONLY),1) CFLAGS += -DDFUHELPER_AUTO_ONLY endif -ifeq ($(FORCE_HELPER),1) -ifneq ($(NO_EMBED_HELPER),1) +ifeq ($(TARGET_OS),Darwin) C_SRC += $(GENDIR)/gen-libcheckra1nhelper.dylib.c endif -CFLAGS += -DFORCE_HELPER -BUILD_OPTIONS += FORCE_HELPER -endif ifneq ($(NO_RAMDISK),1) C_SRC += $(GENDIR)/gen-ramdisk.dmg.lzma.c @@ -149,7 +147,6 @@ $(GENDIR)/gen-%.c: $(RESOURCES_DIR)/% echo '#include ' > $(RESOURCES_DIR)/../$@ cd $(RESOURCES_DIR) && xxd -iC $$(echo $< | cut -d/ -f2) | sed -e 's/unsigned int/uint32_t/' -e 's/unsigned char/uint8_t/' >> ../$@ - $(OBJDIR)/pongo_helper.c.o: pongo_helper.c $(wildcard ../include/*.h) $(RESOURCES_DIR)/ramdisk.dmg $(RESOURCES_DIR)/checkra1n-kpf-pongo $(CC) -c -o $@ $(CFLAGS) -DRAMDISK_UNCOMPRESSED_SIZE="\"$$(wc -c < $(RESOURCES_DIR)/ramdisk.dmg | tr -d ' ')\"" -DKPF_UNCOMPRESSED_SIZE="\"$$(wc -c < $(RESOURCES_DIR)/checkra1n-kpf-pongo | tr -d ' ')\"" $< @@ -167,8 +164,8 @@ ifneq (,$(findstring version-min=, $(CFLAGS))) endif endif -$(RESOURCES_DIR)/libcheckra1nhelper.dylib: chkstk.S - $(CC) $(CFLAGS) $(LDFLAGS) -shared chkstk.S -o $@ +$(RESOURCES_DIR)/libcheckra1nhelper.dylib: + $(MAKE) -C helper $(RESOURCES_DIR)/checkra1n-kpf-pongo: curl -Lfo $@ https://cdn.nickchan.lol/palera1n/artifacts/kpf/iOS15/checkra1n-kpf-pongo @@ -189,9 +186,9 @@ $(RESOURCES_DIR)/Pongo.bin: curl -Lfo $@ https://cdn.nickchan.lol/palera1n/artifacts/kpf/iOS15/Pongo.bin clean: - rm -rf $(OBJDIR)/*.o $(GENDIR)/*.c $(GENDIR)/*.o palera1n palera1n.dSYM libcheckra1nhelper.dylib + rm -rf $(OBJDIR)/*.o $(GENDIR)/*.c $(GENDIR)/*.o palera1n palera1n.dSYM $(RESOURCES_DIR)/libcheckra1nhelper.dylib distclean: clean rm -rf $(RESOURCES_DIR)/* -.PHONY: all clean +.PHONY: all clean $(RESOURCES_DIR)/libcheckra1nhelper.dylib diff --git a/src/exec_checkra1n.c b/src/exec_checkra1n.c index 113ce61..aeaf940 100644 --- a/src/exec_checkra1n.c +++ b/src/exec_checkra1n.c @@ -100,16 +100,23 @@ int exec_checkra1n(void) { return -1; } } -#if defined(__APPLE__) && defined(__arm64__) && (TARGET_OS_IPHONE || defined(FORCE_HELPER)) +#if defined(__APPLE__) + char resolved_c1_path[PATH_MAX], *resolved; + resolved = realpath(checkra1n_path, resolved_c1_path); + + if (!resolved) { + LOG(LOG_FATAL, "Cannot resolve checkra1n path %s: %d (%s)", checkra1n_path, errno, strerror(errno)); + if (ext_checkra1n == NULL) { + unlink(checkra1n_path); + free(checkra1n_path); + } + checkra1n_path = NULL; + return -1; + } + char* libcheckra1nhelper_dylib_path = NULL; - { - struct utsname name; - uname(&name); - unsigned long darwinMajor = strtoul(name.release, NULL, 10); - assert(darwinMajor != 0); -#if !defined(FORCE_HELPER) - if (darwinMajor < 20) { -#endif + if (ext_checkra1n == NULL || gOverrideLibcheckra1nHelper) { + setenv("LIBCHECKRA1NHELPER_CHECKRA1N_PATH", resolved_c1_path, 1); if (gOverrideLibcheckra1nHelper) { libcheckra1nhelper_dylib_path = gOverrideLibcheckra1nHelper; goto setenv_ra1n; @@ -141,9 +148,6 @@ int exec_checkra1n(void) { } setenv_ra1n: setenv("DYLD_INSERT_LIBRARIES", libcheckra1nhelper_dylib_path, 1); -#if !defined(FORCE_HELPER) - } -#endif } #endif char args[0x10] = "-E"; @@ -193,7 +197,7 @@ setenv_ra1n: } if (pongo_path != NULL) free(pongo_path); pongo_path = NULL; -#if defined(__APPLE__) && defined(__arm64__) && (TARGET_OS_IPHONE || defined(FORCE_HELPER)) +#if defined(__APPLE__) if (libcheckra1nhelper_dylib_path != NULL) { if (!gOverrideLibcheckra1nHelper) unlink(libcheckra1nhelper_dylib_path); unsetenv("DYLD_INSERT_LIBRARIES"); diff --git a/src/helper/Makefile b/src/helper/Makefile new file mode 100644 index 0000000..a348590 --- /dev/null +++ b/src/helper/Makefile @@ -0,0 +1,27 @@ +C_SRC = $(wildcard *.c) +C_OBJS = $(patsubst %,../$(OBJDIR)/%,$(C_SRC:.c=.c.o)) + +S_SRC = $(wildcard *.S) +S_OBJS = $(patsubst %,../$(OBJDIR)/%,$(S_SRC:.S=.S.o)) + +CFLAGS += -fvisibility=hidden + +C_OBJS += ../$(GENDIR)/gen-payload-t7000.c.o ../$(GENDIR)/gen-payload-t8011.c.o ../$(GENDIR)/gen-payload-t8012.c.o + +all: ../$(RESOURCES_DIR)/libcheckra1nhelper.dylib + +../$(OBJDIR)/%.c.o: %.c + $(CC) $(CFLAGS) -c -o $@ $< + +../$(OBJDIR)/%.S.o: %.S + $(CC) $(CFLAGS) -c -o $@ $< + +../$(RESOURCES_DIR)/libcheckra1nhelper.dylib: $(C_OBJS) $(S_OBJS) $(wildcard *.h) + $(CC) $(CFLAGS) $(LDFLAGS) -shared $(C_OBJS) $(S_OBJS) -o $@ + +../$(GENDIR)/gen-payload-%.c: payloads/%.bin + echo '#include ' > $@ + cd payloads && xxd -iC $$(echo $< | cut -d/ -f2) | sed -e 's/unsigned int/uint32_t/' -e 's/unsigned char/uint8_t/' >> ../$@ + +../$(GENDIR)/gen-payload-%.c.o: ../$(GENDIR)/gen-payload-%.c + $(CC) $(CFLAGS) -c -o $@ $< diff --git a/src/chkstk.S b/src/helper/chkstk.S similarity index 94% rename from src/chkstk.S rename to src/helper/chkstk.S index 3b6ba6b..d7400b3 100644 --- a/src/chkstk.S +++ b/src/helper/chkstk.S @@ -1,3 +1,7 @@ +#include + +#if defined(__APPLE__) && defined(__arm64__) && TARGET_OS_IPHONE + #define _PTHREAD_STRUCT_DIRECT_STACKADDR_OFFSET -48 #define _PTHREAD_STRUCT_DIRECT_STACKBOTTOM_OFFSET -40 @@ -63,3 +67,4 @@ Lend: sub x10, x10, x9 ldr x11, [x10] b Lexit +#endif diff --git a/src/helper/helper.c b/src/helper/helper.c new file mode 100644 index 0000000..ea3623d --- /dev/null +++ b/src/helper/helper.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "phookra1n.h" + +extern char ***_NSGetArgv(void); +extern int *_NSGetArgc(void); + +__attribute__((constructor)) void ctor(void) +{ + char ***argvp = _NSGetArgv(); + int *argcp = _NSGetArgc(); + + assert(argvp); + assert(argcp); + + int argc = *argcp; + char **argv = *argvp; + +#if TARGET_OS_IPHONE + if (argc == 2 && strcmp(argv[1], "__CHECKRA1N_JIT_PLEASE__") == 0) { + assert(ptrace(PT_TRACE_ME, 0, 0, 0) == 0); + exit(0); + } else { + char exe_path[PATH_MAX]; + uint32_t exe_path_size = PATH_MAX; + assert(_NSGetExecutablePath(exe_path, &exe_path_size) == 0); + pid_t pid; + assert(posix_spawnp(&pid, exe_path, NULL, NULL, (char*[]){"__CHECKRA1N_JIT_PLEASE__",NULL}, NULL) == 0); + assert(waitpid(pid, NULL, 0) == pid); + } +#endif + + char *c1_path = getenv("LIBCHECKRA1NHELPER_CHECKRA1N_PATH"); + + assert(c1_path); + + dprintf("Welcome to Checkra1n Hook!\n"); + + int c1_image_index = 0; + for (uint32_t i = 0; i < _dyld_image_count(); i++) { + if(!strcmp(_dyld_get_image_name(i), c1_path)) { + c1_image_index = i; + break; + } + } + intptr_t slide = _dyld_get_image_vmaddr_slide(c1_image_index); + struct mach_header_64 *mach_header = (struct mach_header_64*)_dyld_get_image_header(c1_image_index); + + uintptr_t cmd_current = (uintptr_t)(mach_header + 1); + uintptr_t cmd_end = cmd_current + mach_header->sizeofcmds; + + const struct segment_command_64 *__TEXT = NULL; + + for (uint32_t i = 0; i < mach_header->ncmds && cmd_current <= cmd_end; i++) { + const struct segment_command_64 *cmd; + + cmd = (struct segment_command_64*)cmd_current; + cmd_current += cmd->cmdsize; + + if (cmd->cmd != LC_SEGMENT_64 || strcmp(cmd->segname, "__TEXT")) { + continue; + } + __TEXT = cmd; + } + + assert(__TEXT); + +#if defined(__arm64__) + assert(__TEXT->vmsize == 0x24000); + setup_hooks_arm64((void*)(__TEXT->vmaddr + slide)); +#endif +} + diff --git a/src/helper/hook_arm64.c b/src/helper/hook_arm64.c new file mode 100644 index 0000000..abe13b5 --- /dev/null +++ b/src/helper/hook_arm64.c @@ -0,0 +1,65 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "phookra1n.h" + +#if defined(__arm64__) + +static void patch(uint32_t *stream, const uint8_t *payload, const uint32_t payload_len) +{ + uint64_t from = (uint64_t)stream; + uint64_t to = (uint64_t)payload; + + uint32_t adrp_off = ((to & ~0xfff) - (from & ~0xfff)) >> 12; + uint32_t add_off = to & 0xfff; + + dprintf("from 0x%llx to 0x%llx 0x%llx 0x%x\n", from, to, ((from & ~0xfff) + (adrp_off << 12)), add_off); + + uint8_t adrp_reg = stream[0] & 0x1f; + uint8_t add_reg = stream[1] & 0x1f; + uint8_t mov1_reg = stream[2] & 0x1f; + uint8_t mov2_reg = stream[3] & 0x1f; + + uint8_t immlo = adrp_off & 0x3; + uint8_t immhi = (adrp_off >> 2) & 0x7ffff; + + stream[0] = 0x90000000 | adrp_reg | immlo << 29 | (immhi << 5); + stream[1] = 0x91000000 | add_reg | add_reg << 5 | (add_off & 0xfff) << 10; + stream[2] = 0x52800000 | mov1_reg | ((payload_len & 0xffff) << 5); + stream[3] = 0x52800000 | mov2_reg | ((payload_len & 0xffff) << 5); + + dprintf("patched: 0x%x 0x%x 0x%x 0x%x\n", stream[0], stream[1], stream[2], stream[3]); +} + +void setup_hooks_arm64(void *stream) +{ + uint32_t + *t8011_patch_base = (uint32_t*)((char*)stream + 0x102E0), + *t7000_patch_base = (uint32_t*)((char*)stream + 0x102F4), + *t8012_patch_base = (uint32_t*)((char*)stream + 0x10290); + + vm_address_t page = (vm_address_t)((char*)stream + 0x10000); + + assert(*t8011_patch_base == 0x90000081); // T8011 + assert(*t7000_patch_base == 0x90000061); // T7000 + assert(*t8012_patch_base == 0xd0000081); // T8012 + + assert(vm_protect(mach_task_self(), page, 0x4000, false, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY) == 0); + + patch(t7000_patch_base, t7000_bin, t7000_bin_len); + patch(t8011_patch_base, t8011_bin, t8011_bin_len); + patch(t8012_patch_base, t8012_bin, t8012_bin_len); + + assert(vm_protect(mach_task_self(), page, 0x4000, false, VM_PROT_READ | VM_PROT_EXECUTE) == 0); + + sys_icache_invalidate((void*)page, 0x4000); + + dprintf("patched checkra1n\n"); +} + +#endif diff --git a/src/helper/payloads/t7000.bin b/src/helper/payloads/t7000.bin new file mode 100644 index 0000000..8495a33 Binary files /dev/null and b/src/helper/payloads/t7000.bin differ diff --git a/src/helper/payloads/t8011.bin b/src/helper/payloads/t8011.bin new file mode 100644 index 0000000..ed121dd Binary files /dev/null and b/src/helper/payloads/t8011.bin differ diff --git a/src/helper/payloads/t8012.bin b/src/helper/payloads/t8012.bin new file mode 100644 index 0000000..8ee2455 Binary files /dev/null and b/src/helper/payloads/t8012.bin differ diff --git a/src/helper/phookra1n.h b/src/helper/phookra1n.h new file mode 100644 index 0000000..f160ebb --- /dev/null +++ b/src/helper/phookra1n.h @@ -0,0 +1,20 @@ +#ifndef PALERA1N_CHECKRA1N_HELPER_H +#define PALERA1N_CHECKRA1N_HELPER_H + +#include +#include + +#define dprintf(...) // printf(__VA_ARGS__) + +extern uint8_t t7000_bin[]; +extern uint32_t t7000_bin_len; + +extern uint8_t t8011_bin[]; +extern uint32_t t8011_bin_len; + +extern uint8_t t8012_bin[]; +extern uint32_t t8012_bin_len; + +void setup_hooks_arm64(void *stream); + +#endif diff --git a/src/usb.xml b/src/usb.xml index 24e1c53..53b3063 100644 --- a/src/usb.xml +++ b/src/usb.xml @@ -3,6 +3,8 @@ platform-application + get-task-allow + com.apple.private.security.no-container com.apple.security.iokit-user-client-class