Skip to content

Commit

Permalink
Merge branch 'opa334:2.x' into dev
Browse files Browse the repository at this point in the history
  • Loading branch information
wwg135 authored May 27, 2024
2 parents 51a44fd + 5c844b2 commit 82cf81a
Show file tree
Hide file tree
Showing 17 changed files with 232 additions and 35 deletions.
4 changes: 2 additions & 2 deletions Application/Dopamine.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2237,7 +2237,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 @@ -2274,7 +2274,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
20 changes: 10 additions & 10 deletions BaseBin/libjailbreak/src/kcall_Fugu14.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,14 @@ void pac_loop(void);

uint64_t mapKernelPage(uint64_t addr)
{
uint64_t page = addr & ~0x3FFFULL;
uint64_t off = addr & 0x3FFFULL;
uint64_t translated = kvtophys(page);
void *map = NULL;
if (kmap(translated, 0x4000, &map) == 0) {
return ((uint64_t)map) + off;
}
return -1;
uint64_t page = addr & ~0x3FFFULL;
uint64_t off = addr & 0x3FFFULL;
uint64_t translated = kvtophys(page);
void *map = NULL;
if (kmap(translated, 0x4000, &map) == 0) {
return ((uint64_t)map) + off;
}
return -1;
}

uint64_t getUserReturnThreadContext(void)
Expand Down Expand Up @@ -130,8 +130,8 @@ int fugu14_kcall_init(int (^threadSigner)(mach_port_t threadPort))

// Write register values
uint64_t str_x8_x9_gadget = kgadget(str_x8_x9);
uint64_t exception_return_after_check = kgadget(exception_return_after_check);
uint64_t brX22 = kgadget(br_x22);
uint64_t exception_return_after_check = kgadget(exception_return_after_check);
uint64_t brX22 = kgadget(br_x22);
kwrite64(actContext + offsetof(kRegisterState, pc), str_x8_x9_gadget);
kwrite32(actContext + offsetof(kRegisterState, cpsr), CPSR_KERN_INTR_DIS);
kwrite64(actContext + offsetof(kRegisterState, lr), exception_return_after_check);
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
Loading

0 comments on commit 82cf81a

Please sign in to comment.