mirror of
https://github.com/objective-see/TaskExplorer.git
synced 2026-03-22 07:02:39 +00:00
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)
This commit is contained in:
+3
-1
@@ -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
|
||||
|
||||
|
||||
@@ -332,4 +332,7 @@
|
||||
//hotkey 'i'
|
||||
#define KEYCODE_I 0x22
|
||||
|
||||
//unknown task
|
||||
#define TASK_PATH_UNKNOWN @"<unknown>"
|
||||
|
||||
#endif
|
||||
|
||||
+29
-3
@@ -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<task.arguments.count; index++)
|
||||
{
|
||||
//add arg
|
||||
[taskArguments appendFormat:@"%@ ", task.arguments[index]];
|
||||
}
|
||||
|
||||
//set args into text field
|
||||
if(0 != taskArguments.length)
|
||||
{
|
||||
//add
|
||||
self.arguments.stringValue = taskArguments;
|
||||
}
|
||||
}
|
||||
|
||||
//set path
|
||||
[self.path setStringValue:[self valueForStringItem:task.binary.path default:@"unknown"]];
|
||||
|
||||
|
||||
@@ -7,8 +7,73 @@
|
||||
//
|
||||
|
||||
#import "ItemBase.h"
|
||||
|
||||
#import <netdb.h>
|
||||
#import <arpa/inet.h>
|
||||
#import <netinet/tcp_fsm.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
//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
|
||||
{
|
||||
|
||||
|
||||
+121
-8
@@ -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
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -14,20 +14,10 @@
|
||||
#import "AppDelegate.h"
|
||||
#import "remoteTaskService.h"
|
||||
|
||||
#import <mach-o/dyld_images.h>
|
||||
#import <mach/mach_init.h>
|
||||
#import <mach/mach_vm.h>
|
||||
#import <sys/types.h>
|
||||
#import <mach/mach.h>
|
||||
#import <sys/ptrace.h>
|
||||
#import <sys/wait.h>
|
||||
#import <syslog.h>
|
||||
#import <libproc.h>
|
||||
#import <sys/sysctl.h>
|
||||
#import <sys/proc_info.h>
|
||||
#import <libproc.h>
|
||||
#import <arpa/inet.h>
|
||||
#import <netinet/tcp_fsm.h>
|
||||
#import <syslog.h>
|
||||
|
||||
|
||||
@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:)
|
||||
|
||||
+15
-25
@@ -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];
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
BIN
Binary file not shown.
+56
-17
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 4.3 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
@@ -6,27 +6,16 @@
|
||||
// Copyright (c) 2015 Objective-See, LLC. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "serviceInterface.h"
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
|
||||
// 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 <remoteTaskProto, NSXPCListenerDelegate>
|
||||
|
||||
|
||||
//
|
||||
//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);
|
||||
|
||||
@@ -10,81 +10,12 @@
|
||||
#import "Utilities.h"
|
||||
#import "remoteTaskService.h"
|
||||
|
||||
|
||||
#import <mach-o/dyld_images.h>
|
||||
#import <mach/mach_init.h>
|
||||
#import <mach/mach_vm.h>
|
||||
#import <sys/types.h>
|
||||
#import <mach/mach.h>
|
||||
#import <sys/ptrace.h>
|
||||
#import <sys/wait.h>
|
||||
#import <sys/sysctl.h>
|
||||
#import <sys/proc_info.h>
|
||||
#import <syslog.h>
|
||||
#import <libproc.h>
|
||||
#import <arpa/inet.h>
|
||||
#import <netinet/tcp_fsm.h>
|
||||
#import <netdb.h>
|
||||
#import <syslog.h>
|
||||
|
||||
//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 <sys/sysctl.h>
|
||||
#import <mach/mach_vm.h>
|
||||
#import <mach-o/dyld_images.h>
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+4
-1
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user