diff --git a/BaseBin/jbctl/src/main.m b/BaseBin/jbctl/src/main.m index 200f2a5f4..fecddbd81 100644 --- a/BaseBin/jbctl/src/main.m +++ b/BaseBin/jbctl/src/main.m @@ -13,7 +13,9 @@ void print_usage(void) printf("Usage: jbctl \n\ Available commands:\n\ proc_set_debugged \t\tMarks the process with the given pid as being debugged, allowing invalid code pages inside of it\n\ - rebuild_trustcache\t\tRebuilds the TrustCache, clearing any previously trustcached files that no longer exists from it (automatically ran daily at midnight)\n\ + trustcache info\t\t\tPrint info about all jailbreak related trustcaches and the cdhashes contained in them\n\ + trustcache clear\t\tClears any existing cdhashes from the jailbreaks trustcaches\n\ + trustcache add \t\tAdd an arbitrary cdhash to the jailbreaks trustcaches\n\ update \tInitiates a jailbreak update either based on a TIPA or based on a basebin.tar file, TIPA installation depends on TrollStore, afterwards it triggers a userspace reboot\n"); } @@ -51,11 +53,69 @@ int main(int argc, char* argv[]) printf("Failed to mark proc of pid %d as debugged\n", pid); } } - else if (!strcmp(cmd, "rebuild_trustcache")) { - //jbdRebuildTrustCache(); - } else if (!strcmp(cmd, "reboot_userspace")) { + else if (!strcmp(cmd, "trustcache")) { + if (argc < 3) { + print_usage(); + return 2; + } + if (getuid() != 0) { + printf("ERROR: trustcache subcommand requires root.\n"); + return 3; + } + const char *trustcacheCmd = argv[2]; + if (!strcmp(trustcacheCmd, "info")) { + xpc_object_t tcArr = nil; + if (jbclient_root_trustcache_info(&tcArr) == 0) { + size_t tcCount = xpc_array_get_count(tcArr); + for (size_t i = 0; i < tcCount; i++) { + xpc_object_t tc = xpc_array_get_dictionary(tcArr, i); + size_t uuidLength = 0; + const void *uuidData = xpc_dictionary_get_data(tc, "uuid", &uuidLength); + xpc_object_t cdhashesArr = xpc_dictionary_get_array(tc, "cdhashes"); + if (uuidData && cdhashesArr) { + size_t length = xpc_array_get_count(cdhashesArr); + char uuidString[uuidLength * 2 + 1]; + convert_data_to_hex_string(uuidData, uuidLength, uuidString); + printf("Jailbreak Trustcache %zd (length: %zd)\n", i, uuidString, length); + for (size_t j = 0; j < length; j++) { + size_t cdhashLength = 0; + const void *cdhashData = xpc_array_get_data(cdhashesArr, j, &cdhashLength); + if (cdhashData) { + char cdhashString[cdhashLength * 2 + 1]; + convert_data_to_hex_string(cdhashData, cdhashLength, cdhashString); + printf("| %zd:\t%s\n", j+1, cdhashString); + } + } + } + } + } + return 0; + } + else if (!strcmp(trustcacheCmd, "clear")) { + return jbclient_root_trustcache_clear(); + } + else if (!strcmp(trustcacheCmd, "add")) { + if (argc < 4) { + print_usage(); + return 2; + } + const char *cdhashString = argv[3]; + if (strlen(cdhashString) != (sizeof(cdhash_t) * 2)) { + printf("ERROR: passed cdhash has wrong length\n"); + return 2; + } + cdhash_t cdhash; + if (convert_hex_string_to_data(cdhashString, &cdhash)) { + printf("ERROR: passed cdhash is malformed\n"); + return 2; + } + return jbclient_root_trustcache_add_cdhash(cdhash, sizeof(cdhash)); + } + } + else if (!strcmp(cmd, "reboot_userspace")) { return reboot3(RB2_USERREBOOT); - } else if (!strcmp(cmd, "update")) { + } + else if (!strcmp(cmd, "update")) { if (argc < 4) { print_usage(); return 2; @@ -106,7 +166,8 @@ int main(int argc, char* argv[]) printf("Staging update failed with error code %lld\n", result); return result; } - } else if (!strcmp(cmd, "internal")) { + } + else if (!strcmp(cmd, "internal")) { if (getuid() != 0) return -1; if (argc < 3) return -1; diff --git a/BaseBin/launchdhook/src/jbserver/jbdomain_root.c b/BaseBin/launchdhook/src/jbserver/jbdomain_root.c index 540c17aef..6f909868d 100644 --- a/BaseBin/launchdhook/src/jbserver/jbdomain_root.c +++ b/BaseBin/launchdhook/src/jbserver/jbdomain_root.c @@ -79,12 +79,24 @@ static int root_set_mac_label(audit_token_t *clientToken, uint64_t slot, uint64_ return 0; } -static int root_add_cdhash(uint8_t *cdhashData, size_t cdhashLen) +static int root_trustcache_info(xpc_object_t *infoOut) +{ + *infoOut = jb_trustcache_info(); + return 0; +} + +static int root_trustcache_add_cdhash(uint8_t *cdhashData, size_t cdhashLen) { if (cdhashLen != CS_CDHASH_LEN) return -1; return jb_trustcache_add_cdhashes((cdhash_t *)cdhashData, 1); } +static int root_trustcache_clear(void) +{ + jb_trustcache_clear(); + return 0; +} + struct jbserver_domain gRootDomain = { .permissionHandler = root_domain_allowed, .actions = { @@ -115,14 +127,6 @@ struct jbserver_domain gRootDomain = { { 0 }, }, }, - // JBS_ROOT_ADD_CDHASH - { - .handler = root_add_cdhash, - .args = (jbserver_arg[]){ - { .name = "cdhash", .type = JBS_TYPE_DATA, .out = false }, - { 0 }, - }, - }, // JBS_ROOT_STEAL_UCRED { .handler = root_steal_ucred, @@ -144,6 +148,29 @@ struct jbserver_domain gRootDomain = { { 0 }, }, }, + // JBS_ROOT_TRUSTCACHE_INFO + { + .handler = root_trustcache_info, + .args = (jbserver_arg[]){ + { .name = "tc-info", .type = JBS_TYPE_ARRAY, .out = true }, + { 0 }, + }, + }, + // JBS_ROOT_ADD_CDHASH + { + .handler = root_trustcache_add_cdhash, + .args = (jbserver_arg[]){ + { .name = "cdhash", .type = JBS_TYPE_DATA, .out = false }, + { 0 }, + }, + }, + // JBS_ROOT_TRUSTCACHE_CLEAR + { + .handler = root_trustcache_clear, + .args = (jbserver_arg[]){ + { 0 }, + }, + }, { 0 }, }, }; diff --git a/BaseBin/libjailbreak/src/info.h b/BaseBin/libjailbreak/src/info.h index adac76f3b..57ba28eea 100644 --- a/BaseBin/libjailbreak/src/info.h +++ b/BaseBin/libjailbreak/src/info.h @@ -423,11 +423,11 @@ void jbinfo_initialize_hardcoded_offsets(void); void jbinfo_initialize_boot_constants(void); xpc_object_t jbinfo_get_serialized(void); -uint64_t get_vm_real_kernel_page_size(); +uint64_t get_vm_real_kernel_page_size(void); #define vm_real_kernel_page_size get_vm_real_kernel_page_size() #define vm_real_kernel_page_mask (vm_real_kernel_page_size - 1) -uint64_t get_vm_real_kernel_page_shift(); +uint64_t get_vm_real_kernel_page_shift(void); #define vm_real_kernel_page_shift get_vm_real_kernel_page_shift() uint64_t get_l1_block_size(void); diff --git a/BaseBin/libjailbreak/src/jbclient_xpc.c b/BaseBin/libjailbreak/src/jbclient_xpc.c index 18271649a..5e58e958e 100644 --- a/BaseBin/libjailbreak/src/jbclient_xpc.c +++ b/BaseBin/libjailbreak/src/jbclient_xpc.c @@ -378,45 +378,69 @@ int jbclient_root_get_sysinfo(xpc_object_t *sysInfoOut) return -1; } -int jbclient_root_add_cdhash(uint8_t *cdhashData, size_t cdhashLen) +int jbclient_root_steal_ucred(uint64_t ucredToSteal, uint64_t *orgUcred) { xpc_object_t xargs = xpc_dictionary_create_empty(); - xpc_dictionary_set_data(xargs, "cdhash", cdhashData, cdhashLen); - xpc_object_t xreply = jbserver_xpc_send(JBS_DOMAIN_ROOT, JBS_ROOT_ADD_CDHASH, xargs); + xpc_dictionary_set_uint64(xargs, "ucred", ucredToSteal); + xpc_object_t xreply = jbserver_xpc_send(JBS_DOMAIN_ROOT, JBS_ROOT_STEAL_UCRED, xargs); xpc_release(xargs); if (xreply) { int64_t result = xpc_dictionary_get_int64(xreply, "result"); + if (orgUcred) *orgUcred = xpc_dictionary_get_uint64(xreply, "org-ucred"); xpc_release(xreply); return result; } return -1; } -int jbclient_root_steal_ucred(uint64_t ucredToSteal, uint64_t *orgUcred) +int jbclient_root_set_mac_label(uint64_t slot, uint64_t label, uint64_t *orgLabel) { xpc_object_t xargs = xpc_dictionary_create_empty(); - xpc_dictionary_set_uint64(xargs, "ucred", ucredToSteal); - xpc_object_t xreply = jbserver_xpc_send(JBS_DOMAIN_ROOT, JBS_ROOT_STEAL_UCRED, xargs); + xpc_dictionary_set_uint64(xargs, "slot", slot); + xpc_dictionary_set_uint64(xargs, "label", label); + xpc_object_t xreply = jbserver_xpc_send(JBS_DOMAIN_ROOT, JBS_ROOT_SET_MAC_LABEL, xargs); xpc_release(xargs); if (xreply) { int64_t result = xpc_dictionary_get_int64(xreply, "result"); - if (orgUcred) *orgUcred = xpc_dictionary_get_uint64(xreply, "org-ucred"); + if (orgLabel) *orgLabel = xpc_dictionary_get_uint64(xreply, "org-label"); xpc_release(xreply); return result; } return -1; } -int jbclient_root_set_mac_label(uint64_t slot, uint64_t label, uint64_t *orgLabel) +int jbclient_root_trustcache_info(xpc_object_t *infoOut) +{ + xpc_object_t xreply = jbserver_xpc_send(JBS_DOMAIN_ROOT, JBS_ROOT_TRUSTCACHE_INFO, NULL); + if (xreply) { + int64_t result = xpc_dictionary_get_int64(xreply, "result"); + xpc_object_t info = xpc_dictionary_get_array(xreply, "tc-info"); + if (infoOut && info) *infoOut = xpc_copy(info); + xpc_release(xreply); + return result; + } + return -1; +} + +int jbclient_root_trustcache_add_cdhash(uint8_t *cdhashData, size_t cdhashLen) { xpc_object_t xargs = xpc_dictionary_create_empty(); - xpc_dictionary_set_uint64(xargs, "slot", slot); - xpc_dictionary_set_uint64(xargs, "label", label); - xpc_object_t xreply = jbserver_xpc_send(JBS_DOMAIN_ROOT, JBS_ROOT_SET_MAC_LABEL, xargs); + xpc_dictionary_set_data(xargs, "cdhash", cdhashData, cdhashLen); + xpc_object_t xreply = jbserver_xpc_send(JBS_DOMAIN_ROOT, JBS_ROOT_TRUSTCACHE_ADD_CDHASH, xargs); xpc_release(xargs); if (xreply) { int64_t result = xpc_dictionary_get_int64(xreply, "result"); - if (orgLabel) *orgLabel = xpc_dictionary_get_uint64(xreply, "org-label"); + xpc_release(xreply); + return result; + } + return -1; +} + +int jbclient_root_trustcache_clear(void) +{ + xpc_object_t xreply = jbserver_xpc_send(JBS_DOMAIN_ROOT, JBS_ROOT_TRUSTCACHE_CLEAR, NULL); + if (xreply) { + int64_t result = xpc_dictionary_get_int64(xreply, "result"); xpc_release(xreply); return result; } diff --git a/BaseBin/libjailbreak/src/jbclient_xpc.h b/BaseBin/libjailbreak/src/jbclient_xpc.h index 69e69209e..0d543d443 100644 --- a/BaseBin/libjailbreak/src/jbclient_xpc.h +++ b/BaseBin/libjailbreak/src/jbclient_xpc.h @@ -24,9 +24,11 @@ int jbclient_watchdog_get_last_userspace_panic(char **panicMessage); int jbclient_root_get_physrw(bool singlePTE, uint64_t *singlePTEAsidPtr); int jbclient_root_sign_thread(mach_port_t threadPort); int jbclient_root_get_sysinfo(xpc_object_t *sysInfoOut); -int jbclient_root_add_cdhash(uint8_t *cdhashData, size_t cdhashLen); int jbclient_root_steal_ucred(uint64_t ucredToSteal, uint64_t *orgUcred); int jbclient_root_set_mac_label(uint64_t slot, uint64_t label, uint64_t *orgLabel); +int jbclient_root_trustcache_info(xpc_object_t *infoOut); +int jbclient_root_trustcache_add_cdhash(uint8_t *cdhashData, size_t cdhashLen); +int jbclient_root_trustcache_clear(void); int jbclient_boomerang_done(void); #endif diff --git a/BaseBin/libjailbreak/src/jbserver.h b/BaseBin/libjailbreak/src/jbserver.h index b2fe61139..9961b1b7a 100644 --- a/BaseBin/libjailbreak/src/jbserver.h +++ b/BaseBin/libjailbreak/src/jbserver.h @@ -81,9 +81,11 @@ enum { JBS_ROOT_GET_PHYSRW = 1, JBS_ROOT_SIGN_THREAD, JBS_ROOT_GET_SYSINFO, - JBS_ROOT_ADD_CDHASH, JBS_ROOT_STEAL_UCRED, JBS_ROOT_SET_MAC_LABEL, + JBS_ROOT_TRUSTCACHE_INFO, + JBS_ROOT_TRUSTCACHE_ADD_CDHASH, + JBS_ROOT_TRUSTCACHE_CLEAR, }; #define JBS_BOOMERANG_DONE 42 diff --git a/BaseBin/libjailbreak/src/trustcache.c b/BaseBin/libjailbreak/src/trustcache.c index 7a0e1c83a..6fe278efe 100644 --- a/BaseBin/libjailbreak/src/trustcache.c +++ b/BaseBin/libjailbreak/src/trustcache.c @@ -133,7 +133,7 @@ void _jb_trustcache_enumerate(void (^enumerateBlock)(uint64_t jbTcKaddr, bool *s }); } -void _jb_trustcache_clear(void) +void jb_trustcache_clear(void) { _jb_trustcache_enumerate(^(uint64_t jbTcKaddr, bool *stop) { kwrite64(jbTcKaddr + offsetof(jb_trustcache, file.length), 0); @@ -219,12 +219,33 @@ int jb_trustcache_add_entry(struct trustcache_entry_v1 entry) int jb_trustcache_add_directory(const char *directoryPath) { -} +}*/ -void jb_trustcache_rebuild(void) +xpc_object_t jb_trustcache_info(void) { + xpc_object_t arr = xpc_array_create_empty(); + _jb_trustcache_enumerate(^(uint64_t jbTcKaddr, bool *stop) { + uuid_t uuid; + kreadbuf(jbTcKaddr + offsetof(jb_trustcache, file.uuid), (void *)uuid, sizeof(uuid)); + uint32_t length = kread32(jbTcKaddr + offsetof(jb_trustcache, file.length)); -}*/ + xpc_object_t tcDict = xpc_dictionary_create_empty(); + xpc_dictionary_set_data(tcDict, "uuid", &uuid, sizeof(uuid)); + + xpc_object_t hashesArr = xpc_array_create_empty(); + for (int i = 0; i < length; i++) { + trustcache_entry_v1 entry; + kreadbuf(jbTcKaddr + offsetof(jb_trustcache, file.entries[i]), &entry, sizeof(entry)); + xpc_array_set_data(hashesArr, XPC_ARRAY_APPEND, &entry.hash, sizeof(entry.hash)); + } + xpc_dictionary_set_value(tcDict, "cdhashes", hashesArr); + xpc_release(hashesArr); + + xpc_array_append_value(arr, tcDict); + xpc_release(tcDict); + }); + return arr; +} void jb_trustcache_debug_print(FILE *f) { diff --git a/BaseBin/libjailbreak/src/trustcache.h b/BaseBin/libjailbreak/src/trustcache.h index 397032b79..bed1e2475 100644 --- a/BaseBin/libjailbreak/src/trustcache.h +++ b/BaseBin/libjailbreak/src/trustcache.h @@ -6,6 +6,7 @@ #include #include #include "trustcache_structs.h" +#include #define BASEBIN_TRUSTCACHE_UUID (uuid_t){'B','A','S','E','B','I','N','\0','\0','\0','\0','\0','\0','\0','\0','\0'} #define DYLD_TRUSTCACHE_UUID (uuid_t){'D','Y','L','D','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0','\0'} @@ -15,6 +16,9 @@ int trustcache_list_insert(uint64_t tcKaddr); int jb_trustcache_add_entries(struct trustcache_entry_v1 *entries, uint32_t entryCount); int jb_trustcache_add_entry(trustcache_entry_v1 entry); int jb_trustcache_add_cdhashes(cdhash_t *hashes, uint32_t hashCount); +xpc_object_t jb_trustcache_info(void); +void jb_trustcache_clear(void); + //int jb_trustcache_add_file(const char *filePath); //int jb_trustcache_add_directory(const char *directoryPath); //void jb_trustcache_rebuild(void); diff --git a/BaseBin/libjailbreak/src/util.c b/BaseBin/libjailbreak/src/util.c index 8028115f5..43b674f1f 100644 --- a/BaseBin/libjailbreak/src/util.c +++ b/BaseBin/libjailbreak/src/util.c @@ -761,6 +761,37 @@ void thread_caffeinate_stop(void) } } +void convert_data_to_hex_string(const void *data, size_t size, char *outBuf) +{ + unsigned char *pin = (unsigned char *)data; + const char *hex = "0123456789ABCDEF"; + char *pout = outBuf; + for(; pin < ((unsigned char *)data)+size; pout+=2, pin++){ + pout[0] = hex[(*pin>>4) & 0xF]; + pout[1] = hex[ *pin & 0xF]; + } + pout[0] = 0; +} + +int convert_hex_string_to_data(const char *string, void *outBuf) +{ + size_t length = strlen(string); + const char *pin = string; + char *pout = outBuf; + for (; pin < string+length; pin++) { + char byte = *pin; + if (byte >= '0' && byte <= '9') byte = byte - '0'; + else if (byte >= 'a' && byte <='f') byte = byte - 'a' + 10; + else if (byte >= 'A' && byte <='F') byte = byte - 'A' + 10; + else return -1; + + int shift = ((pin - (string+length)) % 2) ? 0 : 4; + *pout = (*pout & ~(0xf << shift)) | (byte << shift); + if (shift == 0) pout++; + } + return 0; +} + char *boot_manifest_hash(void) { static char *gBuf = NULL; @@ -774,14 +805,7 @@ char *boot_manifest_hash(void) gBuf = malloc((bootManifestHashLength * 2 * sizeof(char)) + sizeof(char)); unsigned char *buf = (unsigned char *)CFDataGetBytePtr(bootManifestHashData); - unsigned char *pin = buf; - const char *hex = "0123456789ABCDEF"; - char *pout = gBuf; - for(; pin < buf+bootManifestHashLength; pout+=2, pin++){ - pout[0] = hex[(*pin>>4) & 0xF]; - pout[1] = hex[ *pin & 0xF]; - } - pout[0] = 0; + convert_data_to_hex_string(buf, bootManifestHashLength, gBuf); CFRelease(bootManifestHashData); } diff --git a/BaseBin/libjailbreak/src/util.h b/BaseBin/libjailbreak/src/util.h index e419204db..02f48fc9f 100644 --- a/BaseBin/libjailbreak/src/util.h +++ b/BaseBin/libjailbreak/src/util.h @@ -37,6 +37,9 @@ int libarchive_unarchive(const char *fileToExtract, const char *extractionPath); void thread_caffeinate_start(void); void thread_caffeinate_stop(void); +void convert_data_to_hex_string(const void *data, size_t size, char *outBuf); +int convert_hex_string_to_data(const char *string, void *outBuf); + int cmd_wait_for_exit(pid_t pid); int exec_cmd(const char *binary, ...); int exec_cmd_nowait(pid_t *pidOut, const char *binary, ...);