diff --git a/Kernel64Patcher.c b/Kernel64Patcher.c index f01d0ec..27fa48b 100644 --- a/Kernel64Patcher.c +++ b/Kernel64Patcher.c @@ -3,6 +3,10 @@ * gcc Kernel64Patcher.c -o Kernel64Patcher */ +#ifdef __gnu_linux__ + #define _GNU_SOURCE +#endif + #include #include #include @@ -11,6 +15,10 @@ #define GET_OFFSET(kernel_len, x) (x - (uintptr_t) kernel_buf) +static uint32_t arm64_branch_instruction(uintptr_t from, uintptr_t to) { + return from > to ? 0x18000000 - (from - to) / 4 : 0x14000000 + (to - from) / 4; +} + // iOS 15 "%s: firmware validation failed %d\" @%s:%d SPU Firmware Validation Patch int get_SPUFirmwareValidation_patch(void *kernel_buf, size_t kernel_len) { printf("%s: Entering ...\n",__FUNCTION__); @@ -161,6 +169,127 @@ int get_AMFIInitializeLocalSigningPublicKey_patch(void* kernel_buf,size_t kernel return 0; } +//iOS 14 AppleFirmwareUpdate img4 signature check +int get_AppleFirmwareUpdate_img4_signature_check(void* kernel_buf,size_t kernel_len) { + + printf("%s: Entering ...\n",__FUNCTION__); + + char img4_sig_check_string[56] = "%s::%s() Performing img4 validation outside of workloop"; + void* ent_loc = memmem(kernel_buf,kernel_len,img4_sig_check_string,55); + if(!ent_loc) { + printf("%s: Could not find \"%%s::%%s() Performing img4 validation outside of workloop\" string\n",__FUNCTION__); + return -1; + } + printf("%s: Found \"%%s::%%s() Performing img4 validation outside of workloop\" str loc at %p\n",__FUNCTION__,GET_OFFSET(kernel_len,ent_loc)); + addr_t ent_ref = xref64(kernel_buf,0,kernel_len,(addr_t)GET_OFFSET(kernel_len, ent_loc)); + + if(!ent_ref) { + printf("%s: Could not find \"%%s::%%s() Performing img4 validation outside of workloop\" xref\n",__FUNCTION__); + return -1; + } + printf("%s: Found \"%%s::%%s() Performing img4 validation outside of workloop\" xref at %p\n",__FUNCTION__,(void*)ent_ref); + + printf("%s: Patching \"%%s::%%s() Performing img4 validation outside of workloop\" at %p\n\n", __FUNCTION__,(void*)(ent_ref + 0xc)); + *(uint32_t *) (kernel_buf + ent_ref + 0xc) = 0xD2800000; + + return 0; +} + +static addr_t +cbz_ref64_back(const uint8_t *buf, addr_t start, size_t length) { + + //find cbz/cbnz + uint32_t cbz_mask = 0x7E000000; + uint32_t instr = 0; + uint32_t imm = 0; + addr_t cbz = start; + while (cbz) { + instr = *(uint32_t *) (buf + cbz); + if ((instr & cbz_mask) == 0x34000000) { + imm = ((instr & 0x00FFFFFF) >> 5) << 2; + if (cbz + imm == start) + return cbz; + } + cbz -= 4; + } + return 0; +} + +//iOS 15 "could not authenticate personalized root hash!" patch +int get_could_not_authenticate_personalized_root_hash_patch(void* kernel_buf,size_t kernel_len) { + + printf("%s: Entering ...\n", __FUNCTION__); + + //get target offset for new branch + char roothash_authenticated_string[sizeof("successfully validated on-disk root hash")] = "successfully validated on-disk root hash"; + + unsigned char *roothash_authenticated_loc = memmem(kernel_buf, kernel_len, roothash_authenticated_string, sizeof("successfully validated on-disk root hash") - 1); + if(!roothash_authenticated_loc) { + printf("%s: Could not find \"%s\" string\n", __FUNCTION__, roothash_authenticated_string); + return -1; + } + + for (; *roothash_authenticated_loc != 0; roothash_authenticated_loc--); + roothash_authenticated_loc++; + printf("%s: Found \"%s\" str loc at %p\n", __FUNCTION__, roothash_authenticated_string, GET_OFFSET(kernel_len, roothash_authenticated_loc)); + + addr_t roothash_authenticated_ref = xref64(kernel_buf,0,kernel_len,(addr_t)GET_OFFSET(kernel_len, roothash_authenticated_loc)); + if(!roothash_authenticated_ref) { + printf("%s: Could not find \"%s\" xref\n",__FUNCTION__, roothash_authenticated_string); + return -1; + } + printf("%s: Found \"%s\" xref at %p\n",__FUNCTION__, roothash_authenticated_string, (void*) roothash_authenticated_ref); + + //get previous cbz + addr_t branch_target = step64_back(kernel_buf, roothash_authenticated_ref, 20 * 4, 0x34000000, 0x7E000000); + if(!branch_target) { + printf("%s: Could not find previous cbz\n",__FUNCTION__); + return -1; + } + printf("%s: Found previous cbz at %p\n",__FUNCTION__, (void*) branch_target); + branch_target++; + + //get patching offset for new branch + char roothash_failed_string[sizeof("could not authenticate personalized root hash!")] = "could not authenticate personalized root hash!"; + + unsigned char *roothash_failed_loc = memmem(kernel_buf, kernel_len, roothash_failed_string, sizeof("could not authenticate personalized root hash!") - 1); + if(!roothash_failed_loc) { + printf("%s: Could not find \"%s\" string\n", __FUNCTION__, roothash_failed_string); + return -1; + } + + for (; *roothash_failed_loc != 0; roothash_failed_loc--); + roothash_failed_loc++; + printf("%s: Found \"%s\" str loc at %p\n", __FUNCTION__, roothash_failed_string, GET_OFFSET(kernel_len, roothash_failed_loc)); + + addr_t roothash_failed_ref = xref64(kernel_buf,0,kernel_len,(addr_t)GET_OFFSET(kernel_len, roothash_failed_loc)); + if(!roothash_failed_ref) { + printf("%s: Could not find \"%s\" xref\n",__FUNCTION__, roothash_failed_string); + return -1; + } + printf("%s: Found \"%s\" xref at %p\n",__FUNCTION__, roothash_failed_string, (void*) roothash_failed_ref); + + addr_t patch_loc = 0; + + for (int i = 0; i < 16; i++, roothash_failed_ref -= 4) { + if (cbz_ref64_back(kernel_buf, roothash_failed_ref, roothash_failed_ref)) { + printf("%s: Found cbz target at %p\n", __FUNCTION__, (void*) roothash_failed_ref); + patch_loc = roothash_failed_ref; + break; + } + } + + if (!patch_loc) { + printf("%s: Could not find cbz target\n",__FUNCTION__); + return -1; + } + + printf("%s: Patching root hash check at %p\n",__FUNCTION__, (void*) patch_loc); + *((uint32_t *) (kernel_buf + patch_loc)) = arm64_branch_instruction((uintptr_t) patch_loc, (uintptr_t) branch_target); + + return 0; +} + int get_amfi_out_of_my_way_patch(void* kernel_buf,size_t kernel_len) { printf("%s: Entering ...\n",__FUNCTION__); @@ -223,8 +352,10 @@ int main(int argc, char **argv) { if(argc < 4){ printf("Usage: %s \n",argv[0]); printf("\t-a\t\tPatch AMFI\n"); + printf("\t-f\t\tPatch AppleFirmwareUpdate img4 signature check\n"); printf("\t-s\t\tPatch SPUFirmwareValidation (iOS 15 Only)\n"); printf("\t-r\t\tPatch RootVPNotAuthenticatedAfterMounting (iOS 15 Only)\n"); + printf("\t-o\t\tPatch could_not_authenticate_personalized_root_hash (iOS 15 Only)\n"); printf("\t-p\t\tPatch AMFIInitializeLocalSigningPublicKey (iOS 15 Only)\n"); return 0; } @@ -267,6 +398,10 @@ int main(int argc, char **argv) { printf("Kernel: Adding AMFI_get_out_of_my_way patch...\n"); get_amfi_out_of_my_way_patch(kernel_buf,kernel_len); } + if(strcmp(argv[i], "-f") == 0) { + printf("Kernel: Adding AppleFirmwareUpdate img4 signature check patch...\n"); + get_AppleFirmwareUpdate_img4_signature_check(kernel_buf,kernel_len); + } if(strcmp(argv[i], "-s") == 0) { printf("Kernel: Adding SPUFirmwareValidation patch...\n"); get_SPUFirmwareValidation_patch(kernel_buf,kernel_len); @@ -279,6 +414,10 @@ int main(int argc, char **argv) { printf("Kernel: Adding RootVPNotAuthenticatedAfterMounting patch...\n"); get_RootVPNotAuthenticatedAfterMounting_patch(kernel_buf,kernel_len); } + if(strcmp(argv[i], "-o") == 0) { + printf("Kernel: Adding could_not_authenticate_personalized_root_hash patch...\n"); + get_could_not_authenticate_personalized_root_hash_patch(kernel_buf,kernel_len); + } } /* Write patched kernel */ diff --git a/patchfinder64.c b/patchfinder64.c index 3fa2cde..b90c897 100644 --- a/patchfinder64.c +++ b/patchfinder64.c @@ -450,8 +450,6 @@ xref64code(const uint8_t *buf, addr_t start, addr_t end, addr_t what) #include #include #include -#include -//#include "vfs.h" // img4lib #ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ #include @@ -524,178 +522,6 @@ static addr_t kernel_entry = 0; static void *kernel_mh = 0; static addr_t kernel_delta = 0; -int -init_kernel(addr_t base, const char *filename) -{ - size_t rv; - uint8_t buf[0x4000]; - uint8_t *vstr; - unsigned i, j; - const struct mach_header *hdr = (struct mach_header *)buf; - FHANDLE fd = INVALID_HANDLE; - const uint8_t *q; - addr_t min = -1; - addr_t max = 0; - int is64 = 0; - - if (filename == NULL) { -#ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ - rv = kread(base, buf, sizeof(buf)); - if (rv != sizeof(buf) || !MACHO(buf)) { - return -1; - } -#else - (void)base; - return -1; -#endif - } else { - fd = OPEN(filename, O_RDONLY); - if (fd == INVALID_HANDLE) { - return -1; - } - rv = READ(fd, buf, sizeof(buf)); - if (rv != sizeof(buf) || !MACHO(buf)) { - CLOSE(fd); - return -1; - } - } - - if (IS64(buf)) { - is64 = 4; - } - - q = buf + sizeof(struct mach_header) + is64; - for (i = 0; i < hdr->ncmds; i++) { - const struct load_command *cmd = (struct load_command *)q; - if (cmd->cmd == LC_SEGMENT_64 && ((struct segment_command_64 *)q)->vmsize) { - const struct segment_command_64 *seg = (struct segment_command_64 *)q; - if (min > seg->vmaddr) { - min = seg->vmaddr; - } - if (max < seg->vmaddr + seg->vmsize) { - max = seg->vmaddr + seg->vmsize; - } - if (!strcmp(seg->segname, "__TEXT_EXEC")) { - xnucore_base = seg->vmaddr; - xnucore_size = seg->filesize; - } - if (!strcmp(seg->segname, "__PLK_TEXT_EXEC")) { - prelink_base = seg->vmaddr; - prelink_size = seg->filesize; - } - if (!strcmp(seg->segname, "__PPLTEXT")) { - pplcode_base = seg->vmaddr; - pplcode_size = seg->filesize; - } - if (!strcmp(seg->segname, "__TEXT")) { - const struct section_64 *sec = (struct section_64 *)(seg + 1); - for (j = 0; j < seg->nsects; j++) { - if (!strcmp(sec[j].sectname, "__cstring")) { - cstring_base = sec[j].addr; - cstring_size = sec[j].size; - } - } - } - if (!strcmp(seg->segname, "__PRELINK_TEXT")) { - const struct section_64 *sec = (struct section_64 *)(seg + 1); - for (j = 0; j < seg->nsects; j++) { - if (!strcmp(sec[j].sectname, "__text")) { - pstring_base = sec[j].addr; - pstring_size = sec[j].size; - } - } - } - } - if (cmd->cmd == LC_UNIXTHREAD) { - uint32_t *ptr = (uint32_t *)(cmd + 1); - uint32_t flavor = ptr[0]; - struct { - 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 */ - } *thread = (void *)(ptr + 2); - if (flavor == 6) { - kernel_entry = thread->pc; - } - } - q = q + cmd->cmdsize; - } - - if (pstring_base == 0 && pstring_size == 0) { - pstring_base = cstring_base; - pstring_size = cstring_size; - } - if (prelink_base == 0 && prelink_size == 0) { - prelink_base = xnucore_base; - prelink_size = xnucore_size; - } - - kerndumpbase = min; - xnucore_base -= kerndumpbase; - prelink_base -= kerndumpbase; - pplcode_base -= kerndumpbase; - cstring_base -= kerndumpbase; - pstring_base -= kerndumpbase; - kernel_size = max - min; - - if (filename == NULL) { -#ifdef __ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__ - kernel = malloc(kernel_size); - if (!kernel) { - return -1; - } - rv = kread(kerndumpbase, kernel, kernel_size); - if (rv != kernel_size) { - free(kernel); - kernel = NULL; - return -1; - } - - kernel_mh = kernel + base - min; -#endif - } else { - kernel = calloc(1, kernel_size); - if (!kernel) { - CLOSE(fd); - return -1; - } - - q = buf + sizeof(struct mach_header) + is64; - for (i = 0; i < hdr->ncmds; i++) { - const struct load_command *cmd = (struct load_command *)q; - if (cmd->cmd == LC_SEGMENT_64) { - const struct segment_command_64 *seg = (struct segment_command_64 *)q; - size_t sz = PREAD(fd, kernel + seg->vmaddr - min, seg->filesize, seg->fileoff); - if (sz != seg->filesize) { - CLOSE(fd); - free(kernel); - kernel = NULL; - return -1; - } - if (!kernel_mh) { - kernel_mh = kernel + seg->vmaddr - min; - } - if (!strcmp(seg->segname, "__LINKEDIT")) { - kernel_delta = seg->vmaddr - min - seg->fileoff; - } - } - q = q + cmd->cmdsize; - } - - CLOSE(fd); - } - - vstr = boyermoore_horspool_memmem(kernel, kernel_size, (uint8_t *)"Darwin Kernel Version", sizeof("Darwin Kernel Version") - 1); - if (vstr) { - kernel_version = atoi((const char *)vstr + sizeof("Darwin Kernel Version")); - } - - return 0; -} - void term_kernel(void) {