Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

kpf: Add patch to disable Protobox on iOS 16+ #182

Open
wants to merge 1 commit into
base: iOS15
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions checkra1n/kpf/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -762,6 +762,27 @@ bool vnode_lookup_callback(struct xnu_pf_patch* patch, uint32_t* opcode_stream)
return true;
}

bool kpf_protobox_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream)
{
uint32_t adrp1 = opcode_stream[0],
add1 = opcode_stream[1];
const char *str1 = (const char *)(((uint64_t)(opcode_stream) & ~0xfffULL) + adrp_off(adrp1) + ((add1 >> 10) & 0xfff));

uint32_t adrp2 = opcode_stream[4],
add2 = opcode_stream[5];
const char *str2 = (const char *)(((uint64_t)(opcode_stream) & ~0xfffULL) + adrp_off(adrp2) + ((add2 >> 10) & 0xfff));

if (!strcmp(str1, "Restore") && !strcmp(str2, "Darwin")) {
// Make protobox think this device is in "Restore" mode
// This will disable protobox
opcode_stream[2] = 0xD2800020; // mov x0, #1
printf("KPF: Found and patched protobox check @ 0x%llx\n", xnu_ptr_to_va(opcode_stream));
return true;
}

return false;
}

void kpf_find_shellcode_funcs(xnu_pf_patchset_t* xnu_text_exec_patchset) {
// to find this with r2 run:
// /x 00008192007fbef2:00ffffff00ffffff
Expand Down Expand Up @@ -1351,6 +1372,32 @@ void kpf_sandbox_kext_patches(xnu_pf_patchset_t* patchset) {
0xFF000000
};
xnu_pf_maskmatch(patchset, "vnode_lookup", matches, masks, sizeof(masks)/sizeof(uint64_t), true, (void*)vnode_lookup_callback);

// 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
// When injecting into them or using something like Frida, it can prevent certain functionality
// 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
// 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
uint64_t protobox_matches[] = {
0x90000000, // adrp x0, "Restore"@PAGE
0x91000000, // add x0, "Restore"@PAGEOFF
0x94000000, // bl _is_release_type
0x37000000, // tbnz w0, #0, ???
0x90000000, // adrp x0, "Darwin"@PAGE
0x91000000, // add x0, "Darwin"@PAGEOFF
0x94000000, // bl _is_release_type
0x36000000, // tb(n)z w0, #0, ???
};
uint64_t protobox_masks[] = {
0x9f00001f,
0xff8003ff,
0xfc000000,
0xff00001f,
0x9f00001f,
0xff8003ff,
0xfc000000,
0xfe00001f,
};
xnu_pf_maskmatch(patchset, "protobox", protobox_matches, protobox_masks, sizeof(protobox_masks)/sizeof(uint64_t), false, (void *)kpf_protobox_callback);
}

bool vnop_rootvp_auth_callback(struct xnu_pf_patch *patch, uint32_t *opcode_stream) {
Expand Down