Skip to content

Commit

Permalink
Merge branch 'opa334:2.x' into 2.x
Browse files Browse the repository at this point in the history
  • Loading branch information
m1337v authored May 27, 2024
2 parents ddc11e8 + 5c844b2 commit efb496f
Show file tree
Hide file tree
Showing 16 changed files with 222 additions and 25 deletions.
4 changes: 2 additions & 2 deletions Application/Dopamine.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2229,7 +2229,7 @@
"$(PROJECT_DIR)/Dopamine/Dependencies",
"$(PROJECT_DIR)/Dopamine/Resources",
);
MARKETING_VERSION = 2.1.4;
MARKETING_VERSION = 2.1.5;
PRODUCT_BUNDLE_IDENTIFIER = com.opa334.Dopamine;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down Expand Up @@ -2266,7 +2266,7 @@
"$(PROJECT_DIR)/Dopamine/Dependencies",
"$(PROJECT_DIR)/Dopamine/Resources",
);
MARKETING_VERSION = 2.1.4;
MARKETING_VERSION = 2.1.5;
PRODUCT_BUNDLE_IDENTIFIER = com.opa334.Dopamine;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
Expand Down
2 changes: 1 addition & 1 deletion Application/Dopamine/Jailbreak/DOJailbreaker.m
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,7 @@ - (NSError *)createFakeLib

cdhash_t *cdhashes = NULL;
uint32_t cdhashesCount = 0;
macho_collect_untrusted_cdhashes(JBRootPath("/basebin/.fakelib/dyld"), NULL, NULL, &cdhashes, &cdhashesCount);
macho_collect_untrusted_cdhashes(JBRootPath("/basebin/.fakelib/dyld"), NULL, NULL, NULL, NULL, 0, &cdhashes, &cdhashesCount);
if (cdhashesCount != 1) return [NSError errorWithDomain:JBErrorDomain code:JBErrorCodeFailedInitFakeLib userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Got unexpected number of cdhashes for dyld???: %d", cdhashesCount]}];

trustcache_file_v1 *dyldTCFile = NULL;
Expand Down
2 changes: 1 addition & 1 deletion BaseBin/_external/basebin/.version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
2.1.4
2.1.5
45 changes: 40 additions & 5 deletions BaseBin/launchdhook/src/jbserver/jbdomain_systemwide.c
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ static int systemwide_get_boot_uuid(char **bootUUIDOut)
return 0;
}

static int trust_file(const char *filePath, const char *dlopenCallerImagePath, const char *dlopenCallerExecutablePath)
static int trust_file(const char *filePath, const char *dlopenCallerImagePath, const char *dlopenCallerExecutablePath, xpc_object_t preferredArchsArray)
{
// Shared logic between client and server, implemented in client
// This should essentially mean these files never reach us in the first place
Expand All @@ -76,9 +76,23 @@ static int trust_file(const char *filePath, const char *dlopenCallerImagePath, c

if (can_skip_trusting_file(filePath, (bool)dlopenCallerExecutablePath, false)) return -1;

size_t preferredArchCount = 0;
if (preferredArchsArray) preferredArchCount = xpc_array_get_count(preferredArchsArray);
uint32_t preferredArchTypes[preferredArchCount];
uint32_t preferredArchSubtypes[preferredArchCount];
for (size_t i = 0; i < preferredArchCount; i++) {
preferredArchTypes[i] = 0;
preferredArchSubtypes[i] = UINT32_MAX;
xpc_object_t arch = xpc_array_get_value(preferredArchsArray, i);
if (xpc_get_type(arch) == XPC_TYPE_DICTIONARY) {
preferredArchTypes[i] = xpc_dictionary_get_uint64(arch, "type");
preferredArchSubtypes[i] = xpc_dictionary_get_uint64(arch, "subtype");
}
}

cdhash_t *cdhashes = NULL;
uint32_t cdhashesCount = 0;
macho_collect_untrusted_cdhashes(filePath, dlopenCallerImagePath, dlopenCallerExecutablePath, &cdhashes, &cdhashesCount);
macho_collect_untrusted_cdhashes(filePath, dlopenCallerImagePath, dlopenCallerExecutablePath, preferredArchTypes, preferredArchSubtypes, preferredArchCount, &cdhashes, &cdhashesCount);
if (cdhashes && cdhashesCount > 0) {
jb_trustcache_add_cdhashes(cdhashes, cdhashesCount);
free(cdhashes);
Expand All @@ -87,9 +101,9 @@ static int trust_file(const char *filePath, const char *dlopenCallerImagePath, c
}

// Not static because launchd will directly call this from it's posix_spawn hook
int systemwide_trust_binary(const char *binaryPath)
int systemwide_trust_binary(const char *binaryPath, xpc_object_t preferredArchsArray)
{
return trust_file(binaryPath, NULL, NULL);
return trust_file(binaryPath, NULL, NULL, preferredArchsArray);
}

static int systemwide_trust_library(audit_token_t *processToken, const char *libraryPath, const char *callerLibraryPath)
Expand All @@ -105,7 +119,7 @@ static int systemwide_trust_library(audit_token_t *processToken, const char *lib
// This is to support dlopen("@executable_path/whatever", RTLD_NOW) and stuff like that
// (Yes that is a thing >.<)
// Also we need to pass the path of the image that called dlopen due to @loader_path, sigh...
return trust_file(libraryPath, callerLibraryPath, callerPath);
return trust_file(libraryPath, callerLibraryPath, callerPath, NULL);
}

static int systemwide_process_checkin(audit_token_t *processToken, char **rootPathOut, char **bootUUIDOut, char **sandboxExtensionsOut, bool *fullyDebuggedOut)
Expand Down Expand Up @@ -218,6 +232,26 @@ static int systemwide_process_checkin(audit_token_t *processToken, char **rootPa
proc_csflags_set(proc, CS_PLATFORM_BINARY);
}

#ifdef __arm64e__
// On arm64e every image has a trust level associated with it
// "In trust cache" trust levels have higher runtime enforcements, this can be a problem for some tools as Dopamine trustcaches everything that's adhoc signed
// So we add the ability for a binary to get a different trust level using the "jb.pmap_cs_custom_trust" entitlement
// This is for binaries that rely on weaker PMAP_CS checks (e.g. Lua trampolines need it)
xpc_object_t customTrustObj = xpc_copy_entitlement_for_token("jb.pmap_cs.custom_trust", processToken);
if (customTrustObj) {
if (xpc_get_type(customTrustObj) == XPC_TYPE_STRING) {
const char *customTrustStr = xpc_string_get_string_ptr(customTrustObj);
uint32_t customTrust = pmap_cs_trust_string_to_int(customTrustStr);
if (customTrust >= 2) {
uint64_t mainCodeDir = proc_find_main_binary_code_dir(proc);
if (mainCodeDir) {
kwrite32(mainCodeDir + koffsetof(pmap_cs_code_directory, trust), customTrust);
}
}
}
}
#endif

proc_rele(proc);
return 0;
}
Expand Down Expand Up @@ -323,6 +357,7 @@ struct jbserver_domain gSystemwideDomain = {
.handler = systemwide_trust_binary,
.args = (jbserver_arg[]){
{ .name = "binary-path", .type = JBS_TYPE_STRING, .out = false },
{ .name = "preferred-archs", .type = JBS_TYPE_ARRAY, .out = false },
{ 0 },
},
},
Expand Down
2 changes: 1 addition & 1 deletion BaseBin/launchdhook/src/spawn_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <sys/mount.h>
extern char **environ;

extern int systemwide_trust_binary(const char *binaryPath);
extern int systemwide_trust_binary(const char *binaryPath, xpc_object_t preferredArchsArray);
extern int platform_set_process_debugged(uint64_t pid, bool fullyDebugged);

#define LOG_PROCESS_LAUNCHES 0
Expand Down
29 changes: 26 additions & 3 deletions BaseBin/libjailbreak/src/info.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,15 +80,27 @@ void jbinfo_initialize_hardcoded_offsets(void)
gSystemInfo.kernelStruct.pmap.tte = 0x0;
gSystemInfo.kernelStruct.pmap.ttep = 0x8;
#ifdef __arm64e__
gSystemInfo.kernelStruct.pmap.sw_asid = 0xBE + pmapEl2Adjust;
gSystemInfo.kernelStruct.pmap.wx_allowed = 0xC2 + pmapEl2Adjust;
gSystemInfo.kernelStruct.pmap.type = 0xC8 + pmapEl2Adjust;
gSystemInfo.kernelStruct.pmap.pmap_cs_main = 0x90;
gSystemInfo.kernelStruct.pmap.sw_asid = 0xBE + pmapEl2Adjust;
gSystemInfo.kernelStruct.pmap.wx_allowed = 0xC2 + pmapEl2Adjust;
gSystemInfo.kernelStruct.pmap.type = 0xC8 + pmapEl2Adjust;
#else
gSystemInfo.kernelStruct.pmap.sw_asid = 0x96;
gSystemInfo.kernelStruct.pmap.wx_allowed = 0;
gSystemInfo.kernelStruct.pmap.type = 0x9c + pmapA11Adjust;
#endif

#ifdef __arm64e__
// pmap_cs_region
gSystemInfo.kernelStruct.pmap_cs_region.pmap_cs_region_next = 0x0;
gSystemInfo.kernelStruct.pmap_cs_region.cd_entry = 0x28;

// pmap_cs_code_directory
gSystemInfo.kernelStruct.pmap_cs_code_directory.pmap_cs_code_directory_next = 0x0;
gSystemInfo.kernelStruct.pmap_cs_code_directory.main_binary = 0x50;
gSystemInfo.kernelStruct.pmap_cs_code_directory.trust = 0x9C;
#endif

// pt_desc
gSystemInfo.kernelStruct.pt_desc.pmap = 0x10;
gSystemInfo.kernelStruct.pt_desc.va = 0x18;
Expand Down Expand Up @@ -222,6 +234,12 @@ void jbinfo_initialize_hardcoded_offsets(void)
gSystemInfo.kernelStruct.pmap.type = 0x94 + pmapA11Adjust;
#endif

#ifdef __arm64e__
// pmap_cs_code_directory
gSystemInfo.kernelStruct.pmap_cs_code_directory.main_binary = 0x190;
gSystemInfo.kernelStruct.pmap_cs_code_directory.trust = 0x1DC;
#endif

if (strcmp(xnuVersion, "22.1.0") >= 0) { // iOS 16.1+
gSystemInfo.kernelStruct.ipc_space.table_uses_smr = true;
if (strcmp(xnuVersion, "22.3.0") >= 0) { // iOS 16.3+
Expand All @@ -231,6 +249,11 @@ void jbinfo_initialize_hardcoded_offsets(void)
gSystemInfo.kernelStruct.proc.flag = 0x454;
gSystemInfo.kernelStruct.proc.textvp = 0x548;

#ifdef __arm64e__
// pmap_cs_code_directory
gSystemInfo.kernelStruct.pmap_cs_code_directory.trust = 0x1EC;
#endif

if (strcmp(xnuVersion, "22.4.0") == 0) { // iOS 16.4 ONLY
// iOS 16.4 beta 1-3 use the old proc struct, 16.4b4+ use new
if (gSystemInfo.kernelStruct.proc.struct_size != 0x730) {
Expand Down
20 changes: 20 additions & 0 deletions BaseBin/libjailbreak/src/info.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,11 +189,23 @@ struct system_info {
struct {
uint32_t tte;
uint32_t ttep;
uint32_t pmap_cs_main;
uint32_t sw_asid;
uint32_t wx_allowed;
uint32_t type;
} pmap;

struct {
uint32_t pmap_cs_region_next;
uint32_t cd_entry;
} pmap_cs_region;

struct {
uint32_t pmap_cs_code_directory_next;
uint32_t main_binary;
uint32_t trust;
} pmap_cs_code_directory;

struct {
uint32_t pmap;
uint32_t va;
Expand Down Expand Up @@ -359,10 +371,18 @@ extern struct system_info gSystemInfo;
\
iterator(ctx, kernelStruct.pmap.tte); \
iterator(ctx, kernelStruct.pmap.ttep); \
iterator(ctx, kernelStruct.pmap.pmap_cs_main); \
iterator(ctx, kernelStruct.pmap.sw_asid); \
iterator(ctx, kernelStruct.pmap.wx_allowed); \
iterator(ctx, kernelStruct.pmap.type); \
\
iterator(ctx, kernelStruct.pmap_cs_region.pmap_cs_region_next); \
iterator(ctx, kernelStruct.pmap_cs_region.cd_entry); \
\
iterator(ctx, kernelStruct.pmap_cs_code_directory.pmap_cs_code_directory_next); \
iterator(ctx, kernelStruct.pmap_cs_code_directory.main_binary); \
iterator(ctx, kernelStruct.pmap_cs_code_directory.trust); \
\
iterator(ctx, kernelStruct.pt_desc.pmap); \
iterator(ctx, kernelStruct.pt_desc.va); \
iterator(ctx, kernelStruct.pt_desc.ptd_info); \
Expand Down
5 changes: 4 additions & 1 deletion BaseBin/libjailbreak/src/jbclient_xpc.c
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,7 @@ char *realafpath(const char *restrict path, char *restrict resolved_path)
}
}

int jbclient_trust_binary(const char *binaryPath)
int jbclient_trust_binary(const char *binaryPath, xpc_object_t preferredArchsArray)
{
if (!binaryPath) return -1;

Expand All @@ -195,6 +195,9 @@ int jbclient_trust_binary(const char *binaryPath)

xpc_object_t xargs = xpc_dictionary_create_empty();
xpc_dictionary_set_string(xargs, "binary-path", absolutePath);
if (preferredArchsArray) {
xpc_dictionary_set_value(xargs, "preferred-archs", preferredArchsArray);
}
xpc_object_t xreply = jbserver_xpc_send(JBS_DOMAIN_SYSTEMWIDE, JBS_SYSTEMWIDE_TRUST_BINARY, xargs);
xpc_release(xargs);
if (xreply) {
Expand Down
2 changes: 1 addition & 1 deletion BaseBin/libjailbreak/src/jbclient_xpc.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ xpc_object_t jbserver_xpc_send(uint64_t domain, uint64_t action, xpc_object_t xa

char *jbclient_get_jbroot(void);
char *jbclient_get_boot_uuid(void);
int jbclient_trust_binary(const char *binaryPath);
int jbclient_trust_binary(const char *binaryPath, xpc_object_t preferredArchsArray);
int jbclient_trust_library(const char *libraryPath, void *addressInCaller);
int jbclient_process_checkin(char **rootPathOut, char **bootUUIDOut, char **sandboxExtensionsOut, bool *fullyDebuggedOut);
int jbclient_fork_fix(uint64_t childPid);
Expand Down
2 changes: 1 addition & 1 deletion BaseBin/libjailbreak/src/signatures.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@
#include <choma/CodeDirectory.h>

typedef uint8_t cdhash_t[CS_CDHASH_LEN];
void macho_collect_untrusted_cdhashes(const char *path, const char *callerImagePath, const char *callerExecutablePath, cdhash_t **cdhashesOut, uint32_t *cdhashCountOut);
void macho_collect_untrusted_cdhashes(const char *path, const char *callerImagePath, const char *callerExecutablePath, uint32_t *preferredArchTypes, uint32_t *preferredArchSubtypes, size_t preferredArchCount, cdhash_t **cdhashesOut, uint32_t *cdhashCountOut);

#endif
26 changes: 23 additions & 3 deletions BaseBin/libjailbreak/src/signatures.m
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ bool csd_superblob_is_adhoc_signed(CS_DecodedSuperBlob *superblob)
}
}

void macho_collect_untrusted_cdhashes(const char *path, const char *callerImagePath, const char *callerExecutablePath, cdhash_t **cdhashesOut, uint32_t *cdhashCountOut)
void macho_collect_untrusted_cdhashes(const char *path, const char *callerImagePath, const char *callerExecutablePath, uint32_t *preferredArchTypes, uint32_t *preferredArchSubtypes, size_t preferredArchCount, cdhash_t **cdhashesOut, uint32_t *cdhashCountOut)
{
@autoreleasepool {
if (!path) return;
Expand All @@ -140,7 +140,16 @@ void macho_collect_untrusted_cdhashes(const char *path, const char *callerImageP
if (!callerExecutablePath) {
FAT *mainFAT = fat_init_from_path(path);
if (mainFAT) {
MachO *mainMachO = ljb_fat_find_preferred_slice(mainFAT);
MachO *mainMachO = NULL;
if (preferredArchCount > 0) {
for (size_t i = 0; i < preferredArchCount; i++) {
if (preferredArchTypes[i] != 0 && preferredArchSubtypes[i] != UINT32_MAX) {
mainMachO = fat_find_slice(mainFAT, preferredArchTypes[i], preferredArchSubtypes[i]);
if (mainMachO) break;
}
}
}
if (!mainMachO) mainMachO = ljb_fat_find_preferred_slice(mainFAT);
if (mainMachO) {
if (macho_get_filetype(mainMachO) == MH_EXECUTE) {
callerExecutablePath = path;
Expand All @@ -160,7 +169,18 @@ void macho_collect_untrusted_cdhashes(const char *path, const char *callerImageP
NSString *resolvedBinaryPath = resolveDependencyPath(binaryPath, sourceImagePath, sourceExecutablePath);
FAT *fat = fat_init_from_path(resolvedBinaryPath.fileSystemRepresentation);
if (!fat) return;
MachO *macho = ljb_fat_find_preferred_slice(fat);
MachO *macho = NULL;
if ([binaryPath isEqualToString:sourceExecutablePath]) {
if (preferredArchCount > 0) {
for (size_t i = 0; i < preferredArchCount; i++) {
if (preferredArchTypes[i] != 0 && preferredArchSubtypes[i] != UINT32_MAX) {
macho = fat_find_slice(fat, preferredArchTypes[i], preferredArchSubtypes[i]);
if (macho) break;
}
}
}
}
if (!macho) macho = ljb_fat_find_preferred_slice(fat);
if (!macho) {
fat_free(fat);
return;
Expand Down
60 changes: 60 additions & 0 deletions BaseBin/libjailbreak/src/util.c
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,66 @@ int pmap_map_in(uint64_t pmap, uint64_t uaStart, uint64_t paStart, uint64_t size
return 0;
}


#ifdef __arm64e__
uint64_t pmap_find_main_binary_code_dir(uint64_t pmap)
{
uint64_t mainCodeDir = 0;
uint64_t pmap_cs_region = kread_ptr(pmap + koffsetof(pmap, pmap_cs_main));
while (pmap_cs_region && !mainCodeDir) {
uint64_t pmap_cs_code_dir = kread_ptr(pmap_cs_region + koffsetof(pmap_cs_region, cd_entry));
while (pmap_cs_code_dir) {
_Bool mainBinary = kread64(pmap_cs_code_dir + koffsetof(pmap_cs_code_directory, main_binary));
if (mainBinary) {
mainCodeDir = pmap_cs_code_dir;
break;
}
pmap_cs_code_dir = kread_ptr(pmap_cs_code_dir + koffsetof(pmap_cs_code_directory, pmap_cs_code_directory_next));
}
pmap_cs_region = kread_ptr(pmap_cs_region + koffsetof(pmap_cs_region, pmap_cs_region_next));
}
return mainCodeDir;
}

uint64_t proc_find_main_binary_code_dir(uint64_t proc)
{
uint64_t task = proc_task(proc);
uint64_t map = kread_ptr(task + koffsetof(task, map));
uint64_t pmap = kread_ptr(map + koffsetof(vm_map, pmap));
return pmap_find_main_binary_code_dir(pmap);
}

uint32_t pmap_cs_trust_string_to_int(const char *trustString)
{
int trustInt = 0;
if (__builtin_available(iOS 16.0, *)) {
if (!strcmp(trustString, "PMAP_CS_UNTRUSTED")) trustInt = 0;
else if (!strcmp(trustString, "PMAP_CS_RETIRED")) trustInt = 1;
else if (!strcmp(trustString, "PMAP_CS_PROFILE_PREFLIGHT")) trustInt = 2;
else if (!strcmp(trustString, "PMAP_CS_COMPILATION_SERVICE")) trustInt = 3;
else if (!strcmp(trustString, "PMAP_CS_OOP_JIT")) trustInt = 4;
else if (!strcmp(trustString, "PMAP_CS_LOCAL_SIGNING")) trustInt = 5;
else if (!strcmp(trustString, "PMAP_CS_PROFILE_VALIDATED")) trustInt = 6;
else if (!strcmp(trustString, "PMAP_CS_APP_STORE")) trustInt = 7;
else if (!strcmp(trustString, "PMAP_CS_IN_LOADED_TRUST_CACHE")) trustInt = 8;
else if (!strcmp(trustString, "PMAP_CS_IN_STATIC_TRUST_CACHE")) trustInt = 9;
}
else {
if (!strcmp(trustString, "PMAP_CS_UNTRUSTED")) trustInt = 0;
else if (!strcmp(trustString, "PMAP_CS_RETIRED")) trustInt = 1;
else if (!strcmp(trustString, "PMAP_CS_PROFILE_PREFLIGHT")) trustInt = 2;
else if (!strcmp(trustString, "PMAP_CS_COMPILATION_SERVICE")) trustInt = 3;
else if (!strcmp(trustString, "PMAP_CS_LOCAL_SIGNING")) trustInt = 4;
else if (!strcmp(trustString, "PMAP_CS_PROFILE_VALIDATED")) trustInt = 5;
else if (!strcmp(trustString, "PMAP_CS_APP_STORE")) trustInt = 6;
else if (!strcmp(trustString, "PMAP_CS_IN_LOADED_TRUST_CACHE")) trustInt = 7;
else if (!strcmp(trustString, "PMAP_CS_IN_STATIC_TRUST_CACHE")) trustInt = 8;
}
return trustInt;
}

#endif

int sign_kernel_thread(uint64_t proc, mach_port_t threadPort)
{
uint64_t threadKobj = task_get_ipc_port_kobject(proc_task(proc), threadPort);
Expand Down
Loading

0 comments on commit efb496f

Please sign in to comment.