Merge branch 'main' into exp-value-picker

This commit is contained in:
opa334 2022-09-06 11:26:35 +02:00
commit 961e9b3a53
15 changed files with 379 additions and 181 deletions

View File

@ -1,6 +1,6 @@
Package: com.opa334.trollstoreroothelper Package: com.opa334.trollstoreroothelper
Name: trollstoreroothelper Name: trollstoreroothelper
Version: 1.0.3 Version: 1.0.6
Architecture: iphoneos-arm Architecture: iphoneos-arm
Description: An awesome tool of some sort!! Description: An awesome tool of some sort!!
Maintainer: opa334 Maintainer: opa334

View File

@ -8,52 +8,10 @@
#import <objc/runtime.h> #import <objc/runtime.h>
#import "CoreServices.h" #import "CoreServices.h"
#import "Shared.h" #import "Shared.h"
#import <mach-o/getsect.h>
#import <mach-o/dyld.h>
#import <mach/mach.h>
#import <mach-o/loader.h>
#import <mach-o/nlist.h>
#import <mach-o/reloc.h>
#import <mach-o/dyld_images.h>
#import <mach-o/fat.h>
#import <sys/utsname.h> #import <sys/utsname.h>
#import <SpringBoardServices/SpringBoardServices.h> #import <SpringBoardServices/SpringBoardServices.h>
#import <Security/Security.h>
#ifdef __LP64__
#define segment_command_universal segment_command_64
#define mach_header_universal mach_header_64
#define MH_MAGIC_UNIVERSAL MH_MAGIC_64
#define MH_CIGAM_UNIVERSAL MH_CIGAM_64
#else
#define segment_command_universal segment_command
#define mach_header_universal mach_header
#define MH_MAGIC_UNIVERSAL MH_MAGIC
#define MH_CIGAM_UNIVERSAL MH_CIGAM
#endif
#define SWAP32(x) ((((x) & 0xff000000) >> 24) | (((x) & 0xff0000) >> 8) | (((x) & 0xff00) << 8) | (((x) & 0xff) << 24))
uint32_t s32(uint32_t toSwap, BOOL shouldSwap)
{
return shouldSwap ? SWAP32(toSwap) : toSwap;
}
#define CPU_SUBTYPE_ARM64E_NEW_ABI 0x80000002
struct CSSuperBlob {
uint32_t magic;
uint32_t length;
uint32_t count;
};
struct CSBlob {
uint32_t type;
uint32_t offset;
};
#define CS_MAGIC_EMBEDDED_SIGNATURE 0xfade0cc0
#define CS_MAGIC_EMBEDDED_SIGNATURE_REVERSED 0xc00cdefa
#define CS_MAGIC_EMBEDDED_ENTITLEMENTS 0xfade7171
extern mach_msg_return_t SBReloadIconForIdentifier(mach_port_t machport, const char* identifier); extern mach_msg_return_t SBReloadIconForIdentifier(mach_port_t machport, const char* identifier);
@ -65,6 +23,27 @@ extern NSString* BKSOpenApplicationOptionKeyActivateForEvent;
extern void BKSTerminateApplicationForReasonAndReportWithDescription(NSString *bundleID, int reasonID, bool report, NSString *description); extern void BKSTerminateApplicationForReasonAndReportWithDescription(NSString *bundleID, int reasonID, bool report, NSString *description);
typedef CF_OPTIONS(uint32_t, SecCSFlags) {
kSecCSDefaultFlags = 0
};
#define kSecCSRequirementInformation 1 << 2
#define kSecCSSigningInformation 1 << 1
typedef struct __SecCode const *SecStaticCodeRef;
extern CFStringRef kSecCodeInfoEntitlementsDict;
extern CFStringRef kSecCodeInfoCertificates;
extern CFStringRef kSecPolicyAppleiPhoneApplicationSigning;
extern CFStringRef kSecPolicyAppleiPhoneProfileApplicationSigning;
extern CFStringRef kSecPolicyLeafMarkerOid;
OSStatus SecStaticCodeCreateWithPathAndAttributes(CFURLRef path, SecCSFlags flags, CFDictionaryRef attributes, SecStaticCodeRef *staticCode);
OSStatus SecCodeCopySigningInformation(SecStaticCodeRef code, SecCSFlags flags, CFDictionaryRef *information);
CFDataRef SecCertificateCopyExtensionValue(SecCertificateRef certificate, CFTypeRef extensionOID, bool *isCritical);
void SecPolicySetOptionsValue(SecPolicyRef policy, CFStringRef key, CFTypeRef value);
#define kCFPreferencesNoContainer CFSTR("kCFPreferencesNoContainer") #define kCFPreferencesNoContainer CFSTR("kCFPreferencesNoContainer")
typedef CFPropertyListRef (*_CFPreferencesCopyValueWithContainerType)(CFStringRef key, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath); typedef CFPropertyListRef (*_CFPreferencesCopyValueWithContainerType)(CFStringRef key, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
@ -221,117 +200,219 @@ int runLdid(NSArray* args, NSString** output, NSString** errorOutput)
return WEXITSTATUS(status); return WEXITSTATUS(status);
} }
NSDictionary* dumpEntitlements(NSString* binaryPath) SecStaticCodeRef getStaticCodeRef(NSString *binaryPath)
{ {
char* entitlementsData = NULL; if(binaryPath == nil)
uint32_t entitlementsLength = 0;
FILE* machoFile = fopen(binaryPath.UTF8String, "rb");
struct mach_header_universal header;
fread(&header,sizeof(header),1,machoFile);
if(header.magic == FAT_MAGIC || header.magic == FAT_CIGAM)
{ {
fseek(machoFile,0,SEEK_SET); return NULL;
struct fat_header fatHeader;
fread(&fatHeader,sizeof(fatHeader),1,machoFile);
BOOL swpFat = fatHeader.magic == FAT_CIGAM;
for(int i = 0; i < s32(fatHeader.nfat_arch, swpFat); i++)
{
struct fat_arch fatArch;
fseek(machoFile,sizeof(fatHeader) + sizeof(fatArch) * i,SEEK_SET);
fread(&fatArch,sizeof(fatArch),1,machoFile);
if(s32(fatArch.cputype, swpFat) != CPU_TYPE_ARM64)
{
continue;
} }
fseek(machoFile,s32(fatArch.offset, swpFat),SEEK_SET); CFURLRef binaryURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)binaryPath, kCFURLPOSIXPathStyle, false);
struct mach_header_universal header; if(binaryURL == NULL)
fread(&header,sizeof(header),1,machoFile);
BOOL swp = header.magic == MH_CIGAM_UNIVERSAL;
// This code is cursed, don't stare at it too long or it will stare back at you
uint32_t offset = s32(fatArch.offset, swpFat) + sizeof(header);
for(int c = 0; c < s32(header.ncmds, swp); c++)
{ {
fseek(machoFile,offset,SEEK_SET); NSLog(@"[getStaticCodeRef] failed to get URL to binary %@", binaryPath);
struct load_command cmd; return NULL;
fread(&cmd,sizeof(cmd),1,machoFile);
uint32_t normalizedCmd = s32(cmd.cmd,swp);
if(normalizedCmd == LC_CODE_SIGNATURE)
{
struct linkedit_data_command codeSignCommand;
fseek(machoFile,offset,SEEK_SET);
fread(&codeSignCommand,sizeof(codeSignCommand),1,machoFile);
uint32_t codeSignCmdOffset = s32(fatArch.offset, swpFat) + s32(codeSignCommand.dataoff, swp);
fseek(machoFile, codeSignCmdOffset, SEEK_SET);
struct CSSuperBlob superBlob;
fread(&superBlob, sizeof(superBlob), 1, machoFile);
if(SWAP32(superBlob.magic) == CS_MAGIC_EMBEDDED_SIGNATURE)
{
uint32_t itemCount = SWAP32(superBlob.count);
for(int i = 0; i < itemCount; i++)
{
fseek(machoFile, codeSignCmdOffset + sizeof(superBlob) + i * sizeof(struct CSBlob),SEEK_SET);
struct CSBlob blob;
fread(&blob, sizeof(struct CSBlob), 1, machoFile);
fseek(machoFile, codeSignCmdOffset + SWAP32(blob.offset),SEEK_SET);
uint32_t blobMagic;
fread(&blobMagic, sizeof(uint32_t), 1, machoFile);
if(SWAP32(blobMagic) == CS_MAGIC_EMBEDDED_ENTITLEMENTS)
{
uint32_t entitlementsLengthTmp;
fread(&entitlementsLengthTmp, sizeof(uint32_t), 1, machoFile);
entitlementsLength = SWAP32(entitlementsLengthTmp);
entitlementsData = malloc(entitlementsLength - 8);
fread(&entitlementsData[0], entitlementsLength - 8, 1, machoFile);
break;
}
}
} }
break; SecStaticCodeRef codeRef = NULL;
} OSStatus result;
offset += cmd.cmdsize; result = SecStaticCodeCreateWithPathAndAttributes(binaryURL, kSecCSDefaultFlags, NULL, &codeRef);
}
}
}
fclose(machoFile); CFRelease(binaryURL);
NSData* entitlementsNSData = nil; if(result != errSecSuccess)
if(entitlementsData)
{ {
entitlementsNSData = [NSData dataWithBytes:entitlementsData length:entitlementsLength]; NSLog(@"[getStaticCodeRef] failed to create static code for binary %@", binaryPath);
free(entitlementsData); return NULL;
} }
if(entitlementsNSData) return codeRef;
}
NSDictionary* dumpEntitlements(SecStaticCodeRef codeRef)
{
if(codeRef == NULL)
{ {
NSDictionary* plist = [NSPropertyListSerialization propertyListWithData:entitlementsNSData options:NSPropertyListImmutable format:nil error:nil]; NSLog(@"[dumpEntitlements] attempting to dump entitlements without a StaticCodeRef");
NSLog(@"%@ dumped entitlements %@", binaryPath, plist); return nil;
return plist; }
CFDictionaryRef signingInfo = NULL;
OSStatus result;
result = SecCodeCopySigningInformation(codeRef, kSecCSRequirementInformation, &signingInfo);
if(result != errSecSuccess)
{
NSLog(@"[dumpEntitlements] failed to copy signing info from static code");
return nil;
}
NSDictionary *entitlementsNSDict = nil;
CFDictionaryRef entitlements = CFDictionaryGetValue(signingInfo, kSecCodeInfoEntitlementsDict);
if(entitlements == NULL)
{
NSLog(@"[dumpEntitlements] no entitlements specified");
}
else if(CFGetTypeID(entitlements) != CFDictionaryGetTypeID())
{
NSLog(@"[dumpEntitlements] invalid entitlements");
} }
else else
{ {
NSLog(@"Failed to dump entitlements of %@... This is bad", binaryPath); entitlementsNSDict = (__bridge NSDictionary *)(entitlements);
NSLog(@"[dumpEntitlements] dumped %@", entitlementsNSDict);
} }
CFRelease(signingInfo);
return entitlementsNSDict;
}
NSDictionary* dumpEntitlementsFromBinaryAtPath(NSString *binaryPath)
{
// This function is intended for one-shot checks. Main-event functions should retain/release their own SecStaticCodeRefs
if(binaryPath == nil)
{
return nil; return nil;
}
SecStaticCodeRef codeRef = getStaticCodeRef(binaryPath);
if(codeRef == NULL)
{
return nil;
}
NSDictionary *entitlements = dumpEntitlements(codeRef);
CFRelease(codeRef);
return entitlements;
}
BOOL certificateHasDataForExtensionOID(SecCertificateRef certificate, CFStringRef oidString)
{
if(certificate == NULL || oidString == NULL)
{
NSLog(@"[certificateHasDataForExtensionOID] attempted to check null certificate or OID");
return NO;
}
CFDataRef extensionData = SecCertificateCopyExtensionValue(certificate, oidString, NULL);
if(extensionData != NULL)
{
CFRelease(extensionData);
return YES;
}
return NO;
}
BOOL codeCertChainContainsFakeAppStoreExtensions(SecStaticCodeRef codeRef)
{
if(codeRef == NULL)
{
NSLog(@"[codeCertChainContainsFakeAppStoreExtensions] attempted to check cert chain of null static code object");
return NO;
}
CFDictionaryRef signingInfo = NULL;
OSStatus result;
result = SecCodeCopySigningInformation(codeRef, kSecCSSigningInformation, &signingInfo);
if(result != errSecSuccess)
{
NSLog(@"[codeCertChainContainsFakeAppStoreExtensions] failed to copy signing info from static code");
return NO;
}
CFArrayRef certificates = CFDictionaryGetValue(signingInfo, kSecCodeInfoCertificates);
if(certificates == NULL || CFArrayGetCount(certificates) == 0)
{
return NO;
}
// If we match the standard Apple policy, we are signed properly, but we haven't been deliberately signed with a custom root
SecPolicyRef appleAppStorePolicy = SecPolicyCreateWithProperties(kSecPolicyAppleiPhoneApplicationSigning, NULL);
SecTrustRef trust = NULL;
SecTrustCreateWithCertificates(certificates, appleAppStorePolicy, &trust);
if(SecTrustEvaluateWithError(trust, nil))
{
CFRelease(trust);
CFRelease(appleAppStorePolicy);
CFRelease(signingInfo);
NSLog(@"[codeCertChainContainsFakeAppStoreExtensions] found certificate extension, but was issued by Apple (App Store)");
return NO;
}
// We haven't matched Apple, so keep going. Is the app profile signed?
CFRelease(appleAppStorePolicy);
SecPolicyRef appleProfileSignedPolicy = SecPolicyCreateWithProperties(kSecPolicyAppleiPhoneProfileApplicationSigning, NULL);
if(SecTrustSetPolicies(trust, appleProfileSignedPolicy) != errSecSuccess)
{
NSLog(@"[codeCertChainContainsFakeAppStoreExtensions] error replacing trust policy to check for profile-signed app");
CFRelease(trust);
CFRelease(signingInfo);
return NO;
}
if(SecTrustEvaluateWithError(trust, nil))
{
CFRelease(trust);
CFRelease(appleProfileSignedPolicy);
CFRelease(signingInfo);
NSLog(@"[codeCertChainContainsFakeAppStoreExtensions] found certificate extension, but was issued by Apple (profile-signed)");
return NO;
}
// Still haven't matched Apple. Are we using a custom root that would take the App Store fastpath?
CFRelease(appleProfileSignedPolicy);
// Cert chain should be of length 3
if(CFArrayGetCount(certificates) != 3)
{
CFRelease(signingInfo);
NSLog(@"[codeCertChainContainsFakeAppStoreExtensions] certificate chain length != 3");
return NO;
}
// AppleCodeSigning only checks for the codeSigning EKU by default
SecPolicyRef customRootPolicy = SecPolicyCreateWithProperties(kSecPolicyAppleCodeSigning, NULL);
SecPolicySetOptionsValue(customRootPolicy, CFSTR("LeafMarkerOid"), CFSTR("1.2.840.113635.100.6.1.3"));
if(SecTrustSetPolicies(trust, customRootPolicy) != errSecSuccess)
{
NSLog(@"[codeCertChainContainsFakeAppStoreExtensions] error replacing trust policy to check for custom root");
CFRelease(trust);
CFRelease(signingInfo);
return NO;
}
// Need to add our certificate chain to the anchor as it is expected to be a self-signed root
SecTrustSetAnchorCertificates(trust, certificates);
BOOL evaluatesToCustomAnchor = SecTrustEvaluateWithError(trust, nil);
NSLog(@"[codeCertChainContainsFakeAppStoreExtensions] app signed with non-Apple certificate %@ using valid custom certificates", evaluatesToCustomAnchor ? @"IS" : @"is NOT");
CFRelease(trust);
CFRelease(customRootPolicy);
CFRelease(signingInfo);
return evaluatesToCustomAnchor;
} }
BOOL signApp(NSString* appPath, NSError** error) BOOL signApp(NSString* appPath, NSError** error)
{ {
if(!isLdidInstalled()) return NO;
NSDictionary* appInfoDict = [NSDictionary dictionaryWithContentsOfFile:[appPath stringByAppendingPathComponent:@"Info.plist"]]; NSDictionary* appInfoDict = [NSDictionary dictionaryWithContentsOfFile:[appPath stringByAppendingPathComponent:@"Info.plist"]];
if(!appInfoDict) return NO; if(!appInfoDict) return NO;
@ -340,12 +421,44 @@ BOOL signApp(NSString* appPath, NSError** error)
if(![[NSFileManager defaultManager] fileExistsAtPath:executablePath]) return NO; if(![[NSFileManager defaultManager] fileExistsAtPath:executablePath]) return NO;
NSObject *tsBundleIsPreSigned = appInfoDict[@"TSBundlePreSigned"];
if([tsBundleIsPreSigned isKindOfClass:[NSNumber class]])
{
// if TSBundlePreSigned = YES, this bundle has been externally signed so we can skip over signing it now
NSNumber *tsBundleIsPreSignedNum = (NSNumber *)tsBundleIsPreSigned;
if([tsBundleIsPreSignedNum boolValue] == YES)
{
NSLog(@"[signApp] taking fast path for app which declares it has already been signed (%@)", executablePath);
return YES;
}
}
SecStaticCodeRef codeRef = getStaticCodeRef(executablePath);
if(codeRef != NULL)
{
if(codeCertChainContainsFakeAppStoreExtensions(codeRef))
{
NSLog(@"[signApp] taking fast path for app signed using a custom root certificate (%@)", executablePath);
CFRelease(codeRef);
return YES;
}
}
else
{
NSLog(@"[signApp] failed to get static code, can't derive entitlements from %@, continuing anways...", executablePath);
}
if(!isLdidInstalled()) return NO;
NSString* certPath = [trollStoreAppPath() stringByAppendingPathComponent:@"cert.p12"]; NSString* certPath = [trollStoreAppPath() stringByAppendingPathComponent:@"cert.p12"];
NSString* certArg = [@"-K" stringByAppendingPathComponent:certPath]; NSString* certArg = [@"-K" stringByAppendingPathComponent:certPath];
NSString* errorOutput; NSString* errorOutput;
int ldidRet; int ldidRet;
NSDictionary* entitlements = dumpEntitlements(executablePath); NSDictionary* entitlements = dumpEntitlements(codeRef);
CFRelease(codeRef);
if(!entitlements) if(!entitlements)
{ {
NSLog(@"app main binary has no entitlements, signing app with fallback entitlements..."); NSLog(@"app main binary has no entitlements, signing app with fallback entitlements...");
@ -371,9 +484,23 @@ BOOL signApp(NSString* appPath, NSError** error)
return ldidRet == 0; return ldidRet == 0;
} }
void applyPatchesToInfoDictionary(NSString* appPath)
{
NSURL* appURL = [NSURL fileURLWithPath:appPath];
NSURL* infoPlistURL = [appURL URLByAppendingPathComponent:@"Info.plist"];
NSMutableDictionary* infoDictM = [[NSDictionary dictionaryWithContentsOfURL:infoPlistURL error:nil] mutableCopy];
if(!infoDictM) return;
// enable notifications
infoDictM[@"SBAppUsesLocalNotifications"] = @1;
[infoDictM writeToURL:infoPlistURL error:nil];
}
// 170: failed to create container for app bundle // 170: failed to create container for app bundle
// 171: a non trollstore app with the same identifier is already installled // 171: a non trollstore app with the same identifier is already installled
// 172: no info.plist found in app // 172: no info.plist found in app
// 173: app is not signed and cannot be signed because ldid not installed or didn't work
int installApp(NSString* appPath, BOOL sign, BOOL force, NSError** error) int installApp(NSString* appPath, BOOL sign, BOOL force, NSError** error)
{ {
NSLog(@"[installApp force = %d]", force); NSLog(@"[installApp force = %d]", force);
@ -381,10 +508,11 @@ int installApp(NSString* appPath, BOOL sign, BOOL force, NSError** error)
NSString* appId = appIdForAppPath(appPath); NSString* appId = appIdForAppPath(appPath);
if(!appId) return 172; if(!appId) return 172;
applyPatchesToInfoDictionary(appPath);
if(sign) if(sign)
{ {
// if it fails to sign, we don't care if(!signApp(appPath, error)) return 173;
signApp(appPath, error);
} }
BOOL existed; BOOL existed;
@ -420,13 +548,25 @@ int installApp(NSString* appPath, BOOL sign, BOOL force, NSError** error)
// Mark app as TrollStore app // Mark app as TrollStore app
[[NSFileManager defaultManager] createFileAtPath:trollStoreMarkURL.path contents:[NSData data] attributes:nil]; [[NSFileManager defaultManager] createFileAtPath:trollStoreMarkURL.path contents:[NSData data] attributes:nil];
// Apply correct permissions // Apply correct permissions (First run, set everything to 644, owner 33)
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appPath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
NSURL* fileURL; NSURL* fileURL;
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appPath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
while(fileURL = [enumerator nextObject]) while(fileURL = [enumerator nextObject])
{ {
NSString* filePath = fileURL.path; NSString* filePath = fileURL.path;
chown(filePath.UTF8String, 33, 33); chown(filePath.UTF8String, 33, 33);
chmod(filePath.UTF8String, 0644);
}
// Apply correct permissions (Second run, set executables and directories to 0755)
enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appPath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
while(fileURL = [enumerator nextObject])
{
NSString* filePath = fileURL.path;
BOOL isDir;
[[NSFileManager defaultManager] fileExistsAtPath:fileURL.path isDirectory:&isDir];
if([filePath.lastPathComponent isEqualToString:@"Info.plist"]) if([filePath.lastPathComponent isEqualToString:@"Info.plist"])
{ {
NSDictionary* infoDictionary = [NSDictionary dictionaryWithContentsOfFile:filePath]; NSDictionary* infoDictionary = [NSDictionary dictionaryWithContentsOfFile:filePath];
@ -437,10 +577,15 @@ int installApp(NSString* appPath, BOOL sign, BOOL force, NSError** error)
chmod(executablePath.UTF8String, 0755); chmod(executablePath.UTF8String, 0755);
} }
} }
else if([filePath.pathExtension isEqualToString:@"dylib"]) else if(!isDir && [filePath.pathExtension isEqualToString:@"dylib"])
{ {
chmod(filePath.UTF8String, 0755); chmod(filePath.UTF8String, 0755);
} }
else if(isDir)
{
// apparently all dirs are writable by default
chmod(filePath.UTF8String, 0755);
}
} }
// chown 0 all root binaries // chown 0 all root binaries
@ -502,17 +647,10 @@ int installApp(NSString* appPath, BOOL sign, BOOL force, NSError** error)
} }
} }
int uninstallApp(NSString* appId, NSError** error) int uninstallApp(NSString* appPath, NSString* appId, NSError** error)
{ {
NSString* appPath = appPathForAppId(appId, error);
if(!appPath) return 1;
LSApplicationProxy* appProxy = [LSApplicationProxy applicationProxyForIdentifier:appId]; LSApplicationProxy* appProxy = [LSApplicationProxy applicationProxyForIdentifier:appId];
NSLog(@"appProxy: %@", appProxy);
MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil]; MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil];
NSLog(@"1");
NSString *containerPath = [appContainer url].path; NSString *containerPath = [appContainer url].path;
if(containerPath) if(containerPath)
{ {
@ -524,8 +662,8 @@ int uninstallApp(NSString* appId, NSError** error)
// delete group container paths // delete group container paths
[[appProxy groupContainerURLs] enumerateKeysAndObjectsUsingBlock:^(NSString* groupID, NSURL* groupURL, BOOL* stop) [[appProxy groupContainerURLs] enumerateKeysAndObjectsUsingBlock:^(NSString* groupID, NSURL* groupURL, BOOL* stop)
{ {
[[NSFileManager defaultManager] removeItemAtURL:groupURL error:nil];
NSLog(@"deleting %@", groupURL); NSLog(@"deleting %@", groupURL);
[[NSFileManager defaultManager] removeItemAtURL:groupURL error:nil];
}]; }];
// delete app plugin paths // delete app plugin paths
@ -534,15 +672,15 @@ int uninstallApp(NSString* appId, NSError** error)
NSURL* pluginURL = pluginProxy.dataContainerURL; NSURL* pluginURL = pluginProxy.dataContainerURL;
if(pluginURL) if(pluginURL)
{ {
[[NSFileManager defaultManager] removeItemAtPath:pluginURL.path error:error]; NSLog(@"deleting %@", pluginURL);
NSLog(@"deleting %@", pluginURL.path); [[NSFileManager defaultManager] removeItemAtURL:pluginURL error:error];
} }
} }
// unregister app // unregister app
registerPath((char*)appPath.UTF8String, 1); registerPath((char*)appPath.UTF8String, 1);
NSLog(@"deleting %@", [appPath stringByDeletingLastPathComponent]);
NSLog(@"deleting %@", [appPath stringByDeletingLastPathComponent]);
// delete app // delete app
BOOL deleteSuc = [[NSFileManager defaultManager] removeItemAtPath:[appPath stringByDeletingLastPathComponent] error:error]; BOOL deleteSuc = [[NSFileManager defaultManager] removeItemAtPath:[appPath stringByDeletingLastPathComponent] error:error];
if(deleteSuc) if(deleteSuc)
@ -555,6 +693,22 @@ int uninstallApp(NSString* appId, NSError** error)
} }
} }
int uninstallAppByPath(NSString* appPath, NSError** error)
{
if(!appPath) return 1;
NSString* appId = appIdForAppPath(appPath);
if(!appId) return 1;
return uninstallApp(appPath, appId, error);
}
int uninstallAppById(NSString* appId, NSError** error)
{
if(!appId) return 1;
NSString* appPath = appPathForAppId(appId, error);
if(!appPath) return 1;
return uninstallApp(appPath, appId, error);
}
// 166: IPA does not exist or is not accessible // 166: IPA does not exist or is not accessible
// 167: IPA does not appear to contain an app // 167: IPA does not appear to contain an app
@ -597,7 +751,7 @@ void uninstallAllApps(void)
{ {
for(NSString* appPath in trollStoreInstalledAppBundlePaths()) for(NSString* appPath in trollStoreInstalledAppBundlePaths())
{ {
uninstallApp(appIdForAppPath(appPath), nil); uninstallAppById(appIdForAppPath(appPath), nil);
} }
} }
@ -811,8 +965,13 @@ int main(int argc, char *argv[], char *envp[]) {
{ {
if(argc <= 2) return -3; if(argc <= 2) return -3;
NSString* appId = [NSString stringWithUTF8String:argv[2]]; NSString* appId = [NSString stringWithUTF8String:argv[2]];
ret = uninstallApp(appId, &error); ret = uninstallAppById(appId, &error);
} else if([cmd isEqualToString:@"install-trollstore"]) } else if([cmd isEqualToString:@"uninstall-path"])
{
if(argc <= 2) return -3;
NSString* appPath = [NSString stringWithUTF8String:argv[2]];
ret = uninstallAppByPath(appPath, &error);
}else if([cmd isEqualToString:@"install-trollstore"])
{ {
if(argc <= 2) return -3; if(argc <= 2) return -3;
NSString* tsTar = [NSString stringWithUTF8String:argv[2]]; NSString* tsTar = [NSString stringWithUTF8String:argv[2]];

View File

@ -6,7 +6,7 @@
// uicache on steroids // uicache on steroids
extern NSDictionary* dumpEntitlements(NSString* binaryPath); extern NSDictionary* dumpEntitlementsFromBinaryAtPath(NSString* binaryPath);
NSDictionary* constructGroupsContainersForEntitlements(NSDictionary* entitlements, BOOL systemGroups) NSDictionary* constructGroupsContainersForEntitlements(NSDictionary* entitlements, BOOL systemGroups)
{ {
@ -118,7 +118,7 @@ void registerPath(char* cPath, int unregister)
// Add entitlements // Add entitlements
NSString* appExecutablePath = [path stringByAppendingPathComponent:appInfoPlist[@"CFBundleExecutable"]]; NSString* appExecutablePath = [path stringByAppendingPathComponent:appInfoPlist[@"CFBundleExecutable"]];
NSDictionary* entitlements = dumpEntitlements(appExecutablePath); NSDictionary* entitlements = dumpEntitlementsFromBinaryAtPath(appExecutablePath);
if(entitlements) if(entitlements)
{ {
dictToRegister[@"Entitlements"] = entitlements; dictToRegister[@"Entitlements"] = entitlements;
@ -139,6 +139,9 @@ void registerPath(char* cPath, int unregister)
dictToRegister[@"IsDeletable"] = @0; dictToRegister[@"IsDeletable"] = @0;
dictToRegister[@"Path"] = path; dictToRegister[@"Path"] = path;
dictToRegister[@"IsContainerized"] = @(constructContainerizationForEntitlements(entitlements)); dictToRegister[@"IsContainerized"] = @(constructContainerizationForEntitlements(entitlements));
dictToRegister[@"SignerOrganization"] = @"Apple Inc.";
dictToRegister[@"SignatureVersion"] = @132352;
dictToRegister[@"SignerIdentity"] = @"Apple iPhone OS Application Signing";
NSString* teamIdentifier = constructTeamIdentifierForEntitlements(entitlements); NSString* teamIdentifier = constructTeamIdentifierForEntitlements(entitlements);
if(teamIdentifier) dictToRegister[@"TeamIdentifier"] = teamIdentifier; if(teamIdentifier) dictToRegister[@"TeamIdentifier"] = teamIdentifier;
@ -185,7 +188,7 @@ void registerPath(char* cPath, int unregister)
// Add entitlements // Add entitlements
NSString* pluginExecutablePath = [pluginPath stringByAppendingPathComponent:pluginInfoPlist[@"CFBundleExecutable"]]; NSString* pluginExecutablePath = [pluginPath stringByAppendingPathComponent:pluginInfoPlist[@"CFBundleExecutable"]];
NSDictionary* pluginEntitlements = dumpEntitlements(pluginExecutablePath); NSDictionary* pluginEntitlements = dumpEntitlementsFromBinaryAtPath(pluginExecutablePath);
if(pluginEntitlements) if(pluginEntitlements)
{ {
pluginDict[@"Entitlements"] = pluginEntitlements; pluginDict[@"Entitlements"] = pluginEntitlements;
@ -206,6 +209,9 @@ void registerPath(char* cPath, int unregister)
pluginDict[@"Path"] = pluginPath; pluginDict[@"Path"] = pluginPath;
pluginDict[@"PluginOwnerBundleID"] = appBundleID; pluginDict[@"PluginOwnerBundleID"] = appBundleID;
pluginDict[@"IsContainerized"] = @(constructContainerizationForEntitlements(pluginEntitlements)); pluginDict[@"IsContainerized"] = @(constructContainerizationForEntitlements(pluginEntitlements));
pluginDict[@"SignerOrganization"] = @"Apple Inc.";
pluginDict[@"SignatureVersion"] = @132352;
pluginDict[@"SignerIdentity"] = @"Apple iPhone OS Application Signing";
NSString* pluginTeamIdentifier = constructTeamIdentifierForEntitlements(pluginEntitlements); NSString* pluginTeamIdentifier = constructTeamIdentifierForEntitlements(pluginEntitlements);
if(pluginTeamIdentifier) pluginDict[@"TeamIdentifier"] = pluginTeamIdentifier; if(pluginTeamIdentifier) pluginDict[@"TeamIdentifier"] = pluginTeamIdentifier;

View File

@ -55,6 +55,7 @@ int IOGPU_get_command_queue_extra_refills_needed(void)
uname(&u); uname(&u);
// iPhone 7 // iPhone 7
// iPod 7
// iPhone 11 // iPhone 11
// iPhone 12 // iPhone 12
// iPhone 13 // iPhone 13
@ -62,6 +63,7 @@ int IOGPU_get_command_queue_extra_refills_needed(void)
// iPad Pro (10.5-inch, WiFi) // iPad Pro (10.5-inch, WiFi)
if ( if (
strstr(u.machine, "iPhone9,") strstr(u.machine, "iPhone9,")
|| strstr(u.machine, "iPod9,")
|| strstr(u.machine, "iPhone12,") || strstr(u.machine, "iPhone12,")
|| strstr(u.machine, "iPhone13,") || strstr(u.machine, "iPhone13,")
|| strstr(u.machine, "iPhone14,") || strstr(u.machine, "iPhone14,")

View File

@ -10,6 +10,7 @@
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/utsname.h> #include <sys/utsname.h>
#import <sys/sysctl.h>
extern void badLog(const char*, ...); extern void badLog(const char*, ...);
@ -55,16 +56,28 @@ uint64_t kernel_base_from_holder(mach_port_t holder, uint64_t holder_addr)
uint64_t off_task_bsd_info; uint64_t off_task_bsd_info;
#if __arm64e__ #if __arm64e__
if (strstr(u.machine, "iPhone14,")) cpu_subtype_t cpuFamily = 0;
size_t cpuFamilySize = sizeof(cpuFamily);
sysctlbyname("hw.cpufamily", &cpuFamily, &cpuFamilySize, NULL, 0);
bool isA15OrNewer;
if (cpuFamily == CPUFAMILY_ARM_BLIZZARD_AVALANCHE) {
isA15OrNewer = true;
}
else {
isA15OrNewer = false;
}
if (isA15OrNewer)
{ {
off_task_bsd_info = 0x3c8; // ios15.1 a15 // proc_t::task_bsd_info off_task_bsd_info = 0x3c8; // ios15.1 a15 // proc_t::task_bsd_info
} }
else else
{ {
off_task_bsd_info = 0x3b8; //; iOS15.1 a12 // proc_t::task_bsd_info off_task_bsd_info = 0x3b8; //; iOS15.1 a12-a14 // proc_t::task_bsd_info
} }
#else #else
off_task_bsd_info = 0x3A0; off_task_bsd_info = 0x3A0; // a9-a11
#endif #endif
g_self_proc = xpaci(kread64(self_task + off_task_bsd_info)); g_self_proc = xpaci(kread64(self_task + off_task_bsd_info));

View File

@ -52,7 +52,7 @@
<string>iPhoneOS</string> <string>iPhoneOS</string>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0.3</string> <string>1.0.7</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UIDeviceFamily</key> <key>UIDeviceFamily</key>

View File

@ -1,6 +1,6 @@
Package: com.opa334.trollstorehelper Package: com.opa334.trollstorehelper
Name: TrollStore Helper Name: TrollStore Helper
Version: 1.0.3 Version: 1.0.7
Architecture: iphoneos-arm Architecture: iphoneos-arm
Description: Helper app to install and manage TrollStore! Description: Helper app to install and manage TrollStore!
Maintainer: opa334 Maintainer: opa334

View File

@ -50,7 +50,7 @@
<string>iPhoneOS</string> <string>iPhoneOS</string>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.0.3</string> <string>1.0.7</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UIDeviceFamily</key> <key>UIDeviceFamily</key>

View File

@ -55,8 +55,16 @@
{ {
NSString* appPath = [[TSApplicationsManager sharedInstance] installedAppPaths][indexPath.row]; NSString* appPath = [[TSApplicationsManager sharedInstance] installedAppPaths][indexPath.row];
NSString* appId = [[TSApplicationsManager sharedInstance] appIdForAppPath:appPath]; NSString* appId = [[TSApplicationsManager sharedInstance] appIdForAppPath:appPath];
if(appId)
{
[[TSApplicationsManager sharedInstance] uninstallApp:appId]; [[TSApplicationsManager sharedInstance] uninstallApp:appId];
} }
else
{
[[TSApplicationsManager sharedInstance] uninstallAppByPath:appPath];
}
}
} }
@end @end

View File

@ -17,5 +17,6 @@
- (int)installIpa:(NSString*)pathToIpa force:(BOOL)force; - (int)installIpa:(NSString*)pathToIpa force:(BOOL)force;
- (int)installIpa:(NSString*)pathToIpa; - (int)installIpa:(NSString*)pathToIpa;
- (int)uninstallApp:(NSString*)appId; - (int)uninstallApp:(NSString*)appId;
- (int)uninstallAppByPath:(NSString*)path;
@end @end

View File

@ -72,6 +72,9 @@
case 172: case 172:
errorDescription = @"The app does not seem to contain an Info.plist"; errorDescription = @"The app does not seem to contain an Info.plist";
break; break;
case 173:
errorDescription = @"The app is not signed with a fake CoreTrust certificate and ldid does not seem to be installed. Make sure ldid is installed in the settings tab and try again.";
break;
} }
NSError* error = [NSError errorWithDomain:TrollStoreErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : errorDescription}]; NSError* error = [NSError errorWithDomain:TrollStoreErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey : errorDescription}];
@ -100,9 +103,18 @@
- (int)uninstallApp:(NSString*)appId - (int)uninstallApp:(NSString*)appId
{ {
if(!appId) return -200;
int ret = spawnRoot(helperPath(), @[@"uninstall", appId]); int ret = spawnRoot(helperPath(), @[@"uninstall", appId]);
[[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil]; [[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
return ret; return ret;
} }
- (int)uninstallAppByPath:(NSString*)path
{
if(!path) return -200;
int ret = spawnRoot(helperPath(), @[@"uninstall-path", path]);
[[NSNotificationCenter defaultCenter] postNotificationName:@"ApplicationsChanged" object:nil];
return ret;
}
@end @end

View File

@ -77,13 +77,8 @@
NSURL* url = context.URL; NSURL* url = context.URL;
if (url != nil && [url isFileURL]) { if (url != nil && [url isFileURL]) {
[url startAccessingSecurityScopedResource]; [url startAccessingSecurityScopedResource];
NSURL* tmpCopyURL = [NSURL fileURLWithPath:[NSTemporaryDirectory() stringByAppendingPathComponent:url.lastPathComponent]];
[[NSFileManager defaultManager] copyItemAtURL:url toURL:tmpCopyURL error:nil];
void (^doneBlock)(BOOL) = ^(BOOL shouldExit) void (^doneBlock)(BOOL) = ^(BOOL shouldExit)
{ {
[[NSFileManager defaultManager] removeItemAtURL:tmpCopyURL error:nil];
[url stopAccessingSecurityScopedResource]; [url stopAccessingSecurityScopedResource];
[[NSFileManager defaultManager] removeItemAtURL:url error:nil]; [[NSFileManager defaultManager] removeItemAtURL:url error:nil];
@ -105,7 +100,7 @@
{ {
// Update TrollStore itself // Update TrollStore itself
NSLog(@"Updating TrollStore..."); NSLog(@"Updating TrollStore...");
int ret = spawnRoot(helperPath(), @[@"install-trollstore", tmpCopyURL.path]); int ret = spawnRoot(helperPath(), @[@"install-trollstore", url.path]);
doneBlock(ret == 0); doneBlock(ret == 0);
NSLog(@"Updated TrollStore!"); NSLog(@"Updated TrollStore!");
} }

View File

@ -192,7 +192,7 @@
} }
PSSpecifier* otherGroupSpecifier = [PSSpecifier emptyGroupSpecifier]; PSSpecifier* otherGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
[otherGroupSpecifier setProperty:[NSString stringWithFormat:@"TrollStore %@\n\n© 2022 Lars Fröder (opa334)\n\nCredits:\n@LinusHenze: CoreTrust bug\n@zhuowei: CoreTrust bug writeup and cert\n@ProcursusTeam: uicache and ldid build\n@cstar_ow: uicache\n@saurik: ldid", getTrollStoreVersion()] forKey:@"footerText"]; [otherGroupSpecifier setProperty:[NSString stringWithFormat:@"TrollStore %@\n\n© 2022 Lars Fröder (opa334)\n\nCredits:\n@LinusHenze: CoreTrust bug\n@zhuowei: CoreTrust bug writeup and cert\n@lunotech11: Some contributions\n@ProcursusTeam: uicache and ldid build\n@cstar_ow: uicache\n@saurik: ldid", getTrollStoreVersion()] forKey:@"footerText"];
[_specifiers addObject:otherGroupSpecifier]; [_specifiers addObject:otherGroupSpecifier];
// Uninstall TrollStore // Uninstall TrollStore

View File

@ -1,6 +1,6 @@
Package: com.opa334.trollstore Package: com.opa334.trollstore
Name: TrollStore Name: TrollStore
Version: 1.0.3 Version: 1.0.7
Architecture: iphoneos-arm Architecture: iphoneos-arm
Description: An awesome application! Description: An awesome application!
Maintainer: opa334 Maintainer: opa334

View File

@ -30,5 +30,7 @@
<true/> <true/>
<key>com.apple.private.uninstall.deletion</key> <key>com.apple.private.uninstall.deletion</key>
<true/> <true/>
<key>com.apple.private.security.storage.MobileDocuments</key>
<true/>
</dict> </dict>
</plist> </plist>