mirror of https://github.com/opa334/TrollStore.git
Merge branch 'opa334:main' into m1
This commit is contained in:
commit
67d8496962
|
@ -1,6 +1,6 @@
|
||||||
Package: com.opa334.trollstoreroothelper
|
Package: com.opa334.trollstoreroothelper
|
||||||
Name: trollstoreroothelper
|
Name: trollstoreroothelper
|
||||||
Version: 1.0.5
|
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
|
||||||
|
|
398
Helper/main.m
398
Helper/main.m
|
@ -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,124 +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);
|
|
||||||
|
|
||||||
uint32_t archOffset = 0;
|
|
||||||
|
|
||||||
// Get arch offset if FAT binary
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
archOffset = s32(fatArch.offset, swpFat);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fseek(machoFile,archOffset,SEEK_SET);
|
CFURLRef binaryURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, (__bridge CFStringRef)binaryPath, kCFURLPOSIXPathStyle, false);
|
||||||
fread(&header,sizeof(header),1,machoFile);
|
if(binaryURL == NULL)
|
||||||
|
|
||||||
if(header.magic == MH_MAGIC_UNIVERSAL || header.magic == MH_CIGAM_UNIVERSAL)
|
|
||||||
{
|
{
|
||||||
BOOL swp = header.magic == MH_CIGAM_UNIVERSAL;
|
NSLog(@"[getStaticCodeRef] failed to get URL to binary %@", binaryPath);
|
||||||
// This code is cursed, don't stare at it too long or it will stare back at you
|
return NULL;
|
||||||
uint32_t offset = archOffset + sizeof(header);
|
|
||||||
for(int c = 0; c < s32(header.ncmds, swp); c++)
|
|
||||||
{
|
|
||||||
fseek(machoFile,offset,SEEK_SET);
|
|
||||||
struct load_command cmd;
|
|
||||||
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 = archOffset + 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) // YES starting here everything is swapped no matter if CIGAM or MAGIC...
|
|
||||||
{
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset += cmd.cmdsize;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fclose(machoFile);
|
SecStaticCodeRef codeRef = NULL;
|
||||||
|
OSStatus result;
|
||||||
NSData* entitlementsNSData = nil;
|
|
||||||
|
result = SecStaticCodeCreateWithPathAndAttributes(binaryURL, kSecCSDefaultFlags, NULL, &codeRef);
|
||||||
if(entitlementsData)
|
|
||||||
|
CFRelease(binaryURL);
|
||||||
|
|
||||||
|
if(result != errSecSuccess)
|
||||||
{
|
{
|
||||||
entitlementsNSData = [NSData dataWithBytes:entitlementsData length:entitlementsLength];
|
NSLog(@"[getStaticCodeRef] failed to create static code for binary %@", binaryPath);
|
||||||
free(entitlementsData);
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return codeRef;
|
||||||
|
}
|
||||||
|
|
||||||
if(entitlementsNSData)
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil;
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
@ -346,13 +420,45 @@ BOOL signApp(NSString* appPath, NSError** error)
|
||||||
NSString* executablePath = [appPath stringByAppendingPathComponent:executable];
|
NSString* executablePath = [appPath stringByAppendingPathComponent:executable];
|
||||||
|
|
||||||
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...");
|
||||||
|
@ -394,6 +500,7 @@ void applyPatchesToInfoDictionary(NSString* appPath)
|
||||||
// 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);
|
||||||
|
@ -405,8 +512,7 @@ int installApp(NSString* appPath, BOOL sign, BOOL force, NSError** error)
|
||||||
|
|
||||||
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;
|
||||||
|
|
|
@ -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;
|
||||||
|
@ -247,4 +253,4 @@ void registerPath(char* cPath, int unregister)
|
||||||
NSLog(@"Error: Unable to unregister %@", path);
|
NSLog(@"Error: Unable to unregister %@", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
<string>iPhoneOS</string>
|
<string>iPhoneOS</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0.5</string>
|
<string>1.0.7</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIDeviceFamily</key>
|
<key>UIDeviceFamily</key>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Package: com.opa334.trollstorehelper
|
Package: com.opa334.trollstorehelper
|
||||||
Name: TrollStore Helper
|
Name: TrollStore Helper
|
||||||
Version: 1.0.5
|
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
|
||||||
|
|
|
@ -50,7 +50,7 @@
|
||||||
<string>iPhoneOS</string>
|
<string>iPhoneOS</string>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0.5</string>
|
<string>1.0.7</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIDeviceFamily</key>
|
<key>UIDeviceFamily</key>
|
||||||
|
|
|
@ -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}];
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
Package: com.opa334.trollstore
|
Package: com.opa334.trollstore
|
||||||
Name: TrollStore
|
Name: TrollStore
|
||||||
Version: 1.0.5
|
Version: 1.0.7
|
||||||
Architecture: iphoneos-arm
|
Architecture: iphoneos-arm
|
||||||
Description: An awesome application!
|
Description: An awesome application!
|
||||||
Maintainer: opa334
|
Maintainer: opa334
|
||||||
|
|
Loading…
Reference in New Issue