static long dune_clone(struct dune_tf *tf) { unsigned long fs; int rc; unsigned long pc; rdmsrl(MSR_GS_BASE, pc); if (ARG1(tf) != 0) return dune_pthread_create(tf); fs = dune_get_user_fs(); rc = syscall(SYS_clone, ARG0(tf), ARG1(tf), ARG2(tf), ARG3(tf), ARG4(tf)); if (rc < 0) return -errno; if (rc == 0) { dune_enter(); dune_set_user_fs(fs); } return rc; }
LONG rxsupp_rename(struct Library *RexxSupportBase, struct RexxMsg *msg, UBYTE **argstring) { BOOL ok; ok = Rename(ARG1(msg), ARG2(msg)); *argstring = CreateArgstring(ok ? "1" : "0", 1); return RC_OK; }
/* ARG1 = fd de salida. * ARG2 = puntero (en espacio de usuario). * ARG3 = tamaƱo. */ int sys_write( struct registers *r ) { int i; const char *str = (const char *) ARG2(r); if ( ARG1(r) != 1 ) return -1; /* if ( chequear_direccion(r->ecx, r->edx) == MALA ) return -1; */ for ( i = 0; i < ARG3(r); i++ ) kputc( str[i] ); return ARG3(r); }
void *pthread_entry(void *arg) { struct thread_arg *a = arg; struct dune_tf *tf = a->ta_tf; struct dune_tf child_tf; int *tidp = NULL; pid_t tid; int flags = ARG0(tf); if (!a->dune_started) dune_enter(); tid = syscall(SYS_gettid); /* XXX validate */ /* set up tls */ if (flags & CLONE_SETTLS) dune_set_user_fs(ARG4(tf)); if (flags & CLONE_PARENT_SETTID) { tidp = (int *) ARG2(tf); *tidp = tid; } if (flags & CLONE_CHILD_CLEARTID) { tidp = (int *) ARG3(tf); syscall(SYS_set_tid_address, tidp); } /* enter thread */ memcpy(&child_tf, tf, sizeof(child_tf)); child_tf.rip = tf->rip; child_tf.rax = 0; child_tf.rsp = ARG1(tf); /* tell parent tid */ pthread_mutex_lock(&a->ta_mtx); a->ta_tid = tid; pthread_mutex_unlock(&a->ta_mtx); pthread_cond_signal(&a->ta_cnd); do_enter_thread(&child_tf); return NULL; }
/* Force the target to call `dlopen()'. Modify its registers and stack contents * and continue execution until a segmentation fault is caught. Return 0 on * success and -1 on failure. */ static int force_dlopen(pid_t pid, char *filename) { void *linker_addr, *dlopen_off, *dlopen_addr; regs_t regs; size_t size; int r = -1; if(resolve_symbol(LINKER_PATH, DLOPEN_NAME1, &dlopen_off) != 0 && resolve_symbol(LINKER_PATH, DLOPEN_NAME2, &dlopen_off) != 0 && resolve_symbol(LINKER_PATH, DLOPEN_NAME3, &dlopen_off) != 0) { printf("[*] Could not resolve dlopen()\n"); goto ret; } if((linker_addr = get_linker_addr(pid)) == NULL) { printf("[*] Linker not found in PID %d\n", pid); goto ret; } dlopen_addr = linker_addr + (ptrdiff_t)dlopen_off; printf("[*] Resolved dlopen() at %p\n", dlopen_addr); if(read_registers(pid, ®s) != 0) goto ret; /* Prepare `do_dlopen()' input arguments. On Android >= 7, we set the 4th * argument to a value that emulates `__builtin_return_address()', so that * our DSO is loaded in the correct namespace. */ ARG0(regs) = SP(regs) + SP_OFF; ARG1(regs) = RTLD_NOW | RTLD_GLOBAL; ARG2(regs) = 0; ARG3(regs) = PC(regs); /* We set the new PC and also set LR to force the debuggee to crash. */ #if defined(__aarch64__) LR(regs) = 0xffffffffffffffff; PC(regs) = (reg_t)dlopen_addr; #elif defined(__arm__) LR(regs) = 0xffffffff; PC(regs) = (reg_t)dlopen_addr | 1; CPSR(regs) |= 1 << 5; #endif printf("[*] Modifying target's state\n"); if(write_registers(pid, ®s) != 0) goto ret; size = strlen(filename) + 1; if(write_memory(pid, (void *)SP(regs) + SP_OFF, filename, size) != size) goto ret; printf("[*] Waiting for target to throw SIGSEGV or SIGBUS\n"); if(resume_and_wait(pid) != 0) goto ret; r = 0; ret: return r; }
return 0; } return 1; } /************************************************************************/ /* All supported sample and ACL keywords must be declared here. */ /************************************************************************/ /* Note: must not be declared <const> as its list will be overwritten. * Note: fetches that may return multiple types must be declared as the lowest * common denominator, the type that can be casted into all other ones. For * instance IPv4/IPv6 must be declared IPv4. */ static struct sample_fetch_kw_list smp_kws = {ILH, { { "payload", smp_fetch_payload, ARG2(2,UINT,UINT), NULL, SMP_T_CBIN, SMP_USE_L6REQ|SMP_USE_L6RES }, { "payload_lv", smp_fetch_payload_lv, ARG3(2,UINT,UINT,SINT), val_payload_lv, SMP_T_CBIN, SMP_USE_L6REQ|SMP_USE_L6RES }, { "rdp_cookie", smp_fetch_rdp_cookie, ARG1(0,STR), NULL, SMP_T_CSTR, SMP_USE_L6REQ }, { "rdp_cookie_cnt", smp_fetch_rdp_cookie_cnt, ARG1(0,STR), NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "rep_ssl_hello_type", smp_fetch_ssl_hello_type, 0, NULL, SMP_T_UINT, SMP_USE_L6RES }, { "req_len", smp_fetch_len, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req_ssl_hello_type", smp_fetch_ssl_hello_type, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req_ssl_sni", smp_fetch_ssl_hello_sni, 0, NULL, SMP_T_CSTR, SMP_USE_L6REQ }, { "req_ssl_ver", smp_fetch_req_ssl_ver, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req.len", smp_fetch_len, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req.payload", smp_fetch_payload, ARG2(2,UINT,UINT), NULL, SMP_T_CBIN, SMP_USE_L6REQ }, { "req.payload_lv", smp_fetch_payload_lv, ARG3(2,UINT,UINT,SINT), val_payload_lv, SMP_T_CBIN, SMP_USE_L6REQ }, { "req.rdp_cookie", smp_fetch_rdp_cookie, ARG1(0,STR), NULL, SMP_T_CSTR, SMP_USE_L6REQ }, { "req.rdp_cookie_cnt", smp_fetch_rdp_cookie_cnt, ARG1(0,STR), NULL, SMP_T_UINT, SMP_USE_L6REQ }, { "req.ssl_hello_type", smp_fetch_ssl_hello_type, 0, NULL, SMP_T_UINT, SMP_USE_L6REQ },
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { static csh handle = 0; static int omode = -1; int n, ret; cs_insn *insn; int mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: 0; mode |= CS_MODE_BIG_ENDIAN; if (mode != omode) { cs_close (&handle); handle = 0; omode = mode; } if (handle == 0) { ret = cs_open (CS_ARCH_PPC, mode, &handle); if (ret != CS_ERR_OK) { return -1; } cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); } op->delay = 0; op->type = R_ANAL_OP_TYPE_NULL; op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->size = 4; // capstone-next n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { struct Getarg gop = { .handle = handle, .insn = insn, .bits = a->bits }; op->size = insn->size; switch (insn->id) { case PPC_INS_MFLR: op->type = R_ANAL_OP_TYPE_PUSH; break; case PPC_INS_MTLR: op->type = R_ANAL_OP_TYPE_POP; break; case PPC_INS_MR: case PPC_INS_LI: case PPC_INS_LIS: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,%s,=", ARG(1), ARG(0)); break; break; case PPC_INS_RLWINM: op->type = R_ANAL_OP_TYPE_ROL; break; case PPC_INS_SC: op->type = R_ANAL_OP_TYPE_SWI; esilprintf (op, "0,$"); break; case PPC_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; esilprintf (op, ","); break; case PPC_INS_STW: case PPC_INS_STWU: case PPC_INS_STWUX: case PPC_INS_STWX: op->type = R_ANAL_OP_TYPE_STORE; esilprintf (op, "%s,%s", ARG(0), ARG2(1, "=[4]")); break; case PPC_INS_STB: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,%s", ARG(0), ARG2(1, "=[1]")); break; case PPC_INS_STH: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,%s", ARG(0), ARG2(1, "=[2]")); break; case PPC_INS_STWBRX: case PPC_INS_STWCX: op->type = R_ANAL_OP_TYPE_STORE; break; case PPC_INS_LA: case PPC_INS_LBZ: case PPC_INS_LBZU: case PPC_INS_LBZUX: case PPC_INS_LBZX: case PPC_INS_LD: case PPC_INS_LDARX: case PPC_INS_LDBRX: case PPC_INS_LDU: case PPC_INS_LDUX: case PPC_INS_LDX: case PPC_INS_LFD: case PPC_INS_LFDU: case PPC_INS_LFDUX: case PPC_INS_LFDX: case PPC_INS_LFIWAX: case PPC_INS_LFIWZX: case PPC_INS_LFS: case PPC_INS_LFSU: case PPC_INS_LFSUX: case PPC_INS_LFSX: case PPC_INS_LHA: case PPC_INS_LHAU: case PPC_INS_LHAUX: case PPC_INS_LHAX: case PPC_INS_LHBRX: case PPC_INS_LHZ: case PPC_INS_LHZU: case PPC_INS_LWA: case PPC_INS_LWARX: case PPC_INS_LWAUX: case PPC_INS_LWAX: case PPC_INS_LWBRX: case PPC_INS_LWZ: case PPC_INS_LWZU: case PPC_INS_LWZUX: case PPC_INS_LWZX: op->type = R_ANAL_OP_TYPE_LOAD; esilprintf (op, "%s,[4],%s,=", ARG(1), ARG(0)); break; case PPC_INS_SLW: case PPC_INS_SLWI: op->type = R_ANAL_OP_TYPE_SHL; esilprintf (op, "%s,%s,<<,%s,=", ARG(2), ARG(1), ARG(0)); break; case PPC_INS_SRW: case PPC_INS_SRWI: op->type = R_ANAL_OP_TYPE_SHR; esilprintf (op, "%s,%s,>>,%s,=", ARG(2), ARG(1), ARG(0)); break; case PPC_INS_CMPW: case PPC_INS_CMPWI: case PPC_INS_CMPLWI: op->type = R_ANAL_OP_TYPE_CMP; esilprintf (op, "%s,%s,==", ARG(1), ARG(0)); break; case PPC_INS_MULLI: case PPC_INS_MULLW: op->type = R_ANAL_OP_TYPE_MUL; esilprintf (op, "%s,%s,*,%s,=", ARG(2), ARG(1), ARG(0)); break; case PPC_INS_SUB: case PPC_INS_SUBC: case PPC_INS_SUBFIC: case PPC_INS_SUBFZE: op->type = R_ANAL_OP_TYPE_SUB; esilprintf (op, "%s,%s,-,%s,=", ARG(2), ARG(1), ARG(0)); break; case PPC_INS_ADD: case PPC_INS_ADDI: case PPC_INS_ADDC: case PPC_INS_ADDE: case PPC_INS_ADDIC: case PPC_INS_ADDIS: case PPC_INS_ADDME: case PPC_INS_ADDZE: op->type = R_ANAL_OP_TYPE_ADD; esilprintf (op, "%s,%s,+,%s,=", ARG(2), ARG(1), ARG(0)); break; case PPC_INS_MTSPR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,%s,=", ARG(1), ARG(0)); break; case PPC_INS_BCTR: // switch table here op->type = R_ANAL_OP_TYPE_UJMP; esilprintf (op, "ctr,pc,="); break; case PPC_INS_BC: op->type = R_ANAL_OP_TYPE_UJMP; esilprintf (op, "%s,pc,=", ARG(0)); break; case PPC_INS_B: case PPC_INS_BA: op->type = R_ANAL_OP_TYPE_JMP; op->jump = (ut64)(ut32)insn->detail->ppc.operands[0].imm; switch (insn->detail->ppc.operands[0].type) { case PPC_OP_CRX: op->type = R_ANAL_OP_TYPE_CJMP; break; case PPC_OP_REG: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = (ut64)(ut32)insn->detail->ppc.operands[1].imm; op->fail = addr+4; //op->type = R_ANAL_OP_TYPE_UJMP; default: break; } break; case PPC_INS_NOR: op->type = R_ANAL_OP_TYPE_NOR; //esilprintf (op, "%s,%s,^,%s,=", ARG(1), ARG(2), ARG(0)); break; case PPC_INS_XOR: case PPC_INS_XORI: case PPC_INS_XORIS: op->type = R_ANAL_OP_TYPE_XOR; esilprintf (op, "%s,%s,^,%s,=", ARG(1), ARG(2), ARG(0)); break; case PPC_INS_DIVD: case PPC_INS_DIVDU: case PPC_INS_DIVW: case PPC_INS_DIVWU: op->type = R_ANAL_OP_TYPE_DIV; break; case PPC_INS_BL: case PPC_INS_BLA: op->type = R_ANAL_OP_TYPE_CALL; op->jump = (ut64)(ut32)insn->detail->ppc.operands[0].imm; op->fail = addr+4; esilprintf (op, "pc,lr,=,%s,pc,=", ARG(0)); break; case PPC_INS_BLR: case PPC_INS_BLRL: op->type = R_ANAL_OP_TYPE_RET; esilprintf (op, "lr,pc,="); break; case PPC_INS_AND: case PPC_INS_NAND: case PPC_INS_ANDI: case PPC_INS_ANDIS: op->type = R_ANAL_OP_TYPE_AND; break; case PPC_INS_OR: case PPC_INS_ORC: case PPC_INS_ORI: case PPC_INS_ORIS: op->type = R_ANAL_OP_TYPE_OR; esilprintf (op, "%s,%s,|,%s,=", ARG(2), ARG(1), ARG(0)); break; } cs_free (insn, n); //cs_close (&handle); } return op->size; } RAnalPlugin r_anal_plugin_ppc_cs = { .name = "ppc", .desc = "Capstone PowerPC analysis", .license = "BSD", .arch = R_SYS_ARCH_PPC, .bits = 32|64, .op = &analop, .set_reg_profile = &set_reg_profile, }; #ifndef CORELIB struct r_lib_struct_t radare_plugin = { .type = R_LIB_TYPE_ANAL, .data = &r_anal_plugin_ppc_cs, .version = R2_VERSION };
static void syscall_do_foreal(struct dune_tf *tf) { switch (tf->rax) { case SYS_arch_prctl: switch (ARG0(tf)) { case ARCH_GET_FS: *((unsigned long*) ARG1(tf)) = dune_get_user_fs(); tf->rax = 0; break; case ARCH_SET_FS: dune_set_user_fs(ARG1(tf)); tf->rax = 0; break; default: tf->rax = -EINVAL; break; } break; case SYS_brk: tf->rax = umm_brk((unsigned long) ARG0(tf)); break; case SYS_mmap: tf->rax = (unsigned long) umm_mmap((void *) ARG0(tf), (size_t) ARG1(tf), (int) ARG2(tf), (int) ARG3(tf), (int) ARG4(tf), (off_t) ARG5(tf)); break; case SYS_mprotect: tf->rax = umm_mprotect((void *) ARG0(tf), (size_t) ARG1(tf), ARG2(tf)); break; case SYS_munmap: tf->rax = umm_munmap((void *) ARG0(tf), (size_t) ARG1(tf)); break; case SYS_mremap: tf->rax = (unsigned long) umm_mremap((void*) ARG0(tf), (size_t) ARG1(tf), (size_t) ARG2(tf), (int) ARG3(tf), (void*) ARG4(tf)); break; case SYS_shmat: tf->rax = (unsigned long) umm_shmat((int) ARG0(tf), (void*) ARG1(tf), (int) ARG2(tf)); break; case SYS_clone: tf->rax = dune_clone(tf); break; case SYS_execve: tf->rax = exec_execev((const char *)ARG0(tf), (char **const)ARG1(tf), (char **const)ARG2(tf)); break; /* ignore signals for now */ case SYS_rt_sigaction: case SYS_rt_sigprocmask: tf->rax = 0; break; case SYS_sigaltstack: case SYS_signalfd: case SYS_signalfd4: case SYS_rt_sigpending: case SYS_rt_sigreturn: case SYS_rt_sigsuspend: case SYS_rt_sigqueueinfo: case SYS_rt_sigtimedwait: tf->rax = -ENOSYS; break; case SYS_exit_group: case SYS_exit: dune_ret_from_user(ARG0(tf)); break; default: dune_passthrough_syscall(tf); break; } }
static int syscall_check_params(struct dune_tf *tf) { void *ptr = NULL; uint64_t len = 0; char *str = NULL; int err = 0; switch (tf->rax) { case SYS_uname: ptr = (void*) ARG0(tf); len = sizeof(struct utsname); break; case SYS_arch_prctl: if (ARG0(tf) == ARCH_GET_FS) { ptr = (void*) ARG1(tf); len = sizeof(unsigned long); } break; case SYS_access: case SYS_open: case SYS_unlink: str = (char*) ARG0(tf); break; case SYS_openat: str = (char*) ARG1(tf); break; case SYS_getdents: case SYS_read: case SYS_write: case SYS_connect: case SYS_bind: ptr = (void*) ARG1(tf); len = ARG2(tf); break; case SYS_writev: case SYS_readv: err = check_iovec((struct iovec*) ARG1(tf), ARG2(tf)); break; case SYS_stat: case SYS_lstat: str = (char*) ARG0(tf); case SYS_fstat: ptr = (void*) ARG1(tf); len = sizeof(struct stat); break; case SYS_statfs: str = (char*) ARG0(tf); ptr = (void*) ARG1(tf); len = sizeof(struct statfs); break; case SYS_time: ptr = (void*) ARG0(tf); len = sizeof(time_t); break; case SYS_epoll_ctl: ptr = (void*) ARG3(tf); len = sizeof(struct epoll_event); break; case SYS_epoll_wait: ptr = (void*) ARG1(tf); len = ARG2(tf) * sizeof(struct epoll_event); break; case SYS_setsockopt: ptr = (void*) ARG3(tf); len = ARG4(tf); break; case SYS_accept: if (ARG2(tf)) { socklen_t *l = (socklen_t*) ARG2(tf); if (check_extent(l, sizeof(*l))) err = -EFAULT; else { len = *l; ptr = (void*) ARG1(tf); assert(ptr); } } break; case SYS_fcntl: switch (ARG1(tf)) { case F_DUPFD: case F_DUPFD_CLOEXEC: case F_GETFD: case F_SETFD: case F_GETFL: case F_SETFL: case F_GETOWN: case F_SETOWN: break; case F_SETLKW: case F_GETLK: case F_SETLK: ptr = (void*) ARG2(tf); len = sizeof(struct flock); break; default: err = -EFAULT; break; } break; case SYS_ioctl: /* XXX unreliable */ if (_IOC_DIR(ARG1(tf))) { ptr = (void*) ARG2(tf); len = _IOC_SIZE(ARG1(tf)); } break; case SYS_setgroups: ptr = (void*) ARG1(tf); len = sizeof(gid_t) * ARG0(tf); break; case SYS_rt_sigaction: ptr = (void*) ARG1(tf); len = sizeof(struct sigaction); if (ARG2(tf)) { if (check_extent((void*) ARG2(tf), len)) { tf->rax = -EFAULT; return -1; } } break; case SYS_sigaltstack: case SYS_signalfd: case SYS_signalfd4: ptr = (void*) ARG1(tf); len = sizeof(sigset_t); break; case SYS_rt_sigpending: ptr = (void*) ARG0(tf); len = sizeof(sigset_t); break; case SYS_rt_sigprocmask: if (ARG1(tf)) { ptr = (void*) ARG1(tf); len = sizeof(sigset_t); } if (ARG2(tf)) { if (check_extent((void*) ARG2(tf), sizeof(sigset_t))) { tf->rax = -EFAULT; return -1; } } break; case SYS_rt_sigreturn: break; case SYS_rt_sigsuspend: ptr = (void*) ARG0(tf); len = sizeof(sigset_t); break; case SYS_rt_sigqueueinfo: ptr = (void*) ARG1(tf); len = sizeof(siginfo_t); break; case SYS_rt_sigtimedwait: if (check_extent((void*) ARG0(tf), sizeof(siginfo_t))) { tf->rax = -EFAULT; return -1; } if (check_extent((void*) ARG1(tf), sizeof(siginfo_t))) { tf->rax = -EFAULT; return -1; } if (ARG2(tf)) { if (check_extent((void*) ARG2(tf), sizeof(struct timespec))) { tf->rax = -EFAULT; return -1; } } break; /* umm_ checks for correctness */ case SYS_brk: break; case SYS_mprotect: case SYS_munmap: case SYS_mmap: // ptr = (void*) ARG0(tf); // len = ARG1(tf); break; case SYS_getcwd: ptr = (void*) ARG0(tf); len = ARG1(tf); break; case SYS_getrlimit: ptr = (void*) ARG1(tf); len = sizeof(struct rlimit); break; case SYS_sendfile: ptr = (void*) ARG2(tf); len = sizeof(off_t); break; case SYS_getuid: case SYS_setuid: case SYS_getgid: case SYS_setgid: case SYS_getpid: case SYS_epoll_create: case SYS_dup2: case SYS_socket: case SYS_shutdown: case SYS_listen: case SYS_lseek: break; /* XXX - doesn't belong here */ case SYS_close: if (ARG0(tf) < 3) { tf->rax = 0; return -1; } break; case SYS_execve: { char *p = (char*)ARG0(tf); if (check_string(p)) { err = -EFAULT; break; } // XXX: Check arrays break; } default: #if 0 { static FILE *_out; if (!_out) _out = fopen("/tmp/syscall.log", "w"); fprintf(_out, "Syscall %d\n", tf->rax); fflush(_out); } #endif break; } if (ptr != NULL && len != 0 && check_extent(ptr, len)) err = -EFAULT; if (str != NULL && check_string(str)) err = -EFAULT; if (err) { tf->rax = err; return -1; } return 0; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { static csh handle = 0; static int omode = -1, obits = -1; int n, ret; cs_insn *insn; int mode = (a->bits == 64) ? CS_MODE_64 : (a->bits == 32) ? CS_MODE_32 : 0; mode |= a->big_endian ? CS_MODE_BIG_ENDIAN : CS_MODE_LITTLE_ENDIAN; op->delay = 0; op->type = R_ANAL_OP_TYPE_NULL; op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; if (a->cpu && strncmp (a->cpu, "vle", 3) == 0) { // vle is big-endian only if (!a->big_endian) { return -1; } ret = analop_vle (a, op, addr, buf, len); if (ret >= 0) { return op->size; } } if (mode != omode || a->bits != obits) { cs_close (&handle); handle = 0; omode = mode; obits = a->bits; } if (handle == 0) { ret = cs_open (CS_ARCH_PPC, mode, &handle); if (ret != CS_ERR_OK) { return -1; } cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); } op->size = 4; r_strbuf_init (&op->esil); r_strbuf_set (&op->esil, ""); // capstone-next n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); if (n < 1) { op->type = R_ANAL_OP_TYPE_ILL; } else { opex (&op->opex, handle, insn); struct Getarg gop = { .handle = handle, .insn = insn, .bits = a->bits }; op->size = insn->size; op->id = insn->id; switch (insn->id) { #if CS_API_MAJOR >= 4 case PPC_INS_CMPB: #endif case PPC_INS_CMPD: case PPC_INS_CMPDI: case PPC_INS_CMPLD: case PPC_INS_CMPLDI: case PPC_INS_CMPLW: case PPC_INS_CMPLWI: case PPC_INS_CMPW: case PPC_INS_CMPWI: op->type = R_ANAL_OP_TYPE_CMP; op->sign = true; if (ARG (2)[0] == '\0') esilprintf (op, "%s,%s,-,0xff,&,cr0,=", ARG (1), ARG (0)); else esilprintf (op, "%s,%s,-,0xff,&,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_MFLR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "lr,%s,=", ARG (0)); break; case PPC_INS_MTLR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,lr,=", ARG (0)); break; case PPC_INS_MR: case PPC_INS_LI: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,%s,=", ARG (1), ARG (0)); break; case PPC_INS_LIS: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s0000,%s,=", ARG (1), ARG (0)); break; case PPC_INS_CLRLWI: op->type = R_ANAL_OP_TYPE_AND; esilprintf (op, "%s,%s,&,%s,=", ARG (1), cmask32 (ARG (2), "0x1F"), ARG (0)); break; case PPC_INS_RLWINM: op->type = R_ANAL_OP_TYPE_ROL; esilprintf (op, "%s,%s,<<<,%s,&,%s,=", ARG (2), ARG (1), cmask32 (ARG (3), ARG (4)), ARG (0)); break; case PPC_INS_SC: op->type = R_ANAL_OP_TYPE_SWI; esilprintf (op, "0,$"); break; case PPC_INS_EXTSB: op->sign = true; op->type = R_ANAL_OP_TYPE_MOV; if (a->bits == 64) esilprintf (op, "%s,0x80,&,?{,0xFFFFFFFFFFFFFF00,%s,|,%s,=,}", ARG (1), ARG (1), ARG (0)); else esilprintf (op, "%s,0x80,&,?{,0xFFFFFF00,%s,|,%s,=,}", ARG (1), ARG (1), ARG (0)); break; case PPC_INS_EXTSH: op->sign = true; if (a->bits == 64) esilprintf (op, "%s,0x8000,&,?{,0xFFFFFFFFFFFF0000,%s,|,%s,=,}", ARG (1), ARG (1), ARG (0)); else esilprintf (op, "%s,0x8000,&,?{,0xFFFF0000,%s,|,%s,=,}", ARG (1), ARG (1), ARG (0)); break; case PPC_INS_EXTSW: op->sign = true; esilprintf (op, "%s,0x80000000,&,?{,0xFFFFFFFF00000000,%s,|,%s,=,}", ARG (1), ARG (1), ARG (0)); break; case PPC_INS_SYNC: case PPC_INS_ISYNC: case PPC_INS_LWSYNC: case PPC_INS_MSYNC: case PPC_INS_PTESYNC: case PPC_INS_TLBSYNC: case PPC_INS_SLBIA: case PPC_INS_SLBIE: case PPC_INS_SLBMFEE: case PPC_INS_SLBMTE: case PPC_INS_EIEIO: case PPC_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; esilprintf (op, ","); break; case PPC_INS_STW: case PPC_INS_STWU: case PPC_INS_STWUX: case PPC_INS_STWX: case PPC_INS_STWCX: op->type = R_ANAL_OP_TYPE_STORE; esilprintf (op, "%s,%s", ARG (0), ARG2 (1, "=[4]")); break; case PPC_INS_STWBRX: op->type = R_ANAL_OP_TYPE_STORE; break; case PPC_INS_STB: case PPC_INS_STBU: op->type = R_ANAL_OP_TYPE_STORE; esilprintf (op, "%s,%s", ARG (0), ARG2 (1, "=[1]")); break; case PPC_INS_STH: case PPC_INS_STHU: op->type = R_ANAL_OP_TYPE_STORE; esilprintf (op, "%s,%s", ARG (0), ARG2 (1, "=[2]")); break; case PPC_INS_STD: case PPC_INS_STDU: op->type = R_ANAL_OP_TYPE_STORE; esilprintf (op, "%s,%s", ARG (0), ARG2 (1, "=[8]")); break; case PPC_INS_LBZ: #if CS_API_MAJOR >= 4 case PPC_INS_LBZCIX: #endif case PPC_INS_LBZU: case PPC_INS_LBZUX: case PPC_INS_LBZX: op->type = R_ANAL_OP_TYPE_LOAD; esilprintf (op, "%s,%s,=", ARG2 (1, "[1]"), ARG (0)); break; case PPC_INS_LD: case PPC_INS_LDARX: #if CS_API_MAJOR >= 4 case PPC_INS_LDCIX: #endif case PPC_INS_LDU: case PPC_INS_LDUX: case PPC_INS_LDX: op->type = R_ANAL_OP_TYPE_LOAD; esilprintf (op, "%s,%s,=", ARG2 (1, "[8]"), ARG (0)); break; case PPC_INS_LDBRX: op->type = R_ANAL_OP_TYPE_LOAD; break; case PPC_INS_LFD: case PPC_INS_LFDU: case PPC_INS_LFDUX: case PPC_INS_LFDX: case PPC_INS_LFIWAX: case PPC_INS_LFIWZX: case PPC_INS_LFS: case PPC_INS_LFSU: case PPC_INS_LFSUX: case PPC_INS_LFSX: op->type = R_ANAL_OP_TYPE_LOAD; esilprintf (op, "%s,%s,=", ARG2 (1, "[4]"), ARG (0)); break; case PPC_INS_LHA: case PPC_INS_LHAU: case PPC_INS_LHAUX: case PPC_INS_LHAX: case PPC_INS_LHZ: case PPC_INS_LHZU: op->type = R_ANAL_OP_TYPE_LOAD; esilprintf (op, "%s,%s,=", ARG2 (1, "[2]"), ARG (0)); break; case PPC_INS_LHBRX: op->type = R_ANAL_OP_TYPE_LOAD; break; case PPC_INS_LWA: case PPC_INS_LWARX: case PPC_INS_LWAUX: case PPC_INS_LWAX: case PPC_INS_LWZ: #if CS_API_MAJOR >= 4 case PPC_INS_LWZCIX: #endif case PPC_INS_LWZU: case PPC_INS_LWZUX: case PPC_INS_LWZX: op->type = R_ANAL_OP_TYPE_LOAD; esilprintf (op, "%s,%s,=", ARG2 (1, "[4]"), ARG (0)); break; case PPC_INS_LWBRX: op->type = R_ANAL_OP_TYPE_LOAD; break; case PPC_INS_SLW: case PPC_INS_SLWI: op->type = R_ANAL_OP_TYPE_SHL; esilprintf (op, "%s,%s,<<,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_SRW: case PPC_INS_SRWI: op->type = R_ANAL_OP_TYPE_SHR; esilprintf (op, "%s,%s,>>,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_MULLI: op->sign = true; case PPC_INS_MULLW: case PPC_INS_MULLD: op->type = R_ANAL_OP_TYPE_MUL; esilprintf (op, "%s,%s,*,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_SUB: case PPC_INS_SUBC: case PPC_INS_SUBF: case PPC_INS_SUBFIC: case PPC_INS_SUBFZE: op->type = R_ANAL_OP_TYPE_SUB; esilprintf (op, "%s,%s,-,%s,=", ARG (1), ARG (2), ARG (0)); break; case PPC_INS_ADD: case PPC_INS_ADDI: op->sign = true; op->type = R_ANAL_OP_TYPE_ADD; esilprintf (op, "%s,%s,+,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_ADDC: case PPC_INS_ADDIC: op->type = R_ANAL_OP_TYPE_ADD; esilprintf (op, "%s,%s,+,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_ADDE: case PPC_INS_ADDIS: case PPC_INS_ADDME: case PPC_INS_ADDZE: op->type = R_ANAL_OP_TYPE_ADD; esilprintf (op, "%s,%s,+,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_MTSPR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,%s,=", ARG (1), PPCSPR (0)); break; case PPC_INS_BCTR: // switch table here op->type = R_ANAL_OP_TYPE_UJMP; esilprintf (op, "ctr,pc,="); break; case PPC_INS_BCTRL: // switch table here op->type = R_ANAL_OP_TYPE_CALL; esilprintf (op, "pc,lr,=,ctr,pc,="); break; case PPC_INS_B: case PPC_INS_BC: op->jump = ARG (1)[0] == '\0' ? IMM (0) : IMM (1); op->type = R_ANAL_OP_TYPE_CJMP; op->fail = addr + op->size; switch (insn->detail->ppc.bc) { case PPC_BC_LT: if (ARG (1)[0] == '\0') { esilprintf (op, "0,cr0,<,?{,%s,pc,=,},", ARG (0)); } else { esilprintf (op, "0,%s,<,?{,%s,pc,=,},", ARG (0), ARG (1)); } break; case PPC_BC_LE: if (ARG (1)[0] == '\0') { esilprintf (op, "0,cr0,<=,?{,%s,pc,=,},", ARG (0)); } else { esilprintf (op, "0,%s,<=,?{,%s,pc,=,},", ARG (0), ARG (1)); } break; case PPC_BC_EQ: if (ARG (1)[0] == '\0') { esilprintf (op, "0,cr0,==,?{,%s,pc,=,},", ARG (0)); } else { esilprintf (op, "0,%s,==,?{,%s,pc,=,},", ARG (0), ARG (1)); } break; case PPC_BC_GE: if (ARG (1)[0] == '\0') { esilprintf (op, "0,cr0,>=,?{,%s,pc,=,},", ARG (0)); } else { esilprintf (op, "0,%s,>=,?{,%s,pc,=,},", ARG (0), ARG (1)); } break; case PPC_BC_GT: if (ARG (1)[0] == '\0') { esilprintf (op, "0,cr0,>,?{,%s,pc,=,},", ARG (0)); } else { esilprintf (op, "0,%s,>,?{,%s,pc,=,},", ARG (0), ARG (1)); } break; case PPC_BC_NE: if (ARG (1)[0] == '\0') { esilprintf (op, "cr0,?{,%s,pc,=,},", ARG (0)); } else { esilprintf (op, "%s,?{,%s,pc,=,},", ARG (0), ARG (1)); } break; case PPC_BC_INVALID: op->type = R_ANAL_OP_TYPE_JMP; esilprintf (op, "%s,pc,=", ARG (0)); case PPC_BC_UN: // unordered case PPC_BC_NU: // not unordered case PPC_BC_SO: // summary overflow case PPC_BC_NS: // not summary overflow default: break; } break; case PPC_INS_BA: switch (insn->detail->ppc.operands[0].type) { case PPC_OP_CRX: op->type = R_ANAL_OP_TYPE_CJMP; op->fail = addr + op->size; break; case PPC_OP_REG: if (op->type == R_ANAL_OP_TYPE_CJMP) { op->type = R_ANAL_OP_TYPE_UCJMP; } else { op->type = R_ANAL_OP_TYPE_CJMP; } op->jump = IMM (1); op->fail = addr + op->size; //op->type = R_ANAL_OP_TYPE_UJMP; default: break; } break; case PPC_INS_BDNZ: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = IMM (0); op->fail = addr + op->size; esilprintf (op, "1,ctr,-=,ctr,?{,%s,pc,=,}", ARG (0)); break; case PPC_INS_BDNZA: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = IMM (0); op->fail = addr + op->size; break; case PPC_INS_BDNZL: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = IMM (0); op->fail = addr + op->size; break; case PPC_INS_BDNZLA: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = IMM (0); op->fail = addr + op->size; break; case PPC_INS_BDNZLR: op->type = R_ANAL_OP_TYPE_CJMP; op->fail = addr + op->size; esilprintf (op, "1,ctr,-=,ctr,?{,lr,pc,=,},"); break; case PPC_INS_BDNZLRL: op->fail = addr + op->size; op->type = R_ANAL_OP_TYPE_CJMP; break; case PPC_INS_BDZ: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = IMM (0); op->fail = addr + op->size; esilprintf (op, "1,ctr,-=,ctr,0,==,?{,%s,pc,=,}", ARG (0)); break; case PPC_INS_BDZA: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = IMM (0); op->fail = addr + op->size; break; case PPC_INS_BDZL: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = IMM (0); op->fail = addr + op->size; break; case PPC_INS_BDZLA: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = IMM (0); op->fail = addr + op->size; break; case PPC_INS_BDZLR: op->type = R_ANAL_OP_TYPE_CJMP; op->fail = addr + op->size; esilprintf (op, "1,ctr,-=,ctr,0,==,?{,lr,pc,=,}"); break; case PPC_INS_BDZLRL: op->type = R_ANAL_OP_TYPE_CJMP; op->fail = addr + op->size; break; case PPC_INS_BLR: case PPC_INS_BLRL: case PPC_INS_BCLR: case PPC_INS_BCLRL: op->type = R_ANAL_OP_TYPE_CRET; op->fail = addr + op->size; switch (insn->detail->ppc.bc) { case PPC_BC_INVALID: op->type = R_ANAL_OP_TYPE_RET; esilprintf (op, "lr,pc,="); break; case PPC_BC_LT: if (ARG (0)[0] == '\0') { esilprintf (op, "0,cr0,<,?{,lr,pc,=,},"); } else { esilprintf (op, "0,%s,<,?{,lr,pc,=,},", ARG (0)); } break; case PPC_BC_LE: if (ARG (0)[0] == '\0') { esilprintf (op, "0,cr0,<=,?{,lr,pc,=,},"); } else { esilprintf (op, "0,%s,<=,?{,lr,pc,=,},", ARG (0)); } break; case PPC_BC_EQ: if (ARG (0)[0] == '\0') { esilprintf (op, "0,cr0,==,?{,lr,pc,=,},"); } else { esilprintf (op, "0,%s,==,?{,lr,pc,=,},", ARG (0)); } break; case PPC_BC_GE: if (ARG (0)[0] == '\0') { esilprintf (op, "0,cr0,>=,?{,lr,pc,=,},"); } else { esilprintf (op, "0,%s,>=,?{,lr,pc,=,},", ARG (0)); } break; case PPC_BC_GT: if (ARG (0)[0] == '\0') { esilprintf (op, "0,cr0,>,?{,lr,pc,=,},"); } else { esilprintf (op, "0,%s,>,?{,lr,pc,=,},", ARG (0)); } break; case PPC_BC_NE: if (ARG (0)[0] == '\0') { esilprintf (op, "cr0,?{,lr,pc,=,},"); } else { esilprintf (op, "%s,?{,lr,pc,=,},", ARG (0)); } break; case PPC_BC_UN: // unordered case PPC_BC_NU: // not unordered case PPC_BC_SO: // summary overflow case PPC_BC_NS: // not summary overflow default: break; } break; case PPC_INS_NOR: op->type = R_ANAL_OP_TYPE_NOR; esilprintf (op, "%s,%s,|,!,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_XOR: case PPC_INS_XORI: op->type = R_ANAL_OP_TYPE_XOR; esilprintf (op, "%s,%s,^,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_XORIS: op->type = R_ANAL_OP_TYPE_XOR; esilprintf (op, "16,%s,<<,%s,^,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_DIVD: case PPC_INS_DIVW: op->sign = true; op->type = R_ANAL_OP_TYPE_DIV; esilprintf (op, "%s,%s,/,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_DIVDU: case PPC_INS_DIVWU: op->type = R_ANAL_OP_TYPE_DIV; esilprintf (op, "%s,%s,/,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_BL: case PPC_INS_BLA: op->type = R_ANAL_OP_TYPE_CALL; op->jump = IMM (0); op->fail = addr + op->size; esilprintf (op, "pc,lr,=,%s,pc,=", ARG (0)); break; case PPC_INS_TRAP: op->sign = true; op->type = R_ANAL_OP_TYPE_TRAP; break; case PPC_INS_AND: case PPC_INS_NAND: case PPC_INS_ANDI: op->type = R_ANAL_OP_TYPE_AND; esilprintf (op, "%s,%s,&,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_ANDIS: op->type = R_ANAL_OP_TYPE_AND; esilprintf (op, "16,%s,<<,%s,&,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_OR: case PPC_INS_ORI: op->type = R_ANAL_OP_TYPE_OR; esilprintf (op, "%s,%s,|,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_ORIS: op->type = R_ANAL_OP_TYPE_OR; esilprintf (op, "16,%s,<<,%s,|,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_MFPVR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "pvr,%s,=", ARG (0)); break; case PPC_INS_MFSPR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,%s,=", PPCSPR (1), ARG (0)); break; case PPC_INS_MFCTR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "ctr,%s,=", ARG (0)); break; case PPC_INS_MFDCCR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "dccr,%s,=", ARG (0)); break; case PPC_INS_MFICCR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "iccr,%s,=", ARG (0)); break; case PPC_INS_MFDEAR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "dear,%s,=", ARG (0)); break; case PPC_INS_MFMSR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "msr,%s,=", ARG (0)); break; case PPC_INS_MTCTR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,ctr,=", ARG (0)); break; case PPC_INS_MTDCCR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,dccr,=", ARG (0)); break; case PPC_INS_MTICCR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,iccr,=", ARG (0)); break; case PPC_INS_MTDEAR: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,dear,=", ARG (0)); break; case PPC_INS_MTMSR: case PPC_INS_MTMSRD: op->type = R_ANAL_OP_TYPE_MOV; esilprintf (op, "%s,msr,=", ARG (0)); break; // Data Cache Block Zero case PPC_INS_DCBZ: op->type = R_ANAL_OP_TYPE_STORE; esilprintf (op, "%s,%s", ARG (0), ARG2 (1, ",=[128]")); break; case PPC_INS_CLRLDI: op->type = R_ANAL_OP_TYPE_AND; esilprintf (op, "%s,%s,&,%s,=", ARG (1), cmask64 (ARG (2), "0x3F"), ARG (0)); break; case PPC_INS_ROTLDI: op->type = R_ANAL_OP_TYPE_ROL; esilprintf (op, "%s,%s,<<<,%s,=", ARG (2), ARG (1), ARG (0)); break; case PPC_INS_RLDCL: case PPC_INS_RLDICL: op->type = R_ANAL_OP_TYPE_ROL; esilprintf (op, "%s,%s,<<<,%s,&,%s,=", ARG (2), ARG (1), cmask64 (ARG (3), "0x3F"), ARG (0)); break; case PPC_INS_RLDCR: case PPC_INS_RLDICR: op->type = R_ANAL_OP_TYPE_ROL; esilprintf (op, "%s,%s,<<<,%s,&,%s,=", ARG (2), ARG (1), cmask64 (0, ARG (3)), ARG (0)); break; } if (a->fillval) { op_fillval (op, handle, insn); } r_strbuf_fini (&op->esil); cs_free (insn, n); //cs_close (&handle); } return op->size; } static int archinfo(RAnal *a, int q) { if (a->cpu && !strncmp (a->cpu, "vle", 3)) { return 2; } return 4; } RAnalPlugin r_anal_plugin_ppc_cs = { .name = "ppc", .desc = "Capstone PowerPC analysis", .license = "BSD", .esil = true, .arch = "ppc", .bits = 32 | 64, .archinfo = archinfo, .op = &analop, .set_reg_profile = &set_reg_profile, }; #ifndef CORELIB RLibStruct radare_plugin = { .type = R_LIB_TYPE_ANAL, .data = &r_anal_plugin_ppc_cs, .version = R2_VERSION };