diff --git a/App/ProcessMonitor.xcodeproj/project.pbxproj b/App/ProcessMonitor.xcodeproj/project.pbxproj index b3b4e29..dbd8329 100644 --- a/App/ProcessMonitor.xcodeproj/project.pbxproj +++ b/App/ProcessMonitor.xcodeproj/project.pbxproj @@ -3,7 +3,7 @@ archiveVersion = 1; classes = { }; - objectVersion = 50; + objectVersion = 54; objects = { /* Begin PBXBuildFile section */ @@ -113,7 +113,8 @@ CD38A8352358B410004EBB67 /* Project object */ = { isa = PBXProject; attributes = { - LastUpgradeCheck = 1220; + BuildIndependentTargetsInParallel = YES; + LastUpgradeCheck = 1500; ORGANIZATIONNAME = "Patrick Wardle"; TargetAttributes = { CD38A83C2358B410004EBB67 = { @@ -198,9 +199,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = dwarf; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -257,9 +260,11 @@ CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; COPY_PHASE_STRIP = NO; + DEAD_CODE_STRIPPING = YES; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu11; GCC_NO_COMMON_BLOCKS = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES; @@ -281,11 +286,12 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = ProcessMonitor/ProcessMonitor.entitlements; - CODE_SIGN_IDENTITY = "Developer ID Application"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1.5.0; - DEVELOPMENT_TEAM = VBG97UB4TA; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = ZK96P738ZR; ENABLE_HARDENED_RUNTIME = YES; HEADER_SEARCH_PATHS = ../Library/Release; INFOPLIST_FILE = ProcessMonitor/Info.plist; @@ -295,9 +301,9 @@ ); LIBRARY_SEARCH_PATHS = ../Library/Release; MARKETING_VERSION = 1.5.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.processmonitor"; + PRODUCT_BUNDLE_IDENTIFIER = "vin.je.com.objective-see.processmonitor"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "Process Monitor"; + PROVISIONING_PROFILE_SPECIFIER = ""; }; name = Debug; }; @@ -306,11 +312,12 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_ENTITLEMENTS = ProcessMonitor/ProcessMonitor.entitlements; - CODE_SIGN_IDENTITY = "Developer ID Application"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_IDENTITY = "Apple Development"; + CODE_SIGN_STYLE = Automatic; COMBINE_HIDPI_IMAGES = YES; CURRENT_PROJECT_VERSION = 1.5.0; - DEVELOPMENT_TEAM = VBG97UB4TA; + DEAD_CODE_STRIPPING = YES; + DEVELOPMENT_TEAM = ZK96P738ZR; ENABLE_HARDENED_RUNTIME = YES; HEADER_SEARCH_PATHS = ../Library/Release; INFOPLIST_FILE = ProcessMonitor/Info.plist; @@ -320,9 +327,9 @@ ); LIBRARY_SEARCH_PATHS = ../Library/Release; MARKETING_VERSION = 1.5.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.objective-see.processmonitor"; + PRODUCT_BUNDLE_IDENTIFIER = "vin.je.com.objective-see.processmonitor"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = "Process Monitor"; + PROVISIONING_PROFILE_SPECIFIER = ""; }; name = Release; }; diff --git a/App/ProcessMonitor.xcodeproj/xcshareddata/xcschemes/ProcessMonitor.xcscheme b/App/ProcessMonitor.xcodeproj/xcshareddata/xcschemes/ProcessMonitor.xcscheme index 5b4c9e1..9307492 100644 --- a/App/ProcessMonitor.xcodeproj/xcshareddata/xcschemes/ProcessMonitor.xcscheme +++ b/App/ProcessMonitor.xcodeproj/xcshareddata/xcschemes/ProcessMonitor.xcscheme @@ -1,6 +1,6 @@ = arguments.count) { //invalid @@ -108,8 +108,17 @@ BOOL processArgs(NSArray* arguments) goto bail; } - //grab filter name - filterBy = [arguments objectAtIndex:index]; + //grab filter name regex + NSError *regex_error = nil; + filterByRegex = [NSRegularExpression regularExpressionWithPattern:arguments[index] options:0 error:®ex_error]; + if (!filterByRegex || regex_error) { + printf("%s", [NSString stringWithFormat:@"Error creating regex: %@\n", regex_error.localizedDescription].UTF8String); + //invalid + validArgs = NO; + + //bail + goto bail; + } } bail: @@ -118,39 +127,33 @@ BOOL processArgs(NSArray* arguments) } //print usage -void usage() +void usage(void) { //name - NSString* name = nil; + NSString* name = NSBundle.mainBundle.infoDictionary[@"CFBundleName"]; //version - NSString* version = nil; - - //extract name - name = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleName"]; - - //extract version - version = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; + NSString* version = NSBundle.mainBundle.infoDictionary[@"CFBundleVersion"]; //usage printf("\n%s (v%s) usage:\n", name.UTF8String, version.UTF8String); - printf(" -h or -help display this usage info\n"); - printf(" -pretty JSON output is 'pretty-printed'\n"); - printf(" -skipApple ignore Apple (platform) processes \n"); - printf(" -parseEnv parse environment variable information\n"); - printf(" -filter show events matching process name\n\n"); + printf(" -h or -help display this usage info\n"); + printf(" -pretty JSON output is 'pretty-printed'\n"); + printf(" -skipApple ignore Apple (platform) processes \n"); + printf(" -parseEnv parse environment variable information\n"); + printf(" -filter show events matching process name\n\n"); return; } //monitor -BOOL monitor() +BOOL monitor(void) { //(process) events of interest es_event_type_t events[] = {ES_EVENT_TYPE_NOTIFY_EXEC, ES_EVENT_TYPE_NOTIFY_FORK, ES_EVENT_TYPE_NOTIFY_EXIT}; //init monitor - ProcessMonitor* procMon = [[ProcessMonitor alloc] init]; + ProcessMonitor* procMon = ProcessMonitor.new; //define block // automatically invoked upon process events @@ -170,10 +173,10 @@ BOOL monitor() //filter // and no match? skip - if(0 != filterBy.length) + if(nil != filterByRegex) { //check file paths & process - if(YES != [process.path hasSuffix:filterBy]) + if(0 == [filterByRegex numberOfMatchesInString:process.path options:0 range:NSMakeRange(0, process.path.length)]) { //ignore return; @@ -248,7 +251,7 @@ BOOL monitor() //convert to string // note, we manually unescape forward slashes - prettyString = [[[NSString alloc] initWithData:prettyData encoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"]; + prettyString = [[NSString.alloc initWithData:prettyData encoding:NSUTF8StringEncoding] stringByReplacingOccurrencesOfString:@"\\/" withString:@"/"]; bail: diff --git a/Library/Release/ProcessMonitor.h b/Library/Release/ProcessMonitor.h index 8504dbf..1f9bfac 100644 --- a/Library/Release/ProcessMonitor.h +++ b/Library/Release/ProcessMonitor.h @@ -25,7 +25,7 @@ enum csOptions{csNone, csStatic, csDynamic}; enum Signer{None, Apple, AppStore, DevID, AdHoc}; //architectures -enum Architectures{ArchUnknown, ArchAppleSilicon, ArchIntel}; +enum Architectures{ArchUnknown, ArchFail1, ArchFail2, ArchFail3, ArchAppleSilicon, ArchIntel}; //cs options #define CS_STATIC_CHECK YES @@ -41,11 +41,11 @@ typedef void (^ProcessCallbackBlock)(Process* _Nonnull); @interface ProcessMonitor : NSObject //start monitoring -// pass in events of interest, count of said events, flag for codesigning, and callback --(BOOL)start:(es_event_type_t* _Nonnull)events count:(uint32_t)count csOption:(NSUInteger)csOption callback:(ProcessCallbackBlock _Nonnull)callback; +// pass in events of interest, count of said events, flag for codesigning, flag for environment variable collection, and callback +-(BOOL)start:(es_event_type_t* _Nonnull)events count:(uint32_t)count csOption:(NSUInteger)csOption parseEnv:(BOOL)parseEnv callback:(ProcessCallbackBlock _Nonnull)callback; //stop monitoring --(BOOL)stop; +@property (NS_NONATOMIC_IOSONLY, readonly) BOOL stop; @end @@ -89,6 +89,9 @@ typedef void (^ProcessCallbackBlock)(Process* _Nonnull); //args @property(nonatomic, retain)NSMutableArray* _Nonnull arguments; +//environment variables +@property(nonatomic, retain)NSMutableDictionary* _Nullable environment; + //ancestors @property(nonatomic, retain)NSMutableArray* _Nonnull ancestors; @@ -118,6 +121,6 @@ typedef void (^ProcessCallbackBlock)(Process* _Nonnull); //init // flag controls code signing options --(id _Nullable)init:(es_message_t* _Nonnull)message csOption:(NSUInteger)csOption; +-(instancetype _Nullable)init:(es_message_t* _Nonnull)message csOption:(NSUInteger)csOption parseEnv:(BOOL)parseEnv; @end diff --git a/Library/Release/libProcessMonitor.a b/Library/Release/libProcessMonitor.a index 7376f9a..f2c7a5e 100644 Binary files a/Library/Release/libProcessMonitor.a and b/Library/Release/libProcessMonitor.a differ diff --git a/Library/Source/Process.m b/Library/Source/Process.m index 48da9c6..2bdd86e 100644 --- a/Library/Source/Process.m +++ b/Library/Source/Process.m @@ -46,147 +46,147 @@ @implementation Process //init // flag controls code signing options and environment variable collection --(id)init:(es_message_t*)message csOption:(NSUInteger)csOption parseEnv:(BOOL)parseEnv +-(instancetype _Nullable)init:(es_message_t*)message csOption:(NSUInteger)csOption parseEnv:(BOOL)parseEnv { //init super - self = [super init]; + self = super.init; if(nil != self) { //process from msg es_process_t* process = NULL; - + //string value // used for various conversions NSString* string = nil; - + //alloc array for args self.arguments = [NSMutableArray array]; - + //alloc dictionary for environment variables if flag is set self.environment = parseEnv ? [NSMutableDictionary dictionary] : nil; - + //alloc array for parents self.ancestors = [NSMutableArray array]; - + //alloc dictionary for signing info self.signingInfo = [NSMutableDictionary dictionary]; - + //get function pointer getRPID = dlsym(RTLD_NEXT, "responsibility_get_pid_responsible_for_pid"); - + //init exit self.exit = -1; - + //init user id self.uid = -1; - + //init event self.event = -1; - + //set start time self.timestamp = [NSDate date]; - + //set type self.event = message->event_type; - + //event specific logic - + // set type // extract (relevant) process object, etc switch (message->event_type) { - + //exec case ES_EVENT_TYPE_NOTIFY_EXEC: - + //set process (target) process = message->event.exec.target; - + //extract/format args [self extractArgs:&message->event]; - + //extract/format environment variables if(parseEnv) { [self extractEnvironment:&message->event]; } - + break; - + //fork case ES_EVENT_TYPE_NOTIFY_FORK: - + //set process (child) process = message->event.fork.child; - + break; - + //exit case ES_EVENT_TYPE_NOTIFY_EXIT: - + //set process process = message->process; - + //set exit code self.exit = message->event.exit.stat; - + break; - + //default default: - + //set process process = message->process; - + break; } - + //init audit token self.auditToken = [NSData dataWithBytes:&process->audit_token length:sizeof(audit_token_t)]; - + //init pid self.pid = audit_token_to_pid(process->audit_token); - + //init ppid self.ppid = process->ppid; - + //init rpid if(message->version >= 4) self.rpid = audit_token_to_pid(process->responsible_audit_token); - + //init uuid self.uid = audit_token_to_euid(process->audit_token); - + //init path self.path = convertStringToken(&process->executable->path); - + //now generate name self.name = [self getName]; - + //cpu type self.architecture = [self getArchitecture]; - + //add cs flags - self.csFlags = [NSNumber numberWithUnsignedInt:process->codesigning_flags]; - + self.csFlags = @(process->codesigning_flags); + //convert/add signing id if(nil != (string = convertStringToken(&process->signing_id))) { //add self.signingID = string; } - + //convert/add team id if(nil != (string = convertStringToken(&process->team_id))) { //add self.teamID = string; } - + //add platform binary - self.isPlatformBinary = [NSNumber numberWithBool:process->is_platform_binary]; - + self.isPlatformBinary = @(process->is_platform_binary); + //save cd hash self.cdHash = [NSData dataWithBytes:(const void *)process->cdhash length:sizeof(uint8_t)*CS_CDHASH_LEN]; - + //when specified // generate full code signing info if(csNone != csOption) @@ -194,11 +194,11 @@ -(id)init:(es_message_t*)message csOption:(NSUInteger)csOption parseEnv:(BOOL)pa //generate code signing info [self generateCSInfo:csOption]; } - + //enum ancestors [self enumerateAncestors]; } - + return self; } @@ -208,7 +208,7 @@ -(void)generateCSInfo:(NSUInteger)csOption { //generate via helper function self.signingInfo = generateSigningInfo(self, csOption, kSecCSDefaultFlags); - + return; } @@ -218,22 +218,22 @@ -(NSString*)getName { //name NSString* name = nil; - + //app path NSString* appPath = nil; - + //app bundle NSBundle* appBundle = nil; - + //convert path to app path // generally, /Contents/MacOS/blah - appPath = [[[self.path stringByDeletingLastPathComponent] stringByDeletingLastPathComponent] stringByDeletingLastPathComponent]; + appPath = (self.path).stringByDeletingLastPathComponent.stringByDeletingLastPathComponent.stringByDeletingLastPathComponent; if(YES != [appPath hasSuffix:@".app"]) { //bail goto bail; } - + //try load bundle // and verify it's the 'right' bundle appBundle = [NSBundle bundleWithPath:appPath]; @@ -241,77 +241,79 @@ -(NSString*)getName (YES == [appBundle.executablePath isEqualToString:self.path]) ) { //grab name from app's bundle - name = [appBundle infoDictionary][@"CFBundleDisplayName"]; + name = appBundle.infoDictionary[@"CFBundleDisplayName"]; } - + bail: - + //still nil? // just grab from path if(nil == name) { //from path - name = [self.path lastPathComponent]; + name = (self.path).lastPathComponent; } - + return name; } //get process' architecture -(NSUInteger)getArchitecture { - //architecuture + //architecture NSUInteger architecture = ArchUnknown; - + //type - cpu_type_t type = -1; - + cpu_type_t type = (cpu_type_t)0x0BADC0DE; + //size size_t size = 0; - + //mib int mib[CTL_MAXNAME] = {0}; - + //length size_t length = CTL_MAXNAME; - + //proc info struct kinfo_proc procInfo = {0}; - + //get mib for 'proc_cputype' if(noErr != sysctlnametomib("sysctl.proc_cputype", mib, &length)) { + architecture = ArchFail1; //bail goto bail; } - + //add pid mib[length] = self.pid; - + //inc length length++; - + //init size size = sizeof(cpu_type_t); - + //get CPU type if(noErr != sysctl(mib, (u_int)length, &type, &size, 0, 0)) { + architecture = ArchFail2; //bail goto bail; } - + //reversing Activity Monitor // if CPU type is CPU_TYPE_X86_64, Apple sets architecture to 'Intel' if(CPU_TYPE_X86_64 == type) { //intel architecture = ArchIntel; - + //done goto bail; } - + //reversing Activity Monitor // if CPU type is CPU_TYPE_ARM64, Apple checks proc's p_flags // if P_TRANSLATED is set, then they set architecture to 'Intel' @@ -319,26 +321,27 @@ -(NSUInteger)getArchitecture { //default to apple architecture = ArchAppleSilicon; - + //(re)init mib mib[0] = CTL_KERN; mib[1] = KERN_PROC; mib[2] = KERN_PROC_PID; mib[3] = pid; - + //(re)set length length = 4; - + //(re)set size size = sizeof(procInfo); - + //get proc info if(noErr != sysctl(mib, (u_int)length, &procInfo, &size, NULL, 0)) { + architecture = ArchFail3; //bail goto bail; } - + //'P_TRANSLATED' set? // set architecture to 'Intel' if(P_TRANSLATED == (P_TRANSLATED & procInfo.kp_proc.p_flag)) @@ -347,9 +350,9 @@ -(NSUInteger)getArchitecture architecture = ArchIntel; } } - + bail: - + return architecture; } @@ -358,10 +361,10 @@ -(void)extractArgs:(es_events_t *)event { //number of args uint32_t count = 0; - + //argument NSString* argument = nil; - + //get # of args count = es_exec_arg_count(&event->exec); if(0 == count) @@ -369,16 +372,16 @@ -(void)extractArgs:(es_events_t *)event //bail goto bail; } - + //extract all args for(uint32_t i = 0; i < count; i++) { //current arg es_string_token_t currentArg = {0}; - + //extract current arg currentArg = es_exec_arg(&event->exec, i); - + //convert argument argument = convertStringToken(¤tArg); if(nil != argument) @@ -387,9 +390,9 @@ -(void)extractArgs:(es_events_t *)event [self.arguments addObject:argument]; } } - + bail: - + return; } @@ -399,16 +402,16 @@ -(void)extractEnvironment:(es_events_t *)event NSString* envString = nil; NSString* keyString = nil; NSString* valueString = nil; - + uint32_t count = es_exec_env_count(&event->exec); for (uint32_t i = 0; i < count; i++) { keyString = nil; valueString = nil; - + //extract current env es_string_token_t currentEnv = es_exec_env(&event->exec, i); - + //convert string token to env string envString = convertStringToken(¤tEnv); if(envString != nil) @@ -417,7 +420,7 @@ -(void)extractEnvironment:(es_events_t *)event convertEnvironmentVariableStringToKeyValue(envString, &keyString, &valueString); if(keyString != nil && valueString != nil) { - [self.environment setObject:valueString forKey:keyString]; + (self.environment)[keyString] = valueString; } } } @@ -429,7 +432,7 @@ -(void)enumerateAncestors { //current process id pid_t currentPID = -1; - + //parent pid pid_t parentPID = -1; @@ -446,7 +449,7 @@ -(void)enumerateAncestors //get rpid parentPID = getRPID(pid); } - + //couldn't find/get rPID? // default back to using ppid if( (parentPID <= 0) || @@ -455,13 +458,13 @@ -(void)enumerateAncestors //use ppid parentPID = self.ppid; } - + //add parent - [self.ancestors addObject:[NSNumber numberWithInt:parentPID]]; - + [self.ancestors addObject:@(parentPID)]; + //set current to parent currentPID = parentPID; - + //complete ancestry while(YES) { @@ -472,7 +475,7 @@ -(void)enumerateAncestors //get rpid parentPID = getRPID(currentPID); } - + //couldn't find/get rPID? // default back to using standard method if( (parentPID <= 0) || @@ -481,7 +484,7 @@ -(void)enumerateAncestors //get parent pid parentPID = getParentID(currentPID); } - + //done? if( (parentPID <= 0) || (currentPID == parentPID) ) @@ -489,14 +492,14 @@ -(void)enumerateAncestors //bail break; } - + //update currentPID = parentPID; - + //add - [self.ancestors addObject:[NSNumber numberWithInt:parentPID]]; + [self.ancestors addObject:@(parentPID)]; } - + return; } @@ -506,7 +509,7 @@ -(NSString *)description { //description NSMutableString* description = nil; - + //cd hash // requires formatting NSMutableString* cdHash = nil; @@ -527,17 +530,17 @@ -(NSString *)description case ES_EVENT_TYPE_NOTIFY_EXEC: [description appendString:@"\"ES_EVENT_TYPE_NOTIFY_EXEC\","]; break; - + //fork case ES_EVENT_TYPE_NOTIFY_FORK: [description appendString:@"\"ES_EVENT_TYPE_NOTIFY_FORK\","]; break; - + //exit case ES_EVENT_TYPE_NOTIFY_EXIT: [description appendString:@"\"ES_EVENT_TYPE_NOTIFY_EXIT\","]; break; - + default: break; } @@ -547,10 +550,10 @@ -(NSString *)description //start process [description appendString:@"\"process\":{"]; - + //add pid, path, etc [description appendFormat: @"\"pid\":%d,\"name\":\"%@\",\"path\":\"%@\",\"uid\":%d,",self.pid, self.name, self.path, self.uid]; - + //add cpu type switch(self.architecture) { @@ -558,41 +561,61 @@ -(NSString *)description case ArchIntel: [description appendFormat: @"\"architecture\":\"Intel\","]; break; - + //apple case ArchAppleSilicon: [description appendFormat: @"\"architecture\":\"Apple Silicon\","]; break; + //fail1 + case ArchFail1: + [description appendFormat: @"\"architecture\":\"fail1\","]; + break; + + //fail2 + case ArchFail2: + [description appendFormat: @"\"architecture\":\"fail2\","]; + break; + + //fail3 + case ArchFail3: + [description appendFormat: @"\"architecture\":\"fail3\","]; + break; + + //fail3 + case ArchUnknown: + [description appendFormat: @"\"architecture\":\"unknown\","]; + break; + //unknown default: - [description appendString:@"\"architecture\":\"unknown\","]; + [description appendString:@"\"architecture\":\"really-unknown\","]; break; } - + //arguments if(0 != self.arguments.count) { //start list [description appendFormat:@"\"arguments\":["]; - + //add all arguments for(NSString* argument in self.arguments) { //skip blank args if(0 == argument.length) continue; - + //add - [description appendFormat:@"\"%@\",", [argument stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]; + [description appendFormat:@"\"%@\",", [[[argument stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"] stringByReplacingOccurrencesOfString:@"\n" withString:@"\\n"] stringByReplacingOccurrencesOfString:@"\"" withString:@"\\\""]]; } - + //remove last ',' if(YES == [description hasSuffix:@","]) { //remove - [description deleteCharactersInRange:NSMakeRange([description length]-1, 1)]; + [description deleteCharactersInRange:NSMakeRange(description.length-1, 1)]; } - + //terminate list [description appendString:@"],"]; } @@ -602,13 +625,13 @@ -(NSString *)description //add empty list [description appendFormat:@"\"arguments\":[],"]; } - + //environment if(nil != self.environment && 0 != self.environment.count) { //start list [description appendFormat:@"\"environment\":{"]; - + //add all environment variables [self.environment enumerateKeysAndObjectsUsingBlock:^(NSString *key, NSString *value, BOOL * _Nonnull stop) { //add key and encode double quotes @@ -620,7 +643,7 @@ -(NSString *)description if(YES == [description hasSuffix:@","]) { //remove - [description deleteCharactersInRange:NSMakeRange([description length]-1, 1)]; + [description deleteCharactersInRange:NSMakeRange(description.length-1, 1)]; } //terminate object [description appendString:@"},"]; @@ -634,7 +657,7 @@ -(NSString *)description //add ppid [description appendFormat: @"\"ppid\":%d,", self.ppid]; - + //add rpdi [description appendFormat: @"\"rpid\":%d,", self.rpid]; @@ -652,7 +675,7 @@ -(NSString *)description if(YES == [description hasSuffix:@","]) { //remove - [description deleteCharactersInRange:NSMakeRange([description length]-1, 1)]; + [description deleteCharactersInRange:NSMakeRange(description.length-1, 1)]; } //terminate list @@ -660,10 +683,10 @@ -(NSString *)description //signing info (reported) [description appendString:@"\"signing info (reported)\":{"]; - + //add cs flags, platform binary [description appendFormat: @"\"csFlags\":%d,\"platformBinary\":%d,", self.csFlags.intValue, self.isPlatformBinary.intValue]; - + //add signing id if(0 == self.signingID.length) { @@ -676,7 +699,7 @@ -(NSString *)description //append [description appendFormat:@"\"signingID\":\"%@\",", self.signingID]; } - + //add team id if(0 == self.teamID.length) { @@ -689,10 +712,10 @@ -(NSString *)description //append [description appendFormat:@"\"teamID\":\"%@\",", self.teamID]; } - + //alloc string for cd hash cdHash = [NSMutableString string]; - + //format cd hash [self.cdHash enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) { @@ -701,10 +724,10 @@ -(NSString *)description [cdHash appendFormat:@"%02X", ((uint8_t*)bytes)[i]]; } }]; - + //add cs hash [description appendFormat:@"\"cdHash\":\"%@\"", cdHash]; - + //terminate dictionary [description appendString:@"},"]; @@ -716,28 +739,28 @@ -(NSString *)description { //value id value = self.signingInfo[key]; - + //handle `KEY_SIGNATURE_SIGNER` if(YES == [key isEqualToString:KEY_SIGNATURE_SIGNER]) { //convert to pritable switch ([value intValue]) { - + //'None' case None: [description appendFormat:@"\"%@\":\"%@\",", key, @"none"]; break; - + //'Apple' case Apple: [description appendFormat:@"\"%@\":\"%@\",", key, @"Apple"]; break; - + //'App Store' case AppStore: [description appendFormat:@"\"%@\":\"%@\",", key, @"App Store"]; break; - + //'Developer ID' case DevID: [description appendFormat:@"\"%@\":\"%@\",", key, @"Developer ID"]; @@ -747,12 +770,12 @@ -(NSString *)description case AdHoc: [description appendFormat:@"\"%@\":\"%@\",", key, @"AdHoc"]; break; - + default: break; } } - + //number? // add as is else if(YES == [value isKindOfClass:[NSNumber class]]) @@ -765,22 +788,22 @@ -(NSString *)description { //start [description appendFormat:@"\"%@\":[", key]; - + //add each item [value enumerateObjectsUsingBlock:^(id obj, NSUInteger index, BOOL * _Nonnull stop) { - + //add [description appendFormat:@"\"%@\"", obj]; - + //add ',' if(index != ((NSArray*)value).count-1) { //add [description appendString:@","]; } - + }]; - + //terminate [description appendString:@"],"]; } @@ -797,7 +820,7 @@ -(NSString *)description if(YES == [description hasSuffix:@","]) { //remove - [description deleteCharactersInRange:NSMakeRange([description length]-1, 1)]; + [description deleteCharactersInRange:NSMakeRange(description.length-1, 1)]; } //terminate dictionary @@ -828,28 +851,28 @@ pid_t getParentID(pid_t child) { //parent id pid_t parentID = -1; - + //kinfo_proc struct struct kinfo_proc processStruct = {0}; - + //size size_t procBufferSize = 0; - + //mib const u_int mibLength = 4; - + //syscall result int sysctlResult = -1; - + //init buffer length procBufferSize = sizeof(processStruct); - + //init mib int mib[mibLength] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, child}; - + //make syscall sysctlResult = sysctl(mib, mibLength, &processStruct, &procBufferSize, NULL, 0); - + //check if got ppid if( (noErr == sysctlResult) && (0 != procBufferSize) ) @@ -857,6 +880,6 @@ pid_t getParentID(pid_t child) //save ppid parentID = processStruct.kp_eproc.e_ppid; } - + return parentID; } diff --git a/Library/Source/ProcessMonitor.h b/Library/Source/ProcessMonitor.h index f9c4fb9..1f9bfac 100644 --- a/Library/Source/ProcessMonitor.h +++ b/Library/Source/ProcessMonitor.h @@ -25,7 +25,7 @@ enum csOptions{csNone, csStatic, csDynamic}; enum Signer{None, Apple, AppStore, DevID, AdHoc}; //architectures -enum Architectures{ArchUnknown, ArchAppleSilicon, ArchIntel}; +enum Architectures{ArchUnknown, ArchFail1, ArchFail2, ArchFail3, ArchAppleSilicon, ArchIntel}; //cs options #define CS_STATIC_CHECK YES @@ -45,7 +45,7 @@ typedef void (^ProcessCallbackBlock)(Process* _Nonnull); -(BOOL)start:(es_event_type_t* _Nonnull)events count:(uint32_t)count csOption:(NSUInteger)csOption parseEnv:(BOOL)parseEnv callback:(ProcessCallbackBlock _Nonnull)callback; //stop monitoring --(BOOL)stop; +@property (NS_NONATOMIC_IOSONLY, readonly) BOOL stop; @end @@ -90,7 +90,7 @@ typedef void (^ProcessCallbackBlock)(Process* _Nonnull); @property(nonatomic, retain)NSMutableArray* _Nonnull arguments; //environment variables -@property(nonatomic, retain)NSMutableDictionary* _Nonnull environment; +@property(nonatomic, retain)NSMutableDictionary* _Nullable environment; //ancestors @property(nonatomic, retain)NSMutableArray* _Nonnull ancestors; @@ -121,6 +121,6 @@ typedef void (^ProcessCallbackBlock)(Process* _Nonnull); //init // flag controls code signing options --(id _Nullable)init:(es_message_t* _Nonnull)message csOption:(NSUInteger)csOption parseEnv:(BOOL)parseEnv; +-(instancetype _Nullable)init:(es_message_t* _Nonnull)message csOption:(NSUInteger)csOption parseEnv:(BOOL)parseEnv; @end diff --git a/Library/Source/signing.h b/Library/Source/signing.h index 25be0ec..ceb616d 100644 --- a/Library/Source/signing.h +++ b/Library/Source/signing.h @@ -24,10 +24,10 @@ NSMutableDictionary* generateSigningInfo(Process* process, NSUInteger options, SecCSFlags flags); //extract signing info/check via dynamic code ref (process pid) -CFDictionaryRef dynamicCodeCheck(Process* process, SecCSFlags flags, NSMutableDictionary* signingInfo); +CFDictionaryRef dynamicCodeCheck(Process* process, SecCSFlags flags, NSMutableDictionary* signingInfo) CF_RETURNS_NOT_RETAINED; //extact signing info/check via static code ref (process path) -CFDictionaryRef staticCodeCheck(Process* process, SecCSFlags flags, NSMutableDictionary* signingInfo); +CFDictionaryRef staticCodeCheck(Process* process, SecCSFlags flags, NSMutableDictionary* signingInfo) CF_RETURNS_NOT_RETAINED; //determine who signed item NSNumber* extractSigner(SecStaticCodeRef code, SecCSFlags flags, BOOL isDynamic); diff --git a/Library/Source/signing.m b/Library/Source/signing.m index 94cff42..81540e8 100644 --- a/Library/Source/signing.m +++ b/Library/Source/signing.m @@ -66,17 +66,17 @@ } //extract code signing id - if(nil != [(__bridge NSDictionary*)signingDetails objectForKey:(__bridge NSString*)kSecCodeInfoIdentifier]) + if(nil != ((__bridge NSDictionary*)signingDetails)[(__bridge NSString*)kSecCodeInfoIdentifier]) { //extract/save - signingInfo[KEY_SIGNATURE_IDENTIFIER] = [(__bridge NSDictionary*)signingDetails objectForKey:(__bridge NSString*)kSecCodeInfoIdentifier]; + signingInfo[KEY_SIGNATURE_IDENTIFIER] = ((__bridge NSDictionary*)signingDetails)[(__bridge NSString*)kSecCodeInfoIdentifier]; } //extract team signing id - if(nil != [(__bridge NSDictionary*)signingDetails objectForKey:(__bridge NSString*)kSecCodeInfoTeamIdentifier]) + if(nil != ((__bridge NSDictionary*)signingDetails)[(__bridge NSString*)kSecCodeInfoTeamIdentifier]) { //extract/save - signingInfo[KEY_SIGNATURE_TEAM_IDENTIFIER] = [(__bridge NSDictionary*)signingDetails objectForKey:(__bridge NSString*)kSecCodeInfoTeamIdentifier]; + signingInfo[KEY_SIGNATURE_TEAM_IDENTIFIER] = ((__bridge NSDictionary*)signingDetails)[(__bridge NSString*)kSecCodeInfoTeamIdentifier]; } //extract signing authorities @@ -119,7 +119,7 @@ CFDictionaryRef dynamicCodeCheck(Process* process, SecCSFlags flags, NSMutableDi if(errSecSuccess != status) { //set error - signingInfo[KEY_SIGNATURE_STATUS] = [NSNumber numberWithInt:status]; + signingInfo[KEY_SIGNATURE_STATUS] = @(status); //bail goto bail; @@ -130,14 +130,14 @@ CFDictionaryRef dynamicCodeCheck(Process* process, SecCSFlags flags, NSMutableDi if(errSecSuccess != status) { //set error - signingInfo[KEY_SIGNATURE_STATUS] = [NSNumber numberWithInt:status]; + signingInfo[KEY_SIGNATURE_STATUS] = @(status); //bail goto bail; } //happily signed - signingInfo[KEY_SIGNATURE_STATUS] = [NSNumber numberWithInt:errSecSuccess]; + signingInfo[KEY_SIGNATURE_STATUS] = @(errSecSuccess); //determine signer // apple, app store, dev id, adhoc, etc... @@ -182,7 +182,7 @@ CFDictionaryRef staticCodeCheck(Process* process, SecCSFlags flags, NSMutableDic if(nil == process.path) { //set error - signingInfo[KEY_SIGNATURE_STATUS] = [NSNumber numberWithInt:kPOSIXErrorESRCH]; + signingInfo[KEY_SIGNATURE_STATUS] = @(kPOSIXErrorESRCH); //bail goto bail; @@ -193,7 +193,7 @@ CFDictionaryRef staticCodeCheck(Process* process, SecCSFlags flags, NSMutableDic if(errSecSuccess != status) { //set error - signingInfo[KEY_SIGNATURE_STATUS] = [NSNumber numberWithInt:status]; + signingInfo[KEY_SIGNATURE_STATUS] = @(status); //bail goto bail; @@ -204,14 +204,14 @@ CFDictionaryRef staticCodeCheck(Process* process, SecCSFlags flags, NSMutableDic if(errSecSuccess != status) { //set error - signingInfo[KEY_SIGNATURE_STATUS] = [NSNumber numberWithInt:status]; + signingInfo[KEY_SIGNATURE_STATUS] = @(status); //bail goto bail; } //happily signed - signingInfo[KEY_SIGNATURE_STATUS] = [NSNumber numberWithInt:errSecSuccess]; + signingInfo[KEY_SIGNATURE_STATUS] = @(errSecSuccess); //determine signer // apple, app store, dev id, adhoc, etc... @@ -276,7 +276,7 @@ CFDictionaryRef staticCodeCheck(Process* process, SecCSFlags flags, NSMutableDic if(errSecSuccess == validateRequirement(code, isApple, flags, isDynamic)) { //set signer to apple - signer = [NSNumber numberWithInt:Apple]; + signer = @(Apple); } //check 2: "is app store" @@ -284,14 +284,14 @@ CFDictionaryRef staticCodeCheck(Process* process, SecCSFlags flags, NSMutableDic else if(errSecSuccess == validateRequirement(code, isAppStore, flags, isDynamic)) { //set signer to app store - signer = [NSNumber numberWithInt:AppStore]; + signer = @(AppStore); } //check 3: "is dev id" else if(errSecSuccess == validateRequirement(code, isDevID, flags, isDynamic)) { //set signer to dev id - signer = [NSNumber numberWithInt:DevID]; + signer = @(DevID); } //otherwise @@ -299,7 +299,7 @@ CFDictionaryRef staticCodeCheck(Process* process, SecCSFlags flags, NSMutableDic else { //set signer to ad hoc - signer = [NSNumber numberWithInt:AdHoc]; + signer = @(AdHoc); } return signer; @@ -349,7 +349,7 @@ OSStatus validateRequirement(SecStaticCodeRef code, SecRequirementRef requiremen authorities = [NSMutableArray array]; //get cert chain - certificateChain = [signingDetails objectForKey:(__bridge NSString*)kSecCodeInfoCertificates]; + certificateChain = signingDetails[(__bridge NSString*)kSecCodeInfoCertificates]; if(0 == certificateChain.count) { //no certs @@ -363,7 +363,7 @@ OSStatus validateRequirement(SecStaticCodeRef code, SecRequirementRef requiremen commonName = NULL; //extract cert - certificate = (__bridge SecCertificateRef)([certificateChain objectAtIndex:index]); + certificate = (__bridge SecCertificateRef)(certificateChain[index]); //get common name if( (errSecSuccess == SecCertificateCopyCommonName(certificate, &commonName)) &&