static int __system(RIO *io, RIODesc *fd, const char *cmd) { RIOMach *riom = (RIOMach*)fd->data; //printf("ptrace io command (%s)\n", cmd); /* XXX ugly hack for testing purposes */ if (!strcmp (cmd, "pid")) { if (!cmd[3]) { int pid = RIOMACH_PID (fd->data); eprintf ("%d\n", pid); return 0; } int pid = atoi (cmd+4); if (pid != 0) { task_t task = pid_to_task (pid); if (task != -1) { eprintf ("PID=%d\n", pid); riom->pid = pid; riom->task = task; return 0; } } eprintf ("io_mach_system: Invalid pid %d\n", pid); return 1; } else eprintf ("Try: '=!pid'\n"); return 1; }
static int __read(RIO *io, RIODesc *fd, ut8 *buf, int len) { vm_size_t size = 0; int blen, err, copied = 0; int blocksize = 32; RIOMach *riom = (RIOMach *)fd->data; if (task_is_dead (riom->pid)) { return -1; } memset (buf, 0xff, len); if (RIOMACH_PID (fd->data) == 0) { if (io->off < 4096) { return len; } } copied = getNextValid (io, fd, io->off) - io->off; if (copied < 0) copied = 0; while (copied < len) { blen = R_MIN ((len - copied), blocksize); //blen = len; err = vm_read_overwrite (RIOMACH_TASK (fd->data), (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; }
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 = RIOMACH_PID (fd->data); task_t task = pid_to_task (tid); ut64 lower = addr; #if __arm64__ || __aarch64__ size = osize = 16384; // acording to frida #else size = osize = 4096; #endif if (the_lower) { if (addr < the_lower) return the_lower; return addr; } 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; }
static int __read(RIO *io, RIODesc *fd, ut8 *buf, int len) { vm_size_t size = 0; int blen, err, copied = 0; int blocksize = 32; if (RIOMACH_PID (fd->data) == 0) { if (io->off<4096) return len; } memset (buf, 0xff, len); while (copied<len) { blen = R_MIN ((len-copied), blocksize); //blen = len; err = vm_read_overwrite (RIOMACH_TASK (fd->data), (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; //eprintf("invaddr %d\n",len); break; } if (err == -1) { //eprintf ("Cannot read\n"); return -1; } if (size==0) { if (blocksize == 1) { memset (buf+copied, 0xff, len-copied); return len; //size+copied; } blocksize = 1; blen = 1; buf[copied] = 0xff; } //if (size != blen) { return size+copied; } copied += blen; } return len; //(int)size; }
static int __system(RIO *io, RIODesc *fd, const char *cmd) { RIOMach *riom; if (!io || !fd || cmd || !fd->data) { return 0; } riom = (RIOMach*)fd->data; /* XXX ugly hack for testing purposes */ if (!strncmp (cmd, "perm", 4)) { int perm = r_str_rwx (cmd + 4); if (perm) { int pagesize = tsk_pagesize(riom); tsk_setperm (io, riom->task, io->off, pagesize, perm); } else { eprintf ("Usage: =!perm [rwx]\n"); } return 0; } if (!strncmp (cmd, "pid", 3)) { const char *pidstr = cmd + 3; int pid = -1; if (*pidstr) { int pid = RIOMACH_PID (fd->data); eprintf ("%d\n", pid); return 0; } if (!strcmp (pidstr, "0")) { pid = 0; } else { pid = atoi (pidstr); if (!pid) pid = -1; } if (pid != -1) { task_t task = pid_to_task (pid); if (task != -1) { eprintf ("PID=%d\n", pid); riom->pid = pid; riom->task = task; return 0; } } eprintf ("io_mach_system: Invalid pid %d\n", pid); } else { eprintf ("Try: '=!pid' or '=!perm'\n"); } return 1; }
static int __close(RIODesc *fd) { int pid = RIOMACH_PID (fd->data); R_FREE (fd->data); return ptrace (PT_DETACH, pid, 0, 0); }