diff --git a/Bootstrap.xcodeproj/project.pbxproj b/Bootstrap.xcodeproj/project.pbxproj index 3177b58e..df06c2a1 100644 --- a/Bootstrap.xcodeproj/project.pbxproj +++ b/Bootstrap.xcodeproj/project.pbxproj @@ -571,7 +571,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; OTHER_LDFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = com.roothide.Bootstrap; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -609,7 +609,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 1.2.5; + MARKETING_VERSION = 1.2.6; OTHER_LDFLAGS = ""; PRODUCT_BUNDLE_IDENTIFIER = com.roothide.Bootstrap; PRODUCT_NAME = "$(TARGET_NAME)"; diff --git a/Bootstrap.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate b/Bootstrap.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate index 90e5b775..5da74f33 100644 Binary files a/Bootstrap.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate and b/Bootstrap.xcodeproj/project.xcworkspace/xcuserdata/admin.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/Bootstrap/ViewController.m b/Bootstrap/ViewController.m index f53ef59d..1885f38e 100644 --- a/Bootstrap/ViewController.m +++ b/Bootstrap/ViewController.m @@ -97,6 +97,16 @@ BOOL checkServer() return ret; } + +#define PROC_PIDPATHINFO_MAXSIZE (1024) +int proc_pidpath(pid_t pid, void *buffer, uint32_t buffersize); +NSString* getLaunchdPath() +{ + char pathbuf[PROC_PIDPATHINFO_MAXSIZE] = {0}; + ASSERT(proc_pidpath(1, pathbuf, sizeof(pathbuf)) > 0); + return @(pathbuf); +} + void initFromSwiftUI() { BOOL IconCacheRebuilding=NO; @@ -410,11 +420,25 @@ void bootstrapAction() [AppDelegate showMesage:Localized(@"Your device does not seem to have developer mode enabled.\n\nPlease enable developer mode and reboot your device.") title:Localized(@"Error")]; return; } + + NSString* launchdpath = getLaunchdPath(); + if(![launchdpath isEqualToString:@"/sbin/launchd"] && ![launchdpath hasPrefix:@"/var/containers/Bundle/Application/.jbroot-"]) + { + UIAlertController *alert = [UIAlertController alertControllerWithTitle:Localized(@"Error") message:Localized(@"Please reboot device first.") preferredStyle:UIAlertControllerStyleAlert]; + + [alert addAction:[UIAlertAction actionWithTitle:Localized(@"Cancel") style:UIAlertActionStyleDefault handler:nil]]; + [alert addAction:[UIAlertAction actionWithTitle:Localized(@"Reboot Device") style:UIAlertActionStyleDestructive handler:^(UIAlertAction *action) { + ASSERT(spawnRoot(NSBundle.mainBundle.executablePath, @[@"reboot"], nil, nil)==0); + }]]; + + [AppDelegate showAlert:alert]; + return; + } UIImpactFeedbackGenerator* generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleSoft]; [generator impactOccurred]; - if(find_jbroot()) //make sure jbroot() function available + if(find_jbroot(YES)) //make sure jbroot() function available { if([NSFileManager.defaultManager fileExistsAtPath:jbroot(@"/.installed_dopamine")]) { [AppDelegate showMesage:Localized(@"roothide dopamine has been installed on this device, now install this bootstrap may break it!") title:Localized(@"Error")]; diff --git a/Bootstrap/Views/ContentView.swift b/Bootstrap/Views/ContentView.swift index 9ae570ee..58db1a6b 100644 --- a/Bootstrap/Views/ContentView.swift +++ b/Bootstrap/Views/ContentView.swift @@ -27,7 +27,7 @@ struct MainView: View { @State var currentBlobs: [Color] = [] @State var currentHighlights: [Color] = [] - @AppStorage("colorScheme", store: UserDefaults.app()) var colorScheme = 0 + @AppStorage("colorScheme", store: UserDefaults.app()) var colorScheme = 1 @State private var showOptions = false @State private var showCredits = false diff --git a/Bootstrap/basebin/bootstrap.dylib b/Bootstrap/basebin/bootstrap.dylib index 6ccfd8ac..044ab677 100755 Binary files a/Bootstrap/basebin/bootstrap.dylib and b/Bootstrap/basebin/bootstrap.dylib differ diff --git a/Bootstrap/basebin/bootstrapd b/Bootstrap/basebin/bootstrapd index a474a139..87eefa5e 100755 Binary files a/Bootstrap/basebin/bootstrapd and b/Bootstrap/basebin/bootstrapd differ diff --git a/Bootstrap/basebin/devtest b/Bootstrap/basebin/devtest index 2ac47e2d..1f8a02d5 100755 Binary files a/Bootstrap/basebin/devtest and b/Bootstrap/basebin/devtest differ diff --git a/Bootstrap/basebin/preload b/Bootstrap/basebin/preload index 7285a007..aa1f924e 100755 Binary files a/Bootstrap/basebin/preload and b/Bootstrap/basebin/preload differ diff --git a/Bootstrap/basebin/preload.dylib b/Bootstrap/basebin/preload.dylib index fb3affa5..31363a3f 100755 Binary files a/Bootstrap/basebin/preload.dylib and b/Bootstrap/basebin/preload.dylib differ diff --git a/Bootstrap/basebin/rebuildapp b/Bootstrap/basebin/rebuildapp index 5478798b..6310714e 100755 Binary files a/Bootstrap/basebin/rebuildapp and b/Bootstrap/basebin/rebuildapp differ diff --git a/Bootstrap/basebin/uicache b/Bootstrap/basebin/uicache index 041e53be..3d1429e8 100755 Binary files a/Bootstrap/basebin/uicache and b/Bootstrap/basebin/uicache differ diff --git a/Bootstrap/bootstrap.m b/Bootstrap/bootstrap.m index 6f88328a..7086fba6 100644 --- a/Bootstrap/bootstrap.m +++ b/Bootstrap/bootstrap.m @@ -158,6 +158,10 @@ int InstallBootstrap(NSString* jbroot_path) ASSERT(mkdir(jbroot_path.fileSystemRepresentation, 0755) == 0); ASSERT(chown(jbroot_path.fileSystemRepresentation, 0, 0) == 0); + + find_jbroot(YES); //refresh + + //jbroot() and jbrand() available now NSString* bootstrapZstFile = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent: [NSString stringWithFormat:@"strapfiles/bootstrap-%d.tar.zst", getCFMajorVersion()]]; @@ -252,13 +256,13 @@ int InstallBootstrap(NSString* jbroot_path) int ReRandomizeBootstrap() { - //jbroot() unavailable - - NSFileManager* fm = NSFileManager.defaultManager; - uint64_t prev_jbrand = jbrand(); uint64_t new_jbrand = jbrand_new(); + //jbroot() and jbrand() unavailable now + + NSFileManager* fm = NSFileManager.defaultManager; + ASSERT( [fm moveItemAtPath:[NSString stringWithFormat:@"/var/containers/Bundle/Application/.jbroot-%016llX", prev_jbrand] toPath:[NSString stringWithFormat:@"/var/containers/Bundle/Application/.jbroot-%016llX", new_jbrand] error:nil] ); @@ -292,8 +296,10 @@ int ReRandomizeBootstrap() ASSERT([fm createSymbolicLinkAtPath:[jbroot_secondary stringByAppendingPathComponent:@".jbroot"] withDestinationPath:jbroot_path error:nil]); - //jbroot() available now + find_jbroot(YES); //refresh + //jbroot() and jbrand() available now + STRAPLOG("Status: Building Base Binaries"); ASSERT(rebuildBasebin() == 0); @@ -332,6 +338,84 @@ void fixMobileDirectories() } } +#include +NSString* getMachoInstallName(NSString* path) +{ + int fd = open(path.fileSystemRepresentation, O_RDONLY); + if(fd < 0) return nil; + + NSString* installname = nil; + + do { + if(lseek(fd, 0, SEEK_SET) != 0) break; + + struct mach_header_64 header={0}; + if(read(fd, &header, sizeof(header)) != sizeof(header))break; + + //there is no universal macho on Bootstrap + if(header.magic!=MH_MAGIC_64 || header.cputype!= CPU_TYPE_ARM64) break; + + struct load_command* lc = malloc(header.sizeofcmds); + if(!lc) break; + + if(read(fd, lc, header.sizeofcmds) != header.sizeofcmds)break; + + for (uint32_t i = 0; i < header.ncmds; i++) { + if (lc->cmd == LC_ID_DYLIB) + { + struct dylib_command* id_dylib = (struct dylib_command*)lc; + const char* name = (char*)((uint64_t)id_dylib + id_dylib->dylib.name.offset); + installname = @(name); + } + lc = (struct load_command *) ((char *)lc + lc->cmdsize); + } + + } while(0); + + close(fd); + + return installname; +} + +void fixBadPatchFiles() +{ + NSString* dirpath = jbroot(@"/"); + for(NSString* path in [[NSFileManager defaultManager] enumeratorAtPath:dirpath]) { + + if(![path.pathExtension isEqualToString:@"roothidepatch"]) { + continue; + } + + NSString* fullpath = [dirpath stringByAppendingPathComponent:path]; + + struct stat symst; + if(lstat(fullpath.fileSystemRepresentation, &symst) !=0) + { + SYSLOG("scanBadPatchFiles: lstat: %@: %s", fullpath, strerror(errno)); + continue; + } + + if(S_ISLNK(symst.st_mode)) + { + SYSLOG("scanBadPatchFiles: symlink: %@", fullpath); + continue; + } + + STRAPLOG("fixBadPatchFiles: %@", path); + + NSString* installname = getMachoInstallName(fullpath); + + if([installname.stringByDeletingLastPathComponent isEqualToString:@"@loader_path/.jbroot/usr/lib/DynamicPatches"]) + { + ASSERT(unlink(fullpath.fileSystemRepresentation) == 0); + + NSString* sympath = jbroot([@"/usr/lib/DynamicPatches" stringByAppendingPathComponent:installname.lastPathComponent]); + ASSERT(symlink(sympath.fileSystemRepresentation, fullpath.fileSystemRepresentation) == 0); + } + } +} + + int bootstrap() { ASSERT(getuid()==0); @@ -346,7 +430,7 @@ int bootstrap() ASSERT([fm removeItemAtPath:@"/var/jb" error:nil]); } - NSString* jbroot_path = find_jbroot(); + NSString* jbroot_path = find_jbroot(YES); if(!jbroot_path) { STRAPLOG("device is not strapped..."); @@ -385,6 +469,7 @@ int bootstrap() ASSERT(ReRandomizeBootstrap() == 0); fixMobileDirectories(); + fixBadPatchFiles(); } ASSERT(disableRootHideBlacklist()==0); @@ -467,7 +552,7 @@ int unbootstrap() bool isBootstrapInstalled() { - if(!find_jbroot()) + if(!find_jbroot(YES)) return NO; if(![NSFileManager.defaultManager fileExistsAtPath:jbroot(@"/.bootstrapped")] diff --git a/Bootstrap/utils.h b/Bootstrap/utils.h index ffae2d0a..16ff93ba 100644 --- a/Bootstrap/utils.h +++ b/Bootstrap/utils.h @@ -9,7 +9,7 @@ uint64_t jbrand(); uint64_t jbrand_new(); -NSString* find_jbroot(); +NSString* find_jbroot(BOOL force); NSString* jbroot(NSString *path); diff --git a/Bootstrap/utils.m b/Bootstrap/utils.m index 64e0aaa4..beb7d4aa 100644 --- a/Bootstrap/utils.m +++ b/Bootstrap/utils.m @@ -60,37 +60,45 @@ uint64_t resolve_jbrand_value(const char* name) } -NSString* find_jbroot() +NSString* find_jbroot(BOOL force) { - //jbroot path may change when re-randomize it - NSString * jbroot = nil; - NSArray *subItems = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/var/containers/Bundle/Application/" error:nil]; - for (NSString *subItem in subItems) { - if (is_jbroot_name(subItem.UTF8String)) - { - NSString* path = [@"/var/containers/Bundle/Application/" stringByAppendingPathComponent:subItem]; - -// if([NSFileManager.defaultManager fileExistsAtPath: -// [path stringByAppendingPathComponent:@".installed_dopamine"]]) -// continue; + static NSString* cached_jbroot = nil; + if(!force && cached_jbroot) { + return cached_jbroot; + } + @synchronized(@"find_jbroot_lock") + { + //jbroot path may change when re-randomize it + NSString * jbroot = nil; + NSArray *subItems = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:@"/var/containers/Bundle/Application/" error:nil]; + for (NSString *subItem in subItems) { + if (is_jbroot_name(subItem.UTF8String)) + { + NSString* path = [@"/var/containers/Bundle/Application/" stringByAppendingPathComponent:subItem]; - jbroot = path; - break; + // if([NSFileManager.defaultManager fileExistsAtPath: + // [path stringByAppendingPathComponent:@".installed_dopamine"]]) + // continue; + + jbroot = path; + break; + } } + cached_jbroot = jbroot; } - return jbroot; + return cached_jbroot; } NSString *jbroot(NSString *path) { - NSString* jbroot = find_jbroot(); + NSString* jbroot = find_jbroot(NO); ASSERT(jbroot != NULL); //to avoid [nil stringByAppendingString: return [jbroot stringByAppendingPathComponent:path]; } uint64_t jbrand() { - NSString* jbroot = find_jbroot(); + NSString* jbroot = find_jbroot(NO); ASSERT(jbroot != NULL); return resolve_jbrand_value([jbroot lastPathComponent].UTF8String); } diff --git a/Makefile b/Makefile index 2c0ee2af..d4175723 100644 --- a/Makefile +++ b/Makefile @@ -7,8 +7,6 @@ INSTALL_TARGET_PROCESSES = Bootstrap THEOS_PACKAGE_SCHEME = roothide -THEOS_DEVICE_IP = iphone13pm.local - #disable theos auto sign for all mach-o TARGET_CODESIGN = echo "don't sign" diff --git a/README.md b/README.md index 284d0d6f..0d8ca665 100644 --- a/README.md +++ b/README.md @@ -45,6 +45,8 @@ By design, roothide does not inject tweaks into any applications by default. To **A roothide Bootstrap FAQ** is available [here](https://github.com/dleovl/Bootstrap/blob/faq/README.md). +**For installing Bootstrap**, refer to the guides at (https://onejailbreak.com/blog/bootstrap-roothide/)[https://onejailbreak.com/blog/bootstrap-roothide/] + ## Develop tweaks Both rootful and rootless tweaks aren't out-of-the-box compatible with roothide, so you'll need to develop them specifically to support it. You can refer to the developer documentation [here](https://github.com/roothide/Developer). diff --git a/basebin b/basebin index 10fd3c0f..0c8b42ec 160000 --- a/basebin +++ b/basebin @@ -1 +1 @@ -Subproject commit 10fd3c0faeacb83d4e9772c886cb556d083ef6d5 +Subproject commit 0c8b42ecc4cf2ee96f94fa59ad3c449823f90404