static int __write_pid( char *pidpath ) { FILE *pidfile; __abort(0,__get_pid(pidpath)>0,""); __abort(-1,(pidfile = fopen( pidpath, "w"))==NULL,""); fprintf( pidfile, "%d\n", (int) getpid( ) ),fflush(pidfile),fclose(pidfile); return 0; }
static int tsk_pagesize(RIODesc *desc) { int tid = __get_pid (desc); task_t task = pid_to_task (desc, tid); static vm_size_t pagesize = 0; return pagesize ? pagesize : (host_page_size (task, &pagesize) == KERN_SUCCESS) ? pagesize : 4096; }
static char *__system(RIO *io, RIODesc *fd, const char *cmd) { if (!io || !fd || !cmd || !fd->data) { return NULL; } RIODescData *iodd = fd->data; if (iodd->magic != R_MACH_MAGIC) { return NULL; } task_t task = pid_to_task (fd, iodd->tid); /* XXX ugly hack for testing purposes */ if (!strncmp (cmd, "perm", 4)) { int perm = r_str_rwx (cmd + 4); if (perm) { int pagesize = tsk_pagesize (fd); tsk_setperm (io, task, io->off, pagesize, perm); } else { eprintf ("Usage: =!perm [rwx]\n"); } return NULL; } if (!strncmp (cmd, "pid", 3)) { RIODescData *iodd = fd->data; RIOMach *riom = iodd->data; const char *pidstr = cmd + 3; int pid = -1; if (*pidstr) { pid = __get_pid (fd); //return NULL; } else { eprintf ("%d\n", iodd->pid); return NULL; } if (!strcmp (pidstr, "0")) { pid = 0; } else { pid = atoi (pidstr); if (!pid) { pid = -1; } } if (pid != -1) { task_t task = pid_to_task (fd, pid); if (task != -1) { riom->task = task; iodd->pid = pid; iodd->tid = pid; return NULL; } } eprintf ("io_mach_system: Invalid pid %d\n", pid); } else { eprintf ("Try: '=!pid' or '=!perm'\n"); } return NULL; }
static ut64 getNextValid(RIO *io, RIODesc *fd, ut64 addr) { struct vm_region_submap_info_64 info; vm_address_t address = MACH_VM_MIN_ADDRESS; vm_size_t size = (vm_size_t) 0; vm_size_t osize = (vm_size_t) 0; natural_t depth = 0; kern_return_t kr; int tid = __get_pid (fd); task_t task = pid_to_task (fd, tid); ut64 lower = addr; #if __arm64__ || __aarch64__ size = osize = 16384; // acording to frida #else size = osize = 4096; #endif if (the_lower != UT64_MAX) { return R_MAX (addr, the_lower); } for (;;) { mach_msg_type_number_t info_count; info_count = VM_REGION_SUBMAP_INFO_COUNT_64; memset (&info, 0, sizeof (info)); kr = vm_region_recurse_64 (task, &address, &size, &depth, (vm_region_recurse_info_t) &info, &info_count); if (kr != KERN_SUCCESS) { break; } if (lower == addr) { lower = address; } if (info.is_submap) { depth++; continue; } if (addr >= address && addr < address + size) { return addr; } if (address < lower) { lower = address; } if (size < 1) { size = osize; // f**k } address += size; size = 0; } the_lower = lower; return lower; }
struct pid *krg_get_pid(int nr) { struct pid_kddm_object *obj; struct pid *pid; rcu_read_lock(); pid = find_kpid(nr); rcu_read_unlock(); /* * No need to get a reference on pid since we know that it is used on * another node: nobody will free it for the moment. */ if (!pid) return no_pid(nr); spin_lock(&pid_kddm_lock); obj = pid->kddm_obj; BUG_ON(!obj); BUG_ON(obj->pid != pid); if (likely(obj->active)) { obj->attach_pending++; spin_unlock(&pid_kddm_lock); return pid; } /* Slow path: we must grab the kddm object. */ spin_unlock(&pid_kddm_lock); obj = _kddm_grab_object_no_ft(pid_kddm_set, nr); if (IS_ERR(obj)) return NULL; BUG_ON(obj != pid->kddm_obj); BUG_ON(obj->pid != pid); spin_lock(&pid_kddm_lock); __get_pid(obj); spin_unlock(&pid_kddm_lock); _kddm_put_object(pid_kddm_set, nr); return pid; }
static int mach_write_at(RIO *io, RIODesc *desc, const void *buf, int len, ut64 addr) { vm_address_t vaddr = addr; vm_address_t pageaddr; vm_size_t pagesize; vm_size_t total_size; int operms = 0; int pid = __get_pid (desc); if (!desc || pid < 0) { return 0; } task_t task = pid_to_task (desc, pid); if (len < 1 || task_is_dead (desc, task)) { return 0; } pageaddr = tsk_getpagebase (desc, addr); pagesize = tsk_pagesize (desc); total_size = (len > pagesize) ? pagesize * (1 + (len / pagesize)) : pagesize; if (tsk_write (task, vaddr, buf, len)) { return len; } operms = tsk_getperm (io, task, pageaddr); if (!tsk_setperm (io, task, pageaddr, total_size, VM_PROT_READ | VM_PROT_WRITE | VM_PROT_COPY)) { eprintf ("io.mach: Cannot set page perms for %d byte(s) at 0x%08" PFMT64x"\n", (int)pagesize, (ut64)pageaddr); return -1; } if (!tsk_write (task, vaddr, buf, len)) { eprintf ("io.mach: Cannot write on memory\n"); len = -1; } if (operms) { if (!tsk_setperm (io, task, pageaddr, total_size, operms)) { eprintf ("io.mach: Cannot restore page perms\n"); return -1; } } return len; }
static int stop_child(euca_opts *args) { int pid = __get_pid(GETARG(args, pidfile)), rc = 0, i; if (pid <= 0) return -1; fprintf(stderr, "Waiting for process to terminate: pid=%d .", pid); for (i = 0; i < 60 && (rc = kill(pid, SIGTERM)) != -1; i++) { usleep(1000 * 1000), fprintf(stderr, "."), fflush(stderr); } if (i == 0) { i = errno; __die(rc == -1 && i == ESRCH, "No process with the specified pid=%d", pid); __die(rc == -1 && i == EPERM, "Do not have permission to kill pid=%d", pid); } else if (i == 60) { __debug("Forcefully terminating hung process."); kill(pid, SIGKILL); } else { fprintf(stderr, "\nTerminated process with pid=%d\n", pid); } return 0; }
static struct pid *no_pid(int nr) { struct pid_namespace *ns; struct pid_kddm_object *obj; struct pid *pid; obj = _kddm_grab_object_no_ft(pid_kddm_set, nr); if (IS_ERR(obj)) return NULL; BUG_ON(!obj); spin_lock(&pid_kddm_lock); rcu_read_lock(); pid = find_kpid(nr); /* Double check once locked */ rcu_read_unlock(); /* * No need to get a reference on pid since we know that it is used on * another node: nobody will free it for the moment. */ if (!pid) { ns = find_get_krg_pid_ns(); pid = __alloc_pid(ns, &nr); put_pid_ns(ns); if (!pid) goto out_unlock; obj->pid = pid; pid->kddm_obj = obj; } BUG_ON(pid->kddm_obj != obj); __get_pid(obj); out_unlock: spin_unlock(&pid_kddm_lock); _kddm_put_object(pid_kddm_set, nr); return pid; }
static int stop_child( euca_opts *args ) { int pid = __get_pid( GETARG(args,pidfile) ); if( pid <= 0 ) return -1; kill( pid, SIGTERM ); return wait_child(args,pid); }
static int __read(RIO *io, RIODesc *desc, ut8 *buf, int len) { vm_size_t size = 0; int blen, err, copied = 0; int blocksize = 32; RIODescData *dd = (RIODescData *)desc->data; if (!io || !desc || !buf || !dd) { return -1; } if (dd ->magic != r_str_hash ("mach")) { return -1; } memset (buf, 0xff, len); int pid = __get_pid (desc); task_t task = pid_to_task (desc, pid); if (task_is_dead (desc, pid)) { return -1; } if (pid == 0) { if (io->off < 4096) { return len; } } copied = getNextValid (io, desc, io->off) - io->off; if (copied < 0) { copied = 0; } while (copied < len) { blen = R_MIN ((len - copied), blocksize); //blen = len; err = vm_read_overwrite (task, (ut64)io->off + copied, blen, (pointer_t)buf + copied, &size); switch (err) { case KERN_PROTECTION_FAILURE: //eprintf ("r_io_mach_read: kern protection failure.\n"); break; case KERN_INVALID_ADDRESS: if (blocksize == 1) { memset (buf+copied, 0xff, len-copied); return size+copied; } blocksize = 1; blen = 1; buf[copied] = 0xff; break; } if (err == -1 || size < 1) { return -1; } if (size == 0) { if (blocksize == 1) { memset (buf + copied, 0xff, len - copied); return len; } blocksize = 1; blen = 1; buf[copied] = 0xff; } copied += blen; } return len; }