From b99b05888cd97d666bcbcaf6854fdbc800870349 Mon Sep 17 00:00:00 2001 From: Patrick Wardle Date: Thu, 24 Mar 2016 17:02:11 -1000 Subject: [PATCH] pushed logic for getting task's args into XPC service (since needs to be done as root) removed socket/string logic from root XPC service improved 'isAlive' logic to detect dead process improved process enumeration (to not ignore process that we can't get path for) --- AppDelegate.m | 4 +- Consts.h | 3 + InfoWindowController.m | 32 +- Items/Connection.h | 65 +++ Items/Connection.m | 129 +++++- Task.h | 13 +- Task.m | 283 +++++------- TaskEnumerator.m | 40 +- .../xcshareddata/TaskExplorer.xcscmblueprint | 30 ++ .../UserInterfaceState.xcuserstate | Bin 0 -> 21755 bytes Utilities.m | 73 +++- images/closeWait.png | Bin 0 -> 4439 bytes images/closedIcon.png | Bin 0 -> 4528 bytes remoteTaskService/remoteTaskService.h | 19 +- remoteTaskService/remoteTaskService.m | 408 +++++++++--------- serviceInterface.h | 5 +- 16 files changed, 659 insertions(+), 445 deletions(-) create mode 100644 TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xcscmblueprint create mode 100644 TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrick.xcuserdatad/UserInterfaceState.xcuserstate create mode 100644 images/closeWait.png create mode 100644 images/closedIcon.png diff --git a/AppDelegate.m b/AppDelegate.m index 9cdd891..a73dc98 100755 --- a/AppDelegate.m +++ b/AppDelegate.m @@ -20,7 +20,9 @@ //TODO: autolayout vertically //TODO: show 'from where' via quarantine attrz or database!! (simon email) //TODO: detect as procs die via GCD (simon blog post) - +//TODO: missing icon (128) - new icon? +//TODO: exception handling for mutated array! +//TODO: check for "Apple Mac OS Application Signing" for Apple Apps - and add to 'OBJ-See' TODO doc @implementation AppDelegate diff --git a/Consts.h b/Consts.h index 64d874c..7e68dfe 100644 --- a/Consts.h +++ b/Consts.h @@ -332,4 +332,7 @@ //hotkey 'i' #define KEYCODE_I 0x22 +//unknown task +#define TASK_PATH_UNKNOWN @"" + #endif diff --git a/InfoWindowController.m b/InfoWindowController.m index b4c9046..b711938 100644 --- a/InfoWindowController.m +++ b/InfoWindowController.m @@ -95,6 +95,9 @@ // ->when showing info about a task Task* task = nil; + //task arguments + NSMutableString* taskArguments = nil; + //binary // ->when showing info about a dylib Binary* dylib = nil; @@ -136,9 +139,32 @@ [((Task*)self.itemObj) getArguments]; } - //set args - [self.arguments setStringValue:[self valueForStringItem:[task.arguments componentsJoinedByString:@""] default:@"no arguments/unknown"]]; - + //set default value for args + self.arguments.stringValue = @"no arguments/unknown"; + + //set any args + // ->task path and name, make up the first to 'args', so skip/ignore those + if(task.arguments.count > 2) + { + //alloc string to build up args + taskArguments = [NSMutableString string]; + + //build up args string + // ->start at index 2, to skip path/name + for(NSUInteger index = 2; index +#import +#import #import +//socket states +// ->note, index correspondes to numberic value +static const char* socketStates[] = +{ + "closed", + "listening", + "syn sent", + "syn received", + "established", + "close/wait", + "fin wait 1", + "closing", + "last act", + "fin wait 2", + "time wait", +}; + +static const char *socketFamilies[] = +{ + "AF_UNSPEC", + "AF_UNIX", + "AF_INET", + "AF_IMPLINK", + "AF_PUP", + "AF_CHAOS", + "AF_NS", + "AF_ISO", + "AF_ECMA", + "AF_DATAKIT", + "AF_CCITT", + "AF_SNA", + "AF_DECnet", + "AF_DLI", + "AF_LAT", + "AF_HYLINK", + "AF_APPLETALK", + "AF_ROUTE", + "AF_LINK", + "#define", + "AF_COIP", + "AF_CNT", + "pseudo_AF_RTIP", + "AF_IPX", + "AF_SIP", + "pseudo_AF_PIP", + "pseudo_AF_BLUE", + "AF_NDRV", + "AF_ISDN", + "pseudo_AF_KEY", + "AF_INET6", + "AF_NATM", + "AF_SYSTEM", + "AF_NETBIOS", + "AF_PPP", + "pseudo_AF_HDRCMPLT", + "AF_RESERVED_36", +}; +#define SOCKET_FAMILY_MAX (int)(sizeof(socketFamilies)/sizeof(char *)) + + + @interface Connection : ItemBase { diff --git a/Items/Connection.m b/Items/Connection.m index 19a2127..ae3c957 100644 --- a/Items/Connection.m +++ b/Items/Connection.m @@ -39,16 +39,16 @@ self.remotePort = params[KEY_REMOTE_PORT]; //extract/save type - self.type = params[KEY_SOCKET_TYPE]; + self.type = [self socketType2String:params[KEY_SOCKET_TYPE]]; //extract/save family - self.family = params[KEY_SOCKET_FAMILY]; + self.family = [self socketFamily2String:params[KEY_SOCKET_FAMILY]]; //extract/save proto - self.proto = params[KEY_SOCKET_PROTO]; + self.proto = [self socketProto2String:params[KEY_SOCKET_PROTO]]; //extract/save state - self.state = params[KEY_SOCKET_STATE]; + self.state = [self socketState2String:params[KEY_SOCKET_STATE]]; //set icon [self setConnectionIcon]; @@ -104,13 +104,10 @@ //set self.icon = [NSImage imageNamed:@"closedIcon"]; } - - //by design, other connection states won't have an icon - // TODO: maybe add other icons? } //set icon for UDP sockets - // ->can't listen, so just show em as streaming + // ->can't listen, so just show 'em as streaming else if(YES == [self.type isEqualToString:@"SOCK_DGRAM"]) { //set @@ -137,6 +134,122 @@ return; } +//convert a socket type into string +-(NSString*) socketType2String:(NSNumber*)type +{ + //socket type + NSString* socketType = nil; + + //convert + switch(type.intValue) + { + //stream + case SOCK_STREAM: + socketType = @"SOCK_STREAM"; + break; + + //dgram + case SOCK_DGRAM: + socketType = @"SOCK_DGRAM"; + break; + + //raw + case SOCK_RAW: + socketType = @"SOCK_RAW"; + break; + + //rdm + case SOCK_RDM: + socketType = @"SOCK_RDM"; + break; + + //seq packet + case SOCK_SEQPACKET: + socketType = @"SOCK_SEQPACKET"; + break; + + default: + break; + } + + return socketType; +} + + +//convert a socket family into string +-(NSString*) socketFamily2String:(NSNumber*)family +{ + //socket family + NSString* socketFamily = nil; + + //sanity check + if( (family.intValue < 0) || + (family.intValue >= SOCKET_FAMILY_MAX) ) + { + //bail + goto bail; + } + + //init socket family string + socketFamily = [NSString stringWithUTF8String:socketFamilies[family.intValue]]; + +//bail +bail: + + return socketFamily; +} + +//convert a socket protocol into string +-(NSString*) socketProto2String:(NSNumber*)proto +{ + //socket proto + NSString* socketProto = nil; + + //proto struct + struct protoent *protoInfo = NULL; + + //get proto info + protoInfo = getprotobynumber(proto.intValue); + + //sanity check + if(NULL == protoInfo) + { + //bail + goto bail; + } + + //init proto string + // ->name comes from struct + socketProto = [NSString stringWithUTF8String:protoInfo->p_name]; + +//bail +bail: + + return socketProto; +} + + +//convert a socket state into string +-(NSString*) socketState2String:(NSNumber*)state +{ + //socket proto + NSString* socketState = nil; + + //set state + if(state.intValue < TCP_NSTATES) + { + //set state + socketState = [NSString stringWithUTF8String:socketStates[state.intValue]]; + } + //invalid/unknown socket state + else + { + socketState = [NSString stringWithFormat:@"unknown state (%d)", state.intValue]; + } + + return socketState; +} + //build printable connection string -(void)setConnectionString { diff --git a/Task.h b/Task.h index 9cc8df7..7878e75 100644 --- a/Task.h +++ b/Task.h @@ -57,13 +57,12 @@ struct dyld_image_info_32 { //connections @property(nonatomic, retain)NSMutableArray* connections; +//uid @property uid_t uid; + +//parent's pid @property (nonatomic, retain)NSNumber* ppid; - -//signing info -//@property(nonatomic, retain)NSDictionary* signingInfo; - //children @property (nonatomic, retain)NSMutableArray* children; @@ -72,7 +71,11 @@ struct dyld_image_info_32 { //init w/ a pid + path // note: icons are dynamically determined only when process is shown in alert --(id)initWithPID:(NSNumber*)taskPID andPath:(NSString*)taskPath; +-(id)initWithPID:(NSNumber*)taskPID; + +//get task's path +// ->via 'proc_pidpath()' or via task's args ('KERN_PROCARGS2') +-(NSString*)getPath; //get command-line args -(void)getArguments; diff --git a/Task.m b/Task.m index b58671c..790aa6b 100644 --- a/Task.m +++ b/Task.m @@ -14,20 +14,10 @@ #import "AppDelegate.h" #import "remoteTaskService.h" -#import -#import -#import -#import -#import -#import -#import +#import +#import #import #import -#import -#import -#import -#import - @implementation Task @@ -41,10 +31,14 @@ @synthesize arguments; @synthesize connections; -//init w/ a pid + path +//init w/ a pid // note: time consuming init's are done in other methods --(id)initWithPID:(NSNumber*)taskPID andPath:(NSString*)taskPath +-(id)initWithPID:(NSNumber*)taskPID { + //task's path + // ->not iVar, as assigned into task's binary obj + NSString* taskPath = nil; + //existing binaries NSMutableDictionary* existingBinaries = nil; @@ -81,9 +75,16 @@ //get parent id self.ppid = [NSNumber numberWithInteger:getParentID([taskPID intValue])]; + //get task's path + taskPath = [self getPath]; + //try extract existing binary - // ->will succeed for multiple instances of the same task (process) - existingBinary = existingBinaries[taskPath]; + // ->but only if task's path is known + if(YES != [taskPath isEqualToString:TASK_PATH_UNKNOWN]) + { + //lookup + existingBinary = existingBinaries[taskPath]; + } //re-use existing binaries if(nil != existingBinary) @@ -128,179 +129,122 @@ bail: return self; } -//get command-line args --(void)getArguments +//get task's path +// ->via 'proc_pidpath()' or via task's args (via XPC) if that fails... +-(NSString*)getPath { - //'management info base' array - int mib[3] = {0}; + //task path + NSString* taskPath = nil; - //system's size for max args - int systemMaxArgs = 0; + //buffer for process path + char pathBuffer[PROC_PIDPATHINFO_MAXSIZE] = {0}; - //process's args - char* processArgs = NULL; + //status + int status = -1; - //# of args - int numberOfArgs = 0; + //reset buffer + bzero(pathBuffer, PROC_PIDPATHINFO_MAXSIZE); - //start of (each) arg - char* argStart = NULL; - - //size of buffers, etc - size_t size = 0; - - //parser pointer - char *parser; - - //init mib - // ->want system's size for max args - mib[0] = CTL_KERN; - mib[1] = KERN_ARGMAX; - - //first time - // ->alloc array for args - if(nil == self.arguments) + //kernel 'task' is special + if(0 == self.pid.intValue) { - //alloc - arguments = [NSMutableArray array]; - } - - //set size - size = sizeof(systemMaxArgs); - - //get system's size for max args - if(-1 == sysctl(mib, 2, &systemMaxArgs, &size, NULL, 0)) - { - //bail - goto bail; - } - - //alloc space for args - processArgs = malloc(systemMaxArgs); - if(NULL == processArgs) - { - //bail - goto bail; - } - - //init mib - // ->want process args - mib[0] = CTL_KERN; - mib[1] = KERN_PROCARGS2; - mib[2] = [self.pid intValue]; - - //set size - size = (size_t)systemMaxArgs; - - //get process's args - if(-1 == sysctl(mib, 3, processArgs, &size, NULL, 0)) - { - //bail - goto bail; - } - - //extract number of args - // ->at start of buffer - memcpy(&numberOfArgs, processArgs, sizeof(numberOfArgs)); - - //skip procs w/ no args - // ->note: don't care about arg[0] - if(numberOfArgs < 2) - { - //no args - goto bail; - } - - //init point to start of args - // ->they start right after # of args - parser = processArgs + sizeof(numberOfArgs); - - //skip over exe name - // ->always at front, yes, even before arg[0] (which is also exe name) - while(parser < &processArgs[size]) - { - //scan till NULL-terminator - if(0x0 == *parser) - { - //end of exe name - break; - } + //set + taskPath = path2Kernel(); - //next char - parser++; - } - - //sanity check - // ->make sure end-of-buffer wasn't reached - if(parser == &processArgs[size]) - { - //bail + //all set goto bail; } - //skip all trailing NULLs - // ->scan will non-NULL is found - while(parser < &processArgs[size]) + //get task's path via 'proc_pidpath()' + // ->this might fail, so will then attempt via task's args ('KERN_PROCARGS2') + status = proc_pidpath(self.pid.intValue, pathBuffer, sizeof(pathBuffer)); + if(0 != status) { - //scan till NULL-terminator - if(0x0 != *parser) - { - //ok, got to argv[0] - break; - } + //init task's name + taskPath = [NSString stringWithUTF8String:pathBuffer]; + } + //try via task's args (via XPC) + else + { + //grab args + // ->set's 'arguments' iVar + [self getArguments]; - //next char - parser++; - } - - //sanity check - // ->(again), make sure end-of-buffer wasn't reached - if(parser == &processArgs[size]) - { - //bail - goto bail; - } - - //keep scanning until all args are found - // ->each is NULL-terminated - while(parser < &processArgs[size]) - { - //bail if we've hit arg cnt - // ->note: don't save arg[0], so add 1 - if(self.arguments.count + 1 == numberOfArgs) + //sanity check + if( (nil == self.arguments) || + (0 == self.arguments.count) ) { //bail - break; + goto bail; } - //each arg is NULL-terminated - if(*parser == '\0') - { - //save arg - // ->'argStart' is purposely NULL for argv[0] - if(NULL != argStart) - { - [self.arguments addObject:[NSString stringWithUTF8String:argStart]]; - } - - //init string pointer to (possibly) next arg - argStart = ++parser; - } - - //next char - parser++; + //arg[0] should be full path + taskPath = self.arguments.firstObject; } //bail bail: - //free process args - if(NULL != processArgs) + //when task path is still nil + // ->set to const for unknown path... + if(nil == taskPath) { - //free - free(processArgs); + //set + taskPath = TASK_PATH_UNKNOWN; } + return taskPath; +} + +//get command-line args via XPC request to remote service +// ->waits for XPC, then sets 'arguments' iVar +-(void)getArguments +{ + //xpc connection + __block NSXPCConnection* xpcConnection = nil; + + //wait semaphore + dispatch_semaphore_t waitSema = nil; + + //alloc XPC connection + xpcConnection = [[NSXPCConnection alloc] initWithServiceName:@"com.objective-see.remoteTaskService"]; + + //set remote object interface + xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(remoteTaskProto)]; + + //set classes + // ->arrays & strings are what is ok to vend + [xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSString class], nil] + forSelector: @selector(getTaskArgs:withReply:) argumentIndex: 0 ofReply: YES]; + + //resume + [xpcConnection resume]; + + //init wait semaphore + waitSema = dispatch_semaphore_create(0); + + //invoke XPC service (running as r00t) + // ->will enumerate files, then invoke reply block so can save into iVar + [[xpcConnection remoteObjectProxy] getTaskArgs:self.pid withReply:^(NSMutableArray* taskArguments) + { + //close connection + [xpcConnection invalidate]; + + //nil out + xpcConnection = nil; + + //grab array + self.arguments = taskArguments; + + //signal sema + dispatch_semaphore_signal(waitSema); + + }]; + + //wait until XPC is done + // ->XPC reply block will signal semaphore + dispatch_semaphore_wait(waitSema, DISPATCH_TIME_FOREVER); + return; } @@ -328,7 +272,7 @@ bail: xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(remoteTaskProto)]; //set classes - // ->arrays & strings are what is ok to vend + // ->arrays, dictionaries, & strings are what is ok to vend [xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSMutableDictionary class], [NSString class], nil] forSelector: @selector(enumerateDylibs:withReply:) @@ -359,7 +303,8 @@ bail: //add all dylibs for(NSString* dylibPath in dylibPaths) { - //skip main image + //skip main executable image + //TODO: also check realpath() or obj-c equiv! if(YES == [dylibPath isEqualToString:self.binary.path]) { //skip @@ -412,7 +357,7 @@ bail: //add to task's dylibs [self.dylibs addObject:dylib]; - } //all dylibs + }//all dylibs //sort by name self.dylibs = [[self.dylibs sortedArrayUsingComparator:^NSComparisonResult(id a, id b) @@ -488,7 +433,7 @@ bail: xpcConnection.remoteObjectInterface = [NSXPCInterface interfaceWithProtocol:@protocol(remoteTaskProto)]; //set classes - // ->arrays & strings are what is ok to vend + // ->arrays, dictionaries, & strings are what is ok to vend [xpcConnection.remoteObjectInterface setClasses: [NSSet setWithObjects: [NSMutableArray class], [NSMutableDictionary class], [NSString class], nil] forSelector: @selector(enumerateFiles:withReply:) diff --git a/TaskEnumerator.m b/TaskEnumerator.m index 2db2c8a..d06b2e9 100644 --- a/TaskEnumerator.m +++ b/TaskEnumerator.m @@ -250,6 +250,9 @@ //task Task* task = nil; + //status + int status = -1; + //alloc/init list allTasks = [[OrderedDictionary alloc] init]; @@ -259,18 +262,9 @@ //array of pids pid_t* pids = NULL; - //buffer for process path - char pathBuffer[PROC_PIDPATHINFO_MAXSIZE] = {0}; - - //status - int status = -1; - //process ID NSNumber* processID = nil; - //process name - NSString* processName = nil; - //get # of procs numberOfProcesses = proc_listpids(PROC_ALL_PIDS, 0, NULL, 0); @@ -299,30 +293,26 @@ continue; } - //reset buffer - bzero(pathBuffer, PROC_PIDPATHINFO_MAXSIZE); - //init process ID processID = [NSNumber numberWithInt:pids[i]]; - //get path - status = proc_pidpath(pids[i], pathBuffer, sizeof(pathBuffer)); - - //sanity check - // ->this generally just fails if process has exited.... - if( (status < 0) || - (0 == strlen(pathBuffer)) ) + //ignore procs that have exited + if(YES != isAlive(pids[i])) { //skip continue; } - - //init process name - processName = [NSString stringWithUTF8String:pathBuffer]; //init task - // ->pass in pid and name - task = [[Task alloc] initWithPID:processID andPath:processName]; + // ->pass in pid + task = [[Task alloc] initWithPID:processID]; + + //again, ignore procs that have exited + if(YES != isAlive(pids[i])) + { + //skip + continue; + } //add task to list // ->order by pid for now @@ -331,7 +321,7 @@ //always add kernel's task // ->hardcoded pid (0) and path to kernel - task = [[Task alloc] initWithPID:@0 andPath:path2Kernel()]; + task = [[Task alloc] initWithPID:@0]; //add kernel task [allTasks setObject:task forKey:@0]; diff --git a/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xcscmblueprint b/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xcscmblueprint new file mode 100644 index 0000000..b0bb6fb --- /dev/null +++ b/TaskExplorer.xcodeproj/project.xcworkspace/xcshareddata/TaskExplorer.xcscmblueprint @@ -0,0 +1,30 @@ +{ + "DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "61F07AFB33748EF0C810BEEF6126283DAC63A899", + "DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : { + + }, + "DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : { + "61F07AFB33748EF0C810BEEF6126283DAC63A899" : 0, + "7564E3FECD3AE625755C217749E31B3EE2B69E20" : 0 + }, + "DVTSourceControlWorkspaceBlueprintIdentifierKey" : "FE4103FE-6F26-4639-8C9F-D8D32C76D6A9", + "DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : { + "61F07AFB33748EF0C810BEEF6126283DAC63A899" : "TaskExplorer", + "7564E3FECD3AE625755C217749E31B3EE2B69E20" : "machO\/" + }, + "DVTSourceControlWorkspaceBlueprintNameKey" : "TaskExplorer", + "DVTSourceControlWorkspaceBlueprintVersion" : 204, + "DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "TaskExplorer.xcodeproj", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [ + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/bitbucket.org\/objective-see\/taskexplorer.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "61F07AFB33748EF0C810BEEF6126283DAC63A899" + }, + { + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/bitbucket.org\/objective-see\/macho.git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git", + "DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "7564E3FECD3AE625755C217749E31B3EE2B69E20" + } + ] +} \ No newline at end of file diff --git a/TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrick.xcuserdatad/UserInterfaceState.xcuserstate b/TaskExplorer.xcodeproj/project.xcworkspace/xcuserdata/patrick.xcuserdatad/UserInterfaceState.xcuserstate new file mode 100644 index 0000000000000000000000000000000000000000..cf288de936b66c9e58e2302c1b0c10c9081b84d7 GIT binary patch literal 21755 zcmc(H2YggT*Z0hA>B*+|WOtKn0%_Yz`X<>>q=(+(k}PB;Bw=?$i|AYw5wXz~r6i$< zh!jN;6ahs3ufnKS2{IcMfhXsok4 zT}tH%gb{^k#2^-NKAexw$kb^zhtu9rKQgsp!X371mvdCA)lpq*hsQ%xT@8(42;aA6 zODGkFe2^~+M-eCzrK1eg1NB6iC<|qy9F&WCq28zu>Wgke{ZM~201ZTg&|owKRidG2 zG#Z0$N43a~?m&}K9de*qs2Saj=Ab2LDO!e>qsP$WXa#x#ZA079bLe@r1HFJ=L_5(- zXcyXx_Mrpl4fHlTicX^U(MRZ0^f~$hUBL)rOko-`n8h6S!M@lJ`{Mu{jKgpwj=}Lb z3FqKkti&p;#u{9Ri*PY6!4_PBd*R-=5AKVH;}Liy9)+v$?YIWtf$MPtz8e$F<2m>q zJRd)TAH}QiYP<%w;8xs*H{vaL2i}ce#{2Ob_#i%w&*1m*S^NS15PyWvON`#^$4|?T28H`R#9uIb<`GWE47WsJE$isCTLNs1K=+sB_fE)OqR?>Qm}7>I>>y>Kb*O`i;6lBO22_v_Bn8htTnK z0-Z=F(aCfsokeHUIp_$TORH%kT}WH#3c43PkRC)2rbo~t>9O<#x|*(~8|kUEgPuh< z(|6K@UPLdZm(WY;W%P3TG5T?O9lf63KtDxqq_@z|(a+Pn=-u=_dO!Ud{UiMg{VV+k z{U<{+4CBlAF+of)6UKxy(M$}Jz$7vnG&X)u`qp@ zzRUn-AXCWB%K<^g6Ivz&R1 zd7N3ttY;z>=Je__Z5_H*_E`vv+_ zPR6Bi*_@iwbNO5`XW=TizT6;g2se@&#f|3bxdyJ0o60#jC+FgtxM|#UZU#4#o5eMA zbGiGtdEEWnqudJa3GPX5CAW%O&8^{{<~DK9aGSXoxt-ig+%E2Q?f~}&_ZIgKcaHm* zJI{T>eac|xCM8Xn| z_z+*>NBl{^29%7XNCqUtpj4Db0!a{${eT*d#FD`zeY^l~udivCUg5A#u~kWmy7o8J zI-#tg-sNbhtFt+(D$3Qy@^Y;?+oH6TWoye!Wk9Q1m0e*rYAmH?YHfKb5G(_LfsPuR z!&cKlw-=7HN|M#J6S4cweumZCr#9L8)WA6H6YbEiBpIrkt6iY0yGN{�r4!VGM0( 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 literal 0 HcmV?d00001 diff --git a/Utilities.m b/Utilities.m index f8144e7..4391890 100644 --- a/Utilities.m +++ b/Utilities.m @@ -84,7 +84,7 @@ bail: return version; } - +//TODO: calling 'isApple' does this all over again!? //get the signing info of a file NSDictionary* extractSigningInfo(NSString* path) { @@ -115,9 +115,6 @@ NSDictionary* extractSigningInfo(NSString* path) //init signing status signingStatus = [NSMutableDictionary dictionary]; - //signingStatus[KEY_SIGNATURE_STATUS] = @0; - //return signingStatus; - //create static code status = SecStaticCodeCreateWithPath((__bridge CFURLRef)([NSURL fileURLWithPath:path]), kSecCSDefaultFlags, &staticCode); @@ -624,21 +621,18 @@ pid_t getParentID(int pid) //size size_t procBufferSize = sizeof(processStruct); - //mib - const u_int mibLength = 4; - //syscall result int sysctlResult = -1; //init mib - int mib[mibLength] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; //make syscall - sysctlResult = sysctl(mib, mibLength, &processStruct, &procBufferSize, NULL, 0); + sysctlResult = sysctl(mib, sizeof(mib)/sizeof(*mib), &processStruct, &procBufferSize, NULL, 0); //check if got ppid if( (STATUS_SUCCESS == sysctlResult) && - (0 != procBufferSize) ) + (0 != procBufferSize) ) { //save ppid parentID = processStruct.kp_eproc.e_ppid; @@ -695,15 +689,61 @@ BOOL isAlive(pid_t targetPID) //flag BOOL isAlive = YES; + //reset errno + errno = 0; + + //'management info base' array + int mib[4] = {0}; + + //kinfo proc + struct kinfo_proc procInfo = {0}; + //try 'kill' with 0 - // ->no harm done, but will fail with 'ESRCH' if process is dead! - if( (0 != kill(targetPID, 0)) && - (ESRCH == errno) ) + // ->no harm done, but will fail with 'ESRCH' if process is dead + kill(targetPID, 0); + + //dead proc -> 'ESRCH' + // ->'No such process' + if(ESRCH == errno) { - //alive + //dead isAlive = NO; + + //bail + goto bail; } + //size + size_t size = 0; + + //init mib + mib[0] = CTL_KERN; + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_PID; + mib[3] = targetPID; + + //init size + size = sizeof(procInfo); + + //get task's flags + // ->allows to check for zombies + if(0 == sysctl(mib, sizeof(mib)/sizeof(*mib), &procInfo, &size, NULL, 0)) + { + //check for zombies + if(((procInfo.kp_proc.p_stat) & SZOMB) == SZOMB) + { + //dead + isAlive = NO; + + //bail + goto bail; + + } + } + +//bail +bail: + return isAlive; } @@ -903,8 +943,7 @@ BOOL Is32Bit(pid_t targetPID) //bail bail: - return isI386; - + return isI386; } - + diff --git a/images/closeWait.png b/images/closeWait.png new file mode 100644 index 0000000000000000000000000000000000000000..b54084455b3f09f87c55ef6758a1b1912e221859 GIT binary patch literal 4439 zcmdUzX*3k>+sAF$$MVCF-54Yx#aM>14^l{Wk)<*kTNz~6ATyS1Daja&B8{yEMI%}) zSw~D`WC@|hRMrN`Gr#kk=jHSM|9^4c*SWsub6@v4*Ng8t*M)U)vI7Xp3UY98037UX zT-ov0zlWcfeZ$)HgD>~R%y4|ERae)~g3}D~=T(Cots&UbheG%B9QOjXGOUt3? zGI*c_JYX-y4M#(i2i^Efxk+x+6wFy9k?Q(eL2DSkD z%Mn@p!g&o>8innk6Fjpy;V!`c1+=5TCX=ks&6m)4uQ-sbd2aVoPkH*=vY`rWxC<4| zu0oWUz8DW=x=7qS)@C^+#T2_$)zUgtl0^|QxCIT8ySqpc5totm9lZEbf(@~3!_sf4 z&{en=t7*$0bpM42Y>4mwAY)lJL_6MQNqJ8GMsX64)_+Vj;Pxfpu5oF-gB<&ejZl}p zz%ca|XSzw0s_on|mS;-ptzc*?14Kk^*_)q1a;29D3ZP}gS?%bh--xWTjO`x_(t+nt z#id%odaXl+ITR-YEIH^ffdr*%2K6eojOLU7l^z8tRX${Ycsc@`oN^*BwmvjTY?|ZS z*Podbr^3rX?162{tQA+3?b_joirm<2aP*nA&4n|h3+FCp(fGdOn(GK7Lj^4|J}d9< zAo|KM6$9R$^g0n+D7*tcy4kR48J)ZGT3PI&l=YjmN%6d+3zsfML~vQkYdmqXfx^#h zk^^p38PZ$S3Gby3f%}!ovXkwUkwQ&E%Xq2x%B^LfP*S&-=au!zCn?IXM{dNf8v!K& z=vw+wru+lRJn`dywFtPu%zd;#Wkhx}Gc1NeQ-(CU{bq{-4Z-jOsVHF~Cc&fEQ1W+Cc69c8B)7_uV&tUfK5`87*||5acPe6xWn(n9nulSuc$is#nw` zVq=T`81iBWZ?BsvO_C5A(MJyM?>78OGWy3aF^}_9FELSM85_V&JUl#2zzvD{ZT6w_ zn2QJvY=1%zuXl_!tL*D=Oiy1-GO75ouv?7B)08{0r&Pt_k~Fg2J*BJ|p4%ScCaYx1 zovR$xuiZPz0II2HE)y;KYF6sNkwgH%KLM|=Bv!ZCLC??$bM>q9NX@wggq>VJsHeoi z>GP%bXpmu-N5&Pv)V^Afs={lzDR-!)2MZFaZP*4C`j)WYqetVPwgHq8 zs+iyDd}oDWPKY*9(bQ{axvj__Iu7^ z0+l4tM)q#Y-rB_no;_REgdPjeJtxWkhvcZ$4pgd~Q`g1ckFCch%=98CA> zYnxsw3bY&0z4_Wq*rtJ3uK~|)~@^TJKQr@)Ss+9cDu_UXe=}#bd2Fhko*{thJ8EWA3(|9gNw}HDalwkr>8P$nR zjv#4vGqx?8$N-FU5HULD<%lUCch_Bai*pncQ1I!+ZM92gn%#Dq3FFtCq-cc70`u&}szFWCr7g?DP z4mORwqU132c!adjPWkH|{|Tore{Mq#?Yx1}Q&C(*MDWLzJDgN3aqtmc^B$U0Wtsfy zaH}X3{#6I~5wle*z2-P`?X?4MW#o!!?ADQ8`1w!Mo?z~=$uo+Z5ueb>bwMRZRSvnQ zs@@PRO`oYGN|+QB2wQAp##I9Qhlz?k01(nu^yGLHDo(03r&Ap98(uK1n*klExw;Am zREu{TR}Qam?4*cC_!O3H5NPINqiH)J9qm6d^4wM(@TOkx)C(z6LnWP4L6?625x=aZ z5>b9PA&F15D>XISKgr6K(i2KOe5RrcvUqO z-4pH8PRnc04PRoM4i%=(-N$sSYV<-tqfZ5{+dh2b4U^a9gmme*wVXM(%kN+nvhM|x zkK}}i9G&iuhu55EXG)wq-gr-mahYWd^Q|6FGiC46yfG!m2_xnBZs&^(56uV>wpg@k ztMM*-J7_=3^azbLLF;`D*ELb`C>NW~S`_K-h4w-!F#aejqRhX7X?O2tFGR$KO#oNJ zk~yIJx#9A_SsM^wzLW-&sn_O!wsWkR0?Dk5nv;Gf52{x;yo(V+ZLi9f5f zQ1+H=c0;g30nYAXN!n<%(_1e3@W?lIo=Z7&AqUn)r zgZB!st@41Z@#>|G{Hk=)DTd41aVb-x#8C4F_IrNpU41!*Kne~8rc)sD!?d_@4oJ>H z=~#Wr@7Onsi7aFbHKVjDI)$hqP5NlPu1z~OnEM94Ws)R0;sJuMW^m?jju{es#F%T6 zUM{q3|9t5;-$cOTxwNsth> zzi(g0v%sqZ2s;U*ZzTBszuscCvUjsQaTXIhktQd?*s?W3V$T-Z5)w36H4}kB&#Q3; z0rzO4aAa+qZ5aPI{^AxWP~dR2P_X+`&yO!5d;;&0)>l(W1dAPLLmO?M6-a4{pFHc!7R}_fR9P5)JB+Ld4ZZ4$eER0K12N%Nm zj1x-S(!LV*z^uz1y4L~ptrKlCjU9g@&)?^IER96_$K^3Ml$8WZq9$Lz>*3&e+sx+5B5k_30xi z;=vHiDBuBdB;^~4XYj`R&IR)$3uRRYxSE!^`88?1pn*CVKg{7(mOJD6m~wZ%<+|Cm z4Vmo5ae1$WRcSp7M~11+vS{A5D#9fwPp81vOBO&E2t;D;6fbiPY9no4&ld-I^|!OG8CFKj-k zL?-n0C=H8`s5C0i3BgzingMO;x^$i1#m=aDSs)$=dH(fKH?VSxoUU8L;{(Jv-E3OK zEC!gnqCWSe<}aELmtb67$2n2B=l<@~{5zJ&xc#0Kuhr^#My{b?mv}b^jqjB0jvy>l z^j7lNjDJ2n%A-SzrSRQaBxMVotXy0*iM2C0vZMb4<2~ov|?t zx~U7(5W39OuN9gwpMPTQl4>wk;^3Dzj0c&mp7TFz zs~d3&VtDlximTFj2^j-O9X)DT^XCZI`p+v)Ih0mXMg7m*%1YDN^s*1B=FS$L$=6g=g{sAL%@a z_B}c+fNWUOOiJ{(_IrJ2r!Q{Xcg#I3Ro_YVii-&q3jLD7o&lA6?nU>uxui}^Ww5*q zS>}ZSLYk}6)0O3n@jK^wV_k5Q;gQ-5^X3CTx~0!ps-AZG`0yko{OiUzO{D(0zkOUo z9x?J302RpnAZ>dB9Z}YZ({H;~cF{aWyjGzXV*33J?zDCOQ^WboEE^u(ztaVDxUNukH-6G?R;k6SZF;t;(qRA(BfR`g^k}1a>TycyDy1kI;;K3#_^Au zsIK+M)MM+@HQdyurYntN{)T_U>tB7iOCEvzW$LP>JVbSys5~|ak2*TfelV`1ctN3p s%FRk<&+lC4|7&LY|8M2s@n}~xKF53~r@bMYy)fZ$uywL&v)>fIdWx4&1}x( zh%n3MDEpeNpDW`3>Hm2=KJU-t{d~V(&)56?`Mlq+<3n_Iv=J9o5ET#*5J%ctxd6|V zfA_w?2e#l>`X5zrPRbM14XNSIzRGDtVi z9wx5`To^^YJbwVqr3VD*BL5BllkW@ox*nHUHof$d10PI43}R-!ZDFRrZFOz!ZtcXI zy!&go&~8##Ecx`_LFIR~O2obB|6 z?e-C&N6k9Ou9|6;0j5Q21tG1My^zL9=6tu7o4M}K7hd;ky@M|M7m@!;zwiVxjNOT$HboWs@^ z7``C8hTSpl!bkonC@Jt_sH+Ci0AA~8!BnGYIVVOXH0Yn5VUEQPxaV$D_}}&xyZ=+E#4UPNC|v27P3uarsR>-pYgZV$j_Bv+QuzU>S~x=ml8B zI2Oc!n>xGv4jmr1lrwCto6Ba+|zo3+20{k>dfIbX1O^4e(YN`E~Bc z_iqs7+X4p*aYRf(lju%9IQdY$z;=(xm!EIR*>+QbSkJA4PVal_$F_RzA@r6P>SVAL zH^bvctcICeYcA{(+u5(|s=8+nY7aWp4E5y2s1s2SntBErVa{3NvS*n^YB>EV6#4_% zHM-&4JwKV6Q*UlzpFs=AyZxS3_g}si>J_c!W+B8%b)Eg_Mux3o%K7z46cWZdg|BA!Bt)&oJx5BbouA`8l$6x;~Cc#aJ?~Gg0yjx;QxXZ7Bs zC4`<;zIar8b9$qVS86aBCOi=IE7dl^u^3vNM22L~9ONRS<6Wh@=Y;Yoy%u;qycYSy zX07Xy_xHpc;~t#isVH|?kG%dLx&OK(7`-%pIl-ikQM{DvuE0kLH7vz3d=2bC?^r2m z`(N0qV_CEFS#Yq=(t+RvlZIs!8Oja@HLM+t3GTfuX{1?}X8bYC4W$m=q?>2Ab(fG2 zk=%pNE&Wcr?c_(>dPevjHz*kW?AI5!wC2ZPENQy(j=Kz>KzJDEq@Q`L=Bhd9{nGCj zb6UJlB<_)suedr-fhQVbk#PS_y93w`jI$*d-WN8~Z02`lyn1kgls?|CkRzfzbMAG? zdO*jD`RR+ZQ3L!OIlfnfvmO^t4ZC#F=l0!3t&xRz+GkGCXwt&gck?RpD~#ur_ZF&} zq|X(U*y`Wl>uf~H^uQisgWU_0jfJ0kqU-0A5*cL}=fhn1K-i_pYf3KY_F9G$79oHg zJolQoE>rJ<#O2JUl=16SsqdQGqnyRK*!xqj*k*oJ?r$XUgC8QssKMEkVH4Dq zWfAt@sm|88`)eir=Dh&;yD=1*6)02&kG0{R#12k4AFC}W9|axOD$qyc09Q+h`F)gQ zkVm%s0{h&&9reo1K>%wSz2eCDU3)uG)kVceyFsSPWP=bkk=j6=fhoabA>5N8Cw*0z zWf@oQxhZW=`Jjo)To9PiiL-OJ9v9v4%`SL8y6|)rpKB^gT2BBCE+aOcl(I_%kcyCa zNxefJ7imUI%;GjshvU+BzPaf4SUD{oKO?Svf$7oqD)W)$8#BL9lS&CNu~N>ZI}cns zgj?DFh8-$crIjsq??$zva|a7t+K;O_d5Pb+4?3nW{KsdD{-2l>RWh$6ek!pv>-HP8^1$_`sY9Yzo6FWxz?Otm)HMtbGIhp9>{njnKyYu=fs ztXPX52G-bD`@^c$2r5*i4b8c?fK1V6s?xTmFu&T@;9@>qnI%TTRHs!28eGWlH)my% z{Eu0{AVIKUMGt7A4!}Ov|k6Zy~BUW6QL^)1HB;$b{E9z zrcPAPfz}WUf%vr(*zVrQ=-*Zo%=ZTz`)khA;3p;=WCBw#Zw=q|$d-$B@>93Q#ShJC z2ezHn;&gIdf*hnXg?(xtvO`a}tEmys-|$i5oo7kJ6%t0QSrts;WE8{{}{UUJBp|bu2)U!zJ85{`(*7Q$ILhL(k zdW`EtRr2ZLVDcz_!m{bx*S0%dclseP;(6gr3%vHu$5ZR`w`c^8pcFotJaahF`N1ZJ z3ayp<2>7im({j6nc2R5wLi>}1m__^99iLM?_>Ek5cPB=8mMN)c5f0&NV+zCTi;5QEB__QwSjwRjQOeQNSB$~v)Mz$;HFqdxegwqUMnDhb{jM}izu{kgOxB-igoax+ZN2c+s4w+ zm=${l1|Hy=yI->?gk|s@2L`{Mypl)JX_2n`FbaUrsNps1iV7~Kw(+B#dT|m^ui+kH zNS_qTU-X81hsw4`KY(#=52ExYB5yved zArDT6i$Hg%=2aLPIJ*8+sXpDauwGfB_V9xY5g_W<=S^2;j~R{kX{Ihbu8;ah08w~- zb^k=yb!oS|w!r+9_}Ufb0V@n|n-SZeRrz+J1##06E3>799~!O(F#gNUQv~|&kIi}8?N6ki4jgboO{j-?rI<(QbiuX78;mbf2y$}C4>w5CzL|j*b{pG z8B5hAVrrwFb%k+P6Qz#*y;o_iK9~lmT+NpQ8Mytc#Pa>AWvbu!ZnuzrwAQykwf3A@ zV}yGNkPL|sYb(w8(GryM5j{BdumBR1?-(ya1crTf&C-v4`XN&skUMjdS4GO^K%`52(~%6dhyT?2@lr$Z#z*XIKWQL+)#E@U zOXh9^vRNuTz(>_7p>LIjDknZ-R|U!d;}{M|wyS3Jm#QYPYB>P-%>fwLV^_%cpw^PT0v~6c6m9^@W>}3Xnwk`t|Xeu61L2*FRv*33{>} #import "serviceInterface.h" +#import + + // This object implements the protocol which we have defined. It provides the actual behavior for the service. It is 'exported' by the service to make it available to the process hosting the service over an NSXPCConnection. @interface remoteTaskService : NSObject - -// +//default service +(remoteTaskService *)defaultService; @end - -//convert a socket type in to string -NSString* socketType2String(int type); - -//convert a socket family into string -NSString* socketFamily2String(int family); - -//convert a socket protocol into string -NSString* socketProto2String(int proto); - -//convert a socket state into string -NSString* socketState2String(int state); diff --git a/remoteTaskService/remoteTaskService.m b/remoteTaskService/remoteTaskService.m index edfe719..348bdfd 100644 --- a/remoteTaskService/remoteTaskService.m +++ b/remoteTaskService/remoteTaskService.m @@ -10,81 +10,12 @@ #import "Utilities.h" #import "remoteTaskService.h" - -#import -#import -#import -#import -#import -#import -#import -#import -#import +#import #import #import -#import -#import -#import - -//socket states -// ->note, index correspondes to numberic value -static const char* socketStates[] = -{ - "closed", - "listening", - "syn sent", - "syn received", - "established", - "close/wait", - "fin wait 1", - "closing", - "last act", - "fin wait 2", - "time wait", -}; - -static const char *socketFamilies[] = -{ - "AF_UNSPEC", - "AF_UNIX", - "AF_INET", - "AF_IMPLINK", - "AF_PUP", - "AF_CHAOS", - "AF_NS", - "AF_ISO", - "AF_ECMA", - "AF_DATAKIT", - "AF_CCITT", - "AF_SNA", - "AF_DECnet", - "AF_DLI", - "AF_LAT", - "AF_HYLINK", - "AF_APPLETALK", - "AF_ROUTE", - "AF_LINK", - "#define", - "AF_COIP", - "AF_CNT", - "pseudo_AF_RTIP", - "AF_IPX", - "AF_SIP", - "pseudo_AF_PIP", - "pseudo_AF_BLUE", - "AF_NDRV", - "AF_ISDN", - "pseudo_AF_KEY", - "AF_INET6", - "AF_NATM", - "AF_SYSTEM", - "AF_NETBIOS", - "AF_PPP", - "pseudo_AF_HDRCMPLT", - "AF_RESERVED_36", -}; -#define SOCKET_FAMILY_MAX (int)(sizeof(socketFamilies)/sizeof(char *)) - +#import +#import +#import //32bit struct dyld_image_info_32 { @@ -105,9 +36,198 @@ struct dyld_image_info_32 { return shared; } +//get task's commandline args +// ->args returned in array arg +-(void)getTaskArgs:(NSNumber*)taskPID withReply:(void (^)(NSMutableArray *))reply +{ + //task's args + NSMutableArray* arguments = nil; + + //'management info base' array + int mib[3] = {0}; + + //system's size for max args + int systemMaxArgs = 0; + + //process's args + char* taskArgs = NULL; + + //# of args + int numberOfArgs = 0; + + //start of (each) arg + char* argStart = NULL; + + //size of buffers, etc + size_t size = 0; + + //parser pointer + char* parser = NULL; + + //init mib + // ->want system's size for max args + mib[0] = CTL_KERN; + mib[1] = KERN_ARGMAX; + + //alloc array for args + arguments = [NSMutableArray array]; + + //set size + size = sizeof(systemMaxArgs); + + //get system's size for max args + if(-1 == sysctl(mib, 2, &systemMaxArgs, &size, NULL, 0)) + { + //bail + goto bail; + } + + //alloc space for args + taskArgs = malloc(systemMaxArgs); + if(NULL == taskArgs) + { + //bail + goto bail; + } + + //init mib + // ->want process args + mib[0] = CTL_KERN; + mib[1] = KERN_PROCARGS2; + mib[2] = taskPID.intValue; + + //set size + size = (size_t)systemMaxArgs; + + //get process's args + if(-1 == sysctl(mib, 3, taskArgs, &size, NULL, 0)) + { + //bail + goto bail; + } + + //sanity check + // ->ensure buffer is somewhat sane + if(size <= sizeof(int)) + { + //bail + goto bail; + } + + //extract number of args + // ->at start of buffer + memcpy(&numberOfArgs, taskArgs, sizeof(numberOfArgs)); + + //extract task's name + // ->follows # of args (int) and is NULL-terminated + [arguments addObject:[NSString stringWithUTF8String:taskArgs + sizeof(int)]]; + + //init point to start of args + // ->they start right after # of args + parser = taskArgs + sizeof(numberOfArgs); + + //scan until end of task's NULL-terminated path + while(parser < &taskArgs[size]) + { + //scan till NULL-terminator + if(0x0 == *parser) + { + //end of exe name + break; + } + + //next char + parser++; + } + + //sanity check + // ->make sure end-of-buffer wasn't reached + if(parser == &taskArgs[size]) + { + //bail + goto bail; + } + + //skip all trailing NULLs + // ->scan will non-NULL is found + while(parser < &taskArgs[size]) + { + //scan till NULL-terminator + if(0x0 != *parser) + { + //ok, got to argv[0] + break; + } + + //next char + parser++; + } + + //sanity check + // ->(again), make sure end-of-buffer wasn't reached + if(parser == &taskArgs[size]) + { + //bail + goto bail; + } + + //parser should now point to argv[0], task name + // ->init arg start + argStart = parser; + + //keep scanning until all args are found + // ->each is NULL-terminated + while(parser < &taskArgs[size]) + { + //each arg is NULL-terminated + // ->so scan till NULL, then save into array + if(*parser == '\0') + { + //save arg + if(NULL != argStart) + { + //save + [arguments addObject:[NSString stringWithUTF8String:argStart]]; + } + + //init string pointer to (possibly) next arg + argStart = ++parser; + + //bail if we've hit arg cnt + // ->note: added full process path as faux arg[0], so add 1 + if(arguments.count == numberOfArgs + 1) + { + //bail + break; + } + } + + //next char + parser++; + } + +//bail +bail: + + //free process args + if(NULL != taskArgs) + { + //free + free(taskArgs); + + //reset + taskArgs = NULL; + } + + //invoke reply block + reply(arguments); + + return; +} + //enumerate dylibs for a specified task // ->dylibs returned in array arg --(void)enumerateDylibs:(NSNumber*)taskPID withReply:(void (^)(NSMutableArray *))reply; +-(void)enumerateDylibs:(NSNumber*)taskPID withReply:(void (^)(NSMutableArray *))reply { //dylibs NSMutableArray* dylibPaths = nil; @@ -368,7 +488,7 @@ bail: // ->assume vmmap is 'fat', and exec 32bit version (pre El Capitan) else { - //exec 'file' to get file type + //exec vmmap, but it's i386 version results = [[NSString alloc] initWithData:execTask(ARCH, @[@"-i386", VMMAP, [pid stringValue]]) encoding:NSUTF8StringEncoding]; } } @@ -428,6 +548,12 @@ bail: //remove dups [dylibs setArray:[[[NSSet setWithArray:dylibs] allObjects] mutableCopy]]; + + //TODO: remove + if(pid.intValue == 13084) + { + syslog(LOG_ERR, "TASK-EXPLORER: %s\n", dylibs.description.UTF8String); + } //bail bail: @@ -438,7 +564,7 @@ bail: //enumerate open files // ->accomplish this via lsof, since proc_pidinfo() misses some files... --(void)enumerateFiles:(NSNumber*)taskPID withReply:(void (^)(NSMutableArray *))reply; +-(void)enumerateFiles:(NSNumber*)taskPID withReply:(void (^)(NSMutableArray *))reply { //results NSData* results = nil; @@ -551,7 +677,7 @@ bail: //TODO: soi_rcv/soi_snd to get packets!? //enumerate network connections --(void)enumerateNetwork:(NSNumber*)taskPID withReply:(void (^)(NSMutableArray *))reply; +-(void)enumerateNetwork:(NSNumber*)taskPID withReply:(void (^)(NSMutableArray *))reply { //task's sockets NSMutableArray* sockets = nil; @@ -702,21 +828,21 @@ bail: } //set type - socket[KEY_SOCKET_TYPE] = socketType2String(socketInfo.psi.soi_type); + socket[KEY_SOCKET_TYPE] = [NSNumber numberWithInt:socketInfo.psi.soi_type]; //set family // ->for now this will only be 'AF_INET' or 'AF_INET6' - socket[KEY_SOCKET_FAMILY] = socketFamily2String(socketInfo.psi.soi_family); + socket[KEY_SOCKET_FAMILY] = [NSNumber numberWithInt:socketInfo.psi.soi_family]; //set protocol - socket[KEY_SOCKET_PROTO] = socketProto2String(socketInfo.psi.soi_protocol); + socket[KEY_SOCKET_PROTO] = [NSNumber numberWithInt:socketInfo.psi.soi_protocol]; //get state // ->only for stream stockets though if(SOCK_STREAM == socketInfo.psi.soi_type) { //set state - socket[KEY_SOCKET_STATE] = socketState2String(socketInfo.psi.soi_proto.pri_tcp.tcpsi_state); + socket[KEY_SOCKET_STATE] = [NSNumber numberWithInt:socketInfo.psi.soi_proto.pri_tcp.tcpsi_state]; } //add @@ -724,7 +850,6 @@ bail: }//all FDs - //bail bail: @@ -744,122 +869,3 @@ bail: @end -//convert a socket type into string -NSString* socketType2String(int type) -{ - //socket type - NSString* socketType = nil; - - //convert - switch(type) - { - //stream - case SOCK_STREAM: - socketType = @"SOCK_STREAM"; - break; - - //dgram - case SOCK_DGRAM: - socketType = @"SOCK_DGRAM"; - break; - - //raw - case SOCK_RAW: - socketType = @"SOCK_RAW"; - break; - - //rdm - case SOCK_RDM: - socketType = @"SOCK_RDM"; - break; - - //seq packet - case SOCK_SEQPACKET: - socketType = @"SOCK_SEQPACKET"; - break; - - default: - break; - } - - return socketType; -} - - -//convert a socket family into string -NSString* socketFamily2String(int family) -{ - //socket family - NSString* socketFamily = nil; - - //sanity check - if( (family < 0) || - (family >= SOCKET_FAMILY_MAX) ) - { - //bail - goto bail; - } - - //init socket family string - socketFamily = [NSString stringWithUTF8String:socketFamilies[family]]; - -//bail -bail: - - return socketFamily; -} - -//convert a socket protocol into string -NSString* socketProto2String(int proto) -{ - //socket proto - NSString* socketProto = nil; - - //proto struct - struct protoent *protoInfo = NULL; - - //get proto info - protoInfo = getprotobynumber(proto); - - //sanity check - if(NULL == protoInfo) - { - //bail - goto bail; - } - - //init proto string - // ->name comes from struct - socketProto = [NSString stringWithUTF8String:protoInfo->p_name]; - -//bail -bail: - - return socketProto; -} - - -//convert a socket state into string -NSString* socketState2String(int state) -{ - //socket proto - NSString* socketState = nil; - - //set state - if(state < TCP_NSTATES) - { - //set state - socketState = [NSString stringWithUTF8String:socketStates[state]]; - } - //invalid/unknown socket state - else - { - socketState = [NSString stringWithFormat:@"unknown state (%d)", state]; - } - - return socketState; -} - - - - diff --git a/serviceInterface.h b/serviceInterface.h index e84b9b8..bbad03d 100644 --- a/serviceInterface.h +++ b/serviceInterface.h @@ -12,7 +12,10 @@ #import "Task.h" @protocol remoteTaskProto -//- (void)compressFile:(NSFileHandle *)inFile toFile:(NSFileHandle *)outFile withReply:(void (^)(NSError *error))reply; + +//get task's commandline args +// ->args returned in array arg +-(void)getTaskArgs:(NSNumber*)taskPID withReply:(void (^)(NSMutableArray *))reply; //enumerate loaded dylibs in a task -(void)enumerateDylibs:(NSNumber*)taskPID withReply:(void (^)(NSMutableArray *))reply;