Skip to content

Commit 492abab

Browse files
committed
Update protobox/autobox patches
1 parent 3477f15 commit 492abab

File tree

2 files changed

+162
-44
lines changed

2 files changed

+162
-44
lines changed

checkra1n/kpf/main.c

+121-42
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,7 @@ static void kpf_kernel_version_init(xnu_pf_range_t *text_const_range)
169169
// Imports from shellcode.S
170170
extern uint32_t sandbox_shellcode[], sandbox_shellcode_setuid_patch[], sandbox_shellcode_ptrs[], sandbox_shellcode_end[];
171171
extern uint32_t launchd_execve_hook[], launchd_execve_hook_ptr[], launchd_execve_hook_offset[], launchd_execve_hook_pagesize[], launchd_execve_hook_mach_vm_allocate_kernel[];
172+
extern uint32_t proc_set_syscall_filter_mask_shc[], proc_set_syscall_filter_mask_shc_target[], zalloc_ro_mut[];
172173

173174
uint32_t* _mac_mount = NULL;
174175
bool kpf_has_done_mac_mount = false;
@@ -798,25 +799,63 @@ bool vnode_lookup_callback(struct xnu_pf_patch* patch, uint32_t* opcode_stream)
798799
return true;
799800
}
800801

802+
uint32_t* _proc_set_syscall_filter_mask = NULL;
803+
uint32_t* protobox_patchpoint = NULL;
804+
801805
bool kpf_protobox_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream)
802806
{
803-
uint32_t adrp1 = opcode_stream[0],
804-
add1 = opcode_stream[1];
805-
const char *str1 = (const char *)(((uint64_t)(opcode_stream) & ~0xfffULL) + adrp_off(adrp1) + ((add1 >> 10) & 0xfff));
806-
807-
uint32_t adrp2 = opcode_stream[4],
808-
add2 = opcode_stream[5];
809-
const char *str2 = (const char *)(((uint64_t)(opcode_stream) & ~0xfffULL) + adrp_off(adrp2) + ((add2 >> 10) & 0xfff));
810-
811-
if (!strcmp(str1, "Restore") && !strcmp(str2, "Darwin")) {
812-
// Make protobox think this device is in "Restore" mode
813-
// This will disable protobox
814-
opcode_stream[2] = 0xD2800020; // mov x0, #1
815-
printf("KPF: Found and patched protobox check @ 0x%" PRIx64 "\n", xnu_ptr_to_va(opcode_stream));
816-
return true;
807+
uint32_t* b = find_next_insn(opcode_stream, 0x10, 0x14000000, 0xfc000000); // b proc_set_syscall_filter_mask
808+
if (!b) {
809+
panic_at(opcode_stream, "kpf_protobox: Failed to find b proc_set_syscall_filter_mask");
817810
}
818811

819-
return false;
812+
uint32_t* proc_set_syscall_filter_mask = follow_call(b);
813+
uint32_t *stackframe = find_prev_insn(opcode_stream - 1, 0x20, 0xa9007bfd, 0xffc07fff); // stp x29, x30, [sp, ...]
814+
if(!stackframe)
815+
{
816+
panic_at(opcode_stream, "kpf_protobox: Failed to find stack frame");
817+
}
818+
819+
uint32_t *start = find_prev_insn(stackframe - 1, 8, 0xd10003ff, 0xffc003ff); // sub sp, sp, ...
820+
if(!start) {
821+
start = find_prev_insn(stackframe, 10, 0xa9a003e0, 0xffe003e0); // stp xN, xM, [sp, -0x...]!
822+
}
823+
824+
if (!start) {
825+
panic_at(stackframe, "kpf_protobox: Failed to find start of function");
826+
}
827+
828+
uint32_t* bl = find_prev_insn(opcode_stream, 6, 0x94000000, 0xfc000000); // bl zone_require_ro
829+
if (!bl) {
830+
panic_at(opcode_stream, "kpf_protobox: Failed to find zone_require_ro");
831+
}
832+
833+
*bl = 0xaa0003f1; // mov x17, x0
834+
835+
_proc_set_syscall_filter_mask = proc_set_syscall_filter_mask;
836+
837+
protobox_patchpoint = b;
838+
839+
printf("KPF: found protobox\n");
840+
return true;
841+
}
842+
843+
bool kpf_filter_mismatch_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) {
844+
opcode_stream[0] = 0x14000000 | sxt32(opcode_stream[0] >> 5, 19); // cbz -> b
845+
printf("KPF: found syscall filter mismatch\n");
846+
return true;
847+
}
848+
849+
uint32_t* _zalloc_ro_mut = NULL;
850+
bool kpf_zalloc_ro_mut_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) {
851+
uint32_t* _zalloc_ro_mut_candidate = follow_call(&opcode_stream[6]);
852+
if (!_zalloc_ro_mut) _zalloc_ro_mut = _zalloc_ro_mut_candidate;
853+
if (_zalloc_ro_mut != _zalloc_ro_mut_candidate) {
854+
panic("kpf_zalloc_ro_mut: Found multiple zalloc_ro_mut candidates");
855+
}
856+
857+
puts("KPF: Found zalloc_ro_mut");
858+
return true;
820859
}
821860

822861
void kpf_find_shellcode_funcs(xnu_pf_patchset_t* xnu_text_exec_patchset) {
@@ -868,6 +907,29 @@ void kpf_find_shellcode_funcs(xnu_pf_patchset_t* xnu_text_exec_patchset) {
868907
0xffffffff
869908
};
870909
xnu_pf_maskmatch(xnu_text_exec_patchset, "ret0_gadget", iiii_matches, iiii_masks, sizeof(iiii_masks)/sizeof(uint64_t), true, (void*)ret0_gadget_callback);
910+
911+
// find mac label related calls to zalloc_ro_mut
912+
uint64_t zalloc_ro_mut_matches[] = {
913+
0x90000003, // adrp x3, ...
914+
0x91000063, // add x3, x3, ...
915+
0x52800080, // mov w0, #0x4
916+
0xaa1003e1, // mov x1, x{16-31}
917+
0xd2800002, // mov x2, #0x0
918+
0x52800404, // mov w4, #0x20
919+
0x94000000 // bl zalloc_ro_mut
920+
};
921+
922+
uint64_t zalloc_ro_mut_masks[] = {
923+
0x9f00001f,
924+
0xffc003ff,
925+
0xffffffff,
926+
0xfff0ffff,
927+
0xffffffff,
928+
0xffffffff,
929+
0xfc000000
930+
};
931+
932+
xnu_pf_maskmatch(xnu_text_exec_patchset, "zalloc_ro_mut", zalloc_ro_mut_matches, zalloc_ro_mut_masks, sizeof(zalloc_ro_mut_matches) / sizeof(uint64_t), false, (void *)kpf_zalloc_ro_mut_callback);
871933
}
872934

873935
static bool found_mach_traps = false;
@@ -1741,32 +1803,30 @@ void kpf_sandbox_kext_patches(xnu_pf_patchset_t* patchset, bool protobox_used) {
17411803
};
17421804
xnu_pf_maskmatch(patchset, "vnode_lookup", matches, masks, sizeof(masks)/sizeof(uint64_t), true, (void*)vnode_lookup_callback);
17431805

1744-
// 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
1745-
// When injecting into them or using something like Frida, it can prevent certain functionality
1746-
// 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
1747-
// 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
1806+
// /x 0800009008010091081970f8030140b9e00300aae10300aae20300aa:1f00009fff03c0ffff1ff0ffffffffffffffe0ffffffe0ffffffe0ff
1807+
// iOS 15.4+
17481808
if (protobox_used) {
17491809
uint64_t protobox_matches[] = {
1750-
0x90000000, // adrp x0, "Restore"@PAGE
1751-
0x91000000, // add x0, "Restore"@PAGEOFF
1752-
0x94000000, // bl _is_release_type
1753-
0x37000000, // tbnz w0, #0, ???
1754-
0x90000000, // adrp x0, "Darwin"@PAGE
1755-
0x91000000, // add x0, "Darwin"@PAGEOFF
1756-
0x94000000, // bl _is_release_type
1757-
0x36000000, // tb(n)z w0, #0, ???
1810+
0x90000008, // adrp x8, ...
1811+
0x91000108, // add, x8, x8
1812+
0xf8701908, // ldr x8, [x8, w{16-31}, ... #0x3]
1813+
0xb9400103, // ldr w3, [x8]
1814+
0xaa0003e0, // mov x0, x{16-31}
1815+
0xaa0003e1, // mov x1, x{16-31}
1816+
0xaa0003e2 // mov x2, x{16-31}
17581817
};
1818+
17591819
uint64_t protobox_masks[] = {
17601820
0x9f00001f,
1761-
0xff8003ff,
1762-
0xfc000000,
1763-
0xff00001f,
1764-
0x9f00001f,
1765-
0xff8003ff,
1766-
0xfc000000,
1767-
0xfe00001f,
1821+
0xffc003ff,
1822+
0xfff01fff,
1823+
0xffffffff,
1824+
0xffe0ffff,
1825+
0xffe0ffff,
1826+
0xffe0ffff
17681827
};
1769-
xnu_pf_maskmatch(patchset, "protobox", protobox_matches, protobox_masks, sizeof(protobox_masks)/sizeof(uint64_t), true, (void *)kpf_protobox_callback);
1828+
1829+
xnu_pf_maskmatch(patchset, "protobox", protobox_matches, protobox_masks, sizeof(protobox_masks) / sizeof(uint64_t), true, (void *)kpf_protobox_callback);
17701830
}
17711831
}
17721832

@@ -2466,20 +2526,17 @@ static void kpf_cmd(const char *cmd, char *args)
24662526
if (!protobox_string_range) protobox_string_range = text_cstring_range;
24672527

24682528
const char protobox_string[] = "(apply-protobox)";
2469-
const char *protobox_string_match = memmem(protobox_string_range->cacheable_base, protobox_string_range->size, protobox_string, sizeof(protobox_string) - 1);
2529+
const char *protobox_string_match = memmem(protobox_string_range->cacheable_base, protobox_string_range->size, protobox_string, sizeof(protobox_string)-1);
24702530

24712531
#ifdef DEV_BUILD
24722532
// 15.0 beta 3 and later, except bridgeOS
24732533
if ((gKernelVersion.xnuMajor >= 8019 && (xnu_platform() != PLATFORM_BRIDGEOS)) != (protobox_string_match != NULL)) {
24742534
panic("Protobox string doesn't match expected Darwin version");
24752535
}
24762536
#endif
2537+
bool protobox_used = (protobox_string_match != NULL && gKernelVersion.xnuMajor >= 8792);
24772538

2478-
// 16.0 beta 1 and later
2479-
const char constraints_string[] = "mac_proc_check_launch_constraints";
2480-
const char *constraints_string_match = memmem(text_cstring_range->cacheable_base, text_cstring_range->size, constraints_string, sizeof(constraints_string));
2481-
2482-
kpf_sandbox_kext_patches(sandbox_patchset, (protobox_string_match != NULL) && (constraints_string_match != NULL));
2539+
kpf_sandbox_kext_patches(sandbox_patchset, protobox_used);
24832540
xnu_pf_emit(sandbox_patchset);
24842541
xnu_pf_apply(sandbox_text_exec_range, sandbox_patchset);
24852542
xnu_pf_patchset_destroy(sandbox_patchset);
@@ -2564,7 +2621,6 @@ static void kpf_cmd(const char *cmd, char *args)
25642621
if (!vfs_context_current) panic("Missing patch: vfs_context_current");
25652622
if (!kpf_has_done_mac_mount) panic("Missing patch: mac_mount");
25662623

2567-
25682624
if (!has_found_apfs_vfsop_mount && apfs_vfsop_mount_string_match != NULL) {
25692625
if (palera1n_flags & palerain_option_rootful) {
25702626
panic("Missing patch: apfs_vfsop_mount");
@@ -2689,6 +2745,29 @@ static void kpf_cmd(const char *cmd, char *args)
26892745
delta |= 0x94000000;
26902746
*mac_execve_hook = delta;
26912747
}
2748+
2749+
if (protobox_used) {
2750+
if (!_zalloc_ro_mut) panic("Missing patch: zalloc_ro_mut");
2751+
2752+
uint32_t* repatch_proc_set_syscall_filter_mask_shc = (uint32_t*)(proc_set_syscall_filter_mask_shc - shellcode_from + shellcode_to);
2753+
uint32_t* repatch_proc_set_syscall_filter_mask_shc_target = (uint32_t*)(proc_set_syscall_filter_mask_shc_target - shellcode_from + shellcode_to);
2754+
uint32_t* repatch_zalloc_ro_mut = (uint32_t*)(zalloc_ro_mut - shellcode_from + shellcode_to);
2755+
2756+
uint32_t delta = (&repatch_proc_set_syscall_filter_mask_shc[0]) - protobox_patchpoint;
2757+
delta &= 0x03ffffff;
2758+
delta |= 0x14000000;
2759+
*protobox_patchpoint = delta;
2760+
2761+
delta = (&_proc_set_syscall_filter_mask[0]) - repatch_proc_set_syscall_filter_mask_shc_target;
2762+
delta &= 0x03ffffff;
2763+
delta |= 0x14000000;
2764+
*repatch_proc_set_syscall_filter_mask_shc_target = delta;
2765+
2766+
delta = (&_zalloc_ro_mut[0]) - repatch_zalloc_ro_mut;
2767+
delta &= 0x03ffffff;
2768+
delta |= 0x14000000;
2769+
*repatch_zalloc_ro_mut = delta;
2770+
}
26922771

26932772
if(!livefs_string_match) // Only disable snapshot when we can remount realfs
26942773
{

checkra1n/kpf/shellcode.S

+41-2
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,47 @@ proc_selfname:
223223
.quad 0x5151515151515151
224224
vnode_check_open_orig:
225225
.quad 0x5252525252525252
226+
227+
.globl _proc_set_syscall_filter_mask_shc
228+
.globl _proc_set_syscall_filter_mask_shc_target
229+
.globl _zalloc_ro_mut
230+
.globl one_area
231+
one_area:
232+
.balign 0x100, 0xff
233+
234+
_proc_set_syscall_filter_mask_shc:
235+
cbz x2, _proc_set_syscall_filter_mask_shc_target
236+
sub sp, sp, 0x40
237+
stp x19, x20, [sp, 0x10]
238+
stp x21, x22, [sp, 0x20]
239+
stp x29, x30, [sp, 0x30]
240+
mov x19, x0
241+
mov x20, x1
242+
mov x21, x2
243+
mov x22, x3
244+
mov x8, #8
245+
mov x0, x17
246+
mov x1, x21
247+
mov x2, #0
248+
adr x3, one_area
249+
udiv x4, x22, x8
250+
msub x10, x4, x8, x22
251+
cbz x10, Lbl_zalloc_ro_mut
252+
add x4, x4, #1
253+
Lbl_zalloc_ro_mut:
254+
bl _zalloc_ro_mut
255+
mov x0, x19
256+
mov x1, x20
257+
mov x2, x21
258+
mov x3, x22
259+
ldp x19, x20, [sp, 0x10]
260+
ldp x21, x22, [sp, 0x20]
261+
ldp x29, x30, [sp, 0x30]
262+
add sp, sp, 0x40
263+
_proc_set_syscall_filter_mask_shc_target:
264+
b .
265+
_zalloc_ro_mut:
266+
b .
226267
227268
.align 2
228269
.globl _launchd_execve_hook
@@ -433,8 +474,6 @@ _nvram_shc:
433474
ret
434475
_nvram_shc_end:
435476

436-
437-
438477
.globl _kdi_shc
439478
.globl _kdi_shc_orig
440479
.globl _kdi_shc_get

0 commit comments

Comments
 (0)