├── Makefile ├── README.md ├── kern_patcher.c ├── kern_utils.c ├── kern_utils.h └── tfp0.plist /Makefile: -------------------------------------------------------------------------------- 1 | CC = clang 2 | CFLAGS = 3 | LDFLAGS = 4 | 5 | 6 | all: kern_patcher 7 | 8 | kern_patcher: kern_patcher.o kern_utils.o 9 | clang $(LDFLAGS) -o $@ $^ 10 | ldid -Stfp0.plist $@ 11 | 12 | 13 | %.o: %.c 14 | clang $(CFLAGS) -c -o $@ $< 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ios_kern_stuff 2 | ============== 3 | 4 | Random tools and utilities for use with the iOS kernel -------------------------------------------------------------------------------- /kern_patcher.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "kern_utils.h" 5 | 6 | 7 | // Credits go to br0x and comex 8 | static struct patch cck_ios5 = { 9 | 6, "\x32\x20\x00\x21\x20\x22", 10 | 1, "\xfa" 11 | }; 12 | 13 | 14 | int main(int argc, char* argv[]) { 15 | vm_map_t kernel_task = 0; 16 | kern_return_t kr = task_for_pid(mach_task_self(), 0, &kernel_task); 17 | if(kr != 0 || kernel_task == 0) { 18 | fprintf(stderr, "task_for_pid failed: %x\n\tEither you are missing a kernel patch or you don't have the proper entitlements set.\n", kr); 19 | return 1; 20 | } 21 | 22 | printf("Successfully got kernel_task.\nPatching...\n"); 23 | 24 | kr = kern_patch(kernel_task, cck_ios5); 25 | if(kr != KERN_SUCCESS) { 26 | fprintf(stderr, "kern_patch failed: %x\n", kr); 27 | return 1; 28 | } 29 | 30 | printf("Kernel successfully patched! All done!\n"); 31 | return 0; 32 | } 33 | -------------------------------------------------------------------------------- /kern_utils.c: -------------------------------------------------------------------------------- 1 | #include // For printf, fprintf, stderr 2 | #include // For memcmp 3 | #include // For getbufsiz 4 | #include // For everything else 5 | 6 | #include "kern_utils.h" 7 | 8 | // Returns the offset of the beginning of the pattern, if found. 9 | // Errors result in a return value of 0. 10 | // 11 | // TODO: Consider making this function return kern_return_t and 12 | // instead write the address to a vm_address_t* parameter. 13 | vm_address_t kern_find(vm_map_t kern, const char* pattern, vm_size_t pattern_length) { 14 | vm_address_t addr, buf, ret = 0; 15 | // 0xc00 because size must be less than 0x1000. 16 | vm_size_t read_size, bufsiz = 0xc00; 17 | 18 | // Allocate a read buffer in the current task's memory space 19 | kern_return_t kr = vm_allocate(mach_task_self(), &buf, bufsiz, VM_PROT_READ | VM_PROT_WRITE); 20 | if(kr != KERN_SUCCESS) { 21 | fprintf(stderr, "vm_allocate failed: %x\n", kr); 22 | return 0; 23 | } 24 | 25 | printf("Searching for address to patch...\n"); 26 | 27 | // Go through the entire kernel memory looking for pattern 28 | for(addr = 0x80002000; addr < 0x80A00000; addr += bufsiz) { 29 | // Read bufsiz bytes from the kernel into our buffer 30 | kr = vm_read_overwrite(kern, addr, bufsiz, buf, &read_size); 31 | if(kr != KERN_SUCCESS) { 32 | fprintf(stderr, "vm_read_overwrite failed: %x\n", kr); 33 | return 0; 34 | } 35 | 36 | int i, j; 37 | // Loop through the kernel data. 38 | for(i = 0; i < read_size; i++) { 39 | // FIXME: This will fail to find data that overlaps 40 | // page boundaries. 41 | if(memcmp((void*)(buf + i), pattern, pattern_length) == 0) { 42 | ret = addr + i; 43 | break; 44 | } 45 | } 46 | 47 | // Found match; exit loop 48 | if(ret) { 49 | fprintf(stderr, "Found match at %x.\n", ret); 50 | break; 51 | } 52 | } 53 | 54 | // Done searching; try to free up resources like a good little memory manager. 55 | kr = vm_deallocate(mach_task_self(), buf, bufsiz); 56 | if(kr != KERN_SUCCESS) { 57 | fprintf(stderr, "vm_deallocate failed: %x\nAttempting to continue...\n", kr); 58 | } 59 | 60 | if(ret == 0) { 61 | fprintf(stderr, "kern_find was unable to find a match\n"); 62 | } 63 | 64 | return ret; 65 | } 66 | 67 | 68 | // Patches the running kernel after boot 69 | kern_return_t kern_patch(vm_map_t kern, struct patch data) { 70 | // Try to find the address of the pattern 71 | vm_address_t addr = kern_find(kern, data.pattern, data.pattern_length); 72 | if(addr == 0) { 73 | fprintf(stderr, "kern_find failed\n"); 74 | return KERN_FAILURE; 75 | } 76 | return vm_write(kern, addr, (vm_offset_t)data.replace, data.replace_length); 77 | } 78 | -------------------------------------------------------------------------------- /kern_utils.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | struct patch { 4 | vm_size_t pattern_length; 5 | const char* pattern; 6 | vm_size_t replace_length; 7 | const char* replace; 8 | }; 9 | 10 | vm_address_t kern_find(vm_map_t kern, const char* pattern, vm_size_t pattern_length); 11 | kern_return_t kern_patch(vm_map_t kern, struct patch data); 12 | -------------------------------------------------------------------------------- /tfp0.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | get-task-allow 6 | 7 | run-unsigned-code 8 | 9 | task_for_pid-allow 10 | 11 | 12 | 13 | --------------------------------------------------------------------------------