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/>
```
Because a root binary needs special permissions, you need to specify all your root binaries in the Info.plist of your application like so:
```
<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.
You can also add your own binaries into your app bundle.
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
Name: trollstoreroothelper
Version: 1.3.2
Version: 1.3.3
Architecture: iphoneos-arm
Description: An awesome tool of some sort!!
Maintainer: opa334

View File

@ -8,6 +8,8 @@
#import <objc/runtime.h>
#import <TSUtil.h>
#import <sys/utsname.h>
#import <mach-o/loader.h>
#import <mach-o/fat.h>
#import <SpringBoardServices/SpringBoardServices.h>
#import <Security/Security.h>
@ -107,6 +109,51 @@ NSString* appPathForAppId(NSString* appId)
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)
{
if(![[NSFileManager defaultManager] fileExistsAtPath:ldidToCopyPath]) return;
@ -386,25 +433,9 @@ int signApp(NSString* appPath)
while(fileURL = [enumerator nextObject])
{
NSString* filePath = fileURL.path;
BOOL isDir;
[[NSFileManager defaultManager] fileExistsAtPath:fileURL.path isDirectory:&isDir];
if([filePath.lastPathComponent isEqualToString:@"Info.plist"])
if(isMachoFile(filePath))
{
NSDictionary* infoDictionary = [NSDictionary dictionaryWithContentsOfFile: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);
}
}
}
storedEntitlements[filePath] = dumpEntitlementsFromBinaryAtPath(filePath);
}
}
@ -413,11 +444,15 @@ int signApp(NSString* appPath)
[storedEntitlements enumerateKeysAndObjectsUsingBlock:^(NSString* binaryPath, NSDictionary* entitlements, BOOL* stop)
{
NSString* tmpEntitlementPlistPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ent.xml"];
[entitlements writeToURL:[NSURL fileURLWithPath:tmpEntitlementPlistPath] error:nil];
NSString* tmpEntitlementArg = [@"-S" stringByAppendingString:tmpEntitlementPlistPath];
runLdid(@[tmpEntitlementArg, certArg, binaryPath], nil, nil);
[[NSFileManager defaultManager] removeItemAtPath:tmpEntitlementPlistPath error:nil];
NSDictionary* newEntitlements = dumpEntitlementsFromBinaryAtPath(binaryPath);
if(!newEntitlements || ![newEntitlements isEqualToDictionary:entitlements])
{
NSString* tmpEntitlementPlistPath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"ent.xml"];
[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;
}
// Apply correct permissions (First run, set everything to 644, owner 33)
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);
fixPermissionsOfAppBundle(appPath);
// Wipe old version if needed
if(existed)

View File

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

View File

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

View File

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

View File

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

View File

@ -766,20 +766,6 @@ extern UIImage* imageWithSize(UIImage* image, CGSize size);
NSString* version = [self versionString];
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
__block BOOL isUnsandboxed = NO;
[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
__block BOOL canSpawnBinaries = NO;
__block BOOL isPlatformApplication = NO;
[self enumerateAllEntitlements:^(NSString *key, NSObject *value, BOOL *stop)
{
if([key isEqualToString:@"platform-application"])
@ -819,8 +805,8 @@ extern UIImage* imageWithSize(UIImage* image, CGSize size);
NSNumber* valueNum = (NSNumber*)value;
if(valueNum && [valueNum isKindOfClass:NSNumber.class])
{
canSpawnBinaries = valueNum.boolValue;
if(canSpawnBinaries) *stop = YES;
isPlatformApplication = valueNum.boolValue;
if(isPlatformApplication) *stop = YES;
}
}
}];
@ -1072,15 +1058,11 @@ extern UIImage* imageWithSize(UIImage* image, CGSize size);
}
[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]];
}
else if(canSpawnBinaries && hasPersonaMngmt)
{
[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)
else if(isPlatformApplication && isUnsandboxed)
{
[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)
{
[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:[NSListFormatter localizedStringByJoiningStrings:[allowedTccServices allObjects]] attributes:bodyAttributes]];
[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:bodyWarningAttributes]];
}
if (allowedMGKeys.count)
{
[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:[NSListFormatter localizedStringByJoiningStrings:[allowedMGKeys allObjects]] attributes:bodyAttributes]];
[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:bodyWarningAttributes]];
}
if(unrestrictedContainerAccess || accessibleContainers.count)

View File

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