Skip to content

Commit

Permalink
feat(kpf): find off_trustcache for all iOS 16 devices
Browse files Browse the repository at this point in the history
  • Loading branch information
KpwnZ committed Jan 21, 2024
1 parent 741b099 commit c4fa5d4
Showing 1 changed file with 67 additions and 21 deletions.
88 changes: 67 additions & 21 deletions escape/post_exploitation/kpf.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,19 +15,39 @@
static uint64_t prelink_text_addr = 0;
static uint64_t textexec_text_size = 0;
static uint64_t prelink_text_size = 0;
static uint64_t data_data_addr = 0;
static uint64_t data_data_size = 0;
static BOOL kernel_inited = NO;

extern get_kernel_section(struct kfd *kfd, uint64_t kernel_base, const char *segname, const char *sectname, uint64_t *addr, uint64_t *size);
extern void get_kernel_section(struct kfd *kfd, uint64_t kernel_base, const char *segname, const char *sectname, uint64_t *addr, uint64_t *size);

void init_kernel(struct kfd* kfd) {
LOG_FMT_CONSOLE(@"[+] init_kernel %s", __func__);
if (kernel_inited == YES) return;
uint64_t kernel_base = kfd->info.kernel.kernel_slide + 0xFFFFFFF007004000;
get_kernel_section(kfd, kernel_base, "__DATA", "__data", &data_data_addr, &data_data_size);
off_empty_kdata_page = data_data_addr - kfd->info.kernel.kernel_slide + 0x1000;
get_kernel_section(kfd, kernel_base, "__TEXT_EXEC", "__text", &textexec_text_addr, &textexec_text_size);
assert(textexec_text_addr != 0 && textexec_text_size != 0);
LOG_FMT_CONSOLE(@"[+] __TEXT_EXEC 0x%llx", textexec_text_addr);
if (textexec_text_addr == 0) {
textexec_text_addr = 0xFFFFFFF007004000 + kfd->info.kernel.kernel_slide + 0x190000;
LOG_FMT_CONSOLE(@"[-] failed to find %s init with fallback 0x%llx", "textexec_text_addr", textexec_text_addr);
}
if (textexec_text_size == 0) {
textexec_text_size = 0x650000;
LOG_FMT_CONSOLE(@"[-] failed to find %s init with fallback 0x%llx", "textexec_text_size", textexec_text_size);
}

get_kernel_section(kfd, kernel_base, "__PLK_TEXT_EXEC", "__text", &prelink_text_addr, &prelink_text_size);
assert(prelink_text_addr != 0);
LOG_FMT(@"[+] found textexec_text_addr: 0x%llx", textexec_text_addr);
LOG_FMT(@"[+] found prelink_text_addr: 0x%llx", prelink_text_addr);
LOG_FMT_CONSOLE(@"[+] __PLK_TEXT_EXEC 0x%llx", prelink_text_addr);
if (prelink_text_addr == 0) {
prelink_text_addr = 0xFFFFFFF007004000 + kfd->info.kernel.kernel_slide - 0x2230000 + 0x1140000;
prelink_text_size = 0x1000000;
LOG_FMT_CONSOLE(@"[-] failed to find %s init with fallback 0x%llx", "prelink_text_addr", prelink_text_addr);
}

LOG_FMT_CONSOLE(@"[+] found textexec_text_addr: 0x%llx", textexec_text_addr);
LOG_FMT_CONSOLE(@"[+] found prelink_text_addr: 0x%llx", prelink_text_addr);
kernel_inited = YES;
}

Expand Down Expand Up @@ -190,7 +210,7 @@ u64 find_proc_set_ucred_function(struct kfd* kfd) {

uint64_t find_trustcaches_addr(struct kfd *kfd) {
// find "image4 interface not available"
const char *str_target = "image4 interface not available";
const char *str_target = "com.apple.private.pmap.load-trust-cache";
int current_offset = 0;
uint64_t str_addr = 0;
uint64_t searching_addr = 0x30000 + kfd->info.kernel.kernel_slide + 0xFFFFFFF007004000;
Expand Down Expand Up @@ -219,53 +239,77 @@ uint64_t find_trustcaches_addr(struct kfd *kfd) {
*__off = __offset; \
*__reg = (__code & 0x1f); \
} while(0)
#define DISASM_ADD(__code, __imm, __reg1, __reg2) \
#define DISASM_LDR(__code, __imm, __reg1, __reg2) \
do { \
*__imm = ((__code & 0x003FFC00)) >> 7; \
*__reg1 = (__code & 0x1F); \
*__reg2 = ((__code & 0x3E0) >> 5); \
} while(0)
#define DISASM_ADD(__code, __imm, __reg1, __reg2) \
do { \
*__imm = ((__code & 0x003FFC00)) >> 10; \
*__reg1 = (__code & 0x1F); \
*__reg2 = ((__code & 0x3E0) >> 5); \
} while(0)
current_offset = 0;
uint64_t trust_cache_runtime_init = 0;
while (current_offset < textexec_text_size) {
uint8_t *buffer = malloc(0x1000);
kread((u64)kfd, textexec_text_addr + current_offset, buffer, 0x1000);
for (int i = 0; i < 0x1000; i += 4) {
uint64_t current_addr = textexec_text_addr + current_offset + i;
uint64_t page = current_addr & (~(uint64_t)0xFFF);
uint64_t page_offset = (str_addr & (~(uint64_t)0xFFF)) - page;
uint32_t code = ASM_ADRP(page_offset, 0);
if (*(uint32_t *)(buffer + i) == code) {
uint64_t code2 = ASM_ADD((str_addr & 0xFFF), 0, 0);
if (*(uint32_t *)(buffer + i + 4) == code2) {
trust_cache_runtime_init = i + textexec_text_addr + current_offset;
break;
}
uint64_t current_code = *(uint64_t *)(buffer + i);
uint32_t adrp_code = current_code & 0xFFFFFFFF;
uint32_t ldr_code = (current_code >> 32) & 0xFFFFFFFF;

uint64_t page_addr = 0, page_offset = 0, reg = 0;
DISASM_ADRP(adrp_code, &page_addr, &reg);
DISASM_ADD(ldr_code, &page_offset, &reg, &reg);
uint64_t addr = ((current_addr & 0xfffffffffffff000) + page_offset + page_addr);

if (addr == str_addr) {
trust_cache_runtime_init = current_addr;
break;
}
}
free(buffer);
if (trust_cache_runtime_init) break;
current_offset += 0x1000;
}
if (!trust_cache_runtime_init) {
LOG(@"[-] failed to find trustcache_runtime_init");
LOG(@"[-] failed to find trustcache_runtime_init 1");
return 0;
}
uint64_t code = 0;
kread((u64)kfd, trust_cache_runtime_init-0x64, &code, 8);
BOOL found = NO;
uint64_t code_addr = trust_cache_runtime_init;
for (int i = 0; i < 0x100; i += 4) {
code_addr = trust_cache_runtime_init - i;
kread((u64)kfd, code_addr, &code, 8);
if ((code & 0xffffffff) == 0x52800509) {
found = YES;
break;
}
}
if (!found) {
LOG(@"[-] failed to find trustcache_runtime_init 2");
return 0;
}
kread((u64)kfd, code_addr-0x08, &code, 8);
uint32_t adrp_code = code & 0xFFFFFFFF;
uint32_t ldr_code = (code >> 32) & 0xFFFFFFFF;
uint64_t page_addr = 0, page_offset = 0, reg = 0;
DISASM_ADRP(adrp_code, &page_addr, &reg);
LOG_FMT_CONSOLE(@"[KPF_DEBUG] page=0x%llx reg=0x%llx", page_addr, reg);
DISASM_ADD(ldr_code, &page_offset, &reg, &reg);
LOG_FMT_CONSOLE(@"[KPF_DEBUG] pageoff=0x%llx reg=0x%llx reg=0x%llx", page_offset, reg, reg);
uint64_t addr = (((trust_cache_runtime_init-0x64) & 0xfffffffffffff000) + page_offset + page_addr);
uint64_t addr = (((code_addr-0x08) & 0xfffffffffffff000) + page_offset + page_addr);
uint64_t data = 0;
kread((u64)kfd, addr, &data, 8);
data = addr - 0x18;
LOG_FMT_CONSOLE(@"[KPF_DEBUG] data=0x%llx", data);

return data + 0x20;
return data;
}

uint64_t find_proc_updatecsflags(struct kfd *kfd) {
Expand Down Expand Up @@ -306,6 +350,8 @@ uint64_t find_container_initwithcapacity(struct kfd *kfd) {
if ((code & 0xFFFFFFFF) == 0xF9001260) {
LOG_FMT_CONSOLE(@"[KPF_DEBUG] 0x%llx", str - buffer + textexec_text_addr + current_offset - kfd->info.kernel.kernel_slide);
return str - buffer + textexec_text_addr + current_offset - 0x4C;
} else if ((code & 0xFFFFFFFF) == 0xD2800003) {
return str - buffer + textexec_text_addr + current_offset - 0x44;
}
}
current_offset += 0x1000;
Expand Down Expand Up @@ -390,7 +436,7 @@ BOOL find_offset(struct kfd *kfd) {
if (found) return YES;
found = true;
init_kernel(kfd);
kcall_gadget = 0, kread_gadget = 0, kwrite_gadget = 0;
kcall_gadget = 0; kread_gadget = 0; kwrite_gadget = 0;
off_proc_set_ucred = find_proc_set_ucred_function(kfd);
off_add_x0_x0_0x40_ret = find_add_x0_x0_0x40_ret(kfd);
off_trustcache = find_trustcaches_addr(kfd);
Expand Down

0 comments on commit c4fa5d4

Please sign in to comment.