diff --git a/include/pf/15/pf.h b/include/pf/15/pf.h index 11770d9..39f4ba3 100644 --- a/include/pf/15/pf.h +++ b/include/pf/15/pf.h @@ -15,5 +15,6 @@ bool proc_list_mlock_lck_mtx_lock_unlock_finder_15(xnu_pf_patch_t *, void *); bool lck_grp_free_finder_15(xnu_pf_patch_t *, void *); bool proc_ref_rele_finder_15(xnu_pf_patch_t *, void *); bool lck_rw_alloc_init_finder_15(xnu_pf_patch_t *, void *); +bool vm_allocate_external_finder_15(xnu_pf_patch_t *, void *); #endif diff --git a/include/pf/pf_common.h b/include/pf/pf_common.h index ef63625..8896bcb 100644 --- a/include/pf/pf_common.h +++ b/include/pf/pf_common.h @@ -26,6 +26,7 @@ struct pf { #define LISTIZE(...) __VA_ARGS__ +#ifndef PF_DECL32 #define PF_DECL32(name, matches, masks, mmcount, callback, seg) \ { \ .pf_name = name, \ @@ -39,7 +40,9 @@ struct pf { .pf_section = NULL, \ .pf_unused = 0, \ } +#endif +#ifndef PF_DECL_FULL #define PF_DECL_FULL(name, matches, masks, mmcount, access, callback, kext, seg, sect) \ { \ .pf_name = name, \ @@ -53,6 +56,7 @@ struct pf { .pf_section = sect, \ .pf_unused = 0, \ } +#endif #define PF_UNUSED { .pf_unused = 1 } diff --git a/include/pf/pfs.h b/include/pf/pfs.h index 02cbf5a..f6674a1 100644 --- a/include/pf/pfs.h +++ b/include/pf/pfs.h @@ -93,16 +93,18 @@ struct pf g_all_pfs[MAXPF][NUM_SUPPORTED_VERSIONS] = { "__TEXT_EXEC", NULL), PF_DECL_FULL("kalloc_external finder iOS 15", LISTIZE({ - 0x910022f7, /* add x23, x23, #0x8 */ + 0x910022e0, /* add xNN, x23, #0x8 */ 0x910043a8, /* add x8, x29, #0x10 */ 0xf9000fe8, /* str w8, [sp, #0x18] */ + 0x52808008, /* mov w8, #0x400 */ }), LISTIZE({ + 0xffffffe0, /* ignore Rd */ 0xffffffff, /* match exactly */ - 0xffffffff, /* match exactly */ + 0xffffffff, /* ignore offset */ 0xffffffff, /* match exactly */ }), - 3, XNU_PF_ACCESS_32BIT, kalloc_external_finder_14, + 4, XNU_PF_ACCESS_32BIT, kalloc_external_finder_14, "com.apple.driver.AppleMobileFileIntegrity", "__TEXT_EXEC", NULL), }, @@ -589,16 +591,18 @@ struct pf g_all_pfs[MAXPF][NUM_SUPPORTED_VERSIONS] = { 7, lck_rw_alloc_init_finder_14, "__TEXT_EXEC"), PF_DECL_FULL("lck_rw_alloc_init finder iOS 15", LISTIZE({ - 0xd2800016, /* mov x22, #0 */ - 0xf9400260, /* ldr x0, [x19] */ - 0xd2800001, /* mov x1, #0 */ + 0xf9400000, /* ldr x0, [xn, n] */ + 0xd2800001, /* mov x1, #0 */ + 0x94000000, /* bl _lck_rw_alloc_init */ + 0xf9000e60, /* str x0, [x19, #0x18] */ }), LISTIZE({ + 0xffc0001f, /* ignore all but Rt */ 0xffffffff, /* match exactly */ - 0xffffffff, /* match exactly */ + 0xfc000000, /* ignore branch target */ 0xffffffff, /* match exactly */ }), - 3, XNU_PF_ACCESS_32BIT, lck_rw_alloc_init_finder_15, + 4, XNU_PF_ACCESS_32BIT, lck_rw_alloc_init_finder_15, "com.apple.filesystems.lifs", "__TEXT_EXEC", NULL), }, { @@ -1061,44 +1065,46 @@ struct pf g_all_pfs[MAXPF][NUM_SUPPORTED_VERSIONS] = { PF_UNUSED, PF_DECL32("kernel_map finder iOS 15", LISTIZE({ - 0x94000000, /* bl n */ + 0xf9400340, /* ldr x0, [x26] */ + 0x94000000, /* bl _vm_map_page_mask */ 0xaa0003f4, /* mov x20, x0 */ - 0x0, /* ignore this instruction */ - 0x9ba87c00, /* umull Xn, w0, w8 */ + 0xf9400340, /* ldr x0, [x26] */ + 0x94000000, /* bl _vm_map_page_mask */ + 0xaa0003f9, /* mov x25, x0 */ + 0xf9400340, /* ldr x0, [x26] */ + 0x94000000, /* bl _vm_map_page_mask */ }), LISTIZE({ + 0xffffffff, /* match exactly */ 0xfc000000, /* ignore immediate */ 0xffffffff, /* match exactly */ - 0x0, /* ignore this instruction */ - 0xffffffe0, /* ignore Rd */ + 0xffffffff, /* match exactly */ + 0xfc000000, /* ignore immediate */ + 0xffffffff, /* match exactly */ + 0xffffffff, /* match exactly */ + 0xfc000000, /* ignore immediate */ }), - 4, kernel_map_finder_15, "__TEXT_EXEC"), + 8, kernel_map_finder_15, "__TEXT_EXEC"), }, { PF_UNUSED, PF_UNUSED, PF_DECL32("vm_deallocate finder iOS 15", LISTIZE({ - 0x94000000, /* bl n */ - 0xf900001f, /* str xzr, [Xn, n] */ - 0x3900001f, /* strb wzr, [Xn, n] */ - 0xb4000000, /* cbz Xn, n */ - 0x0, /* ignore this instruction */ - 0x0, /* ignore this instruction */ - 0xaa0003e1, /* mov x1, Xn */ - 0xaa0003e2, /* mov x2, Xn */ + 0x94000000, /* bl _vm_deallocate */ + 0xf900007f, /* str xzr, [x19, n] */ + 0xb8000008, /* ldr w8, [x19, n] */ + 0x12147908, /* and w8, w8, #0xfffff7ff */ + 0xb8000008, /* str w8, [x19, n] */ }), LISTIZE({ 0xfc000000, /* ignore immediate */ - 0xffc0001f, /* ignore Rn & immediate */ - 0xffc0001f, /* ignore Rn & immediate */ - 0xff000000, /* ignore Rn & immediate */ - 0x0, /* ignore this instruction */ - 0x0, /* ignore this instruction */ - 0xffe0ffff, /* ignore Rn */ - 0xffe0ffff, /* ignore Rn */ + 0xffff00ff, /* ignore immediate */ + 0xfc00001f, /* ignore immediate */ + 0xffffffff, /* match exactly */ + 0xfc00001f, /* ignore immediate */ }), - 8, vm_deallocate_finder_15, "__TEXT_EXEC"), + 5, vm_deallocate_finder_15, "__TEXT_EXEC"), }, { PF_DECL_FULL("kernel_thread_start,thread_deallocate finder iOS 13", @@ -1302,18 +1308,27 @@ struct pf g_all_pfs[MAXPF][NUM_SUPPORTED_VERSIONS] = { PF_UNUSED, PF_DECL32("current_proc finder iOS 15", LISTIZE({ - 0x39402a88, /* ldrb w8, [x20, #0xa] */ - 0x35000008, /* cbnz w8, n */ - 0x94000000, /* bl current_proc */ - 0xf9000e80, /* str x0, [x20, #0x18] */ + 0xaa0003e0, /* mov x0, xN */ + 0xd2800001, /* mov x1, #0 */ + 0xd2800002, /* mov x2, #0 */ + 0x52800043, /* mov w3, #2 */ + 0x94000000, /* bl n */ + 0xf9400000, /* ldr x0, [Xn, n] */ + 0x94000000, /* bl n */ + 0x94000000, /* bl n */ + }), LISTIZE({ + 0xffe0ffff, /* ignore Rm */ + 0xffffffff, /* match exactly */ 0xffffffff, /* match exactly */ - 0xffc0001f, /* ignore signed offset */ - 0xfc000000, /* ignore immediate */ 0xffffffff, /* match exactly */ + 0xfc000000, /* ignore immediate */ + 0xffc0001f, /* ignore Rn & immediate */ + 0xfc000000, /* ignore immediate */ + 0xfc000000, /* ignore immediate */ }), - 4, current_proc_finder_15, "__TEXT_EXEC"), + 8, current_proc_finder_15, "__TEXT_EXEC"), }, { PF_DECL_FULL("proc stuff finder 1 iOS 13", @@ -1606,24 +1621,26 @@ struct pf g_all_pfs[MAXPF][NUM_SUPPORTED_VERSIONS] = { 5, ipc_port_release_send_finder_13, "__TEXT_EXEC"), PF_DECL32("ipc_object_lock/ipc_port_release_send_and_unlock finder iOS 15", LISTIZE({ - 0x910006e8, /* add x8, x23, #1 */ - 0xf100091f, /* cmp x8, 2 */ - 0x540000a3, /* b.lo 0x1c */ - 0xaa1703e0, /* mov x0, x23 */ - 0x94000000, /* bl _ipc_object_lock */ - 0xaa1703e0, /* mov x0, x23 */ - 0x94000000 /* bl _ipc_port_release_send_and_unlock */ + 0xaa0003f3, /* mov x19, x0 */ + 0x94000000, /* bl ipc_object_lock */ + 0xaa1303e0, /* mov x0, x19 */ + 0x94000000, /* bl ipc_port_release_send_and_unlock */ + 0xa9417bfd, /* ldp x29, x30, [sp, #0x10] */ + 0xa8c24ff4, /* ldp x20, x19, [sp], #0x20 */ + 0x52800000, /* mov w0, #0 */ + 0xd65f03c0, /* ret */ }), LISTIZE({ 0xffffffff, /* match exactly */ + 0xfc000000, /* ignore immediate */ + 0xffffffff, /* match exactly */ + 0xfc000000, /* ignore immediate */ 0xffffffff, /* match exactly */ 0xffffffff, /* match exactly */ 0xffffffff, /* match exactly */ - 0xfc000000, /* ignore immediate */ 0xffffffff, /* match exactly */ - 0xfc000000, /* ignore immediate */ }), - 7, ipc_port_release_send_finder_15, "__TEXT_EXEC"), + 8, ipc_port_release_send_finder_15, "__TEXT_EXEC"), }, { PF_DECL32("lck_rw_free finder iOS 13", @@ -2246,16 +2263,30 @@ struct pf g_all_pfs[MAXPF][NUM_SUPPORTED_VERSIONS] = { 0xfc000000, /* ignore immediate */ }), 2, vm_allocate_external_finder_13, "__TEXT_EXEC"), - PF_DECL32("vm_allocate_external finder iOS 15", + PF_DECL_FULL("vm_allocate_external finder iOS 15", LISTIZE({ - 0x53187C64, /* lsr w4, w3, #0x18 */ - 0x14000000, /* b n */ + 0x2a2003e8, /* mvn w8, w0 */ + 0x93407d08, /* sxtw x8, w8 */ + 0x8a170117, /* and x23, x8, x23 */ + 0xf9400340, /* ldr x0, [x26] */ + 0xd10163a1, /* sub x1, x29, #0x58 */ + 0xaa1703e2, /* mov x2, x23 */ + 0x52800023, /* mov w3, #1 */ + 0x94000000, /* bl vm_allocate */ }), LISTIZE({ + 0xffffffff, /* match exactly */ + 0xffffffff, /* match exactly */ + 0xffffffff, /* match exactly */ + 0xffffffff, /* match exactly */ + 0xffffffff, /* match exactly */ + 0xffffffff, /* match exactly */ 0xffffffff, /* match exactly */ 0xfc000000, /* ignore immediate */ }), - 2, vm_allocate_external_finder_13, "__TEXT_EXEC"), + 8, XNU_PF_ACCESS_32BIT, vm_allocate_external_finder_15, + "com.apple.iokit.IONetworkingFamily", + "__TEXT_EXEC", NULL), }, { PF_DECL32("vm_map_deallocate, offsetof(vm_map_t, refcnt) finder iOS 13", @@ -2353,16 +2384,26 @@ struct pf g_all_pfs[MAXPF][NUM_SUPPORTED_VERSIONS] = { PF_UNUSED, PF_DECL32("proc_ref,proc_rele finder iOS 15", LISTIZE({ - 0xaa1903f8, /* mov x24, x25 */ - 0xaa1803e0, /* mov x0, x24 */ - 0x52800021, /* mov w1, #1 */ + 0xaa1403e0, /* mov x0, x20 */ + 0x94000000, /* bl _proc_rele */ + 0xf9400eb5, /* ldr x21, [x21, #0x18] */ + 0xb4000000, /* cbz x21, n */ + 0xf94012a8, /* ldr x8, [x21, #0x20] */ + 0x9356fd08, /* asr x8, x8, #22 */ + 0xf9400d14, /* ldr x20, [x8, #0x18] */ + 0xaa1403e0, /* mov x0, x20 */ }), LISTIZE({ + 0xffffffff, /* match exactly */ + 0xfc000000, /* ignore immediate */ + 0xffffffff, /* match exactly */ + 0xfc000000, /* ignore immediate */ + 0xffffffff, /* match exactly */ 0xffffffff, /* match exactly */ 0xffffffff, /* match exactly */ 0xffffffff, /* match exactly */ }), - 3, proc_ref_rele_finder_15, "__TEXT_EXEC"), + 8, proc_ref_rele_finder_15, "__TEXT_EXEC"), }, { PF_DECL_FULL("lck_mtx_lock finder iOS 13", diff --git a/include/xnuspy/xnuspy_ctl.h b/include/xnuspy/xnuspy_ctl.h index 5489f67..488945d 100644 --- a/include/xnuspy/xnuspy_ctl.h +++ b/include/xnuspy/xnuspy_ctl.h @@ -34,7 +34,7 @@ enum { COPYINSTR, COPYOUT, - /* Idential to XNU's implementation */ + /* Identical to XNU's implementation */ CURRENT_MAP, CURRENT_PROC, diff --git a/klog/klog.c b/klog/klog.c index 355d73a..f651061 100644 --- a/klog/klog.c +++ b/klog/klog.c @@ -28,7 +28,7 @@ int main(int argc, char **argv){ char buf[1024]; memset(buf, 0, sizeof(buf)); - ssize_t r = read(klog_fd, buf, sizeof(buf)); + ssize_t r = read(klog_fd, buf, sizeof(buf) - 1); if(r < 0){ printf("read failed: %s\n", strerror(errno)); diff --git a/loader/Makefile b/loader/Makefile index fd7429f..a714261 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -11,4 +11,4 @@ TARGET = loader SOURCES = loader.c $(TARGET) : $(SOURCES) - $(CC) $(CFLAGS) $(LDFLAGS) $(SOURCES) -o $(TARGET) + $(CC) $(CFLAGS) $(SOURCES) $(LDFLAGS) -o $(TARGET) diff --git a/module/pf/13/pf.c b/module/pf/13/pf.c index 54747a1..e9c2d63 100644 --- a/module/pf/13/pf.c +++ b/module/pf/13/pf.c @@ -1302,7 +1302,7 @@ bool vm_allocate_external_finder_13(xnu_pf_patch_t *patch, return true; } -/* Confirmed working on all kernels 13.0 - 15.0 */ +/* Confirmed working on all kernels 13.0 - 15.8 */ bool vm_map_deallocate_offsetof_vm_map_refcnt_finder_13(xnu_pf_patch_t *patch, void *cacheable_stream){ /* vm_map_reference does not exist on release kernels because it was @@ -1318,11 +1318,14 @@ bool vm_map_deallocate_offsetof_vm_map_refcnt_finder_13(xnu_pf_patch_t *patch, g_vm_map_deallocate_addr = xnu_ptr_to_va(vm_map_deallocate); - /* Now get the offset of the reference count. Searching - * for add xn, x19, #n */ + /* Now get the offset of the reference count. Searching for + * add x0, xn, #n + * ldxr w8, [x0] + */ uint32_t instr_limit = 100; - while((*vm_map_deallocate & 0xffc003e0) != 0x91000260){ + while((vm_map_deallocate[0] & 0xffc0001f) != 0x91000000 && + (vm_map_deallocate[1] & 0xffffffff) != 0x885f7c08){ if(instr_limit-- == 0) return false; diff --git a/module/pf/14/pf.c b/module/pf/14/pf.c index adba232..a6a76ff 100644 --- a/module/pf/14/pf.c +++ b/module/pf/14/pf.c @@ -12,7 +12,7 @@ uint64_t g_kalloc_external_addr = 0; uint64_t g_kfree_ext_addr = 0; -/* Confirmed working 14.0 - 15.0 */ +/* Confirmed working 14.0 - 15.8 */ bool kalloc_external_finder_14(xnu_pf_patch_t *patch, void *cacheable_stream){ /* We've landed somewhere inside AMFI, kalloc_external is the * branch six instructions down */ diff --git a/module/pf/15/pf.c b/module/pf/15/pf.c index d3144d2..00252da 100644 --- a/module/pf/15/pf.c +++ b/module/pf/15/pf.c @@ -14,25 +14,16 @@ uint64_t g_proc_ref_addr = 0; uint64_t g_proc_rele_addr = 0; uint64_t g_ipc_object_lock_addr = 0; -/* Confirmed working 15.0 */ +/* Confirmed working 15.0 - 15.8 */ bool ipc_port_release_send_finder_15(xnu_pf_patch_t *patch, void *cacheable_stream){ - /* will land in _exception_deliver in iOS 15. There is a sequence - * where they lock/release 4 IPC ports if they are non-null. This - * patchfinder will take us here, then it's just a matter of - * resolving the branches. We get about 26 hits for these matches - * and masks, so let's make sure we're actually in _exception_deliver. - * If we are, then the two instructions behind where we landed will be - * mov x27, #0 and mov x26, x0 */ + /* We land in IOUserClient::releaseNotificationPort, which does almost + * nothing but call ipc_object_lock and ipc_port_release_send_and_unlock */ uint32_t *opcode_stream = cacheable_stream; - - if(opcode_stream[-1] != 0xd280001b && opcode_stream[-2] != 0xaa0003fa) - return false; - xnu_pf_disable_patch(patch); - uint32_t *ipc_port_release_send_and_unlock = get_branch_dst_ptr(opcode_stream + 6); - uint32_t *ipc_object_lock = get_branch_dst_ptr(opcode_stream + 4); + uint32_t *ipc_object_lock = get_branch_dst_ptr(opcode_stream + 1); + uint32_t *ipc_port_release_send_and_unlock = get_branch_dst_ptr(opcode_stream + 3); g_ipc_port_release_send_and_unlock_addr = xnu_ptr_to_va(ipc_port_release_send_and_unlock); g_ipc_object_lock_addr = xnu_ptr_to_va(ipc_object_lock); @@ -68,15 +59,14 @@ bool proc_name_snprintf_strlen_finder_15(xnu_pf_patch_t *patch, return true; } -/* Confirmed working 15.0 */ +/* Confirmed working 15.0-15.8 */ bool current_proc_finder_15(xnu_pf_patch_t *patch, void *cacheable_stream){ - /* This matches four places inside _eval, all of which have a branch - * to current_proc two instructions down */ + /* The next instruction after the pattern is a call to current_proc */ xnu_pf_disable_patch(patch); uint32_t *opcode_stream = cacheable_stream; - uint32_t *current_proc = get_branch_dst_ptr(opcode_stream + 2); + uint32_t *current_proc = get_branch_dst_ptr(opcode_stream + 8); g_current_proc_addr = xnu_ptr_to_va(current_proc); @@ -107,46 +97,35 @@ bool vm_map_unwire_nested_finder_15(xnu_pf_patch_t *patch, return true; } -/* Confirmed working 15.0 */ +/* Confirmed working 15.0-15.8 */ bool kernel_map_finder_15(xnu_pf_patch_t *patch, void *cacheable_stream){ - /* Will land in panic_kernel, the first PC relative addressing pair - * we see from this point on is for kernel_map */ + /* Will at a sequence of four calls to _vm_map_page_mask. + * Just prior to the calls, _kernel_map is loaded into x0: + * adrp x26, 0xfffffff006d4e000 + * ldr x26, [x26, #0x460] + * ldr x0,[x26] + */ uint32_t *opcode_stream = cacheable_stream; - uint32_t limit = 50; - - /* adrp or adr */ - while((*opcode_stream & 0x1f000000) != 0x10000000){ - if(limit-- == 0) - return false; - - opcode_stream++; - } - xnu_pf_disable_patch(patch); - uint64_t *kernel_mapp = (uint64_t *)get_pc_rel_target(opcode_stream); + /* get constant pool entry */ + uint64_t *kernel_mapp = (uint64_t *)get_pc_rel_target(opcode_stream - 2); - g_kernel_map_addr = xnu_ptr_to_va(kernel_mapp); + /* get address in constant pool entry (already a kernel virtual address) */ + g_kernel_map_addr = *kernel_mapp + kernel_slide; puts("xnuspy: found kernel_map"); return true; } -/* Confirmed working 15.0 */ +/* Confirmed working 15.0, 15.5 - 15.8 */ bool vm_deallocate_finder_15(xnu_pf_patch_t *patch, void *cacheable_stream){ - /* will land in ipc_kmsg_clean_partial. we can only - * search for 8 intructions at a time, so we check - * for the 9th instruction (bl _vm_deallocate) */ xnu_pf_disable_patch(patch); uint32_t *opcode_stream = cacheable_stream; - if ((opcode_stream[8] & 0xfc000000) != 0x94000000){ - return false; - } - - uint32_t *vm_deallocate = get_branch_dst_ptr(opcode_stream + 8); + uint32_t *vm_deallocate = get_branch_dst_ptr(opcode_stream + 0); g_vm_deallocate_addr = xnu_ptr_to_va(vm_deallocate); @@ -202,16 +181,16 @@ bool lck_grp_free_finder_15(xnu_pf_patch_t *patch, void *cacheable_stream){ return true; } -/* Confirmed working 15.0 */ +/* Confirmed working 15.0 - 15.8*/ bool proc_ref_rele_finder_15(xnu_pf_patch_t *patch, void *cacheable_stream){ - /* We landed inside proc_rebootscan. A call to proc_ref is three - * instructions down and a call to proc_rele is 14 instructions down */ + /* We landed inside memorystatus_update_vm_pressure, at one of two + * equivalent pieces of code, and use the first one we find. */ xnu_pf_disable_patch(patch); uint32_t *opcode_stream = cacheable_stream; - uint32_t *proc_ref = get_branch_dst_ptr(opcode_stream + 3); - uint32_t *proc_rele = get_branch_dst_ptr(opcode_stream + 14); + uint32_t *proc_ref = get_branch_dst_ptr(opcode_stream + 9); + uint32_t *proc_rele = get_branch_dst_ptr(opcode_stream + 1); g_proc_ref_addr = xnu_ptr_to_va(proc_ref); g_proc_rele_addr = xnu_ptr_to_va(proc_rele); @@ -222,30 +201,34 @@ bool proc_ref_rele_finder_15(xnu_pf_patch_t *patch, void *cacheable_stream){ return true; } -/* Confirmed working 15.0 */ +/* Confirmed working 15.0 - 15.8 */ bool lck_rw_alloc_init_finder_15(xnu_pf_patch_t *patch, void *cacheable_stream){ - /* We landed inside lifs_req_hashtbl_init. The branch to - * lck_rw_alloc_init is three instructions down if we see a - * lsl w8, w0, #1 less than 20 instructions before where we are */ + /* We landed inside OSSymbol::initialize. */ + xnu_pf_disable_patch(patch); + uint32_t *opcode_stream = cacheable_stream; - uint32_t *saved_stream = opcode_stream; - uint32_t limit = 20; + uint32_t *lck_rw_alloc_init = get_branch_dst_ptr(opcode_stream + 2); - while(*opcode_stream != 0x531f7808){ - if(limit-- == 0) - return false; + g_lck_rw_alloc_init_addr = xnu_ptr_to_va(lck_rw_alloc_init); + + puts("xnuspy: found lck_rw_alloc_init"); - opcode_stream--; - } + return true; +} +/* Confirmed working 15.0 - 15.8 */ +bool vm_allocate_external_finder_15(xnu_pf_patch_t *patch, + void *cacheable_stream){ + /* We landed somewhere in IONetworkingFamily */ xnu_pf_disable_patch(patch); - uint32_t *lck_rw_alloc_init = get_branch_dst_ptr(saved_stream + 3); + uint32_t *opcode_stream = cacheable_stream; + uint32_t *vm_allocate = get_branch_dst_ptr(opcode_stream + 7); - g_lck_rw_alloc_init_addr = xnu_ptr_to_va(lck_rw_alloc_init); + g_vm_allocate_external_addr = xnu_ptr_to_va(vm_allocate); - puts("xnuspy: found lck_rw_alloc_init"); + puts("xnuspy: found vm_allocate_external"); return true; } diff --git a/module/pf/offline/.gitignore b/module/pf/offline/.gitignore new file mode 100644 index 0000000..faa62b1 --- /dev/null +++ b/module/pf/offline/.gitignore @@ -0,0 +1 @@ +offline diff --git a/module/pf/offline/Makefile b/module/pf/offline/Makefile new file mode 100644 index 0000000..7035e82 --- /dev/null +++ b/module/pf/offline/Makefile @@ -0,0 +1,5 @@ +CC = clang +CFLAGS = -g -O2 -I../../../include + +offline: offline.c ../../../include/pf/pfs.h + $(CC) $(CFLAGS) offline.c -o offline diff --git a/module/pf/offline/offline.c b/module/pf/offline/offline.c new file mode 100644 index 0000000..1d9aafc --- /dev/null +++ b/module/pf/offline/offline.c @@ -0,0 +1,235 @@ +// Offline patchfinder. +// +// This program exists to test the patchfinder offline (without booting into +// pongoOS), which enables quick iteration on changes and testing with +// different kernel versions. +// +// It is far from perfect, though: The callbacks in module/pf/1*/pf.c are not +// executed, so whatever result you get from pf/offline is only part of the +// story. +// +#include +#include +#include +#include +#include +#include +#include + +#ifndef XNU_PF_ACCESS_32BIT +#define XNU_PF_ACCESS_32BIT 0 +#endif + +#define PF_DECL32(name, matches, masks, mmcount, callback, seg) \ + { \ + .pf_name = name, \ + .pf_matches = matches, \ + .pf_masks = masks, \ + .pf_mmcount = mmcount, \ + .pf_access_type = XNU_PF_ACCESS_32BIT, \ + .pf_callback = NULL /*callback*/, \ + .pf_kext = NULL, \ + .pf_segment = seg, \ + .pf_section = NULL, \ + .pf_unused = 0, \ + } + +#define PF_DECL_FULL(name, matches, masks, mmcount, access, callback, kext, seg, sect) \ + { \ + .pf_name = name, \ + .pf_matches = matches, \ + .pf_masks = masks, \ + .pf_mmcount = mmcount, \ + .pf_access_type = access, \ + .pf_callback = NULL /*callback*/, \ + .pf_kext = kext, \ + .pf_segment = seg, \ + .pf_section = sect, \ + .pf_unused = 0, \ + } + +#include + +uint64_t g_sysent_addr = 0; +uint64_t g_kalloc_canblock_addr = 0; +uint64_t g_kfree_addr_addr = 0; +uint64_t g_sysctl__kern_children_addr = 0; +uint64_t g_sysctl_register_oid_addr = 0; +uint64_t g_sysctl_handle_long_addr = 0; +uint64_t g_name2oid_addr = 0; +uint64_t g_sysctl_geometry_lock_addr = 0; +uint64_t g_lck_rw_done_addr = 0; +uint64_t g_h_s_c_sbn_branch_addr = 0; +uint64_t g_h_s_c_sbn_epilogue_addr = 0; +uint64_t g_lck_grp_alloc_init_addr = 0; +uint64_t g_lck_rw_alloc_init_addr = 0; +uint64_t g_exec_scratch_space_addr = 0; +/* don't count the first opcode */ +uint64_t g_exec_scratch_space_size = -sizeof(uint32_t); +uint32_t *g_ExceptionVectorsBase_stream = NULL; +uint64_t g_bcopy_phys_addr = 0; +uint64_t g_phystokv_addr = 0; +uint64_t g_copyin_addr = 0; +uint64_t g_copyout_addr = 0; +uint64_t g_IOSleep_addr = 0; +uint64_t g_kprintf_addr = 0; +uint64_t g_vm_map_unwire_addr = 0; +uint64_t g_vm_deallocate_addr = 0; +uint64_t g_kernel_map_addr = 0; +uint64_t g_kernel_thread_start_addr = 0; +uint64_t g_thread_deallocate_addr = 0; +uint64_t g_mach_make_memory_entry_64_addr = 0; +uint64_t g_offsetof_struct_thread_map = 0; +uint64_t g_current_proc_addr = 0; +uint64_t g_proc_list_lock_addr = 0; +uint64_t g_proc_ref_locked_addr = 0; +uint64_t g_proc_list_mlock_addr = 0; +uint64_t g_lck_mtx_lock_addr = 0; +uint64_t g_lck_mtx_unlock_addr = 0; +uint64_t g_proc_rele_locked_addr = 0; +uint64_t g_proc_uniqueid_addr = 0; +uint64_t g_proc_pid_addr = 0; +uint64_t g_allproc_addr = 0; +uint64_t g_lck_rw_lock_shared_addr = 0; +uint64_t g_lck_rw_lock_shared_to_exclusive_addr = 0; +uint64_t g_lck_rw_lock_exclusive_addr = 0; +uint64_t g_vm_map_wire_external_addr = 0; +uint64_t g_mach_vm_map_external_addr = 0; + +/* Only for <14.5 */ +uint64_t g_ipc_port_release_send_addr = 0; + +/* Only for >=14.5 */ +uint64_t g_ipc_port_release_send_and_unlock_addr = 0; + +uint64_t g_lck_rw_free_addr = 0; +uint64_t g_lck_grp_free_addr = 0; +int g_patched_doprnt_hide_pointers = 0; +uint64_t g_copyinstr_addr = 0; +uint64_t g_thread_terminate_addr = 0; +int g_patched_pinst_set_tcr = 0; +int g_patched_all_msr_tcr_el1_x18 = 0; +uint64_t g_snprintf_addr = 0; +uint64_t g_strlen_addr = 0; +uint64_t g_proc_name_addr = 0; +uint64_t g_strncmp_addr = 0; +uint64_t g_memset_addr = 0; +uint64_t g_memmove_addr = 0; +uint64_t g_panic_addr = 0; +uint64_t g_mach_to_bsd_errno_addr = 0; +uint64_t g_xnuspy_sysctl_mib_ptr = 0; +uint64_t g_xnuspy_sysctl_mib_count_ptr = 0; +uint64_t g_xnuspy_ctl_callnum = 0; + +/* Only for >=14.5 && <15.0 */ +uint64_t g_io_lock_addr = 0; + +uint64_t g_vm_allocate_external_addr = 0; +uint64_t g_vm_map_deallocate_addr = 0; +uint64_t g_offsetof_struct_vm_map_refcnt = 0; +uint64_t g_IOLog_addr = 0; + + +struct mapping { + void *data; + size_t size; +}; + +struct mapping *map_file(const char *path) +{ + struct mapping *m = malloc(sizeof(*m)); + if (!m) return NULL; + + int fd = open(path, O_RDONLY); + if (fd < 0) return NULL; + + struct stat statbuf; + int res = fstat(fd, &statbuf); + if (res < 0) return NULL; + + m->size = statbuf.st_size; + m->data = mmap(NULL, (m->size + 0xffff) & ~0xffff, PROT_READ, MAP_PRIVATE, fd, 0); + if (m->data == MAP_FAILED) return NULL; + + close(fd); + return m; +} + +bool find_version(struct mapping *m, int *major, int *minor, int *patch) +{ + const char *needle = "Darwin Kernel Version "; + + void *eureka = memmem(m->data, m->size, needle, strlen(needle)); + if (!eureka) return false; + + sscanf(eureka + strlen(needle), "%d.%d.%d", major, minor, patch); + return major != 0; +} + +int main(int argc, char **argv) +{ + if (argc != 2) { + fprintf(stderr, "Usage: %s kernel\n", argv[0]); + exit(1); + } + + struct mapping *m = map_file(argv[1]); + if (!m) { + fprintf(stderr, "Failed to open %s\n", argv[1]); + exit(1); + } + + int major, minor, patchlevel; + if (!find_version(m, &major, &minor, &patchlevel)) { + fprintf(stderr, "Failed to find kernel version\n"); + exit(1); + } + + printf("[!] Kernel version %d.%d.%d\n", major, minor, patchlevel); + int version; + switch (major) { + case 19: version = 0; break; + case 20: version = 1; break; + case 21: version = 2; break; + default: + fprintf(stderr, "Unsupported kernel version\n"); + exit(1); + } + + + for (size_t pf_idx = 0; pf_idx < MAXPF; pf_idx++) { + struct pf *pf = &g_all_pfs[pf_idx][version]; + if (!pf->pf_name) + continue; + + printf("[?] %s\n", pf->pf_name); + //for (int i = 0; i < pf->pf_mmcount; i++) + // printf("[.] %08lx %08lx\n", pf->pf_matches[i], pf->pf_masks[i]); + + int matches = 0; + bool matched = false; + const uint32_t *code = m->data; + for (size_t k = 0; k < m->size / sizeof(uint32_t); k++) { + if ((code[k] & pf->pf_masks[matches]) == pf->pf_matches[matches]) { + if (++matches == pf->pf_mmcount) { + // Print fake address that's kind of works in the kernel's __TEXT segment + printf("[+] > %016llx ->", k * sizeof(uint32_t) + 0xfffffff007003ff4ull); + for (int i = 0; i < 4; i++) + printf(" %08x", code[k - (matches-1) + i]); + printf("\n"); + + matched = true; + matches = 0; + } + } else { + matches = 0; + } + } + + if (!matched) + printf("[-] === NOPE ===\n"); + + } + + return 0; +}