FindProcess.m 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. /**
  2. This class was created because proc_listallpids never resolves properly in the entire project
  3. is built as ObjC++. Tried to keep everything that is objective-c related isolated to this class.
  4. This class has two main purposes, to convert a ProcessName into a pid via
  5. + (pid_t) find_process:(const char*) name
  6. And to receive a distributed notification from CycriptLoader.dylib after it successfully
  7. sets up a server inside the library that we have injected.
  8. Ideally it'd be much nicer just to drop into cycript from our current process using the port #
  9. we received. Also it'd be nice to not use distributed notifications, but it was the quickest and
  10. easiest way to get this done.
  11. */
  12. #import "FindProcess.h"
  13. #include <stdio.h>
  14. #include <stdint.h>
  15. #include <mach/mach.h>
  16. #include <dlfcn.h>
  17. #include <pthread.h>
  18. #include <unistd.h>
  19. #import <Foundation/Foundation.h>
  20. #include <mach-o/dyld.h>
  21. #import <objc/runtime.h>
  22. #include <sys/cdefs.h>
  23. #include <sys/types.h>
  24. #include <sys/param.h>
  25. #include <mach/boolean.h>
  26. #include <dispatch/dispatch.h>
  27. #include <stdlib.h>
  28. #include <spawn.h>
  29. #include <assert.h>
  30. #import <Foundation/Foundation.h>
  31. #import <Security/Security.h>
  32. @interface NSDistributedNotificationCenter : NSNotificationCenter
  33. + (id)defaultCenter;
  34. - (void)addObserver:(id)arg1 selector:(SEL)arg2 name:(id)arg3 object:(id)arg4;
  35. - (void)postNotificationName:(id)arg1 object:(id)arg2 userInfo:(id)arg3;
  36. @end
  37. #define DLog(format, ...) CFShow((__bridge CFStringRef)[NSString stringWithFormat:format, ## __VA_ARGS__]);
  38. extern char*** _NSGetEnviron(void);
  39. extern int proc_listallpids(void*, int);
  40. extern int proc_pidpath(int, void*, uint32_t);
  41. static int process_buffer_size = 4096;
  42. @implementation FindProcess
  43. //we receive cycriptPortAvailable from CycriptLoader.dylib after its successfully started a server.
  44. - (void)startListeningForAppName:(NSString *)appName {
  45. NSDistributedNotificationCenter *notificationCenter = [NSDistributedNotificationCenter defaultCenter];
  46. [notificationCenter addObserver:self selector:@selector(portAvailable:)
  47. name:@"cycriptPortAvailable" object:nil];
  48. }
  49. - (void)portAvailable:(NSNotification *)n {
  50. NSString *port = [n userInfo][@"port"];
  51. //DLog(@"we got a port! %@", port);
  52. DLog(@"cycript started on port: %@! Press return & then run the following command to connect:\n", port);
  53. DLog(@"cycript -r 127.0.0.1:%@", port);
  54. //exit(0); //when we exited here it would tear down the injected process, no idea why.
  55. }
  56. //plucked and modified from AppSyncUnified
  57. + (pid_t) find_process:(const char*) name {
  58. pid_t *pid_buffer;
  59. char path_buffer[MAXPATHLEN];
  60. int count, i, ret;
  61. boolean_t res = FALSE;
  62. pid_t ppid_ret = 0;
  63. pid_buffer = (pid_t*)calloc(1, process_buffer_size);
  64. assert(pid_buffer != NULL);
  65. count = proc_listallpids(pid_buffer, process_buffer_size);
  66. if(count) {
  67. for(i = 0; i < count; i++) {
  68. pid_t ppid = pid_buffer[i];
  69. ret = proc_pidpath(ppid, (void*)path_buffer, sizeof(path_buffer));
  70. if(ret < 0) {
  71. printf("(%s:%d) proc_pidinfo() call failed.\n", __FILE__, __LINE__);
  72. continue;
  73. }
  74. if(strstr(path_buffer, name)) {
  75. res = TRUE;
  76. ppid_ret = ppid;
  77. break;
  78. }
  79. }
  80. }
  81. free(pid_buffer);
  82. return ppid_ret;
  83. }
  84. @end