main.m 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220
  1. #import <Foundation/Foundation.h>
  2. #include <stdio.h>
  3. #include <mach/mach.h>
  4. #include <mach/error.h>
  5. #include <string.h>
  6. #include <unistd.h>
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include "helpers/patchfinder64.h"
  10. #include "kern_utils.h"
  11. #include "helpers/kmem.h"
  12. #include "helpers/kexecute.h"
  13. #include "mach/jailbreak_daemonServer.h"
  14. #import <sys/param.h>
  15. //more stuff from electra jailbreakd
  16. #define CS_OPS_STATUS 0 /* return status */
  17. #define CS_GET_TASK_ALLOW 0x0000004 /* has get-task-allow entitlement */
  18. #define CS_INSTALLER 0x0000008 /* has installer entitlement */
  19. #define CS_HARD 0x0000100 /* don't load invalid pages */
  20. #define CS_KILL 0x0000200 /* kill process if it becomes invalid */
  21. #define CS_RESTRICT 0x0000800 /* tell dyld to treat restricted */
  22. #define CS_PLATFORM_BINARY 0x4000000 /* this is a platform binary */
  23. #define CS_DEBUGGED 0x10000000 /* process is currently or has previously been debugged and allowed to run with invalid pages */
  24. int csops(pid_t pid, unsigned int ops, void * useraddr, size_t usersize);
  25. #define PROC_PIDPATHINFO_MAXSIZE (4 * MAXPATHLEN)
  26. int proc_pidpath(pid_t pid, void *buffer, uint32_t buffersize);
  27. typedef boolean_t (*dispatch_mig_callback_t)(mach_msg_header_t *message, mach_msg_header_t *reply);
  28. mach_msg_return_t dispatch_mig_server(dispatch_source_t ds, size_t maxmsgsz, dispatch_mig_callback_t callback);
  29. kern_return_t bootstrap_check_in(mach_port_t bootstrap_port, const char *service, mach_port_t *server_port);
  30. #define JAILBREAKD_COMMAND_ENTITLE 1
  31. #define JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT 2
  32. #define JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT_FROM_XPCPROXY 3
  33. #define JAILBREAKD_COMMAND_FIXUP_SETUID 4
  34. #define JAILBREAKDDEBUG 1
  35. mach_port_t tfpzero;
  36. uint64_t kernel_base;
  37. uint64_t kernel_slide;
  38. #define MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT 6
  39. int memorystatus_control(uint32_t command, int32_t pid, uint32_t flags, void *buffer, size_t buffersize);
  40. int remove_memory_limit(void) {
  41. return memorystatus_control(MEMORYSTATUS_CMD_SET_JETSAM_TASK_LIMIT, getpid(), 0, NULL, 0);
  42. }
  43. int is_valid_command(uint8_t command) {
  44. return (command == JAILBREAKD_COMMAND_ENTITLE ||
  45. command == JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT ||
  46. command == JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT_FROM_XPCPROXY ||
  47. command == JAILBREAKD_COMMAND_FIXUP_SETUID);
  48. }
  49. int handle_command(uint8_t command, uint32_t pid) {
  50. if (!is_valid_command(command)) {
  51. NSLog(@"Invalid command recieved.");
  52. return 1;
  53. }
  54. char *name = proc_name(pid);
  55. if (command == JAILBREAKD_COMMAND_ENTITLE) {
  56. NSLog(@"JAILBREAKD_COMMAND_ENTITLE PID: %d NAME: %s", pid, name);
  57. setcsflagsandplatformize(pid);
  58. }
  59. if (command == JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT) {
  60. NSLog(@"JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT PID: %d NAME: %s", pid, name);
  61. setcsflagsandplatformize(pid);
  62. kill(pid, SIGCONT);
  63. }
  64. if (command == JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT_FROM_XPCPROXY) {
  65. #ifdef JAILBREAKDDEBUG
  66. fprintf(stderr,"JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT_FROM_XPCPROXY PID: %d\n", pid);
  67. #endif
  68. __block int PID = pid;
  69. dispatch_queue_t queue = dispatch_queue_create("org.coolstar.jailbreakd.delayqueue", NULL);
  70. dispatch_async(queue, ^{
  71. char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
  72. bzero(pathbuf, sizeof(pathbuf));
  73. int tries = 0;
  74. int ret = proc_pidpath(PID, pathbuf, sizeof(pathbuf));
  75. while (ret > 0 && strcmp(pathbuf, "/usr/libexec/xpcproxy") == 0 && tries < 5000){
  76. proc_pidpath(PID, pathbuf, sizeof(pathbuf));
  77. usleep(100);
  78. tries++;
  79. }
  80. if (tries >= 5000){
  81. fprintf(stderr, "Warning: xpcproxy timer timed out for PID %d\n", pid);
  82. }
  83. uint32_t flags;
  84. csops(pid, CS_OPS_STATUS, &flags, 0);
  85. #ifdef JAILBREAKDDEBUG
  86. fprintf(stderr, "Waiting for CSFlags to reset for PID %d...\n", pid);
  87. #endif
  88. tries = 0;
  89. while ((flags & (CS_PLATFORM_BINARY | CS_INSTALLER | CS_GET_TASK_ALLOW | CS_DEBUGGED)) != 0 &&
  90. (flags & (CS_RESTRICT | CS_HARD | CS_KILL)) == 0 &&
  91. tries < 5000){
  92. csops(pid, CS_OPS_STATUS, &flags, 0);
  93. usleep(100);
  94. tries++;
  95. }
  96. if (tries >= 5000){
  97. fprintf(stderr, "Warning: CSFlag timer timed out for PID %d\n", pid);
  98. }
  99. setcsflagsandplatformize(PID);
  100. kill(PID, SIGCONT);
  101. #ifdef JAILBREAKDDEBUG
  102. fprintf(stderr,"Called SIGCONT on pid %d from ENTITLE_AND_SIGCONT_FROM_XPCPROXY\n", PID);
  103. #endif
  104. });
  105. dispatch_release(queue);
  106. }
  107. /*
  108. if (command == JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT_FROM_XPCPROXY) {
  109. NSLog(@"JAILBREAKD_COMMAND_ENTITLE_AND_SIGCONT_FROM_XPCPROXY PID: %d NAME: %s", pid, name);
  110. __block int blk_pid = pid;
  111. dispatch_queue_t queue = dispatch_queue_create("org.coolstar.jailbreakd.delayqueue", NULL);
  112. dispatch_async(queue, ^{
  113. char pathbuf[PROC_PIDPATHINFO_MAXSIZE];
  114. bzero(pathbuf, sizeof(pathbuf));
  115. int ret = proc_pidpath(blk_pid, pathbuf, sizeof(pathbuf));
  116. while (ret > 0 && strcmp(pathbuf, "/usr/libexec/xpcproxy") == 0) {
  117. proc_pidpath(blk_pid, pathbuf, sizeof(pathbuf));
  118. usleep(100);
  119. }
  120. setcsflagsandplatformize(blk_pid);
  121. kill(blk_pid, SIGCONT);
  122. });
  123. dispatch_release(queue);
  124. }
  125. */
  126. if (command == JAILBREAKD_COMMAND_FIXUP_SETUID) {
  127. NSLog(@"JAILBREAKD_FIXUP_SETUID PID: %d NAME: %s", pid, name);
  128. fixupsetuid(pid);
  129. }
  130. free(name);
  131. return 0;
  132. }
  133. kern_return_t jbd_call(mach_port_t server_port, uint8_t command, uint32_t pid) {
  134. return (handle_command(command, pid) == 0) ? KERN_SUCCESS : KERN_FAILURE;
  135. }
  136. int main(int argc, char **argv, char **envp) {
  137. kern_return_t err;
  138. NSLog(@"start");
  139. unlink("/var/tmp/jailbreakd.pid");
  140. kernel_base = strtoull(getenv("KernelBase"), NULL, 16);
  141. kernprocaddr = strtoull(getenv("KernProcAddr"), NULL, 16);
  142. offset_zonemap = strtoull(getenv("ZoneMapOffset"), NULL, 16);
  143. kernel_slide = kernel_base - 0xFFFFFFF007004000;
  144. remove_memory_limit();
  145. err = host_get_special_port(mach_host_self(), HOST_LOCAL_NODE, 4, &tfpzero);
  146. if (err != KERN_SUCCESS) {
  147. NSLog(@"host_get_special_port 4: %s", mach_error_string(err));
  148. return -1;
  149. }
  150. init_kernel(kernel_base, NULL);
  151. init_kexecute();
  152. NSLog(@"[jailbreakd] tfp: 0x%016llx", (uint64_t)tfpzero);
  153. NSLog(@"[jailbreakd] slide: 0x%016llx", kernel_slide);
  154. NSLog(@"[jailbreakd] kernproc: 0x%016llx", kernprocaddr);
  155. NSLog(@"[jailbreakd] zonemap: 0x%016llx", offset_zonemap);
  156. // set up mach stuff
  157. mach_port_t server_port;
  158. if ((err = bootstrap_check_in(bootstrap_port, "zone.sparkes.jailbreakd", &server_port))) {
  159. NSLog(@"Failed to check in: %s", mach_error_string(err));
  160. return -1;
  161. }
  162. dispatch_source_t server = dispatch_source_create(DISPATCH_SOURCE_TYPE_MACH_RECV, server_port, 0, dispatch_get_main_queue());
  163. dispatch_source_set_event_handler(server, ^{
  164. dispatch_mig_server(server, jbd_jailbreak_daemon_subsystem.maxsize, jailbreak_daemon_server);
  165. });
  166. dispatch_resume(server);
  167. // Now ready for connections!
  168. NSLog(@"mach server now running!");
  169. FILE *f = fopen("/var/tmp/jailbreakd.pid", "w");
  170. fprintf(f, "%d\n", getpid());
  171. fclose(f);
  172. // Start accepting connections
  173. dispatch_main();
  174. term_kexecute();
  175. return 0;
  176. }