From c6ea42cf5a9532932b7247cf143a5916c848aec4 Mon Sep 17 00:00:00 2001 From: opa334 Date: Tue, 28 Nov 2023 01:04:40 +0100 Subject: [PATCH] Readd ldid for use on iOS 14 --- Exploits/fastPathSign/src/codesign.m | 39 ++++-- RootHelper/main.m | 192 +++++++++++++++++++++++++- Shared/TSUtil.h | 1 + Shared/TSUtil.m | 5 + TrollStore/Resources/Info.plist | 1 + TrollStore/TSApplicationsManager.m | 13 +- TrollStore/TSInstallationController.h | 2 + TrollStore/TSInstallationController.m | 44 ++++++ TrollStore/TSSceneDelegate.m | 21 +++ TrollStore/TSSettingsListController.h | 1 + TrollStore/TSSettingsListController.m | 105 ++++++++++++++ install_trollhelper.md | 4 +- install_trollhelperota_arm64e.md | 2 +- install_trollhelperota_ios15.md | 2 +- 14 files changed, 418 insertions(+), 14 deletions(-) diff --git a/Exploits/fastPathSign/src/codesign.m b/Exploits/fastPathSign/src/codesign.m index 197a46a..81b094b 100644 --- a/Exploits/fastPathSign/src/codesign.m +++ b/Exploits/fastPathSign/src/codesign.m @@ -1,6 +1,7 @@ #include #include #include +#include #ifdef __cplusplus extern "C" { @@ -64,12 +65,27 @@ typedef struct CF_BRIDGED_TYPE(id) __SecCodeSigner* SecCodeSignerRef SPI_AVAILAB typedef struct __SecCodeSigner* SecCodeSignerRef SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0)); #endif -extern const CFStringRef kSecCodeSignerEntitlements SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0)); -extern const CFStringRef kSecCodeSignerIdentifier SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0)); -extern const CFStringRef kSecCodeSignerIdentity SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0)); -extern const CFStringRef kSecCodeSignerPreserveMetadata SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0)); -extern const CFStringRef kSecCodeSignerRequirements SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0)); -extern const CFStringRef kSecCodeSignerResourceRules SPI_AVAILABLE(macos(10.5), ios(15.0), macCatalyst(13.0)); +const CFStringRef kSecCodeSignerApplicationData = CFSTR("application-specific"); +const CFStringRef kSecCodeSignerDetached = CFSTR("detached"); +const CFStringRef kSecCodeSignerDigestAlgorithm = CFSTR("digest-algorithm"); +const CFStringRef kSecCodeSignerDryRun = CFSTR("dryrun"); +const CFStringRef kSecCodeSignerEntitlements = CFSTR("entitlements"); +const CFStringRef kSecCodeSignerFlags = CFSTR("flags"); +const CFStringRef kSecCodeSignerIdentifier = CFSTR("identifier"); +const CFStringRef kSecCodeSignerIdentifierPrefix = CFSTR("identifier-prefix"); +const CFStringRef kSecCodeSignerIdentity = CFSTR("signer"); +const CFStringRef kSecCodeSignerPageSize = CFSTR("pagesize"); +const CFStringRef kSecCodeSignerRequirements = CFSTR("requirements"); +const CFStringRef kSecCodeSignerResourceRules = CFSTR("resource-rules"); +const CFStringRef kSecCodeSignerSDKRoot = CFSTR("sdkroot"); +const CFStringRef kSecCodeSignerSigningTime = CFSTR("signing-time"); +const CFStringRef kSecCodeSignerRequireTimestamp = CFSTR("timestamp-required"); +const CFStringRef kSecCodeSignerTimestampServer = CFSTR("timestamp-url"); +const CFStringRef kSecCodeSignerTimestampAuthentication = CFSTR("timestamp-authentication"); +const CFStringRef kSecCodeSignerTimestampOmitCertificates = CFSTR("timestamp-omit-certificates"); +const CFStringRef kSecCodeSignerPreserveMetadata = CFSTR("preserve-metadata"); +const CFStringRef kSecCodeSignerTeamIdentifier = CFSTR("teamidentifier"); +const CFStringRef kSecCodeSignerPlatformIdentifier = CFSTR("platform-identifier"); #ifdef BRIDGED_SECCODESIGNER OSStatus SecCodeSignerCreate(CFDictionaryRef parameters, SecCSFlags flags, SecCodeSignerRef* __nonnull CF_RETURNS_RETAINED signer) @@ -91,6 +107,13 @@ extern const CFStringRef kSecCodeInfoResourceDirectory; /* Internal */ int codesign_sign_adhoc(const char *path, bool preserveMetadata, NSDictionary *customEntitlements) { + // We need to do this shit because iOS 14 does not have the symbol + OSStatus (*__SecCodeSignerCreate)(CFDictionaryRef parameters, SecCSFlags flags, SecCodeSignerRef *signerRef) = dlsym(RTLD_DEFAULT, "SecCodeSignerCreate"); + OSStatus (*__SecCodeSignerAddSignatureWithErrors)(SecCodeSignerRef signerRef, SecStaticCodeRef codeRef, SecCSFlags flags, CFErrorRef *errors) = dlsym(RTLD_DEFAULT, "SecCodeSignerAddSignatureWithErrors"); + // if this is not found, all bets are off + if (!__SecCodeSignerCreate) return 404; + if (!__SecCodeSignerAddSignatureWithErrors) return 404; + NSString *filePath = [NSString stringWithUTF8String:path]; OSStatus status = 0; int retval = 200; @@ -127,13 +150,13 @@ int codesign_sign_adhoc(const char *path, bool preserveMetadata, NSDictionary *c } SecCodeSignerRef signerRef; - status = SecCodeSignerCreate((__bridge CFDictionaryRef)parameters, kSecCSDefaultFlags, &signerRef); + status = __SecCodeSignerCreate((__bridge CFDictionaryRef)parameters, kSecCSDefaultFlags, &signerRef); if (status == 0) { SecStaticCodeRef code; status = SecStaticCodeCreateWithPathAndAttributes((__bridge CFURLRef)[NSURL fileURLWithPath:filePath], kSecCSDefaultFlags, (__bridge CFDictionaryRef)@{}, &code); if (status == 0) { CFErrorRef errors; - status = SecCodeSignerAddSignatureWithErrors(signerRef, code, kSecCSDefaultFlags, &errors); + status = __SecCodeSignerAddSignatureWithErrors(signerRef, code, kSecCSDefaultFlags, &errors); if (status == 0) { CFDictionaryRef newSigningInformation; // Difference from codesign: added kSecCSSigningInformation, kSecCSRequirementInformation, kSecCSInternalInformation diff --git a/RootHelper/main.m b/RootHelper/main.m index aa42cc5..8a38668 100644 --- a/RootHelper/main.m +++ b/RootHelper/main.m @@ -240,6 +240,105 @@ void setTSURLSchemeState(BOOL newState, NSString* customAppPath) } } +void installLdid(NSString* ldidToCopyPath, NSString* ldidVersion) +{ + if(![[NSFileManager defaultManager] fileExistsAtPath:ldidToCopyPath]) return; + + NSString* ldidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"]; + NSString* ldidVersionPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid.version"]; + + if([[NSFileManager defaultManager] fileExistsAtPath:ldidPath]) + { + [[NSFileManager defaultManager] removeItemAtPath:ldidPath error:nil]; + } + + [[NSFileManager defaultManager] copyItemAtPath:ldidToCopyPath toPath:ldidPath error:nil]; + + NSData* ldidVersionData = [ldidVersion dataUsingEncoding:NSUTF8StringEncoding]; + [ldidVersionData writeToFile:ldidVersionPath atomically:YES]; + + chmod(ldidPath.fileSystemRepresentation, 0755); + chmod(ldidVersionPath.fileSystemRepresentation, 0644); +} + +BOOL isLdidInstalled(void) +{ + NSString* ldidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"]; + return [[NSFileManager defaultManager] fileExistsAtPath:ldidPath]; +} + +int runLdid(NSArray* args, NSString** output, NSString** errorOutput) +{ + NSString* ldidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"]; + NSMutableArray* argsM = args.mutableCopy ?: [NSMutableArray new]; + [argsM insertObject:ldidPath.lastPathComponent atIndex:0]; + + NSUInteger argCount = [argsM count]; + char **argsC = (char **)malloc((argCount + 1) * sizeof(char*)); + + for (NSUInteger i = 0; i < argCount; i++) + { + argsC[i] = strdup([[argsM objectAtIndex:i] UTF8String]); + } + argsC[argCount] = NULL; + + posix_spawn_file_actions_t action; + posix_spawn_file_actions_init(&action); + + int outErr[2]; + pipe(outErr); + posix_spawn_file_actions_adddup2(&action, outErr[1], STDERR_FILENO); + posix_spawn_file_actions_addclose(&action, outErr[0]); + + int out[2]; + pipe(out); + posix_spawn_file_actions_adddup2(&action, out[1], STDOUT_FILENO); + posix_spawn_file_actions_addclose(&action, out[0]); + + pid_t task_pid; + int status = -200; + int spawnError = posix_spawn(&task_pid, [ldidPath fileSystemRepresentation], &action, NULL, (char* const*)argsC, NULL); + for (NSUInteger i = 0; i < argCount; i++) + { + free(argsC[i]); + } + free(argsC); + + if(spawnError != 0) + { + NSLog(@"posix_spawn error %d\n", spawnError); + return spawnError; + } + + do + { + if (waitpid(task_pid, &status, 0) != -1) { + //printf("Child status %dn", WEXITSTATUS(status)); + } else + { + perror("waitpid"); + return -222; + } + } while (!WIFEXITED(status) && !WIFSIGNALED(status)); + + close(outErr[1]); + close(out[1]); + + NSString* ldidOutput = getNSStringFromFile(out[0]); + if(output) + { + *output = ldidOutput; + } + + NSString* ldidErrorOutput = getNSStringFromFile(outErr[0]); + if(errorOutput) + { + *errorOutput = ldidErrorOutput; + } + + return WEXITSTATUS(status); +} + BOOL certificateHasDataForExtensionOID(SecCertificateRef certificate, CFStringRef oidString) { if(certificate == NULL || oidString == NULL) @@ -377,6 +476,52 @@ int signApp(NSString* appPath) return -1; } #else +int signAdhoc(NSString *filePath, NSDictionary *entitlements) +{ + if (@available(iOS 15, *)) { + return codesign_sign_adhoc(filePath.fileSystemRepresentation, true, entitlements); + } + // If iOS 14 is so great, how come there is no iOS 14 2????? + else { + if(!isLdidInstalled()) return 173; + + NSString *entitlementsPath = nil; + NSString *signArg = @"-s"; + NSString* errorOutput; + if(entitlements) + { + NSData *entitlementsXML = [NSPropertyListSerialization dataWithPropertyList:entitlements format:NSPropertyListXMLFormat_v1_0 options:0 error:nil]; + if (entitlementsXML) { + entitlementsPath = [[NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString] stringByAppendingPathExtension:@"plist"]; + [entitlementsXML writeToFile:entitlementsPath atomically:NO]; + signArg = [@"-S" stringByAppendingString:entitlementsPath]; + } + + } + int ldidRet = runLdid(@[signArg, filePath], nil, &errorOutput); + if (entitlementsPath) { + [[NSFileManager defaultManager] removeItemAtPath:entitlementsPath error:nil]; + } + + NSLog(@"ldid exited with status %d", ldidRet); + + NSLog(@"- ldid error output start -"); + + printMultilineNSString(errorOutput); + + NSLog(@"- ldid error output end -"); + + if(ldidRet == 0) + { + return 0; + } + else + { + return 175; + } + } +} + int signApp(NSString* appPath) { NSDictionary* appInfoDict = infoDictionaryForAppPath(appPath); @@ -460,7 +605,7 @@ int signApp(NSString* appPath) } // First attempt ad hoc signing - int r = codesign_sign_adhoc(tmpPath.fileSystemRepresentation, true, entitlementsToUse); + int r = signAdhoc(tmpPath, entitlementsToUse); if (r != 0) { NSLog(@"[%@] Adhoc signing failed with error code %d, continuing anyways...\n", filePath, r); } @@ -545,6 +690,7 @@ void applyPatchesToInfoDictionary(NSString* appPath) // 170: failed to create container for app bundle // 171: a non trollstore app with the same identifier is already installled // 172: no info.plist found in app +// 173: app is not signed and cannot be signed because ldid not installed or didn't work // 174: int installApp(NSString* appPackagePath, BOOL sign, BOOL force, BOOL isTSUpdate, BOOL useInstalldMethod) { @@ -892,6 +1038,41 @@ int installTrollStore(NSString* pathToTar) NSString* tmpTrollStorePath = [tmpPayloadPath stringByAppendingPathComponent:@"TrollStore.app"]; if(![[NSFileManager defaultManager] fileExistsAtPath:tmpTrollStorePath]) return 1; + if (@available(iOS 15, *)) {} else { + // Transfer existing ldid installation if it exists + // But only if the to-be-installed version of TrollStore is 1.5.0 or above + // This is to make it possible to downgrade to older versions still + + NSString* toInstallInfoPlistPath = [tmpTrollStorePath stringByAppendingPathComponent:@"Info.plist"]; + if(![[NSFileManager defaultManager] fileExistsAtPath:toInstallInfoPlistPath]) return 1; + + NSDictionary* toInstallInfoDict = [NSDictionary dictionaryWithContentsOfFile:toInstallInfoPlistPath]; + NSString* toInstallVersion = toInstallInfoDict[@"CFBundleVersion"]; + + NSComparisonResult result = [@"1.5.0" compare:toInstallVersion options:NSNumericSearch]; + if(result != NSOrderedDescending) + { + NSString* existingLdidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"]; + NSString* existingLdidVersionPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid.version"]; + if([[NSFileManager defaultManager] fileExistsAtPath:existingLdidPath]) + { + NSString* tmpLdidPath = [tmpTrollStorePath stringByAppendingPathComponent:@"ldid"]; + if(![[NSFileManager defaultManager] fileExistsAtPath:tmpLdidPath]) + { + [[NSFileManager defaultManager] copyItemAtPath:existingLdidPath toPath:tmpLdidPath error:nil]; + } + } + if([[NSFileManager defaultManager] fileExistsAtPath:existingLdidVersionPath]) + { + NSString* tmpLdidVersionPath = [tmpTrollStorePath stringByAppendingPathComponent:@"ldid.version"]; + if(![[NSFileManager defaultManager] fileExistsAtPath:tmpLdidVersionPath]) + { + [[NSFileManager defaultManager] copyItemAtPath:existingLdidVersionPath toPath:tmpLdidVersionPath error:nil]; + } + } + } + } + // Merge existing URL scheme settings value if(!getTSURLSchemeState(nil)) { @@ -1171,6 +1352,15 @@ int MAIN_NAME(int argc, char *argv[], char *envp[]) } uninstallTrollStore(YES); } + else if([cmd isEqualToString:@"install-ldid"]) + { + if (@available(iOS 15, *)) {} else { + if(args.count < 3) return -3; + NSString* ldidPath = args[1]; + NSString* ldidVersion = args[2]; + installLdid(ldidPath, ldidVersion); + } + } else if([cmd isEqualToString:@"refresh"]) { refreshAppRegistrations(YES); diff --git a/Shared/TSUtil.h b/Shared/TSUtil.h index 0ead96c..2b44578 100644 --- a/Shared/TSUtil.h +++ b/Shared/TSUtil.h @@ -12,6 +12,7 @@ extern int spawnRoot(NSString* path, NSArray* args, NSString** stdOut, NSString* extern void killall(NSString* processName, BOOL softly); extern void respring(void); extern void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVersion)); +extern void fetchLatestLdidVersion(void (^completionHandler)(NSString* latestVersion)); extern NSArray* trollStoreInstalledAppBundlePaths(); extern NSArray* trollStoreInstalledAppContainerPaths(); diff --git a/Shared/TSUtil.m b/Shared/TSUtil.m index 9058b9c..1c439b6 100644 --- a/Shared/TSUtil.m +++ b/Shared/TSUtil.m @@ -310,6 +310,11 @@ void fetchLatestTrollStoreVersion(void (^completionHandler)(NSString* latestVers github_fetchLatestVersion(@"opa334/TrollStore", completionHandler); } +void fetchLatestLdidVersion(void (^completionHandler)(NSString* latestVersion)) +{ + github_fetchLatestVersion(@"opa334/ldid", completionHandler); +} + NSArray* trollStoreInstalledAppContainerPaths() { NSMutableArray* appContainerPaths = [NSMutableArray new]; diff --git a/TrollStore/Resources/Info.plist b/TrollStore/Resources/Info.plist index 1b56953..8dd7926 100644 --- a/TrollStore/Resources/Info.plist +++ b/TrollStore/Resources/Info.plist @@ -191,6 +191,7 @@ TSRootBinaries trollstorehelper + ldid diff --git a/TrollStore/TSApplicationsManager.m b/TrollStore/TSApplicationsManager.m index 9494ff3..b42526a 100644 --- a/TrollStore/TSApplicationsManager.m +++ b/TrollStore/TSApplicationsManager.m @@ -47,11 +47,20 @@ extern NSUserDefaults* trollStoreUserDefaults(); case 172: errorDescription = @"The app does not contain an Info.plist file."; break; + case 173: + errorDescription = @"The app is not signed with a fake CoreTrust certificate and ldid is not installed. Install ldid in the settings tab and try again."; + break; case 174: errorDescription = @"The app's main executable does not exist."; break; - case 175: - errorDescription = @"Failed to sign the app."; + case 175: { + if (@available(iOS 15, *)) { + errorDescription = @"Failed to sign the app."; + } + else { + errorDescription = @"Failed to sign the app. ldid returned a non zero status code."; + } + } break; case 176: errorDescription = @"The app's Info.plist is missing required values."; diff --git a/TrollStore/TSInstallationController.h b/TrollStore/TSInstallationController.h index 96ebdc2..0c64233 100644 --- a/TrollStore/TSInstallationController.h +++ b/TrollStore/TSInstallationController.h @@ -9,4 +9,6 @@ + (void)handleAppInstallFromRemoteURL:(NSURL*)remoteURL completion:(void (^)(BOOL, NSError*))completion; ++ (void)installLdid; + @end \ No newline at end of file diff --git a/TrollStore/TSInstallationController.m b/TrollStore/TSInstallationController.m index 9fedb61..0b3e674 100644 --- a/TrollStore/TSInstallationController.m +++ b/TrollStore/TSInstallationController.m @@ -187,4 +187,48 @@ extern NSUserDefaults* trollStoreUserDefaults(void); }); } ++ (void)installLdid +{ + fetchLatestLdidVersion(^(NSString* latestVersion) + { + if(!latestVersion) return; + dispatch_async(dispatch_get_main_queue(), ^ + { + NSURL* ldidURL = [NSURL URLWithString:@"https://github.com/opa334/ldid/releases/latest/download/ldid"]; + NSURLRequest* ldidRequest = [NSURLRequest requestWithURL:ldidURL]; + + [TSPresentationDelegate startActivity:@"Installing ldid"]; + + NSURLSessionDownloadTask* downloadTask = [NSURLSession.sharedSession downloadTaskWithRequest:ldidRequest completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) + { + if(error) + { + UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Error downloading ldid: %@", error] preferredStyle:UIAlertControllerStyleAlert]; + UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil]; + [errorAlert addAction:closeAction]; + + dispatch_async(dispatch_get_main_queue(), ^ + { + [TSPresentationDelegate stopActivityWithCompletion:^ + { + [TSPresentationDelegate presentViewController:errorAlert animated:YES completion:nil]; + }]; + }); + } + else if(location) + { + spawnRoot(rootHelperPath(), @[@"install-ldid", location.path, latestVersion], nil, nil); + dispatch_async(dispatch_get_main_queue(), ^ + { + [TSPresentationDelegate stopActivityWithCompletion:nil]; + [[NSNotificationCenter defaultCenter] postNotificationName:@"TrollStoreReloadSettingsNotification" object:nil userInfo:nil]; + }); + } + }]; + + [downloadTask resume]; + }); + }); +} + @end \ No newline at end of file diff --git a/TrollStore/TSSceneDelegate.m b/TrollStore/TSSceneDelegate.m index 47d25e8..a90b4be 100644 --- a/TrollStore/TSSceneDelegate.m +++ b/TrollStore/TSSceneDelegate.m @@ -72,6 +72,23 @@ } } +// We want to auto install ldid if either it doesn't exist +// or if it's the one from an old TrollStore version that's no longer supported +- (void)handleLdidCheck +{ + if (@available(iOS 15, *)) {} else { + NSString* tsAppPath = [NSBundle mainBundle].bundlePath; + + NSString* ldidPath = [tsAppPath stringByAppendingPathComponent:@"ldid"]; + NSString* ldidVersionPath = [tsAppPath stringByAppendingPathComponent:@"ldid.version"]; + + if(![[NSFileManager defaultManager] fileExistsAtPath:ldidPath] || ![[NSFileManager defaultManager] fileExistsAtPath:ldidVersionPath]) + { + [TSInstallationController installLdid]; + } + } +} + - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { // Use this method to optionally configure and attach the UIWindow `window` to the provided UIWindowScene `scene`. // If using a storyboard, the `window` property will automatically be initialized and attached to the scene. @@ -87,6 +104,10 @@ { [self handleURLContexts:connectionOptions.URLContexts scene:(UIWindowScene*)scene]; } + else + { + [self handleLdidCheck]; + } } diff --git a/TrollStore/TSSettingsListController.h b/TrollStore/TSSettingsListController.h index 959d405..fc573ee 100644 --- a/TrollStore/TSSettingsListController.h +++ b/TrollStore/TSSettingsListController.h @@ -4,5 +4,6 @@ { PSSpecifier* _installPersistenceHelperSpecifier; NSString* _newerVersion; + NSString* _newerLdidVersion; } @end \ No newline at end of file diff --git a/TrollStore/TSSettingsListController.m b/TrollStore/TSSettingsListController.m index bca25b7..861e3ba 100644 --- a/TrollStore/TSSettingsListController.m +++ b/TrollStore/TSSettingsListController.m @@ -33,6 +33,28 @@ extern NSUserDefaults* trollStoreUserDefaults(void); }); } }); + + if (@available(iOS 15, *)) {} else { + fetchLatestLdidVersion(^(NSString* latestVersion) + { + NSString* ldidVersionPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"ldid.version"]; + NSString* ldidVersion = nil; + NSData* ldidVersionData = [NSData dataWithContentsOfFile:ldidVersionPath]; + if(ldidVersionData) + { + ldidVersion = [[NSString alloc] initWithData:ldidVersionData encoding:NSUTF8StringEncoding]; + } + + if(![latestVersion isEqualToString:ldidVersion]) + { + _newerLdidVersion = latestVersion; + dispatch_async(dispatch_get_main_queue(), ^ + { + [self reloadSpecifiers]; + }); + } + }); + } } - (NSMutableArray*)specifiers @@ -91,6 +113,84 @@ extern NSUserDefaults* trollStoreUserDefaults(void); [_specifiers addObject:rebuildIconCacheSpecifier]; + if (@available(iOS 15, *)) { } + else { + NSString* ldidPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"ldid"]; + NSString* ldidVersionPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"ldid.version"]; + BOOL ldidInstalled = [[NSFileManager defaultManager] fileExistsAtPath:ldidPath]; + + NSString* ldidVersion = nil; + NSData* ldidVersionData = [NSData dataWithContentsOfFile:ldidVersionPath]; + if(ldidVersionData) + { + ldidVersion = [[NSString alloc] initWithData:ldidVersionData encoding:NSUTF8StringEncoding]; + } + + PSSpecifier* signingGroupSpecifier = [PSSpecifier emptyGroupSpecifier]; + signingGroupSpecifier.name = @"Signing"; + + if(ldidInstalled) + { + [signingGroupSpecifier setProperty:@"ldid is installed and allows TrollStore to install unsigned IPA files." forKey:@"footerText"]; + } + else + { + [signingGroupSpecifier setProperty:@"In order for TrollStore to be able to install unsigned IPAs, ldid has to be installed using this button. It can't be directly included in TrollStore because of licensing issues." forKey:@"footerText"]; + } + + [_specifiers addObject:signingGroupSpecifier]; + + if(ldidInstalled) + { + NSString* installedTitle = @"ldid: Installed"; + if(ldidVersion) + { + installedTitle = [NSString stringWithFormat:@"%@ (%@)", installedTitle, ldidVersion]; + } + + PSSpecifier* ldidInstalledSpecifier = [PSSpecifier preferenceSpecifierNamed:installedTitle + target:self + set:nil + get:nil + detail:nil + cell:PSStaticTextCell + edit:nil]; + [ldidInstalledSpecifier setProperty:@NO forKey:@"enabled"]; + ldidInstalledSpecifier.identifier = @"ldidInstalled"; + [_specifiers addObject:ldidInstalledSpecifier]; + + if(_newerLdidVersion && ![_newerLdidVersion isEqualToString:ldidVersion]) + { + NSString* updateTitle = [NSString stringWithFormat:@"Update to %@", _newerLdidVersion]; + PSSpecifier* ldidUpdateSpecifier = [PSSpecifier preferenceSpecifierNamed:updateTitle + target:self + set:nil + get:nil + detail:nil + cell:PSButtonCell + edit:nil]; + ldidUpdateSpecifier.identifier = @"updateLdid"; + [ldidUpdateSpecifier setProperty:@YES forKey:@"enabled"]; + ldidUpdateSpecifier.buttonAction = @selector(installOrUpdateLdidPressed); + [_specifiers addObject:ldidUpdateSpecifier]; + } + } + else + { + PSSpecifier* installLdidSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Install ldid" + target:self + set:nil + get:nil + detail:nil + cell:PSButtonCell + edit:nil]; + installLdidSpecifier.identifier = @"installLdid"; + [installLdidSpecifier setProperty:@YES forKey:@"enabled"]; + installLdidSpecifier.buttonAction = @selector(installOrUpdateLdidPressed); + [_specifiers addObject:installLdidSpecifier]; + } + } + PSSpecifier* persistenceGroupSpecifier = [PSSpecifier emptyGroupSpecifier]; persistenceGroupSpecifier.name = @"Persistence"; [_specifiers addObject:persistenceGroupSpecifier]; @@ -265,6 +365,11 @@ extern NSUserDefaults* trollStoreUserDefaults(void); respring(); } +- (void)installOrUpdateLdidPressed +{ + [TSInstallationController installLdid]; +} + - (void)installPersistenceHelperPressed { NSMutableArray* appCandidates = [NSMutableArray new]; diff --git a/install_trollhelper.md b/install_trollhelper.md index caf44ba..88a2ee0 100644 --- a/install_trollhelper.md +++ b/install_trollhelper.md @@ -14,7 +14,9 @@ 4. Wait a few seconds, your device should respring and TrollStore will be installed. -5. Done, you can now share IPA files with TrollStore and they will be permanently installed on your device. +5. Open the TrollStore app and press "Install ldid" in the Settings tab, then read the information under "Persistence", the TrollHelper app on the home screen will be your persistence helper. + +6. Done, you can now share IPA files with TrollStore and they will be permanently installed on your device. ## Unjailbreaking while retaining TrollStore diff --git a/install_trollhelperota_arm64e.md b/install_trollhelperota_arm64e.md index ddf4d6c..e18d8eb 100644 --- a/install_trollhelperota_arm64e.md +++ b/install_trollhelperota_arm64e.md @@ -20,6 +20,6 @@ 7. You can now either delete the "GTA Car Tracker" app, or register it as the persistence helper by opening it and tapping the option at the bottom. If you do this, don't delete the app. -8. Open the TrollStore app and read the information under "Persistence", and install the Persistence Helper into a system app if you want persistence (not needed if you registered the GTA Car Tracker app as the persistence helper in step 7). +8. Open the TrollStore app and press "Install ldid" in the Settings tab, then read the information under "Persistence", and install the Persistence Helper into a system app if you want persistence (not needed if you registered the GTA Car Tracker app as the persistence helper in step 7). 9. Done, you can now share IPA files with TrollStore and they will be permanently installed on your device. diff --git a/install_trollhelperota_ios15.md b/install_trollhelperota_ios15.md index 94717d3..9543b56 100644 --- a/install_trollhelperota_ios15.md +++ b/install_trollhelperota_ios15.md @@ -20,6 +20,6 @@ 7. You can now either delete the "GTA Car Tracker" app, or register it as the persistence helper by opening it and tapping the option at the bottom. If you do this, don't delete the app. -8. Open the TrollStore app and read the information under "Persistence", and install the Persistence Helper into a system app if you want persistence (not needed if you registered the GTA Car Tracker app as the persistence helper in step 7). +8. Open the TrollStore app and press "Install ldid" in the Settings tab, then read the information under "Persistence", and install the Persistence Helper into a system app if you want persistence (not needed if you registered the GTA Car Tracker app as the persistence helper in step 7). 9. Done, you can now share IPA files with TrollStore and they will be permanently installed on your device.