Skip to content

Commit

Permalink
Deprecate fakelib in favor of redirecting dyld via namecache hax, scr…
Browse files Browse the repository at this point in the history
…apped cause this causes weird issues on iOS 16
  • Loading branch information
opa334 committed Feb 16, 2025
1 parent 3c32c14 commit 9ca30be
Show file tree
Hide file tree
Showing 21 changed files with 184 additions and 247 deletions.
2 changes: 0 additions & 2 deletions Application/Dopamine/Jailbreak/DOEnvironmentManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,6 @@ NS_ASSUME_NONNULL_BEGIN
- (BOOL)isIDownloadEnabled;
- (void)setIDownloadEnabled:(BOOL)enabled needsUnsandbox:(BOOL)needsUnsandbox;
- (void)setIDownloadLoaded:(BOOL)loaded needsUnsandbox:(BOOL)needsUnsandbox;
- (BOOL)isFakelibMounted;
- (int)setFakelibMounted:(BOOL)mounted;
- (int)setPrivatePrebootProtected:(BOOL)protected;
- (BOOL)isJailbreakHidden;
- (void)setJailbreakHidden:(BOOL)hidden;
Expand Down
23 changes: 2 additions & 21 deletions Application/Dopamine/Jailbreak/DOEnvironmentManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -495,23 +495,6 @@ - (void)setIDownloadLoaded:(BOOL)loaded needsUnsandbox:(BOOL)needsUnsandbox
}
}

- (BOOL)isFakelibMounted
{
struct statfs fsb;
if (statfs("/usr/lib", &fsb) != 0) return NO;
return strcmp(fsb.f_mntonname, "/usr/lib") == 0;
}

- (int)setFakelibMounted:(BOOL)mounted
{
int r = 0;
if (mounted != [self isFakelibMounted]) {
const char *arg = mounted ? "mount" : "unmount";
r = exec_cmd(JBROOT_PATH("/basebin/jbctl"), "internal", "fakelib", arg, NULL);
}
return r;
}

- (int)setPrivatePrebootProtected:(BOOL)protected
{
const char *arg = protected ? "activate" : "deactivate";
Expand All @@ -537,16 +520,14 @@ - (void)setJailbreakHidden:(BOOL)hidden
if ([self isJailbroken]) {
[self unregisterJailbreakApps];
[self setPrivatePrebootProtected:NO];
[self setFakelibMounted:NO];
jbclient_platform_set_systemwide_domain_enabled(false);
jbclient_platform_set_jailbreak_hidden(true);
}
[[NSFileManager defaultManager] removeItemAtPath:@"/var/jb" error:nil];
}
else {
[[NSFileManager defaultManager] createSymbolicLinkAtPath:@"/var/jb" withDestinationPath:JBROOT_PATH(@"/") error:nil];
if ([self isJailbroken]) {
jbclient_platform_set_systemwide_domain_enabled(true);
[self setFakelibMounted:YES];
jbclient_platform_set_jailbreak_hidden(false);
[self setPrivatePrebootProtected:YES];
[self refreshJailbreakApps];
}
Expand Down
79 changes: 39 additions & 40 deletions Application/Dopamine/Jailbreak/DOJailbreaker.m
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ typedef NS_ENUM(NSInteger, JBErrorCode) {
JBErrorCodeFailedBasebinTrustcache = -10,
JBErrorCodeFailedLaunchdInjection = -11,
JBErrorCodeFailedInitProtection = -12,
JBErrorCodeFailedInitFakeLib = -13,
JBErrorCodeFailedApplyDyldPatch = -13,
JBErrorCodeFailedDuplicateApps = -14,
};

Expand Down Expand Up @@ -324,6 +324,36 @@ - (NSError *)loadBasebinTrustcache
return NULL;
}

- (NSError *)applyDyldPatch
{
int r = basebin_generate(false);
if (r != 0) {
return [NSError errorWithDomain:JBErrorDomain code:JBErrorCodeFailedApplyDyldPatch userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Generating basebin failed with error: %d", r]}];
}

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

trustcache_file_v1 *dyldTCFile = NULL;
r = trustcache_file_build_from_cdhashes(cdhashes, cdhashesCount, &dyldTCFile);
free(cdhashes);
if (r == 0) {
int r = trustcache_file_upload_with_uuid(dyldTCFile, DYLD_TRUSTCACHE_UUID);
if (r != 0) return [NSError errorWithDomain:JBErrorDomain code:JBErrorCodeFailedApplyDyldPatch userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Failed to upload dyld trustcache: %d", r]}];
free(dyldTCFile);
}
else {
return [NSError errorWithDomain:JBErrorDomain code:JBErrorCodeFailedApplyDyldPatch userInfo:@{NSLocalizedDescriptionKey : @"Failed to build dyld trustcache"}];
}

r = apply_dyld_switcheroo();
if (r != 0) return [NSError errorWithDomain:JBErrorDomain code:JBErrorCodeFailedApplyDyldPatch userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Failed to apply switcheroo on dyld vnode: %d", r]}];

return nil;
}

- (NSError *)injectLaunchdHook
{
// Host a boomerang server that will be used by launchdhook to get the jailbreak primitives from this app
Expand Down Expand Up @@ -368,6 +398,9 @@ - (NSError *)injectLaunchdHook
dispatch_semaphore_wait(info.boomerangDone, DISPATCH_TIME_FOREVER);
mach_port_deallocate(mach_task_self(), serverPort);

// Now that dyld is patched and jbserver is up, we want to make systemhook inject into any binary we spawn
setenv("DYLD_INSERT_LIBRARIES", JBROOT_PATH("/basebin/systemhook.dylib"), 1);

return nil;
}

Expand All @@ -380,40 +413,6 @@ - (NSError *)applyProtection
return nil;
}

- (NSError *)createFakeLib
{
int r = basebin_generate(false);
if (r != 0) {
return [NSError errorWithDomain:JBErrorDomain code:JBErrorCodeFailedInitFakeLib userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Creating fakelib failed with error: %d", r]}];
}

cdhash_t *cdhashes = NULL;
uint32_t cdhashesCount = 0;
file_collect_untrusted_cdhashes_by_path(JBROOT_PATH("/basebin/.fakelib/dyld"), &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;
r = trustcache_file_build_from_cdhashes(cdhashes, cdhashesCount, &dyldTCFile);
free(cdhashes);
if (r == 0) {
int r = trustcache_file_upload_with_uuid(dyldTCFile, DYLD_TRUSTCACHE_UUID);
if (r != 0) return [NSError errorWithDomain:JBErrorDomain code:JBErrorCodeFailedInitFakeLib userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Failed to upload dyld trustcache: %d", r]}];
free(dyldTCFile);
}
else {
return [NSError errorWithDomain:JBErrorDomain code:JBErrorCodeFailedInitFakeLib userInfo:@{NSLocalizedDescriptionKey : @"Failed to build dyld trustcache"}];
}

r = [[DOEnvironmentManager sharedManager] setFakelibMounted:YES];
if (r != 0) {
return [NSError errorWithDomain:JBErrorDomain code:JBErrorCodeFailedInitFakeLib userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"Mounting fakelib failed with error: %d", r]}];
}

// Now that fakelib is up, we want to make systemhook inject into any binary we spawn
setenv("DYLD_INSERT_LIBRARIES", "/usr/lib/systemhook.dylib", 1);
return nil;
}

- (NSError *)ensureNoDuplicateApps
{
NSMutableSet *dopamineInstalledAppIds = [NSMutableSet new];
Expand Down Expand Up @@ -547,6 +546,10 @@ - (void)runWithError:(NSError **)errOut didRemoveJailbreak:(BOOL*)didRemove show
[[DOUIManager sharedInstance] sendLog:DOLocalizedString(@"Loading BaseBin TrustCache") debug:NO];
*errOut = [self loadBasebinTrustcache];
if (*errOut) return;

[[DOUIManager sharedInstance] sendLog:DOLocalizedString(@"Patching dyld") debug:NO];
*errOut = [self applyDyldPatch];
if (*errOut) return;

[[DOUIManager sharedInstance] sendLog:DOLocalizedString(@"Initializing Environment") debug:NO];
*errOut = [self injectLaunchdHook];
Expand All @@ -558,11 +561,7 @@ - (void)runWithError:(NSError **)errOut didRemoveJailbreak:(BOOL*)didRemove show
[[DOUIManager sharedInstance] sendLog:DOLocalizedString(@"Initializing Protection") debug:NO];
*errOut = [self applyProtection];
if (*errOut) return;

[[DOUIManager sharedInstance] sendLog:DOLocalizedString(@"Applying Bind Mount") debug:NO];
*errOut = [self createFakeLib];
if (*errOut) return;


// Unsandbox iconservicesagent so that app icons can work
exec_cmd_trusted(JBROOT_PATH("/usr/bin/killall"), "-9", "iconservicesagent", NULL);

Expand Down
51 changes: 0 additions & 51 deletions BaseBin/dyldhook/src/fakelib_redirect.c

This file was deleted.

38 changes: 0 additions & 38 deletions BaseBin/jbctl/src/internal.m
Original file line number Diff line number Diff line change
Expand Up @@ -70,27 +70,6 @@ int protection_set_active(bool active)
return r;
}

bool fakelib_is_mounted(void)
{
struct statfs fsb;
if (statfs("/usr/lib", &fsb) != 0) return NO;
return strcmp(fsb.f_mntonname, "/usr/lib") == 0;
}

int fakelib_set_mounted(bool mounted)
{
int r = 0;
if (mounted != fakelib_is_mounted()) {
if (mounted) {
r = mount_unsandboxed("bindfs", "/usr/lib", MNT_RDONLY, (void *)JBROOT_PATH("/basebin/.fakelib"));
}
else {
r = unmount_unsandboxed("/usr/lib", MNT_FORCE);
}
}
return r;
}

int jbctl_handle_internal(const char *command, int argc, char* argv[])
{
if (!strcmp(command, "launchd_stash_port")) {
Expand Down Expand Up @@ -151,23 +130,6 @@ int jbctl_handle_internal(const char *command, int argc, char* argv[])
}
return -1;
}
else if (!strcmp(command, "fakelib")) {
bool toMount = false;
if (argc > 1) {
if (!strcmp(argv[1], "mount")) {
toMount = true;
}
else if (!strcmp(argv[1], "unmount")) {
toMount = false;
}
else {
return -1;
}

return fakelib_set_mounted(toMount);
}
return -1;
}
else if (!strcmp(command, "startup")) {
protection_set_active(true);
char *panicMessage = NULL;
Expand Down
24 changes: 19 additions & 5 deletions BaseBin/launchdhook/src/jbserver/jbdomain_platform.c
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
#include <libjailbreak/codesign.h>
#include <libjailbreak/libjailbreak.h>

extern void systemwide_domain_set_enabled(bool enabled);

static bool platform_domain_allowed(audit_token_t clientToken)
{
pid_t pid = audit_token_to_pid(clientToken);
Expand All @@ -31,6 +29,22 @@ static int platform_stage_jailbreak_update(const char *updateTar)
return 1;
}

int platform_domin_set_jailbreak_hidden(bool hidden)
{
gSystemInfo.jailbreakInfo.isHidden = hidden;

if (hidden) {
revert_dyld_switcheroo();
}
else {
apply_dyld_switcheroo();
}

extern void systemwide_domain_set_enabled(bool enabled);
systemwide_domain_set_enabled(!hidden);
return 0;
}

struct jbserver_domain gPlatformDomain = {
.permissionHandler = platform_domain_allowed,
.actions = {
Expand Down Expand Up @@ -60,11 +74,11 @@ struct jbserver_domain gPlatformDomain = {
{ 0 },
},
},
// JBS_PLATFORM_SET_SYSTEMWIDE_DOMAIN_ENABLED
// JBS_PLATFORM_SET_JAILBREAK_HIDDEN
{
.handler = systemwide_domain_set_enabled,
.handler = platform_domin_set_jailbreak_hidden,
.args = (jbserver_arg[]){
{ .name = "enabled", .type = JBS_TYPE_BOOL, .out = false },
{ .name = "hidden", .type = JBS_TYPE_BOOL, .out = false },
{ 0 },
},
},
Expand Down
4 changes: 2 additions & 2 deletions BaseBin/launchdhook/src/jbserver/jbdomain_systemwide.c
Original file line number Diff line number Diff line change
Expand Up @@ -158,8 +158,8 @@ int systemwide_trust_file(audit_token_t *processToken, int rfd, struct siginfo *
struct statfs fsb;
int fsr = fstatfs(fd, &fsb);
if (fsr == 0) {
// Anything on the rootfs or fakelib mount point can be ignored as it's guaranteed to already be in trustcache
if (!strcmp(fsb.f_mntonname, "/") || !strcmp(fsb.f_mntonname, "/usr/lib")) {
// Anything on the rootfs mount point can be ignored as it's guaranteed to already be in trustcache
if (!strcmp(fsb.f_mntonname, "/")) {
close(fd);
return 0;
}
Expand Down
16 changes: 4 additions & 12 deletions BaseBin/launchdhook/src/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,13 @@
initIPCHooks();
initJetsamHook();

if (getenv("DOPAMINE_IS_HIDDEN") != 0) {
// If the jailbreak is currently hidden, fakelib had to be mounted again before the userspace reboot
// Now that the userspace reboot is over, we can unmount it again

// Just like when we mount it inside the posix_spawn hook, the jbserver is not up at this point in time
// So we need to host our own here again, just so that jbctl can talk to it
mach_port_t serverPort = jbserver_local_start();
jbctl_earlyboot(serverPort, "internal", "fakelib", "unmount", NULL);
jbserver_local_stop();
if (jbinfo(isHidden)) {
// If the jailbreak is currently hidden, dyld had to be redirected again before the userspace reboot
// Now that the userspace reboot is over, we can revert that again
revert_dyld_switcheroo();

// Also disable the systemwide domain again
systemwide_domain_set_enabled(false);

// No need to keep this around
unsetenv("DOPAMINE_IS_HIDDEN");
}

// This will ensure launchdhook is always reinjected after userspace reboots
Expand Down
Loading

0 comments on commit 9ca30be

Please sign in to comment.