/** This class was created because proc_listallpids never resolves properly in the entire project is built as ObjC++. Tried to keep everything that is objective-c related isolated to this class. This class has two main purposes, to convert a ProcessName into a pid via + (pid_t) find_process:(const char*) name And to receive a distributed notification from CycriptLoader.dylib after it successfully sets up a server inside the library that we have injected. Ideally it'd be much nicer just to drop into cycript from our current process using the port # we received. Also it'd be nice to not use distributed notifications, but it was the quickest and easiest way to get this done. */ #import "FindProcess.h" #include #include #include #include #include #include #import #include #import #include #include #include #include #include #include #include #include #import #import @interface NSDistributedNotificationCenter : NSNotificationCenter + (id)defaultCenter; - (void)addObserver:(id)arg1 selector:(SEL)arg2 name:(id)arg3 object:(id)arg4; - (void)postNotificationName:(id)arg1 object:(id)arg2 userInfo:(id)arg3; @end #define DLog(format, ...) CFShow((__bridge CFStringRef)[NSString stringWithFormat:format, ## __VA_ARGS__]); extern char*** _NSGetEnviron(void); extern int proc_listallpids(void*, int); extern int proc_pidpath(int, void*, uint32_t); static int process_buffer_size = 4096; @implementation FindProcess //we receive cycriptPortAvailable from CycriptLoader.dylib after its successfully started a server. - (void)startListeningForAppName:(NSString *)appName { NSDistributedNotificationCenter *notificationCenter = [NSDistributedNotificationCenter defaultCenter]; [notificationCenter addObserver:self selector:@selector(portAvailable:) name:@"cycriptPortAvailable" object:nil]; } - (void)portAvailable:(NSNotification *)n { NSString *port = [n userInfo][@"port"]; //DLog(@"we got a port! %@", port); DLog(@"cycript started on port: %@! Press return & then run the following command to connect:\n", port); DLog(@"cycript -r 127.0.0.1:%@", port); //exit(0); //when we exited here it would tear down the injected process, no idea why. } //plucked and modified from AppSyncUnified + (pid_t) find_process:(const char*) name { pid_t *pid_buffer; char path_buffer[MAXPATHLEN]; int count, i, ret; boolean_t res = FALSE; pid_t ppid_ret = 0; pid_buffer = (pid_t*)calloc(1, process_buffer_size); assert(pid_buffer != NULL); count = proc_listallpids(pid_buffer, process_buffer_size); if(count) { for(i = 0; i < count; i++) { pid_t ppid = pid_buffer[i]; ret = proc_pidpath(ppid, (void*)path_buffer, sizeof(path_buffer)); if(ret < 0) { printf("(%s:%d) proc_pidinfo() call failed.\n", __FILE__, __LINE__); continue; } if(strstr(path_buffer, name)) { res = TRUE; ppid_ret = ppid; break; } } } free(pid_buffer); return ppid_ret; } @end