├── .gitignore ├── Entitlements.h ├── README.md └── main.m /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | -------------------------------------------------------------------------------- /Entitlements.h: -------------------------------------------------------------------------------- 1 | // 2 | // Entitlements.h 3 | // printents 4 | // 5 | // Created by Serena on 18/12/2022 6 | // 7 | 8 | 9 | #ifndef Entitlements_h 10 | #define Entitlements_h 11 | 12 | // Reverse engineered from Apple's AppSandbox.framework 13 | @interface AppSandboxEntitlements : NSObject 14 | + (AppSandboxEntitlements *)entitlementsForCodeAtURL:(NSURL *)appURL error:(NSError **)error; 15 | - (NSDictionary *)allEntitlements; 16 | @end 17 | 18 | #endif /* Entitlements_h */ 19 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # printents 2 | 3 | A CommandLine tool that prints the entitlements of an .app bundle or any executable on device, demonstrating the AppSandbox private framework. 4 | usage: `printents `, ie `printents /Application/Safari.app` or `printents /usr/libexec/locationd --format json` 5 | 6 | ## Compiling 7 | To compile, run `clang main.m -F/System/Library/PrivateFrameworks -framework AppSandbox -framework Foundation -fobjc-arc` 8 | ## Options 9 | `-f, --format`: speciifes the format of the output, of which there is 3: 10 | 11 | - `NSDictionary` 12 | - `JSON` 13 | - `XML` 14 | 15 | -------------------------------------------------------------------------------- /main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // printents 4 | // 5 | // Created by Serena on 18/12/2022 6 | // 7 | // clang main.m -F/System/Library/PrivateFrameworks -framework AppSandbox -framework Foundation -fobjc-arc 8 | 9 | @import Foundation; 10 | #include 11 | #include "Entitlements.h" 12 | 13 | #if !__has_feature(objc_arc) 14 | #error ARC is needed, please build with -fobjc-arc 15 | #endif 16 | 17 | typedef NS_ENUM(NSUInteger, EntitlementsOutputFormatType) { 18 | EntitlementsOutputFormatTypeJSON, 19 | EntitlementsOutputFormatTypeXML, 20 | EntitlementsOutputFormatTypeNSDictionary, 21 | }; 22 | 23 | void print_usage(char **argv) { 24 | printf("usage: %s [OPTIONS]\n", argv[0]); 25 | printf("Options: \n"); 26 | 27 | printf("\t-f, --format , where output-format is one of:\n"); 28 | printf("\t\t json\n"); 29 | printf("\t\t xml\n"); 30 | printf("\t\t nsdictionary\n"); 31 | 32 | printf("examples:\n"); 33 | printf("\t\t %s /Applications/Antoine.app\n", argv[0]); 34 | printf("\t\t %s --format json /Applications/Xcode.app\n", argv[0]); 35 | } 36 | 37 | #define CHECK_ERROR(condition, message, ...) \ 38 | if (condition) { \ 39 | fprintf(stderr, message, ##__VA_ARGS__); \ 40 | return -1; \ 41 | } 42 | 43 | int printFromSerializedData(NSDictionary *entsDictionary, EntitlementsOutputFormatType type) { 44 | NSError *error; 45 | NSData *data; 46 | 47 | switch (type) { 48 | case EntitlementsOutputFormatTypeJSON: 49 | data = [NSJSONSerialization dataWithJSONObject:entsDictionary options: NSJSONWritingPrettyPrinted | NSJSONWritingSortedKeys | NSJSONWritingWithoutEscapingSlashes error:&error]; 50 | break; 51 | case EntitlementsOutputFormatTypeXML: 52 | data = [NSPropertyListSerialization dataWithPropertyList:entsDictionary format:NSPropertyListXMLFormat_v1_0 options:0 error:&error]; 53 | break; 54 | case EntitlementsOutputFormatTypeNSDictionary: break; // never supposed to be here anyways 55 | } 56 | 57 | const char *errorCString = error.localizedDescription.UTF8String; 58 | CHECK_ERROR(error || !data, "Error while converting dictionary to JSON: %s\n", errorCString ? errorCString : "Unknown Error") 59 | 60 | NSString *string = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 61 | printf("%s\n", string.UTF8String); 62 | return 0; 63 | } 64 | 65 | int main(int argc, char **argv) { 66 | if (argc < 2) { 67 | print_usage(argv); 68 | return -1; 69 | } 70 | 71 | EntitlementsOutputFormatType outputFormat = EntitlementsOutputFormatTypeXML; 72 | int opt; 73 | 74 | while (true) { 75 | static struct option long_options[] = { 76 | {"format", required_argument, 0, 'f'}, 77 | {0, 0, 0, 0} 78 | }; 79 | 80 | opt = getopt_long (argc, argv, "f:", long_options, NULL); 81 | 82 | if (opt == -1) break; 83 | 84 | switch (opt) { 85 | case 'f': { 86 | if (!strcmp(optarg, "json")) outputFormat = EntitlementsOutputFormatTypeJSON; 87 | else if (!strcmp(optarg, "xml")) outputFormat = EntitlementsOutputFormatTypeXML; 88 | else if (!strcmp(optarg, "nsdictionary")) outputFormat = EntitlementsOutputFormatTypeNSDictionary; 89 | break; 90 | } 91 | default: 92 | printf("unknown flag / option\n"); 93 | return -1; 94 | } 95 | } 96 | 97 | if (!(optind < argc)) { 98 | printf("Error: didn't specify path to print entitlements of\n"); 99 | print_usage(argv); 100 | return -1; 101 | } 102 | 103 | NSURL *itemURL = [NSURL fileURLWithPath: @(argv[optind++])]; 104 | NSError *error; 105 | 106 | AppSandboxEntitlements *ents = [AppSandboxEntitlements entitlementsForCodeAtURL:itemURL error:&error]; 107 | CHECK_ERROR(error, "Error while fetching entitlements: %s\n", error.localizedDescription.UTF8String) 108 | NSDictionary *entsDictionary = ents.allEntitlements; 109 | 110 | if (outputFormat == EntitlementsOutputFormatTypeNSDictionary) 111 | printf("%s\n", entsDictionary.description.UTF8String); 112 | else 113 | printFromSerializedData(entsDictionary, outputFormat); 114 | 115 | return 0; 116 | } 117 | --------------------------------------------------------------------------------