Skip to content

Commit

Permalink
fixes and enhancements
Browse files Browse the repository at this point in the history
- Fixed an issue where a "multi jbroot" error might occur on re-jailbreak

- Fixed an issue where an "updatelinks" error might occur on re-jailbreak

- Fixed an issue where tweaks might not work after a few days of jailbreaking

- Fixed an issue where some jailbroken processes may not work correctly when updating packages

- Fixed bad posix_spawn call causing some apps to crash

- Prevent doapmine app from being launched again if jailbreak fails

- Hide more jailbreak traces

- Update built-in roothide manager

- Update built-in sileo package

- Update built-in strapfiles
  • Loading branch information
roothider committed Jan 9, 2025
1 parent f11dcab commit c293236
Show file tree
Hide file tree
Showing 21 changed files with 390 additions and 143 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/roothide.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ jobs:
- name: Upload Artifact
id: dopamine-latest-upload
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: roothide-Dopamine2-v${{ env.tag }}.tipa
path: |
Expand Down
130 changes: 75 additions & 55 deletions Application/Dopamine/Jailbreak/DOBootstrapper.m
Original file line number Diff line number Diff line change
Expand Up @@ -976,15 +976,6 @@ -(int) InstallBootstrap:(NSString*)installPath WithCompletion:(void (^)(NSError
ASSERT([fm moveItemAtPath:jbroot(@"/tmp") toPath:[jbroot_secondary stringByAppendingPathComponent:@"/var/tmp"] error:nil]);
ASSERT([fm createSymbolicLinkAtPath:jbroot(@"/tmp") withDestinationPath:@"var/tmp" error:nil]);

for(NSString* item in [fm contentsOfDirectoryAtPath:jbroot_path error:nil])
{
if([item isEqualToString:@"var"])
continue;

ASSERT([fm createSymbolicLinkAtPath:[jbroot_secondary stringByAppendingPathComponent:item] withDestinationPath:[jbroot_path stringByAppendingPathComponent:item] error:nil]);
}

ASSERT([fm removeItemAtPath:[jbroot_secondary stringByAppendingPathComponent:@".jbroot"] error:nil]);
ASSERT([fm createSymbolicLinkAtPath:[jbroot_secondary stringByAppendingPathComponent:@".jbroot"]
withDestinationPath:jbroot_path error:nil]);

Expand All @@ -994,7 +985,9 @@ -(int) InstallBootstrap:(NSString*)installPath WithCompletion:(void (^)(NSError
ASSERT([fm createDirectoryAtPath:jbroot(@"/var/mobile/Library/Preferences") withIntermediateDirectories:YES attributes:attr error:nil]);
}

ASSERT([self buildPackageSources:completion] == 0);
if([self buildPackageSources:completion] != 0) {
return -1;
}

STRAPLOG("Status: Bootstrap Installed");

Expand All @@ -1021,21 +1014,6 @@ -(int) ReRandomizeBootstrap:(void (^)(NSError *))completion

NSString* jbroot_path = [NSString stringWithFormat:@"/var/containers/Bundle/Application/.jbroot-%016llX", new_jbrand];
NSString* jbroot_secondary = [NSString stringWithFormat:@"/var/mobile/Containers/Shared/AppGroup/.jbroot-%016llX", new_jbrand];

for(NSString* item in [fm contentsOfDirectoryAtPath:jbroot_path error:nil])
{
if([item isEqualToString:@"var"])
continue;

NSString* checkpath = [jbroot_secondary stringByAppendingPathComponent:item];

struct stat st;
if(lstat(checkpath.fileSystemRepresentation, &st)==0) {
ASSERT([fm removeItemAtPath:checkpath error:nil]);
}

ASSERT([fm createSymbolicLinkAtPath:checkpath withDestinationPath:[jbroot_path stringByAppendingPathComponent:item] error:nil]);
}

ASSERT([fm removeItemAtPath:[jbroot_path stringByAppendingPathComponent:@"/private/var"] error:nil]);
ASSERT([fm createSymbolicLinkAtPath:[jbroot_path stringByAppendingPathComponent:@"/private/var"]
Expand All @@ -1056,14 +1034,38 @@ -(int) doBootstrap:(void (^)(NSError *))completion {

NSFileManager* fm = NSFileManager.defaultManager;

int count=0;
NSArray *subItems = [fm contentsOfDirectoryAtPath:@"/var/containers/Bundle/Application/" error:nil];
for (NSString *subItem in subItems) {
if (is_jbroot_name(subItem.UTF8String))
count++;
int installedCount=0;
NSString* dirpath = @"/var/containers/Bundle/Application/";
NSArray *subItems = [fm contentsOfDirectoryAtPath:dirpath error:nil];
for (NSString *subItem in subItems)
{
if (!is_jbroot_name(subItem.UTF8String)) continue;

NSString* jbroot_path = [dirpath stringByAppendingPathComponent:subItem];

if([fm fileExistsAtPath:[jbroot_path stringByAppendingPathComponent:@"/.bootstrapped"]]
|| [fm fileExistsAtPath:[jbroot_path stringByAppendingPathComponent:@"/.thebootstrapped"]]) {
completion([NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedExtracting userInfo:@{NSLocalizedDescriptionKey : @"\n\nYour device has been bootstrapped through the Bootstrap app, please disable tweak for apps in AppList and UnBootstrap before jailbreaking.\n\n\n"}]);
return -1;
}

if([fm fileExistsAtPath:[jbroot_path stringByAppendingPathComponent:@"/.installed_dopamine"]]) {
installedCount++;
continue;
}


STRAPLOG("remove unknown/unfinished jbroot %@", subItem);

NSString* jbroot_secondary = [NSString stringWithFormat:@"/var/mobile/Containers/Shared/AppGroup/%@", subItem];
if([fm fileExistsAtPath:jbroot_secondary]) {
ASSERT([fm removeItemAtPath:jbroot_secondary error:nil]);
}

ASSERT([fm removeItemAtPath:jbroot_path error:nil]);
}

if(count > 1) {
if(installedCount > 1) {
completion([NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedExtracting userInfo:@{NSLocalizedDescriptionKey : @"\n\nThere are multi jbroot in /var/containers/Bundle/Applicaton/\n\n\n"}]);
return -1;
}
Expand All @@ -1077,43 +1079,26 @@ -(int) doBootstrap:(void (^)(NSError *))completion {

STRAPLOG("bootstrap @ %@", jbroot_path);

ASSERT([self InstallBootstrap:jbroot_path WithCompletion:completion] == 0);

} else if([fm fileExistsAtPath:jbroot(@"/.bootstrapped")] || [fm fileExistsAtPath:jbroot(@"/.thebootstrapped")]) {

completion([NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedExtracting userInfo:@{NSLocalizedDescriptionKey : @"\n\nYour device has been bootstrapped through the Bootstrap app, please disable tweak for apps in AppList and UnBootstrap before jailbreaking.\n\n\n"}]);
if([self InstallBootstrap:jbroot_path WithCompletion:completion] != 0) {
return -1;

} else if(![fm fileExistsAtPath:jbroot(@"/.installed_dopamine")]) {

STRAPLOG("remove unfinished bootstrap %@", jbroot_path);

uint64_t prev_jbrand = jbrand();

ASSERT([fm removeItemAtPath:jbroot_path error:nil]);

NSString* jbroot_secondary = [NSString stringWithFormat:@"/var/mobile/Containers/Shared/AppGroup/.jbroot-%016llX", prev_jbrand];
if([fm fileExistsAtPath:jbroot_secondary]) {
STRAPLOG("remove unfinished bootstrap %@", jbroot_secondary);
ASSERT([fm removeItemAtPath:jbroot_secondary error:nil]);
}

STRAPLOG("bootstrap @ %@", jbroot_path);

ASSERT([self InstallBootstrap:jbroot_path WithCompletion:completion] == 0);

} else {
STRAPLOG("device is strapped: %@", jbroot_path);

ASSERT([fm fileExistsAtPath:jbroot(@"/.installed_dopamine")]);

NSString* dopamineVersion = [NSString stringWithContentsOfFile:jbroot(@"/.installed_dopamine") encoding:NSUTF8StringEncoding error:nil];
if(dopamineVersion.intValue != DOPAMINE_INSTALL_VERSION) {
completion([NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedExtracting userInfo:@{NSLocalizedDescriptionKey : @"\n\nroothide Doapmine 1 is already installed on your device.\n\n\n"}]);
completion([NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedExtracting userInfo:@{NSLocalizedDescriptionKey : @"\n\nYour device has been jailbroken through the roothide Dopamine 1.x\n\n\n"}]);
return -1;
}

STRAPLOG("Status: Rerandomize jbroot");

ASSERT([self ReRandomizeBootstrap:completion] == 0);
if([self ReRandomizeBootstrap:completion] != 0) {
return -1;
}
}

STRAPLOG("Status: Bootstrap Successful");
Expand Down Expand Up @@ -1223,6 +1208,39 @@ - (void)prepareBootstrapWithCompletion:(void (^)(NSError *))completion
}
}

-(int) fixBootstrapSymlink:(NSString*)path
{
const char* jbpath = jbroot(path).fileSystemRepresentation;

struct stat st={0};
assert(lstat(jbpath, &st) == 0);
if (!S_ISLNK(st.st_mode)) {
return 0;
}

char link[PATH_MAX+1] = {0};
assert(readlink(jbpath, link, sizeof(link)-1) > 0);
if(link[0] != '/') {
return 0;
}

NSString* _link = @(link).stringByStandardizingPath.stringByResolvingSymlinksInPath;

NSString *pattern = @"^/var/containers/Bundle/Application/\\.jbroot-[0-9A-Z]{16}(/.+)$";
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:nil];
NSTextCheckingResult *match = [regex firstMatchInString:_link options:0 range:NSMakeRange(0, [_link length])];
assert(match != nil);

NSString* target = [_link substringWithRange:[match rangeAtIndex:1]];
NSString* newlink = [@".jbroot" stringByAppendingPathComponent:target];

assert(unlink(jbpath) == 0);
assert(symlink(newlink.fileSystemRepresentation, jbpath) == 0);
assert(access(jbpath, F_OK) == 0);

return 0;
}

- (NSError *)finalizeBootstrap
{
// Initial setup on first jailbreak
Expand All @@ -1243,6 +1261,8 @@ - (NSError *)finalizeBootstrap
else
{
[[DOUIManager sharedInstance] sendLog:@"Updating Symlinks" debug:NO];
[self fixBootstrapSymlink:@"/bin/sh"];
[self fixBootstrapSymlink:@"/usr/bin/sh"];
int r = exec_cmd_trusted(JBROOT_PATH("/bin/sh"), "/usr/libexec/updatelinks.sh", NULL);
if (r != 0) {
return [NSError errorWithDomain:bootstrapErrorDomain code:BootstrapErrorCodeFailedFinalising userInfo:@{NSLocalizedDescriptionKey : [NSString stringWithFormat:@"updatelinks.sh returned %d\n", r]}];
Expand Down
2 changes: 1 addition & 1 deletion Application/Dopamine/Jailbreak/DOEnvironmentManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ NS_ASSUME_NONNULL_BEGIN
- (NSError *)deleteBootstrap;
- (NSError *)reinstallPackageManagers;

- (BOOL)isRootlessDopamineJailbroken;
- (BOOL)isOtherJailbreakActived;

@end

Expand Down
30 changes: 22 additions & 8 deletions Application/Dopamine/Jailbreak/DOEnvironmentManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -236,19 +236,33 @@ - (BOOL)isInstalledThroughTrollStore
return trollstoreInstallation;
}

- (BOOL)isRootlessDopamineJailbroken
- (BOOL)isOtherJailbreakActived
{
struct statfs fs;
int sfsret = statfs("/usr/lib", &fs);
if (sfsret == 0) {
return strcmp(fs.f_mntonname, "/usr/lib")==0;
}
return NO;
if(access("/dev/md0", F_OK)==0) {
return YES;
}

if(access("/dev/rmd0", F_OK)==0) {
return YES;
}

struct statfs fs;
int sfsret = statfs("/usr/lib", &fs);
if (sfsret == 0) {
if(strcmp(fs.f_mntonname, "/usr/lib")==0) {
return YES;
}
}

return NO;
}

- (BOOL)isJailbroken
{
if([self isRootlessDopamineJailbroken])
if([self isOtherJailbreakActived])
return NO;

if(!jbclient_get_jbroot())
return NO;

static BOOL jailbroken = NO;
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 @@ -612,10 +612,10 @@ - (void)runWithError:(NSError **)errOut didRemoveJailbreak:(BOOL*)didRemove show
[[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);
*/

*errOut = [self finalizeBootstrapIfNeeded];
if (*errOut) return;
Expand Down
Binary file modified Application/Dopamine/Resources/bootstrap_1800.tar.zst
Binary file not shown.
Binary file modified Application/Dopamine/Resources/bootstrap_1900.tar.zst
Binary file not shown.
Binary file modified Application/Dopamine/Resources/roothideapp.deb
Binary file not shown.
Binary file modified Application/Dopamine/Resources/sileo.deb
Binary file not shown.
4 changes: 2 additions & 2 deletions Application/Dopamine/UI/DOMainViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,8 @@ -(void)setupStack

self.jailbreakBtn = [[DOJailbreakButton alloc] initWithAction: [UIAction actionWithTitle:jailbreakButtonTitle image:jailbreakButtonImage identifier:@"jailbreak" handler:^(__kindof UIAction * _Nonnull action) {

if([DOEnvironmentManager.sharedManager isRootlessDopamineJailbroken]) {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:DOLocalizedString(@"Error") message:DOLocalizedString(@"rootless dopamine jailbroken at present, please reboot the device.") preferredStyle:UIAlertControllerStyleAlert];
if([DOEnvironmentManager.sharedManager isOtherJailbreakActived]) {
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:DOLocalizedString(@"Error") message:DOLocalizedString(@"Your device currently has another jailbreak activated, please reboot device.") preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *rebootAction = [UIAlertAction actionWithTitle:DOLocalizedString(@"Button_Close") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
//exit(0);
}];
Expand Down
2 changes: 1 addition & 1 deletion BaseBin/launchdhook/src/crashreporter.m
Original file line number Diff line number Diff line change
Expand Up @@ -414,7 +414,7 @@ void crashreporter_catch_objc(NSException *e)
void crashreporter_pause(void)
{
if (gCrashReporterState == kCrashReporterStateActive) {
task_set_exception_ports(mach_task_self_, EXC_MASK_CRASH_RELATED, 0, EXCEPTION_DEFAULT, ARM_THREAD_STATE64);
task_set_exception_ports(mach_task_self_, EXC_MASK_CRASH_RELATED, MACH_PORT_NULL, 0, 0);
NSSetUncaughtExceptionHandler(defaultNSExceptionHandler);
defaultNSExceptionHandler = nil;
gCrashReporterState = kCrashReporterStatePaused;
Expand Down
2 changes: 1 addition & 1 deletion BaseBin/launchdhook/src/ipc_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ int sandbox_check_by_audit_token_hook(audit_token_t au, const char *operation, i
if (strncmp((char *)name, "cy:", 3) == 0 || strncmp((char *)name, "lh:", 3) == 0) {

bool allow=true;
char pathbuf[PATH_MAX]={0};
char pathbuf[4*MAXPATHLEN]={0};
pid_t pid = audit_token_to_pid(au);
if(pid>0 && proc_pidpath(pid, pathbuf, sizeof(pathbuf))>0) {
if(isBlacklisted(pathbuf)) {
Expand Down
4 changes: 3 additions & 1 deletion BaseBin/launchdhook/src/jbserver/jbdomain_systemwide.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ char *combine_strings(char separator, char **components, int count)
#include "exec_patch.h"
#include "libjailbreak/log.h"

extern bool gFirstLoad;

bool is_sub_path(const char* parent, const char* child)
{
char real_child[PATH_MAX]={0};
Expand Down Expand Up @@ -291,7 +293,7 @@ static int systemwide_process_checkin(audit_token_t *processToken, char **rootPa
else if (string_has_suffix(procPath, "/Dopamine.app/Dopamine")) {
char roothidefile[PATH_MAX];
snprintf(roothidefile, sizeof(roothidefile), "%s.roothide",procPath);
if(access(roothidefile, F_OK)==0) {
if(access(roothidefile, F_OK)==0 && !gFirstLoad) {
// svuid = 0, svgid = 0
uint64_t ucred = proc_ucred(proc);
kwrite32(proc + koffsetof(proc, svuid), 0);
Expand Down
2 changes: 2 additions & 0 deletions BaseBin/launchdhook/src/main.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
char HOOK_DYLIB_PATH[PATH_MAX] = {0};

bool gInEarlyBoot = true;
bool gFirstLoad = false;

#define RB_QUICK 0x400
#define RB_PANIC 0x800
Expand Down Expand Up @@ -159,6 +160,7 @@ void lockAllDSCText(void)
// Here we should have been injected into a live launchd on the fly
// In this case, we are not in early boot...
gInEarlyBoot = false;
gFirstLoad = true;
firstLoad = true;
}

Expand Down
8 changes: 7 additions & 1 deletion BaseBin/launchdhook/src/spawn_hook.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ extern int platform_set_process_debugged(uint64_t pid, bool fullyDebugged);
#define LOG_PROCESS_LAUNCHES 0

extern bool gInEarlyBoot;
extern bool gFirstLoad;

void early_boot_done(void)
{
Expand Down Expand Up @@ -244,6 +245,11 @@ int __posix_spawn_hook(pid_t *restrict pidp, const char *restrict path, struct _
}
}

if(gFirstLoad) {
//we should not enable system-wide injection until the jailbreak is finalized (userspace reboot).
return __posix_spawn_orig_wrapper(pidp, path, desc, argv, envp);
}

if (isBlacklisted(path)) {
JBLogDebug("blacklisted app %s", path);

Expand All @@ -253,7 +259,7 @@ int __posix_spawn_hook(pid_t *restrict pidp, const char *restrict path, struct _
envbuf_unsetenv(&envc, "_SafeMode");
envbuf_unsetenv(&envc, "_MSSafeMode");

int ret = __posix_spawn_orig_wrapper(pidp, path, desc, argv, envp);
int ret = __posix_spawn_orig_wrapper(pidp, path, desc, argv, envc);

envbuf_free(envc);

Expand Down
12 changes: 6 additions & 6 deletions BaseBin/libjailbreak/src/jbserver.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,12 +23,12 @@ int jbserver_received_xpc_message(struct jbserver_impl *server, xpc_object_t xms
xpc_dictionary_get_audit_token(xmsg, &clientToken);

pid_t pid = audit_token_to_pid(clientToken);
char callerPath[4 * MAXPATHLEN];
if (proc_pidpath(pid, callerPath, sizeof(callerPath)) < 0) {
return -1;
}
if (isBlacklisted(callerPath)){
return -1;
char callerPath[4 * MAXPATHLEN]; /* proc_pidpath is not always reliable,
it will return ENOENT if the original executable file of a running process is removed from disk (e.g. upgrading/reinstalling a package) */
if (proc_pidpath(pid, callerPath, sizeof(callerPath)) > 0) {
if (isBlacklisted(callerPath)) {
return -1;
}
}

if (domain->permissionHandler) {
Expand Down
Loading

0 comments on commit c293236

Please sign in to comment.