mirror of https://github.com/opa334/TrollStore.git
1.0.3
This commit is contained in:
parent
771fbb6408
commit
e2fd9515ad
164
Helper/main.m
164
Helper/main.m
|
@ -8,9 +8,54 @@
|
||||||
#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 <SpringBoardServices/SpringBoardServices.h>
|
#import <SpringBoardServices/SpringBoardServices.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);
|
||||||
@interface SBSHomeScreenService : NSObject
|
@interface SBSHomeScreenService : NSObject
|
||||||
- (void)reloadIcons;
|
- (void)reloadIcons;
|
||||||
|
@ -176,38 +221,111 @@ int runLdid(NSArray* args, NSString** output, NSString** errorOutput)
|
||||||
return WEXITSTATUS(status);
|
return WEXITSTATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* dumpEntitlements(NSString* binaryPath)
|
NSDictionary* dumpEntitlements(NSString* binaryPath)
|
||||||
{
|
{
|
||||||
NSString* output;
|
char* entitlementsData = NULL;
|
||||||
NSString* errorOutput;
|
uint32_t entitlementsLength = 0;
|
||||||
|
|
||||||
int ldidRet = runLdid(@[@"-e", binaryPath], &output, &errorOutput);
|
FILE* machoFile = fopen(binaryPath.UTF8String, "rb");
|
||||||
|
struct mach_header_universal header;
|
||||||
|
fread(&header,sizeof(header),1,machoFile);
|
||||||
|
|
||||||
NSLog(@"entitlements dump exited with status %d", ldidRet);
|
if(header.magic == FAT_MAGIC || header.magic == FAT_CIGAM)
|
||||||
|
{
|
||||||
|
fseek(machoFile,0,SEEK_SET);
|
||||||
|
|
||||||
NSLog(@"- dump error output start -");
|
struct fat_header fatHeader;
|
||||||
|
fread(&fatHeader,sizeof(fatHeader),1,machoFile);
|
||||||
|
|
||||||
printMultilineNSString(errorOutput);
|
BOOL swpFat = fatHeader.magic == FAT_CIGAM;
|
||||||
|
|
||||||
NSLog(@"- dump error output end -");
|
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);
|
||||||
|
|
||||||
NSLog(@"- dumped entitlements output start -");
|
if(s32(fatArch.cputype, swpFat) != CPU_TYPE_ARM64)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
printMultilineNSString(output);
|
fseek(machoFile,s32(fatArch.offset, swpFat),SEEK_SET);
|
||||||
|
struct mach_header_universal header;
|
||||||
|
fread(&header,sizeof(header),1,machoFile);
|
||||||
|
|
||||||
NSLog(@"- dumped entitlements output end -");
|
BOOL swp = header.magic == MH_CIGAM_UNIVERSAL;
|
||||||
|
|
||||||
return output;
|
// 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);
|
||||||
|
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 = 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NSDictionary* dumpEntitlementsDict(NSString* binaryPath)
|
break;
|
||||||
{
|
}
|
||||||
NSString* entitlementsString = dumpEntitlements(binaryPath);
|
|
||||||
NSData* plistData = [entitlementsString dataUsingEncoding:NSUTF8StringEncoding];
|
offset += cmd.cmdsize;
|
||||||
NSError *error;
|
}
|
||||||
NSPropertyListFormat format;
|
}
|
||||||
NSDictionary* plist = [NSPropertyListSerialization propertyListWithData:plistData options:NSPropertyListImmutable format:&format error:&error];
|
}
|
||||||
return plist;
|
|
||||||
|
fclose(machoFile);
|
||||||
|
|
||||||
|
NSData* entitlementsNSData = nil;
|
||||||
|
|
||||||
|
if(entitlementsData)
|
||||||
|
{
|
||||||
|
entitlementsNSData = [NSData dataWithBytes:entitlementsData length:entitlementsLength];
|
||||||
|
free(entitlementsData);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(entitlementsNSData)
|
||||||
|
{
|
||||||
|
NSDictionary* plist = [NSPropertyListSerialization propertyListWithData:entitlementsNSData options:NSPropertyListImmutable format:nil error:nil];
|
||||||
|
NSLog(@"%@ dumped entitlements %@", binaryPath, plist);
|
||||||
|
return plist;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
NSLog(@"Failed to dump entitlements of %@... This is bad", binaryPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOL signApp(NSString* appPath, NSError** error)
|
BOOL signApp(NSString* appPath, NSError** error)
|
||||||
|
@ -227,8 +345,8 @@ BOOL signApp(NSString* appPath, NSError** error)
|
||||||
NSString* errorOutput;
|
NSString* errorOutput;
|
||||||
int ldidRet;
|
int ldidRet;
|
||||||
|
|
||||||
NSString* entitlements = dumpEntitlements(executablePath);
|
NSDictionary* entitlements = dumpEntitlements(executablePath);
|
||||||
if(entitlements.length == 0)
|
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...");
|
||||||
// app has no entitlements, sign with fallback entitlements
|
// app has no entitlements, sign with fallback entitlements
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
|
|
||||||
// uicache on steroids
|
// uicache on steroids
|
||||||
|
|
||||||
extern NSDictionary* dumpEntitlementsDict(NSString* binaryPath);
|
extern NSDictionary* dumpEntitlements(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 = dumpEntitlementsDict(appExecutablePath);
|
NSDictionary* entitlements = dumpEntitlements(appExecutablePath);
|
||||||
if(entitlements)
|
if(entitlements)
|
||||||
{
|
{
|
||||||
dictToRegister[@"Entitlements"] = entitlements;
|
dictToRegister[@"Entitlements"] = entitlements;
|
||||||
|
@ -185,7 +185,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 = dumpEntitlementsDict(pluginExecutablePath);
|
NSDictionary* pluginEntitlements = dumpEntitlements(pluginExecutablePath);
|
||||||
if(pluginEntitlements)
|
if(pluginEntitlements)
|
||||||
{
|
{
|
||||||
pluginDict[@"Entitlements"] = pluginEntitlements;
|
pluginDict[@"Entitlements"] = pluginEntitlements;
|
||||||
|
|
|
@ -239,6 +239,8 @@ int writeRemountPrivatePreboot(void)
|
||||||
|
|
||||||
[self updateStatus:@"Done!"];
|
[self updateStatus:@"Done!"];
|
||||||
|
|
||||||
|
NSLog(@"%@", helperOutput);
|
||||||
|
|
||||||
// Print installed message
|
// Print installed message
|
||||||
if(ret == 0)
|
if(ret == 0)
|
||||||
{
|
{
|
||||||
|
|
|
@ -76,6 +76,19 @@
|
||||||
[refreshAppRegistrationsSpecifier setProperty:@YES forKey:@"enabled"];
|
[refreshAppRegistrationsSpecifier setProperty:@YES forKey:@"enabled"];
|
||||||
refreshAppRegistrationsSpecifier.buttonAction = @selector(refreshAppRegistrations);
|
refreshAppRegistrationsSpecifier.buttonAction = @selector(refreshAppRegistrations);
|
||||||
[_specifiers addObject:refreshAppRegistrationsSpecifier];
|
[_specifiers addObject:refreshAppRegistrationsSpecifier];
|
||||||
|
|
||||||
|
PSSpecifier* uninstallTrollStoreSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Uninstall TrollStore"
|
||||||
|
target:self
|
||||||
|
set:nil
|
||||||
|
get:nil
|
||||||
|
detail:nil
|
||||||
|
cell:PSButtonCell
|
||||||
|
edit:nil];
|
||||||
|
uninstallTrollStoreSpecifier.identifier = @"uninstallTrollStore";
|
||||||
|
[uninstallTrollStoreSpecifier setProperty:@YES forKey:@"enabled"];
|
||||||
|
[uninstallTrollStoreSpecifier setProperty:NSClassFromString(@"PSDeleteButtonCell") forKey:@"cellClass"];
|
||||||
|
uninstallTrollStoreSpecifier.buttonAction = @selector(uninstallTrollStorePressed);
|
||||||
|
[_specifiers addObject:uninstallTrollStoreSpecifier];
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -201,6 +214,22 @@
|
||||||
[downloadTask resume];
|
[downloadTask resume];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)uninstallTrollStorePressed
|
||||||
|
{
|
||||||
|
UIAlertController* uninstallWarningAlert = [UIAlertController alertControllerWithTitle:@"Warning" message:@"About to uninstall TrollStore and all of the apps installed by it. Continue?" preferredStyle:UIAlertControllerStyleAlert];
|
||||||
|
|
||||||
|
UIAlertAction* cancelAction = [UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil];
|
||||||
|
[uninstallWarningAlert addAction:cancelAction];
|
||||||
|
|
||||||
|
UIAlertAction* continueAction = [UIAlertAction actionWithTitle:@"Continue" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action)
|
||||||
|
{
|
||||||
|
spawnRoot(helperPath(), @[@"uninstall-trollstore"]);
|
||||||
|
exit(0);
|
||||||
|
}];
|
||||||
|
[uninstallWarningAlert addAction:continueAction];
|
||||||
|
|
||||||
|
[self presentViewController:uninstallWarningAlert animated:YES completion:nil];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)uninstallPersistenceHelperPressed
|
- (void)uninstallPersistenceHelperPressed
|
||||||
{
|
{
|
||||||
|
|
|
@ -47,3 +47,19 @@ cd out
|
||||||
COPYFILE_DISABLE=1 tar -czvf TrollStore.tar ./TrollStore.app
|
COPYFILE_DISABLE=1 tar -czvf TrollStore.tar ./TrollStore.app
|
||||||
rm -rf ./TrollStore.app
|
rm -rf ./TrollStore.app
|
||||||
cd -
|
cd -
|
||||||
|
|
||||||
|
# Step five: compile installer
|
||||||
|
xcodebuild -project ../Installer/TrollInstaller/TrollInstaller.xcodeproj -scheme TrollInstaller -destination generic/platform=iOS -archivePath ./out/Installer.xcarchive archive
|
||||||
|
|
||||||
|
if [[ -f "./out/Installer.xcarchive/Products/Applications/TrollInstaller.app/embedded.mobileprovision" ]]; then
|
||||||
|
rm ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app/embedded.mobileprovision
|
||||||
|
fi
|
||||||
|
|
||||||
|
ldid -s ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app
|
||||||
|
mkdir ./out/Payload
|
||||||
|
mv ./out/Installer.xcarchive/Products/Applications/TrollInstaller.app ./out/Payload/TrollInstaller.app
|
||||||
|
cd out
|
||||||
|
zip -vr TrollInstaller.ipa Payload
|
||||||
|
cd -
|
||||||
|
rm -rf ./out/Payload
|
||||||
|
rm -rf ./out/Installer.xcarchive
|
Loading…
Reference in New Issue