This commit is contained in:
opa334 2022-10-31 23:39:28 +01:00
parent 97726b53aa
commit 636419ee53
9 changed files with 76 additions and 134 deletions

View File

@ -157,17 +157,7 @@ When your app is not sandboxed, you can spawn other binaries using posix_spawn,
<true/> <true/>
``` ```
Because a root binary needs special permissions, you need to specify all your root binaries in the Info.plist of your application like so: You can also add your own binaries into your app bundle.
```
<key>TSRootBinaries</key>
<array>
<string>roothelper1</string>
<string>some/nested/roothelper</string>
</array>
```
Note: The paths in the TSRootBinaries array are relative to the location of the Info.plist, you can also include this key in other bundles such as app plugins.
Afterwards you can use the [spawnRoot function in TSUtil.m](./Shared/TSUtil.m#L74) to spawn the binary as root. Afterwards you can use the [spawnRoot function in TSUtil.m](./Shared/TSUtil.m#L74) to spawn the binary as root.

View File

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

View File

@ -8,6 +8,8 @@
#import <objc/runtime.h> #import <objc/runtime.h>
#import <TSUtil.h> #import <TSUtil.h>
#import <sys/utsname.h> #import <sys/utsname.h>
#import <mach-o/loader.h>
#import <mach-o/fat.h>
#import <SpringBoardServices/SpringBoardServices.h> #import <SpringBoardServices/SpringBoardServices.h>
#import <Security/Security.h> #import <Security/Security.h>
@ -107,6 +109,51 @@ NSString* appPathForAppId(NSString* appId)
return nil; return nil;
} }
BOOL isMachoFile(NSString* filePath)
{
FILE* file = fopen(filePath.UTF8String, "r");
if(!file) return NO;
fseek(file, 0, SEEK_SET);
uint32_t magic;
fread(&magic, sizeof(uint32_t), 1, file);
fclose(file);
return magic == FAT_MAGIC || magic == FAT_CIGAM || magic == MH_MAGIC_64 || magic == MH_CIGAM_64;
}
void fixPermissionsOfAppBundle(NSString* appBundlePath)
{
// Apply correct permissions (First run, set everything to 644, owner 33)
NSURL* fileURL;
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appBundlePath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
while(fileURL = [enumerator nextObject])
{
NSString* filePath = fileURL.path;
chown(filePath.UTF8String, 33, 33);
chmod(filePath.UTF8String, 0644);
}
// Apply correct permissions (Second run, set executables and directories to 0755)
enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appBundlePath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
while(fileURL = [enumerator nextObject])
{
NSString* filePath = fileURL.path;
BOOL isDir;
[[NSFileManager defaultManager] fileExistsAtPath:fileURL.path isDirectory:&isDir];
if(isDir || isMachoFile(filePath))
{
chmod(filePath.UTF8String, 0755);
}
}
// Set .app directory permissions too
chmod(appBundlePath.UTF8String, 0755);
chown(appBundlePath.UTF8String, 33, 33);
}
void installLdid(NSString* ldidToCopyPath) void installLdid(NSString* ldidToCopyPath)
{ {
if(![[NSFileManager defaultManager] fileExistsAtPath:ldidToCopyPath]) return; if(![[NSFileManager defaultManager] fileExistsAtPath:ldidToCopyPath]) return;
@ -386,25 +433,9 @@ int signApp(NSString* appPath)
while(fileURL = [enumerator nextObject]) while(fileURL = [enumerator nextObject])
{ {
NSString* filePath = fileURL.path; NSString* filePath = fileURL.path;
if(isMachoFile(filePath))
BOOL isDir;
[[NSFileManager defaultManager] fileExistsAtPath:fileURL.path isDirectory:&isDir];
if([filePath.lastPathComponent isEqualToString:@"Info.plist"])
{ {
NSDictionary* infoDictionary = [NSDictionary dictionaryWithContentsOfFile:filePath]; storedEntitlements[filePath] = dumpEntitlementsFromBinaryAtPath(filePath);
NSArray* tsRootBinaries = infoDictionary[@"TSRootBinaries"];
if(tsRootBinaries && [tsRootBinaries isKindOfClass:[NSArray class]])
{
for(NSString* rootBinary in tsRootBinaries)
{
if([rootBinary isKindOfClass:[NSString class]])
{
NSString* rootBinaryPath = [[filePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:rootBinary];
storedEntitlements[rootBinaryPath] = dumpEntitlementsFromBinaryAtPath(rootBinaryPath);
}
}
}
} }
} }
@ -413,11 +444,15 @@ int signApp(NSString* appPath)
[storedEntitlements enumerateKeysAndObjectsUsingBlock:^(NSString* binaryPath, NSDictionary* entitlements, BOOL* stop) [storedEntitlements enumerateKeysAndObjectsUsingBlock:^(NSString* binaryPath, NSDictionary* entitlements, BOOL* stop)
{ {
NSString* tmpEntitlementPlistPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ent.xml"]; NSDictionary* newEntitlements = dumpEntitlementsFromBinaryAtPath(binaryPath);
[entitlements writeToURL:[NSURL fileURLWithPath:tmpEntitlementPlistPath] error:nil]; if(!newEntitlements || ![newEntitlements isEqualToDictionary:entitlements])
NSString* tmpEntitlementArg = [@"-S" stringByAppendingString:tmpEntitlementPlistPath]; {
runLdid(@[tmpEntitlementArg, certArg, binaryPath], nil, nil); NSString* tmpEntitlementPlistPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ent.xml"];
[[NSFileManager defaultManager] removeItemAtPath:tmpEntitlementPlistPath error:nil]; [entitlements writeToURL:[NSURL fileURLWithPath:tmpEntitlementPlistPath] error:nil];
NSString* tmpEntitlementArg = [@"-S" stringByAppendingString:tmpEntitlementPlistPath];
runLdid(@[tmpEntitlementArg, certArg, binaryPath], nil, nil);
[[NSFileManager defaultManager] removeItemAtPath:tmpEntitlementPlistPath error:nil];
}
}]; }];
} }
@ -554,68 +589,7 @@ int installApp(NSString* appPath, BOOL sign, BOOL force)
return 177; return 177;
} }
// Apply correct permissions (First run, set everything to 644, owner 33) fixPermissionsOfAppBundle(appPath);
NSURL* fileURL;
NSDirectoryEnumerator *enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appPath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
while(fileURL = [enumerator nextObject])
{
NSString* filePath = fileURL.path;
chown(filePath.UTF8String, 33, 33);
chmod(filePath.UTF8String, 0644);
NSLog(@"[installApp] setting %@ to chown(33,33) chmod(0644)", filePath);
}
// Apply correct permissions (Second run, set executables and directories to 0755)
enumerator = [[NSFileManager defaultManager] enumeratorAtURL:[NSURL fileURLWithPath:appPath] includingPropertiesForKeys:nil options:0 errorHandler:nil];
while(fileURL = [enumerator nextObject])
{
NSString* filePath = fileURL.path;
BOOL isDir;
[[NSFileManager defaultManager] fileExistsAtPath:fileURL.path isDirectory:&isDir];
if([filePath.lastPathComponent isEqualToString:@"Info.plist"])
{
NSDictionary* infoDictionary = [NSDictionary dictionaryWithContentsOfFile:filePath];
NSString* executable = infoDictionary[@"CFBundleExecutable"];
if(executable && [executable isKindOfClass:[NSString class]])
{
NSString* executablePath = [[filePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:executable];
chmod(executablePath.UTF8String, 0755);
NSLog(@"[installApp] applied permissions for bundle executable %@", executablePath);
}
NSArray* tsRootBinaries = infoDictionary[@"TSRootBinaries"];
if(tsRootBinaries && [tsRootBinaries isKindOfClass:[NSArray class]])
{
for(NSString* rootBinary in tsRootBinaries)
{
if([rootBinary isKindOfClass:[NSString class]])
{
NSString* rootBinaryPath = [[filePath stringByDeletingLastPathComponent] stringByAppendingPathComponent:rootBinary];
if([[NSFileManager defaultManager] fileExistsAtPath:rootBinaryPath])
{
chmod(rootBinaryPath.UTF8String, 0755);
chown(rootBinaryPath.UTF8String, 0, 0);
NSLog(@"[installApp] applied permissions for root binary %@", rootBinaryPath);
}
}
}
}
}
else if(!isDir && [filePath.pathExtension isEqualToString:@"dylib"])
{
chmod(filePath.UTF8String, 0755);
}
else if(isDir)
{
// apparently all dirs are writable by default
chmod(filePath.UTF8String, 0755);
}
}
// Set .app directory permissions too
chmod(appPath.UTF8String, 0755);
chown(appPath.UTF8String, 33, 33);
// Wipe old version if needed // Wipe old version if needed
if(existed) if(existed)

View File

@ -24,9 +24,10 @@
- (BOOL)registerApplicationDictionary:(NSDictionary*)dict; - (BOOL)registerApplicationDictionary:(NSDictionary*)dict;
- (BOOL)unregisterApplication:(id)arg1; - (BOOL)unregisterApplication:(id)arg1;
- (BOOL)_LSPrivateRebuildApplicationDatabasesForSystemApps:(BOOL)arg1 internal:(BOOL)arg2 user:(BOOL)arg3; - (BOOL)_LSPrivateRebuildApplicationDatabasesForSystemApps:(BOOL)arg1 internal:(BOOL)arg2 user:(BOOL)arg3;
- (BOOL)uninstallApplication:(NSString*)arg1 withOptions:(id)arg2;
- (BOOL)openApplicationWithBundleID:(NSString *)arg1 ; - (BOOL)openApplicationWithBundleID:(NSString *)arg1 ;
- (void)enumerateApplicationsOfType:(NSUInteger)type block:(void (^)(LSApplicationProxy*))block; - (void)enumerateApplicationsOfType:(NSUInteger)type block:(void (^)(LSApplicationProxy*))block;
- (BOOL)installApplication:(NSString*)pathToExtractedApp withOptions:(NSDictionary*)options;
- (BOOL)uninstallApplication:(NSString*)appId withOptions:(NSDictionary*)options;
@end @end
@interface LSEnumerator : NSEnumerator @interface LSEnumerator : NSEnumerator

View File

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

View File

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

View File

@ -50,7 +50,7 @@
<string>iPhoneOS</string> <string>iPhoneOS</string>
</array> </array>
<key>CFBundleVersion</key> <key>CFBundleVersion</key>
<string>1.3.2</string> <string>1.3.3</string>
<key>LSRequiresIPhoneOS</key> <key>LSRequiresIPhoneOS</key>
<true/> <true/>
<key>UIDeviceFamily</key> <key>UIDeviceFamily</key>
@ -188,10 +188,5 @@
</array> </array>
<key>LSSupportsOpeningDocumentsInPlace</key> <key>LSSupportsOpeningDocumentsInPlace</key>
<false/> <false/>
<key>TSRootBinaries</key>
<array>
<string>trollstorehelper</string>
<string>ldid</string>
</array>
</dict> </dict>
</plist> </plist>

View File

@ -766,20 +766,6 @@ extern UIImage* imageWithSize(UIImage* image, CGSize size);
NSString* version = [self versionString]; NSString* version = [self versionString];
NSString* sizeString = [self sizeString]; NSString* sizeString = [self sizeString];
// Check if any bundle contains a root binary
__block BOOL containsRootBinary = NO;
[self enumerateAllInfoDictionaries:^(NSString *key, NSObject *value, BOOL *stop) {
if([key isEqualToString:@"TSRootBinaries"])
{
NSArray* valueArr = (NSArray*)value;
if([valueArr isKindOfClass:NSArray.class])
{
containsRootBinary = valueArr.count;
if(containsRootBinary) *stop = YES;
}
}
}];
// Check if any bundles main binary runs unsandboxed // Check if any bundles main binary runs unsandboxed
__block BOOL isUnsandboxed = NO; __block BOOL isUnsandboxed = NO;
[self enumerateAllEntitlements:^(NSString *key, NSObject *value, BOOL *stop) { [self enumerateAllEntitlements:^(NSString *key, NSObject *value, BOOL *stop) {
@ -811,7 +797,7 @@ extern UIImage* imageWithSize(UIImage* image, CGSize size);
}]; }];
// Check if any bundles main binary can spawn an external binary // Check if any bundles main binary can spawn an external binary
__block BOOL canSpawnBinaries = NO; __block BOOL isPlatformApplication = NO;
[self enumerateAllEntitlements:^(NSString *key, NSObject *value, BOOL *stop) [self enumerateAllEntitlements:^(NSString *key, NSObject *value, BOOL *stop)
{ {
if([key isEqualToString:@"platform-application"]) if([key isEqualToString:@"platform-application"])
@ -819,8 +805,8 @@ extern UIImage* imageWithSize(UIImage* image, CGSize size);
NSNumber* valueNum = (NSNumber*)value; NSNumber* valueNum = (NSNumber*)value;
if(valueNum && [valueNum isKindOfClass:NSNumber.class]) if(valueNum && [valueNum isKindOfClass:NSNumber.class])
{ {
canSpawnBinaries = valueNum.boolValue; isPlatformApplication = valueNum.boolValue;
if(canSpawnBinaries) *stop = YES; if(isPlatformApplication) *stop = YES;
} }
} }
}]; }];
@ -1072,15 +1058,11 @@ extern UIImage* imageWithSize(UIImage* image, CGSize size);
} }
[description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\nCapabilities" attributes:headerAttributes]]; [description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\nCapabilities" attributes:headerAttributes]];
if(containsRootBinary && canSpawnBinaries && hasPersonaMngmt) if(isPlatformApplication && isUnsandboxed && hasPersonaMngmt)
{ {
[description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nThe app can spawn its own embedded binaries with root privileges." attributes:bodyDangerAttributes]]; [description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nThe app can spawn its own embedded binaries with root privileges." attributes:bodyDangerAttributes]];
} }
else if(canSpawnBinaries && hasPersonaMngmt) else if(isPlatformApplication && isUnsandboxed)
{
[description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nThe app can spawn arbitary binaries as root, but does not contain any such binaries by itself." attributes:bodyWarningAttributes]];
}
else if(canSpawnBinaries)
{ {
[description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nThe app can spawn arbitary binaries as the mobile user." attributes:bodyWarningAttributes]]; [description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nThe app can spawn arbitary binaries as the mobile user." attributes:bodyWarningAttributes]];
} }
@ -1092,15 +1074,15 @@ extern UIImage* imageWithSize(UIImage* image, CGSize size);
if(allowedTccServices.count) if(allowedTccServices.count)
{ {
[description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\nPrivacy" attributes:headerAttributes]]; [description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\nPrivacy" attributes:headerAttributes]];
[description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nThe app can access the following services without asking for permission:\n" attributes:bodyDangerAttributes]]; [description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nThe app can access the following services without asking for permission:\n" attributes:bodyWarningAttributes]];
[description appendAttributedString:[[NSAttributedString alloc] initWithString:[NSListFormatter localizedStringByJoiningStrings:[allowedTccServices allObjects]] attributes:bodyAttributes]]; [description appendAttributedString:[[NSAttributedString alloc] initWithString:[NSListFormatter localizedStringByJoiningStrings:[allowedTccServices allObjects]] attributes:bodyWarningAttributes]];
} }
if (allowedMGKeys.count) if (allowedMGKeys.count)
{ {
[description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\nDevice Info" attributes:headerAttributes]]; [description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\n\nDevice Info" attributes:headerAttributes]];
[description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nThe app can access protected information about this device.\n" attributes:bodyWarningAttributes]]; [description appendAttributedString:[[NSAttributedString alloc] initWithString:@"\nThe app can access protected information about this device:\n" attributes:bodyWarningAttributes]];
[description appendAttributedString:[[NSAttributedString alloc] initWithString:[NSListFormatter localizedStringByJoiningStrings:[allowedMGKeys allObjects]] attributes:bodyAttributes]]; [description appendAttributedString:[[NSAttributedString alloc] initWithString:[NSListFormatter localizedStringByJoiningStrings:[allowedMGKeys allObjects]] attributes:bodyWarningAttributes]];
} }
if(unrestrictedContainerAccess || accessibleContainers.count) if(unrestrictedContainerAccess || accessibleContainers.count)

View File

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