error_t increase_priority (void) { mach_port_t pset = MACH_PORT_NULL, psetcntl = MACH_PORT_NULL; error_t err; err = thread_get_assignment (mach_thread_self (), &pset); if (err) goto out; err = host_processor_set_priv (_hurd_host_priv, pset, &psetcntl); if (err) goto out; err = thread_max_priority (mach_thread_self (), psetcntl, 0); if (err) goto out; err = task_priority (mach_task_self (), 2, 1); out: if (MACH_PORT_VALID (pset)) mach_port_deallocate (mach_task_self (), pset); if (MACH_PORT_VALID (psetcntl)) mach_port_deallocate (mach_task_self (), psetcntl); return err; }
kern_return_t lotto_pset_port (mach_port_t *pset_port, boolean_t need_privileged) { /* * modifies: pset_port * effects: Attempts to obtain a port for the current processor set. * If unable to obtain a privileged port, an ordinary port is * returned unless need_privileged is set. If successful, sets * pset_port and returns KERN_SUCCESS, otherwise KERN_FAILURE. * */ host_t auth; // mach_port_t auth, pset; kern_return_t result; processor_set_name_t default_pset, pset; /* obtain priv host port */ // auth = mach_host_priv_self(); // if (!MACH_PORT_VALID(auth)) // { /* fail if unable and need priv */ if (need_privileged) return(KERN_FAILURE); /* fallback to unprivileged auth */ auth = mach_host_self(); // } /* obtain default pset port */ printf("Get Default pset for auth %d\n",auth); result = processor_set_default(auth, &default_pset); if (result != KERN_SUCCESS) return(result); printf("Get Default pset for auth %d\n",auth); /* obtain priv pset port */ result = host_processor_set_priv(auth, default_pset, &pset); if (result != KERN_SUCCESS) { /* fail uf unable and need priv */ if (need_privileged) return(result); /* fallback to default pset port */ pset = default_pset; } /* set pset port */ *pset_port = pset; /* everything OK */ return(KERN_SUCCESS); }
/// Iterate all tasks and update/create their information. /// @return The call returns -1 on error, 0 indicate successful completion. static int read_tasks_table(void) { kern_return_t kr; processor_set_t pset; task_array_t tasks; processor_set_name_array_t psets; mach_msg_type_number_t i, j, pcnt, tcnt; kr = host_processor_sets(task_manager_port, &psets, &pcnt); if (kr != KERN_SUCCESS) { syslog(LOG_ERR, "error in host_processor_sets(): %s", mach_error_string(kr)); return -1; } for (i = 0; i < pcnt; i++) { kr = host_processor_set_priv(task_manager_port, psets[i], &pset); if (kr != KERN_SUCCESS) { syslog(LOG_ERR, "error in host_processor_set_priv(): %s", mach_error_string(kr)); return -1; } kr = processor_set_tasks(pset, &tasks, &tcnt); if (kr != KERN_SUCCESS) { syslog(LOG_ERR, "error in processor_set_tasks(): %s", mach_error_string(kr)); return -1; } for (j = 0; j < tcnt; j++) { read_task_info(tasks[j]); kr = mach_port_deallocate(mach_task_self(), tasks[j]); if (kr != KERN_SUCCESS) { syslog(LOG_WARNING, "%s, error in mach_port_deallocate(): %s", __FUNCTION__, mach_error_string(kr)); } } kr = vm_deallocate(mach_task_self(), (vm_address_t)tasks, tcnt * sizeof(processor_set_t)); kr = mach_port_deallocate(mach_task_self(), pset); kr = mach_port_deallocate(mach_task_self(), psets[i]); } kr = vm_deallocate(mach_task_self(), (vm_address_t)psets, pcnt * sizeof(processor_set_t)); return 0; }
static task_t task_for_pid_workaround(int pid) { host_t myhost = mach_host_self(); mach_port_t psDefault = 0; mach_port_t psDefault_control = 0; task_array_t tasks = NULL; mach_msg_type_number_t numTasks = 0; kern_return_t kr = -1; int i; if (pid == -1) { return MACH_PORT_NULL; } kr = processor_set_default (myhost, &psDefault); if (kr != KERN_SUCCESS) { return MACH_PORT_NULL; } kr = host_processor_set_priv (myhost, psDefault, &psDefault_control); if (kr != KERN_SUCCESS) { // eprintf ("host_processor_set_priv failed with error 0x%x\n", kr); //mach_error ("host_processor_set_priv",kr); return MACH_PORT_NULL; } numTasks = 0; kr = processor_set_tasks (psDefault_control, &tasks, &numTasks); if (kr != KERN_SUCCESS) { // eprintf ("processor_set_tasks failed with error %x\n", kr); return MACH_PORT_NULL; } if (pid == 0) { /* kernel task */ return tasks[0]; } for (i = 0; i < numTasks; i++) { int pid2 = -1; pid_for_task (i, &pid2); if (pid == pid2) { return tasks[i]; } } return MACH_PORT_NULL; }
void default_pager_set_policy( mach_port_t master_host_port) { host_priority_info_data_t host_pri_info; mach_port_t default_processor_set_name; mach_port_t default_processor_set; policy_rr_base_data_t rr_base; policy_rr_limit_data_t rr_limit; kern_return_t r; mach_msg_type_number_t count; static char here[] = "default_pager_set_policy"; count = HOST_PRIORITY_INFO_COUNT; r = host_info(mach_host_self(), HOST_PRIORITY_INFO, (host_info_t) &host_pri_info, &count); if (r != KERN_SUCCESS) dprintf(("Could not get host priority info. Error = 0x%x\n", r)); rr_base.quantum = 0; rr_base.base_priority = host_pri_info.system_priority; rr_limit.max_priority = host_pri_info.system_priority; (void)processor_set_default(mach_host_self(), &default_processor_set_name); (void)host_processor_set_priv(master_host_port, default_processor_set_name, &default_processor_set); r = task_set_policy(default_pager_self, default_processor_set, POLICY_RR, (policy_base_t) & rr_base, POLICY_RR_BASE_COUNT, (policy_limit_t) & rr_limit, POLICY_RR_LIMIT_COUNT, TRUE); if (r != KERN_SUCCESS) dprintf(("task_set_policy returned 0x%x %s\n", r, mach_error_string(r))); }
/* * Credits to Jonathan Levin! * This function is able to "exploit" the processor_set_tasks mach trap to retrieve * the kernel's mach port. This only works on systems where SIP is either disabled or * not present at all. * If you want to use an alternative method to read from kernel memory, try with enabling * /dev/kmem and read from that device. * * Note that code in this project is tuned to read directly from kernel task, hence you * just need to disable SIP and you're good to go, instead of rewriting code to support * /dev/kmem. */ mach_port_t task_for_pid_workaround(int Pid) { host_t myhost = mach_host_self(); mach_port_t psDefault; mach_port_t psDefault_control; task_array_t tasks; mach_msg_type_number_t numTasks; int i; kern_return_t kr; kr = processor_set_default(myhost, &psDefault); kr = host_processor_set_priv(myhost, psDefault, &psDefault_control); if (kr != KERN_SUCCESS) { fprintf(stderr, "host_processor_set_priv failed with error %x\n", kr); mach_error("host_processor_set_priv",kr); exit(1); } kr = processor_set_tasks(psDefault_control, &tasks, &numTasks); if (kr != KERN_SUCCESS) { fprintf(stderr,"processor_set_tasks failed with error %x\n",kr); exit(1); } for (i = 0; i < numTasks; i++) { int pid; pid_for_task(tasks[i], &pid); if (pid == Pid) return (tasks[i]); } return (MACH_PORT_NULL); }
bool SysInfo::GetAllProcess() { kern_return_t error; processor_set_t *psets, pset; task_t *tasks; unsigned i, j, pcnt, tcnt; m_nTotalTime = 0; host_priv_t libtop_port = mach_host_self(); // 必须获得系统root权限才能访问所有process list,下面这段代码不能获得,暂用pxl制作包来解决权限问题 host_t myhost = mach_host_self(); processor_set_name_t p_default_set; processor_set_t p_default_set_control; /* get the default processor set */ error = processor_set_default(myhost, &p_default_set); if (KERN_SUCCESS != error) { printf("Error in processor_set_default(): %s \n",mach_error_string(error)); char szInfo[256] = { 0 }; snprintf(szInfo, sizeof(szInfo) - 1, "processor_set_default error"); LogMsg(szInfo); } /* get the control port for this processor set */ error = host_processor_set_priv(myhost, p_default_set, &p_default_set_control); if (KERN_SUCCESS != error) { } error = host_processor_sets(libtop_port, &psets, &pcnt); if (error != KERN_SUCCESS) { GetProcessInfo(mach_task_self()); return TRUE; } m_pInfoList.clear(); for (i = 0; i < pcnt; i++) { error = host_processor_set_priv(libtop_port, psets[i], &pset); if (error != KERN_SUCCESS) { printf("Error in host_processor_set_priv(): %s \n",mach_error_string(error)); char szInfo[256] = { 0 }; snprintf(szInfo, sizeof(szInfo) - 1, "host_processor_set_priv error"); LogMsg(szInfo); return true; } error = processor_set_tasks(pset, &tasks, &tcnt); if (error != KERN_SUCCESS) { printf("Error in processor_set_tasks(): %s \n",mach_error_string(error)); char szInfo[256] = { 0 }; snprintf(szInfo, sizeof(szInfo) - 1, "processor_set_tasks error"); LogMsg(szInfo); return true; } for (j = 0; j < tcnt; j++) { if (GetProcessInfo(tasks[j])) { return true; } mach_port_deallocate(mach_task_self(),tasks[j]); } error = vm_deallocate((vm_map_t)mach_task_self(),(vm_address_t)tasks, tcnt * sizeof(task_t)); if (error != KERN_SUCCESS) { printf("Error in vm_deallocate(): %s \n",mach_error_string(error)); return true; } if ((error = mach_port_deallocate(mach_task_self(),pset)) != KERN_SUCCESS || (error = mach_port_deallocate(mach_task_self(),psets[i])) != KERN_SUCCESS) { printf("Error in mach_port_deallocate(): %s \n",mach_error_string(error)); return true; } } error = vm_deallocate((vm_map_t)mach_task_self(),(vm_address_t)psets, pcnt * sizeof(processor_set_t)); if (error != KERN_SUCCESS) { printf("Error in vm_deallocate(): %s \n",mach_error_string(error)); return true; } return false; }
int main(int argc, char ** argv) { int option = 0; struct config cfg = {0}; header(); if (argc < 2) { usage(); } while( (option=getopt(argc,argv,"ha:Aco:Ci:rRs")) != -1 ) { switch(option) { case 'h': usage(); exit(1); case 'a': cfg.interrupt = atoi(optarg); break; case 'A': cfg.show_all_descriptors = 1; break; case 'c': cfg.create_file_archive = 1; break; case 'r': cfg.read_file_archive = 1; break; case 'R': cfg.restore_idt = 1; break; case 'o': if(strlen(optarg) > MAXPATHLEN - 1) { ERROR_MSG("File name too long."); return -1; } strncpy(cfg.out_filename, optarg, sizeof(cfg.out_filename)); break; case 'C': cfg.compare_idt = 1; break; case 'i': if(strlen(optarg) > MAXPATHLEN - 1) { ERROR_MSG("File name too long."); return -1; } strncpy(cfg.in_filename, optarg, sizeof(cfg.in_filename)); break; case 's': cfg.resolve = 1; break; } } OUTPUT_MSG(""); if (getuid() != 0) { ERROR_MSG("This program needs to be run as root!"); return -1; } cfg.kernel_type = get_kernel_type(); if (cfg.kernel_type == -1) { ERROR_MSG("Unable to retrieve kernel type."); return -1; } else if (cfg.kernel_type == X86) { ERROR_MSG("32 bits kernels not supported."); return -1; } cfg.idt_addr = get_addr_idt(cfg.kernel_type); cfg.idt_size = get_size_idt(); cfg.idt_entries = cfg.idt_size / sizeof(struct descriptor_idt); /* we need to populate the size variable else syscall fails */ cfg.kaslr_size = sizeof(cfg.kaslr_size); get_kaslr_slide(&cfg.kaslr_size, &cfg.kaslr_slide); OUTPUT_MSG("[INFO] Kaslr slide is 0x%llx", cfg.kaslr_slide); OUTPUT_MSG("[INFO] IDT base address is: 0x%llx", cfg.idt_addr); OUTPUT_MSG("[INFO] IDT size: 0x%x\n", cfg.idt_size); /* test if we can read kernel memory using processor_set_tasks() vulnerability */ /* vulnerability presented at BlackHat Asia 2014 by Ming-chieh Pan, Sung-ting Tsai. */ /* also described in Mac OS X and iOS Internals, page 387 */ host_t host_port = mach_host_self(); mach_port_t proc_set_default = 0; mach_port_t proc_set_default_control = 0; task_array_t all_tasks = NULL; mach_msg_type_number_t all_tasks_cnt = 0; kern_return_t kr = 0; int valid_kernel_port = 0; kr = processor_set_default(host_port, &proc_set_default); if (kr == KERN_SUCCESS) { kr = host_processor_set_priv(host_port, proc_set_default, &proc_set_default_control); if (kr == KERN_SUCCESS) { kr = processor_set_tasks(proc_set_default_control, &all_tasks, &all_tasks_cnt); if (kr == KERN_SUCCESS) { DEBUG_MSG("Found valid kernel port using processor_set_tasks() vulnerability!"); cfg.kernel_port = all_tasks[0]; valid_kernel_port = 1; } } } /* if we can't use the vulnerability then try /dev/kmem */ if (valid_kernel_port == 0) { if( (cfg.fd_kmem = open("/dev/kmem",O_RDWR)) == -1 ) { ERROR_MSG("Error while opening /dev/kmem. Is /dev/kmem enabled?"); ERROR_MSG("Verify that /Library/Preferences/SystemConfiguration/com.apple.Boot.plist has kmem=1 parameter configured."); return -1; } } if (cfg.resolve == 1) { retrieve_kernel_symbols(&cfg); } if(cfg.interrupt >= 0 || cfg.show_all_descriptors == 1) { show_idt_info(&cfg); } if(cfg.create_file_archive == 1) { create_idt_archive(&cfg); } if(cfg.read_file_archive == 1) { read_idt_archive(&cfg); } if(cfg.compare_idt == 1) { compare_idt(&cfg); } if(cfg.restore_idt == 1) { compare_idt(&cfg); } return 0; }
static void * intrthread(void *arg) { struct irq *irq = arg; mach_port_t delivery_port; mach_port_t pset, psetcntl; int ret; int val; rumpuser_component_kthread(); ret = mach_port_allocate (mach_task_self (), MACH_PORT_RIGHT_RECEIVE, &delivery_port); if (ret) err(ret, "mach_port_allocate"); ret = thread_get_assignment (mach_thread_self (), &pset); if (ret) err(ret, "thread_get_assignment"); ret = host_processor_set_priv (master_host, pset, &psetcntl); if (ret) err(ret, "host_processor_set_priv"); thread_max_priority (mach_thread_self (), psetcntl, 0); ret = thread_priority (mach_thread_self (), RUMP_IRQ_PRIO, 0); if (ret) err(ret, "thread_priority"); ret = device_intr_register(master_device, irq->intrline, 0, 0x04000000, delivery_port, MACH_MSG_TYPE_MAKE_SEND); if (ret) { warn("device_intr_register"); return 0; } device_intr_enable (master_device, irq->intrline, TRUE); int irq_server (mach_msg_header_t *inp, mach_msg_header_t *outp) { mach_intr_notification_t *intr_header = (mach_intr_notification_t *) inp; ((mig_reply_header_t *) outp)->RetCode = MIG_NO_REPLY; if (inp->msgh_id != MACH_INTR_NOTIFY) return 0; /* It's an interrupt not for us. It shouldn't happen. */ if (intr_header->line != irq->intrline) { printf ("We get interrupt %d, %d is expected", intr_header->line, irq->intrline); return 1; } rumpcomp_pci_confread(0, irq->device, 0, 0x04, &val); if (val & 0x400) { printf("interrupt disabled!\n"); val &= ~0x400; rumpcomp_pci_confwrite(0, irq->device, 0, 0x04, val); } rumpuser_component_schedule(NULL); irq->handler(irq->data); rumpuser_component_unschedule(); /* If the irq has been disabled by the linux device, * we don't need to reenable the real one. */ device_intr_enable (master_device, irq->intrline, TRUE); return 1; }
int main (int argc, char **argv, char **envp) { mach_port_t boot; error_t err; mach_port_t pset, psetcntl; void *genport; process_t startup_port; struct argp argp = { 0, 0, 0, "Hurd process server" }; argp_parse (&argp, argc, argv, 0, 0, 0); initialize_version_info (); err = task_get_bootstrap_port (mach_task_self (), &boot); assert_perror (err); if (boot == MACH_PORT_NULL) error (2, 0, "proc server can only be run by init during boot"); proc_bucket = ports_create_bucket (); proc_class = ports_create_class (0, 0); generic_port_class = ports_create_class (0, 0); exc_class = ports_create_class (exc_clean, 0); ports_create_port (generic_port_class, proc_bucket, sizeof (struct port_info), &genport); generic_port = ports_get_right (genport); /* Create the initial proc object for init (PID 1). */ startup_proc = create_startup_proc (); /* Create our own proc object (we are PID 0). */ self_proc = allocate_proc (mach_task_self ()); assert (self_proc); complete_proc (self_proc, 0); startup_port = ports_get_send_right (startup_proc); err = startup_procinit (boot, startup_port, &startup_proc->p_task, &authserver, &master_host_port, &master_device_port); assert_perror (err); mach_port_deallocate (mach_task_self (), startup_port); mach_port_mod_refs (mach_task_self (), authserver, MACH_PORT_RIGHT_SEND, 1); _hurd_port_set (&_hurd_ports[INIT_PORT_AUTH], authserver); mach_port_deallocate (mach_task_self (), boot); proc_death_notify (startup_proc); add_proc_to_hash (startup_proc); /* Now that we have the task port. */ /* Set our own argv and envp locations. */ self_proc->p_argv = (vm_address_t) argv; self_proc->p_envp = (vm_address_t) envp; /* Give ourselves good scheduling performance, because we are so important. */ err = thread_get_assignment (mach_thread_self (), &pset); assert_perror (err); err = host_processor_set_priv (master_host_port, pset, &psetcntl); assert_perror (err); thread_max_priority (mach_thread_self (), psetcntl, 0); assert_perror (err); err = task_priority (mach_task_self (), 2, 1); assert_perror (err); mach_port_deallocate (mach_task_self (), pset); mach_port_deallocate (mach_task_self (), psetcntl); { /* Get our stderr set up to print on the console, in case we have to panic or something. */ mach_port_t cons; error_t err; err = device_open (master_device_port, D_READ|D_WRITE, "console", &cons); assert_perror (err); stdin = mach_open_devstream (cons, "r"); stdout = stderr = mach_open_devstream (cons, "w"); mach_port_deallocate (mach_task_self (), cons); } while (1) ports_manage_port_operations_multithread (proc_bucket, message_demuxer, 0, 0, 0); }