static void test_invalids() { struct invalid_instructions invalids[] = {{ CS_ARCH_ARM, CS_MODE_THUMB, "Thumb", 1, {{ (unsigned char *)"\xbd\xe8\x1e\xff", 4, "invalid thumb2 pop because sp used and because both pc and lr are " "present at the same time" }}, }}; struct invalid_instructions * invalid = NULL; uint64_t address = 0x1000; cs_insn *insn; int i; int j; size_t count; printf("\nShould be invalid\n" "-----------------\n"); for (i = 0; i < sizeof(invalids)/sizeof(invalids[0]); i++) { cs_err err; invalid = invalids + i; err = cs_open(invalid->arch, invalid->mode, &handle); if (err) { printf("Failed on cs_open() with error returned: %u\n", err); continue; } cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME); for (j = 0; j < invalid->num_invalid_codes; ++j) { struct invalid_code *invalid_code = NULL; char *hex_str = NULL; invalid_code = invalid->invalid_codes + j; hex_str = hex_string(invalid_code->code, invalid_code->size); printf("%s %s: %s\n", invalid->platform_comment, hex_str, invalid_code->comment); free(hex_str); count = cs_disasm(handle, invalid_code->code, invalid_code->size, address, 0, &insn ); if (count) { size_t k; printf(" ERROR:\n"); for (k = 0; k < count; k++) { printf(" 0x%"PRIx64":\t%s\t%s\n", insn[k].address, insn[k].mnemonic, insn[k].op_str); print_insn_detail(&insn[k]); } cs_free(insn, count); } else { printf(" SUCCESS: invalid\n"); } } cs_close(&handle); } }
void emulate_constructor(dmp_ctx_t *ctx, uint64_t constructor_address, struct hierarchy_entry_head *head) { if (!ctx) return; if (!ctx->kimage_mh || !ctx->map || !ctx->reg_map) return; uint64_t kimage_base = find_kimage_base(ctx->kimage_mh); uint64_t kimage_os_metaclass_constructor = find_kimage_os_metaclass_constructor(ctx->kimage_mh, kimage_base); csh handle; cs_insn *insn; size_t count; cs_regs regs_read = {0}, regs_write = {0}; uint8_t read_count, write_count; if (cs_open(CS_ARCH_ARM64, CS_MODE_ARM, &handle) != CS_ERR_OK) return; cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); uint8_t *constructor_code = (uint8_t *)KERNEL_ADDR_TO_MAP(ctx->kimage_mh, kimage_base, constructor_address); uint64_t constructor_size = get_constructor_size(ctx->kimage_mh, constructor_address, kimage_base); count = cs_disasm(handle, constructor_code, constructor_size, constructor_address, 0, &insn); if (count > 0) { size_t j; for (j = 0; j < count; j++) { if (cs_regs_access(handle, &insn[j], regs_read, &read_count, regs_write, &write_count) == 0) { switch (insn[j].id) { case ARM64_INS_ADR: { uint64_t adr_addr = 0; int is_adrp = 0; uint32_t rd = 0; int32_t off = 0; if (aarch64_decode_adr(*(uint32_t *)(&insn[j].bytes), &is_adrp, &rd, &off)) { adr_addr = insn[j].address + off; } get_ctx_reg_map_reg(ctx, regs_write[0]) = adr_addr; break; } case ARM64_INS_ADRP: { uint64_t adr_addr = 0; int is_adrp = 0; uint32_t rd = 0; int32_t off = 0; if (aarch64_decode_adr(*(uint32_t *)(&insn[j].bytes), &is_adrp, &rd, &off)) { adr_addr = ((insn[j].address + off) >> 12) << 12; } get_ctx_reg_map_reg(ctx, regs_write[0]) = adr_addr; break; } case ARM64_INS_LDR: { uint64_t ldr_addr = 0; int is_w = 0; int is64 = 0; uint32_t rt = 0; int32_t s_off = 0; uint32_t u_off = 0; if (aarch64_decode_ldr_literal(*(uint32_t *)(&insn[j].bytes), &is_w, &is64, &rt, &s_off)) { ldr_addr = insn[j].address + s_off; uint64_t ldr_deref = *(uint64_t *)KERNEL_ADDR_TO_MAP(ctx->kimage_mh, kimage_base, ldr_addr); get_ctx_reg_map_reg(ctx, regs_write[0]) = ldr_deref; } else if (aarch64_decode_ldr_immediate(*(uint32_t *)(&insn[j].bytes), &u_off)) { uint64_t op1 = get_ctx_reg_map_reg(ctx, regs_read[0]); op1 += u_off; uint64_t ldr_addr = *(uint64_t *)KERNEL_ADDR_TO_MAP(ctx->kimage_mh, kimage_base, op1); get_ctx_reg_map_reg(ctx, regs_write[0]) = ldr_addr; } break; } case ARM64_INS_ADD: { uint32_t off = 0; if (aarch64_decode_add(*(uint32_t *)(&insn[j].bytes), &off)) { uint64_t op1 = get_ctx_reg_map_reg(ctx, regs_read[0]); op1 += off; get_ctx_reg_map_reg(ctx, regs_write[0]) = op1; } break; } case ARM64_INS_MOV: { uint64_t op1 = get_ctx_reg_map_reg(ctx, regs_read[0]); get_ctx_reg_map_reg(ctx, regs_write[0]) = op1; break; } /* ugly. libdump should be independent of iokitdumper, but I was lazy and this was the quickest way to map constructors lmao */ case ARM64_INS_BL: { int is_bl = 0; int32_t off = 0; if (aarch64_decode_b(*(uint32_t *)(&insn[j].bytes), &is_bl, &off)) { if (insn[j].address + off == kimage_os_metaclass_constructor) { const char *kext_name = get_kext_name(ctx->map, ctx->kimage_mh); struct hierarchy_entry *entry = malloc(sizeof(struct hierarchy_entry)); strncpy(entry->class_name, (char *)KERNEL_ADDR_TO_MAP(ctx->kimage_mh, kimage_base, get_ctx_reg_map_reg(ctx, REG_X1)), sizeof(entry->class_name)); if (kext_name) strncpy(entry->kext_name, kext_name, sizeof(entry->kext_name)); else { if (((void *)ctx->map->map_data == (void *)ctx->kimage_mh)) { strncpy(entry->kext_name, "kernel", sizeof(entry->kext_name)); } else { strncpy(entry->kext_name, "unknown", sizeof(entry->kext_name)); } } struct hierarchy_regs_set set = {0}; set.reg_x0 = get_ctx_reg_map_reg(ctx, REG_X0); set.reg_x1 = get_ctx_reg_map_reg(ctx, REG_X1); set.reg_x2 = get_ctx_reg_map_reg(ctx, REG_X2); entry->set = set; if (head) { if (SLIST_EMPTY(head)) { SLIST_INSERT_HEAD(head, entry, entries); prev = entry; } else { SLIST_INSERT_AFTER(prev, entry, entries); prev = entry; } } else { free(entry); } } } break; } } } }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; cs_insn *insn; int mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: (a->bits==16)? CS_MODE_16: 0; int n, ret = cs_open (CS_ARCH_X86, mode, &handle); op->type = R_ANAL_OP_TYPE_NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { int rs = a->bits/8; const char *pc = (a->bits==16)?"ip": (a->bits==32)?"eip":"rip"; const char *sp = (a->bits==16)?"sp": (a->bits==32)?"esp":"rsp"; op->size = insn->size; switch (insn->id) { case X86_INS_FNOP: case X86_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; if (a->decode) esilprintf (op, ""); break; case X86_INS_HLT: op->type = R_ANAL_OP_TYPE_TRAP; break; case X86_INS_CLI: case X86_INS_STI: case X86_INS_CLC: case X86_INS_STC: break; case X86_INS_MOV: case X86_INS_MOVZX: case X86_INS_MOVABS: case X86_INS_MOVHPD: case X86_INS_MOVHPS: case X86_INS_MOVLPD: case X86_INS_MOVLPS: case X86_INS_MOVBE: case X86_INS_MOVSB: case X86_INS_MOVSD: case X86_INS_MOVSQ: case X86_INS_MOVSS: case X86_INS_MOVSW: case X86_INS_MOVD: case X86_INS_MOVQ: case X86_INS_MOVDQ2Q: op->type = R_ANAL_OP_TYPE_MOV; break; case X86_INS_CMP: case X86_INS_VCMP: case X86_INS_CMPPD: case X86_INS_CMPPS: case X86_INS_CMPSW: case X86_INS_CMPSD: case X86_INS_CMPSQ: case X86_INS_CMPSB: case X86_INS_CMPSS: case X86_INS_TEST: op->type = R_ANAL_OP_TYPE_CMP; break; case X86_INS_LEA: op->type = R_ANAL_OP_TYPE_LEA; break; case X86_INS_ENTER: case X86_INS_PUSH: case X86_INS_PUSHAW: case X86_INS_PUSHAL: case X86_INS_PUSHF: op->type = R_ANAL_OP_TYPE_PUSH; break; case X86_INS_LEAVE: case X86_INS_POP: case X86_INS_POPAW: case X86_INS_POPAL: case X86_INS_POPF: case X86_INS_POPCNT: op->type = R_ANAL_OP_TYPE_POP; break; case X86_INS_RET: case X86_INS_RETF: case X86_INS_IRET: case X86_INS_IRETD: case X86_INS_IRETQ: case X86_INS_SYSRET: op->type = R_ANAL_OP_TYPE_RET; if (a->decode) esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, pc, rs, sp); break; case X86_INS_INT1: case X86_INS_INT3: case X86_INS_INTO: case X86_INS_INT: case X86_INS_VMCALL: case X86_INS_VMMCALL: case X86_INS_SYSCALL: op->type = R_ANAL_OP_TYPE_TRAP; if (a->decode) esilprintf (op, "%d,$", (int)INSOP(0).imm); break; case X86_INS_JL: case X86_INS_JLE: case X86_INS_JA: case X86_INS_JAE: case X86_INS_JB: case X86_INS_JBE: case X86_INS_JCXZ: case X86_INS_JECXZ: case X86_INS_JO: case X86_INS_JNO: case X86_INS_JS: case X86_INS_JNS: case X86_INS_JP: case X86_INS_JNP: case X86_INS_JE: case X86_INS_JNE: case X86_INS_JG: case X86_INS_JGE: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = addr+op->size; if (a->decode) { if (INSOP(0).type==X86_OP_IMM) { // TODO } } break; case X86_INS_CALL: case X86_INS_LCALL: if (INSOP(0).type==X86_OP_IMM) { op->type = R_ANAL_OP_TYPE_CALL; // TODO: what if UCALL? // TODO: use imm_size op->jump = INSOP(0).imm; op->fail = addr+op->size; } else { op->type = R_ANAL_OP_TYPE_UCALL; } break; case X86_INS_JMP: case X86_INS_LJMP: // TODO: what if UJMP? op->jump = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_JMP; if (a->decode) { ut64 dst = INSOP(0).imm; esilprintf (op, "0x%"PFMT64x",%s,=", dst, pc); } break; case X86_INS_IN: case X86_INS_INSW: case X86_INS_INSD: case X86_INS_INSB: case X86_INS_OUT: case X86_INS_OUTSB: case X86_INS_OUTSD: case X86_INS_OUTSW: op->type = R_ANAL_OP_TYPE_IO; break; case X86_INS_VXORPD: case X86_INS_VXORPS: case X86_INS_VPXORD: case X86_INS_VPXORQ: case X86_INS_VPXOR: case X86_INS_KXORW: case X86_INS_PXOR: case X86_INS_XOR: op->type = R_ANAL_OP_TYPE_XOR; break; case X86_INS_OR: op->type = R_ANAL_OP_TYPE_OR; break; case X86_INS_SUB: case X86_INS_DEC: case X86_INS_PSUBB: case X86_INS_PSUBW: case X86_INS_PSUBD: case X86_INS_PSUBQ: case X86_INS_PSUBSB: case X86_INS_PSUBSW: case X86_INS_PSUBUSB: case X86_INS_PSUBUSW: op->type = R_ANAL_OP_TYPE_SUB; break; case X86_INS_AND: case X86_INS_ANDN: case X86_INS_ANDPD: case X86_INS_ANDPS: case X86_INS_ANDNPD: case X86_INS_ANDNPS: op->type = R_ANAL_OP_TYPE_AND; break; case X86_INS_DIV: op->type = R_ANAL_OP_TYPE_DIV; break; case X86_INS_MUL: op->type = R_ANAL_OP_TYPE_MUL; break; case X86_INS_INC: case X86_INS_ADD: case X86_INS_FADD: case X86_INS_ADDPD: op->type = R_ANAL_OP_TYPE_ADD; break; } } cs_free (insn, n); cs_close (&handle); } return op->size; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; cs_insn *insn; int mode, n, ret; mode = CS_MODE_BIG_ENDIAN; ret = cs_open (CS_ARCH_SYSZ, mode, &handle); op->type = R_ANAL_OP_TYPE_NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // 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); op->size = insn->size; switch (insn->id) { case SYSZ_INS_BRCL: case SYSZ_INS_BRASL: op->type = R_ANAL_OP_TYPE_CALL; break; case SYSZ_INS_BR: op->type = R_ANAL_OP_TYPE_JMP; break; case SYSZ_INS_BRC: case SYSZ_INS_BER: case SYSZ_INS_BHR: case SYSZ_INS_BHER: case SYSZ_INS_BLR: case SYSZ_INS_BLER: case SYSZ_INS_BLHR: case SYSZ_INS_BNER: case SYSZ_INS_BNHR: case SYSZ_INS_BNHER: case SYSZ_INS_BNLR: case SYSZ_INS_BNLER: case SYSZ_INS_BNLHR: case SYSZ_INS_BNOR: case SYSZ_INS_BOR: case SYSZ_INS_BASR: case SYSZ_INS_BRAS: case SYSZ_INS_BRCT: case SYSZ_INS_BRCTG: op->type = R_ANAL_OP_TYPE_CJMP; break; case SYSZ_INS_JE: case SYSZ_INS_JGE: case SYSZ_INS_JHE: case SYSZ_INS_JGHE: case SYSZ_INS_JH: case SYSZ_INS_JGH: case SYSZ_INS_JLE: case SYSZ_INS_JGLE: case SYSZ_INS_JLH: case SYSZ_INS_JGLH: case SYSZ_INS_JL: case SYSZ_INS_JGL: case SYSZ_INS_JNE: case SYSZ_INS_JGNE: case SYSZ_INS_JNHE: case SYSZ_INS_JGNHE: case SYSZ_INS_JNH: case SYSZ_INS_JGNH: case SYSZ_INS_JNLE: case SYSZ_INS_JGNLE: case SYSZ_INS_JNLH: case SYSZ_INS_JGNLH: case SYSZ_INS_JNL: case SYSZ_INS_JGNL: case SYSZ_INS_JNO: case SYSZ_INS_JGNO: case SYSZ_INS_JO: case SYSZ_INS_JGO: case SYSZ_INS_JG: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = addr+op->size; break; case SYSZ_INS_J: op->type = R_ANAL_OP_TYPE_JMP; op->jump = INSOP(0).imm; op->fail = UT64_MAX; break; } } cs_free (insn, n); cs_close (&handle); } return op->size; }
static int analop(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { int n, ret, opsize = -1; static csh hndl = 0; static int omode = -1; static int obits = 32; cs_insn* insn; int mode = anal->big_endian? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; if (anal->cpu && *anal->cpu) { if (!strcmp (anal->cpu, "micro")) { mode |= CS_MODE_MICRO; } else if (!strcmp (anal->cpu, "r6")) { mode |= CS_MODE_MIPS32R6; } else if (!strcmp (anal->cpu, "v3")) { mode |= CS_MODE_MIPS3; } else if (!strcmp (anal->cpu, "v2")) { #if CS_API_MAJOR > 3 mode |= CS_MODE_MIPS2; #endif } } mode |= (anal->bits==64)? CS_MODE_MIPS64: CS_MODE_MIPS32; if (mode != omode || anal->bits != obits) { cs_close (&hndl); hndl = 0; omode = mode; obits = anal->bits; } // XXX no arch->cpu ?!?! CS_MODE_MICRO, N64 op->delay = 0; op->type = R_ANAL_OP_TYPE_ILL; if (len < 4) { return -1; } op->size = 4; if (hndl == 0) { ret = cs_open (CS_ARCH_MIPS, mode, &hndl); if (ret != CS_ERR_OK) { goto fin; } cs_option (hndl, CS_OPT_DETAIL, CS_OPT_ON); } n = cs_disasm (hndl, (ut8*)buf, len, addr, 1, &insn); if (n < 1 || insn->size < 1) { goto beach; } op->type = R_ANAL_OP_TYPE_NULL; op->delay = 0; op->jump = UT64_MAX; op->fail = UT64_MAX; op->id = insn->id; opsize = op->size = insn->size; switch (insn->id) { case MIPS_INS_INVALID: op->type = R_ANAL_OP_TYPE_ILL; break; case MIPS_INS_LB: case MIPS_INS_LBU: case MIPS_INS_LBUX: case MIPS_INS_LW: case MIPS_INS_LWC1: case MIPS_INS_LWC2: case MIPS_INS_LWL: case MIPS_INS_LWR: case MIPS_INS_LWXC1: case MIPS_INS_LD: case MIPS_INS_LDC1: case MIPS_INS_LDC2: case MIPS_INS_LDL: case MIPS_INS_LDR: case MIPS_INS_LDXC1: op->type = R_ANAL_OP_TYPE_LOAD; op->refptr = 4; switch (OPERAND(1).type) { case MIPS_OP_MEM: if (OPERAND(1).mem.base == MIPS_REG_GP) { op->ptr = anal->gp + OPERAND(1).mem.disp; op->refptr = 4; } break; case MIPS_OP_IMM: op->ptr = OPERAND(1).imm; break; case MIPS_OP_REG: // wtf? break; default: break; } // TODO: fill break; case MIPS_INS_SD: case MIPS_INS_SW: case MIPS_INS_SB: case MIPS_INS_SH: case MIPS_INS_SWC1: case MIPS_INS_SWC2: case MIPS_INS_SWL: case MIPS_INS_SWR: case MIPS_INS_SWXC1: op->type = R_ANAL_OP_TYPE_STORE; break; case MIPS_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case MIPS_INS_SYSCALL: op->type = R_ANAL_OP_TYPE_SWI; break; case MIPS_INS_BREAK: op->type = R_ANAL_OP_TYPE_TRAP; break; case MIPS_INS_JALR: op->type = R_ANAL_OP_TYPE_UCALL; op->delay = 1; break; case MIPS_INS_JAL: case MIPS_INS_JALS: case MIPS_INS_JALX: case MIPS_INS_JRADDIUSP: case MIPS_INS_BAL: // (no blezal/bgtzal or blezall/bgtzall, only blezalc/bgtzalc) case MIPS_INS_BLTZAL: // Branch on <0 and link case MIPS_INS_BGEZAL: // Branch on >=0 and link case MIPS_INS_BLTZALL: // "likely" versions case MIPS_INS_BGEZALL: case MIPS_INS_BLTZALC: // compact versions case MIPS_INS_BLEZALC: case MIPS_INS_BGEZALC: case MIPS_INS_BGTZALC: case MIPS_INS_JIALC: case MIPS_INS_JIC: op->type = R_ANAL_OP_TYPE_CALL; op->jump = IMM(0); switch (insn->id) { case MIPS_INS_JIALC: case MIPS_INS_JIC: case MIPS_INS_BLTZALC: case MIPS_INS_BLEZALC: case MIPS_INS_BGEZALC: case MIPS_INS_BGTZALC: // compact vesions (no delay) op->delay = 0; op->fail = addr+4; break; default: op->delay = 1; op->fail = addr+8; break; } break; case MIPS_INS_LI: case MIPS_INS_LUI: SET_VAL (op, 1); op->type = R_ANAL_OP_TYPE_MOV; break; case MIPS_INS_MOVE: op->type = R_ANAL_OP_TYPE_MOV; break; case MIPS_INS_ADD: case MIPS_INS_ADDI: case MIPS_INS_ADDU: case MIPS_INS_ADDIU: case MIPS_INS_DADD: case MIPS_INS_DADDI: case MIPS_INS_DADDIU: SET_VAL (op, 2); op->sign = (insn->id == MIPS_INS_ADDI || insn->id == MIPS_INS_ADD); op->type = R_ANAL_OP_TYPE_ADD; if (REGID(0) == MIPS_REG_SP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = -IMM(2); } break; case MIPS_INS_SUB: case MIPS_INS_SUBV: case MIPS_INS_SUBVI: case MIPS_INS_DSUBU: case MIPS_INS_FSUB: case MIPS_INS_FMSUB: case MIPS_INS_SUBU: case MIPS_INS_DSUB: case MIPS_INS_SUBS_S: case MIPS_INS_SUBS_U: case MIPS_INS_SUBUH: case MIPS_INS_SUBUH_R: SET_VAL (op,2); op->sign = insn->id == MIPS_INS_SUB; op->type = R_ANAL_OP_TYPE_SUB; break; case MIPS_INS_MULV: case MIPS_INS_MULT: case MIPS_INS_MULSA: case MIPS_INS_FMUL: case MIPS_INS_MUL: case MIPS_INS_DMULT: case MIPS_INS_DMULTU: op->type = R_ANAL_OP_TYPE_MUL; break; case MIPS_INS_XOR: case MIPS_INS_XORI: SET_VAL (op,2); op->type = R_ANAL_OP_TYPE_XOR; break; case MIPS_INS_AND: case MIPS_INS_ANDI: SET_VAL (op,2); op->type = R_ANAL_OP_TYPE_AND; if (REGID(0) == MIPS_REG_SP) { op->stackop = R_ANAL_STACK_ALIGN; } break; case MIPS_INS_NOT: op->type = R_ANAL_OP_TYPE_NOT; break; case MIPS_INS_OR: case MIPS_INS_ORI: SET_VAL (op,2); op->type = R_ANAL_OP_TYPE_OR; break; case MIPS_INS_DIV: case MIPS_INS_DIVU: case MIPS_INS_DDIV: case MIPS_INS_DDIVU: case MIPS_INS_FDIV: case MIPS_INS_DIV_S: case MIPS_INS_DIV_U: op->type = R_ANAL_OP_TYPE_DIV; break; case MIPS_INS_CMPGDU: case MIPS_INS_CMPGU: case MIPS_INS_CMPU: case MIPS_INS_CMPI: op->type = R_ANAL_OP_TYPE_CMP; break; case MIPS_INS_J: case MIPS_INS_B: case MIPS_INS_BZ: case MIPS_INS_BEQ: case MIPS_INS_BNZ: case MIPS_INS_BNE: case MIPS_INS_BNEL: case MIPS_INS_BEQL: case MIPS_INS_BEQZ: case MIPS_INS_BNEG: case MIPS_INS_BNEGI: case MIPS_INS_BNEZ: case MIPS_INS_BTEQZ: case MIPS_INS_BTNEZ: case MIPS_INS_BLTZ: case MIPS_INS_BLTZL: case MIPS_INS_BLEZ: case MIPS_INS_BLEZL: case MIPS_INS_BGEZ: case MIPS_INS_BGEZL: case MIPS_INS_BGTZ: case MIPS_INS_BGTZL: case MIPS_INS_BLEZC: case MIPS_INS_BGEZC: case MIPS_INS_BLTZC: case MIPS_INS_BGTZC: if (insn->id == MIPS_INS_J || insn->id == MIPS_INS_B ) { op->type = R_ANAL_OP_TYPE_JMP; } else { op->type = R_ANAL_OP_TYPE_CJMP; } if (OPERAND(0).type == MIPS_OP_IMM) { op->jump = IMM(0); } else if (OPERAND(1).type == MIPS_OP_IMM) { op->jump = IMM(1); } else if (OPERAND(2).type == MIPS_OP_IMM) { op->jump = IMM(2); } switch (insn->id) { case MIPS_INS_BLEZC: case MIPS_INS_BGEZC: case MIPS_INS_BLTZC: case MIPS_INS_BGTZC: // compact versions (no delay) op->delay = 0; op->fail = addr+4; break; default: op->delay = 1; op->fail = addr+8; break; } break; case MIPS_INS_JR: case MIPS_INS_JRC: op->type = R_ANAL_OP_TYPE_RJMP; op->delay = 1; // register is $ra, so jmp is a return if (insn->detail->mips.operands[0].reg == MIPS_REG_RA) { op->type = R_ANAL_OP_TYPE_RET; } break; case MIPS_INS_SLT: case MIPS_INS_SLTI: op->sign = true; SET_VAL (op, 2); break; case MIPS_INS_SLTIU: SET_VAL (op, 2); break; case MIPS_INS_SHRAV: case MIPS_INS_SHRAV_R: case MIPS_INS_SHRA: case MIPS_INS_SHRA_R: case MIPS_INS_SRA: op->type = R_ANAL_OP_TYPE_SAR; SET_VAL (op,2); break; case MIPS_INS_SHRL: case MIPS_INS_SRLV: case MIPS_INS_SRL: op->type = R_ANAL_OP_TYPE_SHR; SET_VAL (op,2); break; case MIPS_INS_SLLV: case MIPS_INS_SLL: op->type = R_ANAL_OP_TYPE_SHL; SET_VAL (op,2); break; } beach: set_opdir (op); if (anal->decode) { if (analop_esil (anal, op, addr, buf, len, &hndl, insn) != 0) { r_strbuf_fini (&op->esil); } } if (anal->fillval) { op_fillval (anal, op, &hndl, insn); } cs_free (insn, n); //cs_close (&handle); fin: return opsize; }
main (int argc, char **argv) { int errs = 0; int nprocs = 1; int c; extern int optind; extern char *optarg; char *name; extern GROUP *hostGroup; GROUP *group; EXE *exe; EXE *dummy; CHANNEL *channel = cs_channel (NULL, "dummy_chan"); supervisor_mode = 1 << 2; while((c = getopt (argc, argv, "n:vis")) != -1) { switch (c) { case 'v': verbose++; break; case 'i': cs_nowait (); break; case 'n': nprocs = atoi (optarg); break; case 's': supervisor_mode |= (1 << 0) | (1 << 3); break; case '?': errs++; break; } } if (errs || optind != (argc-1)) { fprintf (stderr, "usage: %s [-vin num] file\n", argv[0]); exit (1); } group = cs_group (NULL, "code"); cs_option (group, "commit", "transputer"); /* cs_option (hostGroup, "connect", group); */ exe = cs_exe (group, "code", name = argv[optind], "OutChan dummy", channel, 0); for (c = 0; c < nprocs - 1; c++) { CHANNEL *next = cs_channel (NULL, "dummy_chan"); dummy = cs_exe (NULL, "dummy_exe", "dummy.ex8", "InChan in", channel, "OutChan out", next, 0); cs_option (dummy, "mode", "system"); channel = next; } dummy = cs_exe (NULL, "dummy_exe", "dummy.ex8", "InChan in", channel, 0); cs_option (dummy, "mode", "system"); cs_load (); }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; cs_insn *insn; int mode, n, ret; mode = CS_MODE_BIG_ENDIAN; if (!strcmp (a->cpu, "v9")) mode |= CS_MODE_V9; ret = cs_open (CS_ARCH_SPARC, mode, &handle); op->type = R_ANAL_OP_TYPE_NULL; op->size = 0; op->delay = 0; op->jump = UT64_MAX; op->fail = UT64_MAX; op->val = UT64_MAX; op->ptr = UT64_MAX; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { op->size = insn->size; switch (insn->id) { case SPARC_INS_MOV: op->type = R_ANAL_OP_TYPE_MOV; break; case SPARC_INS_RETT: op->type = R_ANAL_OP_TYPE_RET; break; case SPARC_INS_UNIMP: op->type = R_ANAL_OP_TYPE_UNK; break; case SPARC_INS_CALL: switch (INSOP(0).type) { case SPARC_OP_MEM: // TODO break; case SPARC_OP_REG: op->type = R_ANAL_OP_TYPE_UCALL; break; default: op->type = R_ANAL_OP_TYPE_CALL; op->jump = INSOP(0).imm; break; } break; case SPARC_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case SPARC_INS_CMP: op->type = R_ANAL_OP_TYPE_CMP; break; case SPARC_INS_JMP: case SPARC_INS_JMPL: op->type = R_ANAL_OP_TYPE_JMP; op->jump = INSOP(0).imm; break; case SPARC_INS_LDD: case SPARC_INS_LD: case SPARC_INS_LDQ: case SPARC_INS_LDSB: case SPARC_INS_LDSH: case SPARC_INS_LDSW: case SPARC_INS_LDUB: case SPARC_INS_LDUH: case SPARC_INS_LDX: op->type = R_ANAL_OP_TYPE_LOAD; break; case SPARC_INS_STBAR: case SPARC_INS_STB: case SPARC_INS_STD: case SPARC_INS_ST: case SPARC_INS_STH: case SPARC_INS_STQ: case SPARC_INS_STX: op->type = R_ANAL_OP_TYPE_STORE; break; case SPARC_INS_ORCC: case SPARC_INS_ORNCC: case SPARC_INS_ORN: case SPARC_INS_OR: op->type = R_ANAL_OP_TYPE_OR; break; case SPARC_INS_B: case SPARC_INS_BMASK: case SPARC_INS_BRGEZ: case SPARC_INS_BRGZ: case SPARC_INS_BRLEZ: case SPARC_INS_BRLZ: case SPARC_INS_BRNZ: case SPARC_INS_BRZ: case SPARC_INS_FB: switch (INSOP(0).type) { case SPARC_OP_REG: op->type = R_ANAL_OP_TYPE_CJMP; if (INSCC != SPARC_CC_ICC_N) // never op->jump = INSOP(1).imm; if (INSCC != SPARC_CC_ICC_A) // always op->fail = addr+4; break; case SPARC_OP_IMM: op->type = R_ANAL_OP_TYPE_CJMP; if (INSCC != SPARC_CC_ICC_N) // never op->jump = INSOP(0).imm; if (INSCC != SPARC_CC_ICC_A) // always op->fail = addr+4; break; default: // MEM? break; } break; case SPARC_INS_FHSUBD: case SPARC_INS_FHSUBS: case SPARC_INS_FPSUB16: case SPARC_INS_FPSUB16S: case SPARC_INS_FPSUB32: case SPARC_INS_FPSUB32S: case SPARC_INS_FSUBD: case SPARC_INS_FSUBQ: case SPARC_INS_FSUBS: case SPARC_INS_SUBCC: case SPARC_INS_SUBX: case SPARC_INS_SUBXCC: case SPARC_INS_SUB: case SPARC_INS_TSUBCCTV: case SPARC_INS_TSUBCC: op->type = R_ANAL_OP_TYPE_SUB; break; case SPARC_INS_ADDCC: case SPARC_INS_ADDX: case SPARC_INS_ADDXCC: case SPARC_INS_ADDXC: case SPARC_INS_ADDXCCC: case SPARC_INS_ADD: case SPARC_INS_FADDD: case SPARC_INS_FADDQ: case SPARC_INS_FADDS: case SPARC_INS_FHADDD: case SPARC_INS_FHADDS: case SPARC_INS_FNADDD: case SPARC_INS_FNADDS: case SPARC_INS_FNHADDD: case SPARC_INS_FNHADDS: case SPARC_INS_FPADD16: case SPARC_INS_FPADD16S: case SPARC_INS_FPADD32: case SPARC_INS_FPADD32S: case SPARC_INS_FPADD64: case SPARC_INS_TADDCCTV: case SPARC_INS_TADDCC: op->type = R_ANAL_OP_TYPE_ADD; break; case SPARC_INS_FDMULQ: case SPARC_INS_FMUL8SUX16: case SPARC_INS_FMUL8ULX16: case SPARC_INS_FMUL8X16: case SPARC_INS_FMUL8X16AL: case SPARC_INS_FMUL8X16AU: case SPARC_INS_FMULD: case SPARC_INS_FMULD8SUX16: case SPARC_INS_FMULD8ULX16: case SPARC_INS_FMULQ: case SPARC_INS_FMULS: case SPARC_INS_FSMULD: case SPARC_INS_MULX: case SPARC_INS_SMULCC: case SPARC_INS_SMUL: case SPARC_INS_UMULCC: case SPARC_INS_UMULXHI: case SPARC_INS_UMUL: case SPARC_INS_XMULX: case SPARC_INS_XMULXHI: op->type = R_ANAL_OP_TYPE_MUL; break; case SPARC_INS_FDIVD: case SPARC_INS_FDIVQ: case SPARC_INS_FDIVS: case SPARC_INS_SDIVCC: case SPARC_INS_SDIVX: case SPARC_INS_SDIV: case SPARC_INS_UDIVCC: case SPARC_INS_UDIVX: case SPARC_INS_UDIV: op->type = R_ANAL_OP_TYPE_DIV; break; } } cs_free (insn, n); cs_close (&handle); } return op->size; }
/// Get a pointer from an offset. void* GetPointerFromOffset(void* ptr, Offset *off) { // skip if done. if (off->pointer != nullptr) { return off->pointer; } // can't do it. if(ptr == nullptr) { return nullptr; } // Get a code pointer. void *code = ptr + off->base_offset; csh handle; cs_insn *insn; size_t count; // open capstone (murgle threading) if (cs_open(ermor_capstone_arch, ermor_capstone_mode, &handle) != CS_ERR_OK) { printf("Failed to open capstone.\n"); return -1; } // spin up details to get operands cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); /// Get the number of instructions extracted; we only want the first. // Give it 64 bytes; total overkill, but we need the instruction value. count = cs_disasm(handle, code, 64, (uintptr_t)code, 0, &insn); if (count > 0) { uint8_t read_count, write_count, i; // Print assembly #if defined __arm__ #else cs_x86 *inst = &(insn[0].detail->x86); #if defined __CAPSTONE_CHECKING for(int i = 0; i < inst->op_count; i++) { printf("operand: %d | %lld\n", inst->operands[i].type, inst->operands[i].size); } #endif//__CAPSTONE_CHECKING cs_x86_op *operand; uint32_t opcode = 0; memcpy(&opcode, inst->opcode, 4); switch(opcode) { case 0x8B: // mov { // Displacement value of operand[1] + size + base off->pointer = (char*)code + inst->operands[1].mem.disp + insn[0].size; } break; case 0x83: // cmp switch(inst->modrm) { case 0x3D: { // Displacement value of operand[0] + size + base off->pointer = (char*)code + inst->operands[0].mem.disp + insn[0].size; } break; } break; } #endif cs_free(insn, count); } else { printf("ERROR: Failed to disassemble given code!\n"); } cs_close(&handle); return off->pointer; }
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; op->id = insn->id; 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)insn->detail->ppc.operands[0].imm; switch (insn->detail->ppc.bc) { #if 0 case PPC_BC_INVALID: // non-conditional op->type = R_ANAL_OP_TYPE_ILL; break; #endif case PPC_BC_LT: case PPC_BC_LE: case PPC_BC_EQ: case PPC_BC_GE: case PPC_BC_GT: case PPC_BC_NE: case PPC_BC_UN: case PPC_BC_NU: case PPC_BC_SO: case PPC_BC_NS: op->type = R_ANAL_OP_TYPE_CJMP; op->fail = addr + 4; break; default: break; } switch (insn->detail->ppc.operands[0].type) { case PPC_OP_CRX: op->type = R_ANAL_OP_TYPE_CJMP; 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 = (ut64)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)insn->detail->ppc.operands[0].imm; op->fail = addr + 4; esilprintf (op, "pc,lr,=,%s,pc,=", ARG(0)); break; case PPC_INS_TRAP: op->type = R_ANAL_OP_TYPE_TRAP; 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; } static int archinfo(RAnal *anal, int q) { return 4; /* :D */ } RAnalPlugin r_anal_plugin_ppc_cs = { .name = "ppc", .desc = "Capstone PowerPC analysis", .license = "BSD", .arch = "ppc", .bits = 32|64, .archinfo = archinfo, .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 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 };
BOOL interptFunction(HANDLE hProcess, FUNCTION function){ unsigned char *buffer; SIZE_T bytesRead = 0; if(!(buffer = malloc(function.size))) return FALSE; if(!ReadProcessMemory(hProcess, (void*)function.startAddr, buffer, function.size, &bytesRead) && bytesRead != function.size){ MessageBoxA(NULL, "ReadProcessMemory2 failed!", "FAILED", 0); return FALSE; } csh handle; cs_insn *insn; size_t count; if (cs_open(CS_ARCH_X86, CS_MODE_32, &handle) != CS_ERR_OK) return -1; cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); count = cs_disasm(handle, buffer, function.size, function.startAddr, 0, &insn); PABS_INSTRUCTION pAbsInstruction = NULL; size_t byteCounter = 0; if (count > 0) { size_t currIns = 0; cs_x86 *x86_insn = NULL; for (currIns = 0; currIns < count; currIns++) { if(!strcmp(insn[currIns].mnemonic, "jmp") || !strcmp(insn[currIns].mnemonic, "call")){ x86_insn = &(insn[currIns].detail->x86); if(x86_insn->op_count != 1)//Something went wrong return FALSE; cs_x86_op *operand = &(x86_insn->operands[0]); if(operand->type != X86_OP_IMM) continue; if(operand->imm > function.startAddr + function.size){ if(!fixRelativeJmpOrCall(operand->imm, byteCounter, &pAbsInstruction, insn[currIns].size,strcmp(insn[currIns].mnemonic, "jmp"))) return FALSE; printf("Found one relative jmp/call to fix!\n"); byteCounter += 6; } else byteCounter += insn[currIns].size; } else byteCounter += insn[currIns].size; } cs_free(insn, count); } else printf("ERROR: Failed to disassemble given code!\n"); cs_close(&handle); fflush(stdout); if(!getAbsoluteAddressStorage(hProcess, pAbsInstruction)) return FALSE; BYTE* newFunction = createNewFunction(buffer, byteCounter, pAbsInstruction); if(!newFunction) return FALSE; BYTE* encryptedFunction = malloc(byteCounter); if(!encryptedFunction) return FALSE; memcpy(encryptedFunction, newFunction, byteCounter); int encryptLocation = 0; while(encryptLocation<byteCounter){ encryptedFunction[encryptLocation++] ^= 0xF2; } #define SHELL_SIZE 108 unsigned char sexyShell[SHELL_SIZE] = { 0x60, 0x9C, 0xB9, 0x00, 0x00, 0x00, 0x00, 0x81, 0xF9, 0xFF, 0x00, 0x00, 0x00, 0x75, 0x4C, 0xC7, 0x05, 0x78, 0x56, 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0xBB, 0x69, 0x00, 0x00, 0x00, 0xB8, 0x68, 0x00, 0x00, 0x00, 0xBF, 0x67, 0x00, 0x00, 0x00, 0x89, 0xDA, 0xD1, 0xE2, 0x01, 0xC2, 0x83, 0xC2, 0x01, 0xBE, 0x78, 0x56, 0x34, 0x12, 0x39, 0xFA, 0x7E, 0x17, 0xC6, 0x07, 0x90, 0x83, 0xC7, 0x01, 0x89, 0x3D, 0x78, 0x56, 0x34, 0x12, 0x89, 0xD9, 0xA4, 0x80, 0x77, 0xFF, 0xF2, 0xE2, 0xF9, 0xEB, 0x13, 0x89, 0xC7, 0x89, 0x3D, 0x78, 0x56, 0x34, 0x12, 0xEB, 0xEB, 0x83, 0xC1, 0x01, 0x89, 0x0D, 0x78, 0x56, 0x34, 0x12, 0x9D, 0x61, 0xFF, 0x25, 0x78, 0x56, 0x34, 0x12 }; HANDLE address2 = VirtualAllocEx(hProcess, NULL, byteCounter+sizeof(DWORD)+SHELL_SIZE+byteCounter*3, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);//4 extra bytes for the address if(!address2) return FALSE; if(!WriteProcessMemory(hProcess, (void*)address2, (void*)encryptedFunction, byteCounter, NULL))//Write the encrypted function to memory return FALSE; if(!WriteProcessMemory(hProcess, (void*)address2+byteCounter+sizeof(DWORD)+SHELL_SIZE, (void*)newFunction, byteCounter, NULL))//Write the function to memory return FALSE; DWORD olaAmigos = (DWORD)address2+byteCounter+sizeof(DWORD); if(!WriteProcessMemory(hProcess, (void*)address2+byteCounter, &olaAmigos, sizeof(DWORD), NULL))//Write the address of the shellcode return FALSE; //Convert shell code to self modyfing code //setting the correct counter address DWORD counterAddress = (DWORD)address2+byteCounter+sizeof(DWORD)+0x3; memcpy(sexyShell+0x11, &counterAddress,sizeof(DWORD)); memcpy(sexyShell+0x60, &counterAddress,sizeof(DWORD)); //setting the function size memcpy(sexyShell+0x1A, &byteCounter,sizeof(DWORD)); //setting the startAddress DWORD startAddress = (DWORD)address2+byteCounter+sizeof(DWORD)+SHELL_SIZE; memcpy(sexyShell+0x1F, &startAddress,sizeof(DWORD)); //setting addressOfUnencripted DWORD addressOfUnencripted = (DWORD)address2+byteCounter+sizeof(DWORD)+0x24; memcpy(sexyShell+0x24, &startAddress,sizeof(DWORD)); memcpy(sexyShell+0x42, &addressOfUnencripted, sizeof(DWORD)); memcpy(sexyShell+0x55, &addressOfUnencripted, sizeof(DWORD)); memcpy(sexyShell+0x68, &addressOfUnencripted, sizeof(DWORD)); //functionStoreAddress memcpy(sexyShell+0x32, &address2,sizeof(DWORD)); if(!WriteProcessMemory(hProcess, (void*)address2+byteCounter+sizeof(DWORD), sexyShell, SHELL_SIZE, NULL))//Write the shellcode return FALSE; DWORD fdxTmp = (DWORD)address2+byteCounter; unsigned char absJmp[6] = "\xFF\x25"; memcpy(absJmp+2, &fdxTmp, sizeof(DWORD));//Copy the address that contains the address of the function if(!WriteProcessMemory(hProcess, (void*)function.startAddr, absJmp, 6, NULL))//Write the address of the function return FALSE; return TRUE; }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { static int omode = -1; static int obits = 32; cs_insn* insn = NULL; cs_mode mode = 0; int ret, n = 0; mode |= (a->big_endian)? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; if (mode != omode || a->bits != obits) { cs_close (&cd); cd = 0; // unnecessary omode = mode; obits = a->bits; } // replace this with the asm.features? if (a->cpu && strstr (a->cpu, "68000")) mode |= CS_MODE_M68K_000; if (a->cpu && strstr (a->cpu, "68010")) mode |= CS_MODE_M68K_010; if (a->cpu && strstr (a->cpu, "68020")) mode |= CS_MODE_M68K_020; if (a->cpu && strstr (a->cpu, "68030")) mode |= CS_MODE_M68K_030; if (a->cpu && strstr (a->cpu, "68040")) mode |= CS_MODE_M68K_040; if (a->cpu && strstr (a->cpu, "68060")) mode |= CS_MODE_M68K_060; op->size = 4; op->buf_asm[0] = 0; if (cd == 0) { ret = cs_open (CS_ARCH_M68K, mode, &cd); if (ret) { ret = -1; goto beach; } } if (a->features && *a->features) { cs_option (cd, CS_OPT_DETAIL, CS_OPT_ON); } else { cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); } // XXX: passing ->pc crashes in capstone, will be back after fixed n = cs_disasm (cd, buf, R_MIN (4, len), 0, 1, &insn); //a->pc, 1, &insn); if (n<1) { ret = -1; goto beach; } op->size = 0; if (insn->size<1) { ret = -1; goto beach; } if (a->features && *a->features) { if (!check_features (a, insn)) { op->size = insn->size; strcpy (op->buf_asm, "illegal"); } } if (!op->size) { op->size = insn->size; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]?" ":"", insn->op_str); } { char *p = r_str_replace (strdup (op->buf_asm), "$", "0x", true); if (p) { strcpy (op->buf_asm, p); free (p); } } cs_free (insn, n); beach: //cs_close (&cd); if (!op->buf_asm[0]) strcpy (op->buf_asm, "invalid"); return op->size; }
static void test() { #define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00\x00\x91\x92" #define RANDOM_CODE "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78" cs_opt_skipdata skipdata = { // rename default "data" instruction from ".byte" to "db" "db", }; cs_opt_skipdata skipdata_callback = { "db", &mycallback, }; struct platform platforms[] = { { CS_ARCH_X86, CS_MODE_32, (unsigned char*)X86_CODE32, sizeof(X86_CODE32) - 1, "X86 32 (Intel syntax) - Skip data", }, { CS_ARCH_ARM, CS_MODE_ARM, (unsigned char*)RANDOM_CODE, sizeof(RANDOM_CODE) - 1, "Arm - Skip data", }, { CS_ARCH_X86, CS_MODE_32, (unsigned char*)X86_CODE32, sizeof(X86_CODE32) - 1, "X86 32 (Intel syntax) - Skip data with custom mnemonic", CS_OPT_INVALID, CS_OPT_OFF, CS_OPT_SKIPDATA_SETUP, (size_t) &skipdata, }, { CS_ARCH_ARM, CS_MODE_ARM, (unsigned char*)RANDOM_CODE, sizeof(RANDOM_CODE) - 1, "Arm - Skip data with callback", CS_OPT_INVALID, CS_OPT_OFF, CS_OPT_SKIPDATA_SETUP, (size_t) &skipdata_callback, }, }; csh handle; uint64_t address = 0x1000; cs_insn *insn; cs_err err; int i; size_t count; for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) { printf("****************\n"); printf("Platform: %s\n", platforms[i].comment); err = cs_open(platforms[i].arch, platforms[i].mode, &handle); if (err) { printf("Failed on cs_open() with error returned: %u\n", err); continue; } if (platforms[i].opt_type) cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); // turn on SKIPDATA mode cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON); cs_option(handle, platforms[i].opt_skipdata, platforms[i].skipdata); count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn); if (count) { size_t j; print_string_hex(platforms[i].code, platforms[i].size); printf("Disasm:\n"); for (j = 0; j < count; j++) { printf("0x%" PRIx64 ":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); } // print out the next offset, after the last insn printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size); // free memory allocated by cs_disasm() cs_free(insn, count); } else { printf("****************\n"); printf("Platform: %s\n", platforms[i].comment); print_string_hex(platforms[i].code, platforms[i].size); printf("ERROR: Failed to disasm given code!\n"); } printf("\n"); cs_close(&handle); } }
static int setup_issue(void **state) { csh *handle; char **list_params; int size_params; int arch, mode; int i, index, result; char *(*function)(csh *, cs_mode, cs_insn*); getDetail = 0; failed_setup = 0; if (e_flag == 0) while (counter < size_lines && strncmp(list_lines[counter], "!# ", 3)) counter++; // get issue line else while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6)) counter++; counter++; if (e_flag == 0) while (counter < size_lines && strncmp(list_lines[counter], "!#", 2)) counter++; // get arch line else while (counter < size_lines && strncmp(list_lines[counter], "// !# ", 6)) counter++; if (e_flag == 0) list_params = split(list_lines[counter] + 3, ", ", &size_params); else list_params = split(list_lines[counter] + 6, ", ", &size_params); arch = get_value(arches, NUMARCH, list_params[0]); if (!strcmp(list_params[0], "CS_ARCH_ARM64")) mc_mode = 2; else mc_mode = 1; mode = 0; for (i = 0; i < NUMMODE; ++i) { if (strstr(list_params[1], modes[i].str)) { mode += modes[i].value; switch (modes[i].value) { case CS_MODE_16: mc_mode = 0; break; case CS_MODE_64: mc_mode = 2; break; case CS_MODE_THUMB: mc_mode = 1; break; default: break; } } } if (arch == -1) { fprintf(stderr, "[ ERROR ] --- Arch is not supported!\n"); failed_setup = 1; return -1; } handle = (csh *)calloc(1, sizeof(csh)); if(cs_open(arch, mode, handle) != CS_ERR_OK) { fprintf(stderr, "[ ERROR ] --- Cannot initialize capstone\n"); failed_setup = 1; return -1; } for (i = 0; i < NUMOPTION; ++i) { if (strstr(list_params[2], options[i].str)) { if (cs_option(*handle, options[i].first_value, options[i].second_value) != CS_ERR_OK) { fprintf(stderr, "[ ERROR ] --- Option is not supported for this arch/mode\n"); failed_setup = 1; return -1; } if (i == 0) { result = set_function(arch); if (result == -1) { fprintf(stderr, "[ ERROR ] --- Cannot get details\n"); failed_setup = 1; return -1; } getDetail = 1; } } } *state = (void *)handle; issue_mode = mode; if (e_flag == 0) while (counter < size_lines && strncmp(list_lines[counter], "0x", 2)) counter++; else while (counter < size_lines && strncmp(list_lines[counter], "// 0x", 5)) counter++; free_strs(list_params, size_params); return 0; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; #if USE_ITER_API static #endif cs_insn *insn = NULL; int mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: (a->bits==16)? CS_MODE_16: 0; int n, ret = cs_open (CS_ARCH_X86, mode, &handle); int regsz = 4; if (ret != CS_ERR_OK) { return 0; } switch (a->bits) { case 64: regsz = 8; break; case 16: regsz = 2; break; default: case 32: regsz = 4; break; } memset (op, '\0', sizeof (RAnalOp)); op->cycles = 1; // aprox op->type = R_ANAL_OP_TYPE_NULL; op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->src[0] = NULL; op->src[1] = NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next #if USE_ITER_API { ut64 naddr = addr; size_t size = len; if (insn == NULL) insn = cs_malloc (handle); n = cs_disasm_iter (handle, (const uint8_t**)&buf, &size, (uint64_t*)&naddr, insn); } #else n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); #endif struct Getarg gop = { .handle = handle, .insn = insn, .bits = a->bits }; if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { int rs = a->bits/8; const char *pc = (a->bits==16)?"ip": (a->bits==32)?"eip":"rip"; const char *sp = (a->bits==16)?"sp": (a->bits==32)?"esp":"rsp"; const char *bp = (a->bits==16)?"bp": (a->bits==32)?"ebp":"rbp"; op->size = insn->size; op->family = 0; op->prefix = 0; switch (insn->detail->x86.prefix[0]) { case X86_PREFIX_REPNE: op->prefix |= R_ANAL_OP_PREFIX_REPNE; break; case X86_PREFIX_REP: op->prefix |= R_ANAL_OP_PREFIX_REP; break; case X86_PREFIX_LOCK: op->prefix |= R_ANAL_OP_PREFIX_LOCK; break; } switch (insn->id) { case X86_INS_FNOP: case X86_INS_NOP: case X86_INS_PAUSE: op->type = R_ANAL_OP_TYPE_NOP; if (a->decode) esilprintf (op, ","); break; case X86_INS_HLT: op->type = R_ANAL_OP_TYPE_TRAP; break; case X86_INS_FBLD: case X86_INS_FBSTP: case X86_INS_FCOMPP: case X86_INS_FDECSTP: case X86_INS_FEMMS: case X86_INS_FFREE: case X86_INS_FICOM: case X86_INS_FICOMP: case X86_INS_FINCSTP: case X86_INS_FNCLEX: case X86_INS_FNINIT: case X86_INS_FNSTCW: case X86_INS_FNSTSW: case X86_INS_FPATAN: case X86_INS_FPREM: case X86_INS_FPREM1: case X86_INS_FPTAN: #if CS_API_MAJOR >=4 case X86_INS_FFREEP: #endif case X86_INS_FRNDINT: case X86_INS_FRSTOR: case X86_INS_FNSAVE: case X86_INS_FSCALE: case X86_INS_FSETPM: case X86_INS_FSINCOS: case X86_INS_FNSTENV: case X86_INS_FXAM: case X86_INS_FXSAVE: case X86_INS_FXSAVE64: case X86_INS_FXTRACT: case X86_INS_FYL2X: case X86_INS_FYL2XP1: case X86_INS_FISTTP: case X86_INS_FSQRT: case X86_INS_FXCH: case X86_INS_FTST: case X86_INS_FUCOMPI: case X86_INS_FUCOMI: case X86_INS_FUCOMPP: case X86_INS_FUCOMP: case X86_INS_FUCOM: op->type = R_ANAL_OP_TYPE_SUB; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FLDCW: case X86_INS_FLDENV: case X86_INS_FLDL2E: case X86_INS_FLDL2T: case X86_INS_FLDLG2: case X86_INS_FLDLN2: case X86_INS_FLDPI: case X86_INS_FLDZ: case X86_INS_FLD1: case X86_INS_FLD: op->type = R_ANAL_OP_TYPE_LOAD; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FIST: case X86_INS_FISTP: case X86_INS_FST: case X86_INS_FSTP: case X86_INS_FSTPNCE: case X86_INS_FXRSTOR: case X86_INS_FXRSTOR64: op->type = R_ANAL_OP_TYPE_STORE; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FDIV: case X86_INS_FIDIV: case X86_INS_FDIVP: case X86_INS_FDIVR: case X86_INS_FIDIVR: case X86_INS_FDIVRP: case X86_INS_FSUBR: case X86_INS_FISUBR: case X86_INS_FSUBRP: case X86_INS_FSUB: case X86_INS_FISUB: case X86_INS_FSUBP: op->type = R_ANAL_OP_TYPE_SUB; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_FMUL: case X86_INS_FIMUL: case X86_INS_FMULP: op->type = R_ANAL_OP_TYPE_MUL; op->family = R_ANAL_OP_FAMILY_FPU; break; case X86_INS_CLI: case X86_INS_STI: case X86_INS_CLC: case X86_INS_STC: op->type = R_ANAL_OP_TYPE_SWI; op->family = R_ANAL_OP_FAMILY_PRIV; break; // cmov case X86_INS_SETNE: case X86_INS_SETNO: case X86_INS_SETNP: case X86_INS_SETNS: case X86_INS_SETO: case X86_INS_SETP: case X86_INS_SETS: case X86_INS_SETL: case X86_INS_SETLE: case X86_INS_SETB: case X86_INS_SETG: case X86_INS_SETAE: case X86_INS_SETA: case X86_INS_SETBE: case X86_INS_SETE: case X86_INS_SETGE: op->type = R_ANAL_OP_TYPE_CMOV; op->family = 0; if (a->decode) { char *dst = getarg (&gop, 0, 0, NULL); switch (insn->id) { case X86_INS_SETE: esilprintf (op, "zf,%s,=", dst); break; case X86_INS_SETNE: esilprintf (op, "zf,!,%s,=", dst); break; case X86_INS_SETO: esilprintf (op, "of,%s,=", dst); break; case X86_INS_SETNO: esilprintf (op, "of,!,%s,=", dst); break; case X86_INS_SETP: esilprintf (op, "pf,%s,=", dst); break; case X86_INS_SETNP: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETS: esilprintf (op, "sf,%s,=", dst); break; case X86_INS_SETNS: esilprintf (op, "sf,!,%s,=", dst); break; case X86_INS_SETB: esilprintf (op, "cf,%s,=", dst); break; case X86_INS_SETAE: esilprintf (op, "cf,!,%s,=", dst); break; /* TODO */ #if 0 SETLE/SETNG Sets the byte in the operand to 1 if the Zero Flag is set or the Sign Flag is not equal to the Overflow Flag, otherwise sets the operand to 0. SETBE/SETNA Sets the byte in the operand to 1 if the Carry Flag or the Zero Flag is set, otherwise sets the operand to 0. SETL/SETNGE Sets the byte in the operand to 1 if the Sign Flag is not equal to the Overflow Flag, otherwise sets the operand to 0. case X86_INS_SETL: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETLE: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETG: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETA: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETBE: esilprintf (op, "pf,!,%s,=", dst); break; case X86_INS_SETGE: esilprintf (op, "pf,!,%s,=", dst); break; break; #endif } free (dst); } break; // cmov case X86_INS_CMOVA: case X86_INS_CMOVAE: case X86_INS_CMOVB: case X86_INS_CMOVBE: case X86_INS_FCMOVBE: case X86_INS_FCMOVB: case X86_INS_CMOVE: case X86_INS_FCMOVE: case X86_INS_CMOVG: case X86_INS_CMOVGE: case X86_INS_CMOVL: case X86_INS_CMOVLE: case X86_INS_FCMOVNBE: case X86_INS_FCMOVNB: case X86_INS_CMOVNE: case X86_INS_FCMOVNE: case X86_INS_CMOVNO: case X86_INS_CMOVNP: case X86_INS_FCMOVNU: case X86_INS_CMOVNS: case X86_INS_CMOVO: case X86_INS_CMOVP: case X86_INS_FCMOVU: case X86_INS_CMOVS: // mov case X86_INS_MOV: case X86_INS_MOVAPS: case X86_INS_MOVAPD: case X86_INS_MOVZX: case X86_INS_MOVUPS: case X86_INS_MOVABS: case X86_INS_MOVHPD: case X86_INS_MOVHPS: case X86_INS_MOVLPD: case X86_INS_MOVLPS: case X86_INS_MOVBE: case X86_INS_MOVSB: case X86_INS_MOVSD: case X86_INS_MOVSQ: case X86_INS_MOVSS: case X86_INS_MOVSX: case X86_INS_MOVSXD: case X86_INS_MOVSW: case X86_INS_MOVD: case X86_INS_MOVQ: case X86_INS_MOVDQ2Q: { op->type = R_ANAL_OP_TYPE_MOV; op->ptr = UT64_MAX; switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->ptr = UT64_MAX; op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } else { op->ptr = UT64_MAX; } if (a->decode) { if (op->prefix & R_ANAL_OP_PREFIX_REP) { int width = INSOP(0).size; const char *src = cs_reg_name(handle, INSOP(1).mem.base); const char *dst = cs_reg_name(handle, INSOP(0).mem.base); const char *counter = (a->bits==16)?"cx": (a->bits==32)?"ecx":"rcx"; esilprintf (op, "%s,!,?{,BREAK,},%s,DUP,%s,DUP,"\ "%s,[%d],%s,=[%d],df,?{,%d,%s,-=,%d,%s,-=,},"\ "df,!,?{,%d,%s,+=,%d,%s,+=,},%s,--=,%s," \ "?{,8,GOTO,},%s,=,%s,=", counter, src, dst, src, width, dst, width, width, src, width, dst, width, src, width, dst, counter, counter, dst, src); } else { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } } break; default: if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,=", src, dst); free (src); free (dst); } break; } if (op->refptr<1 || op->ptr == UT64_MAX) { switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } } } break; case X86_INS_SHL: case X86_INS_SHLD: case X86_INS_SHLX: op->type = R_ANAL_OP_TYPE_SHL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "<<"); esilprintf (op, "%s,%s,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAR: case X86_INS_SARX: op->type = R_ANAL_OP_TYPE_SAR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, ">>"); esilprintf (op, "%s,%s,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAL: op->type = R_ANAL_OP_TYPE_SAL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "<<"); esilprintf (op, "%s,%s,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SALC: op->type = R_ANAL_OP_TYPE_SAL; if (a->decode) { esilprintf (op, "$z,DUP,zf,=,al,="); } break; case X86_INS_SHR: case X86_INS_SHRD: case X86_INS_SHRX: op->type = R_ANAL_OP_TYPE_SHR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,>>=,$z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_CMP: case X86_INS_CMPPD: case X86_INS_CMPPS: case X86_INS_CMPSW: case X86_INS_CMPSD: case X86_INS_CMPSQ: case X86_INS_CMPSB: case X86_INS_CMPSS: case X86_INS_TEST: if (insn->id == X86_INS_TEST) { op->type = R_ANAL_OP_TYPE_ACMP; //compare via and if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "0,%s,%s,&,==,$z,zf,=,$p,pf,=,$s,sf,=,0,cf,=,0,of,=", src, dst); free (src); free (dst); } } else { op->type = R_ANAL_OP_TYPE_CMP; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,==,$z,zf,=,$b%d,cf,=,$p,pf,=,$s,sf,=", src, dst, (INSOP(0).size*8)); free (src); free (dst); } } switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } op->ptr = INSOP(1).imm; break; default: switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } break; case X86_OP_IMM: op->ptr = INSOP(1).imm; break; default: break; } break; } break; case X86_INS_LEA: op->type = R_ANAL_OP_TYPE_LEA; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); char *dst = getarg (&gop, 1, 2, NULL); esilprintf (op, "%s,%s,=", dst, src); free (src); free (dst); } switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; switch (INSOP(1).mem.base) { case X86_REG_RIP: op->ptr += addr + op->size; break; case X86_REG_RBP: case X86_REG_EBP: op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; break; default: /* unhandled */ break; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } break; case X86_INS_ENTER: case X86_INS_PUSH: case X86_INS_PUSHAW: case X86_INS_PUSHAL: case X86_INS_PUSHF: { char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%d,%s,-=,%s,%s,=[%d]", rs, sp, dst, sp, rs); free (dst); } switch (INSOP(0).type) { case X86_OP_IMM: op->ptr = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_PUSH; break; default: op->type = R_ANAL_OP_TYPE_UPUSH; break; } op->stackop = R_ANAL_STACK_INC; op->stackptr = regsz; break; case X86_INS_LEAVE: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { esilprintf (op, "%s,%s,=,%s,[%d],%s,=,%d,%s,+=", bp, sp, sp, rs, bp, rs, sp); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_POP: case X86_INS_POPF: case X86_INS_POPAW: case X86_INS_POPAL: case X86_INS_POPCNT: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, dst, rs, sp); free (dst); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_RET: case X86_INS_RETF: case X86_INS_RETFQ: case X86_INS_IRET: case X86_INS_IRETD: case X86_INS_IRETQ: case X86_INS_SYSRET: op->type = R_ANAL_OP_TYPE_RET; if (a->decode) esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, pc, rs, sp); op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_INT3: if (a->decode) esilprintf (op, "3,$"); op->type = R_ANAL_OP_TYPE_TRAP; // TRAP break; case X86_INS_INT1: if (a->decode) esilprintf (op, "1,$"); op->type = R_ANAL_OP_TYPE_SWI; // TRAP break; case X86_INS_INT: if (a->decode) esilprintf (op, "%d,$", R_ABS((int)INSOP(0).imm)); op->type = R_ANAL_OP_TYPE_SWI; break; case X86_INS_SYSCALL: op->type = R_ANAL_OP_TYPE_SWI; break; case X86_INS_INTO: case X86_INS_VMCALL: case X86_INS_VMMCALL: op->type = R_ANAL_OP_TYPE_TRAP; if (a->decode) esilprintf (op, "%d,$", (int)INSOP(0).imm); break; case X86_INS_JL: case X86_INS_JLE: case X86_INS_JA: case X86_INS_JAE: case X86_INS_JB: case X86_INS_JBE: case X86_INS_JCXZ: case X86_INS_JECXZ: case X86_INS_JRCXZ: case X86_INS_JO: case X86_INS_JNO: case X86_INS_JS: case X86_INS_JNS: case X86_INS_JP: case X86_INS_JNP: case X86_INS_JE: case X86_INS_JNE: case X86_INS_JG: case X86_INS_JGE: case X86_INS_LOOP: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = addr+op->size; if (a->decode) { char *dst = getarg (&gop, 0, 2, NULL); switch (insn->id) { case X86_INS_JL: esilprintf (op, "of,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JLE: esilprintf (op, "of,sf,^,zf,|,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JA: esilprintf (op, "cf,zf,|,!,?{,%s,%s,=,}",dst, pc); break; case X86_INS_JAE: esilprintf (op, "cf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JB: esilprintf (op, "cf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JO: esilprintf (op, "of,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNO: esilprintf (op, "of,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JE: esilprintf (op, "zf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JGE: esilprintf (op, "of,!,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNE: esilprintf (op, "zf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JG: esilprintf (op, "sf,of,!,^,zf,!,&,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JS: esilprintf (op, "sf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNS: esilprintf (op, "sf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JP: esilprintf (op, "pf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNP: esilprintf (op, "pf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JBE: esilprintf (op, "zf,cf,|,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JCXZ: esilprintf (op, "cx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JECXZ: esilprintf (op, "ecx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JRCXZ: esilprintf (op, "rcx,!,?{,%s,%s,=,}", dst, pc); break; } free (dst); } break; case X86_INS_CALL: case X86_INS_LCALL: switch (INSOP(0).type) { case X86_OP_IMM: op->type = R_ANAL_OP_TYPE_CALL; // TODO: what if UCALL? // TODO: use imm_size op->jump = INSOP(0).imm; op->fail = addr+op->size; break; case X86_OP_MEM: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; if (INSOP(0).mem.base == 0) { op->ptr = INSOP(0).mem.disp; } break; default: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; break; } if (a->decode) { char* arg = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s," "%d,%s,-=,%s," "=[]," "%s,%s,=", pc, rs, sp, sp, arg, pc); free (arg); } break; case X86_INS_JMP: case X86_INS_LJMP: if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,=", src, pc); free (src); } // TODO: what if UJMP? switch (INSOP(0).type) { case X86_OP_IMM: op->jump = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_JMP; if (a->decode) { ut64 dst = INSOP(0).imm; esilprintf (op, "0x%"PFMT64x",%s,=", dst, pc); } break; case X86_OP_MEM: op->type = R_ANAL_OP_TYPE_UJMP; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr = INSOP(0).mem.disp; op->ptr += addr + insn->size; op->refptr = 8; } else { cs_x86_op in = INSOP(0); if (in.mem.index == 0 && in.mem.base == 0 && in.mem.scale == 1) { op->type = R_ANAL_OP_TYPE_UJMP; op->ptr = in.mem.disp; if (a->decode) { esilprintf (op, "0x%"PFMT64x",[],%s,=", op->ptr, pc); } } } break; case X86_OP_REG: case X86_OP_FP: default: // other? op->type = R_ANAL_OP_TYPE_UJMP; break; } break; case X86_INS_IN: case X86_INS_INSW: case X86_INS_INSD: case X86_INS_INSB: case X86_INS_OUT: case X86_INS_OUTSB: case X86_INS_OUTSD: case X86_INS_OUTSW: op->type = R_ANAL_OP_TYPE_IO; break; case X86_INS_VXORPD: case X86_INS_VXORPS: case X86_INS_VPXORD: case X86_INS_VPXORQ: case X86_INS_VPXOR: case X86_INS_XORPS: case X86_INS_KXORW: case X86_INS_PXOR: case X86_INS_XOR: op->type = R_ANAL_OP_TYPE_XOR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "^"); esilprintf (op, "%s,%s,$z,zf,=,$p,pf,=,0,cf,=,0,of,=,$s,sf,=", src, dst); free (src); free (dst); } break; case X86_INS_OR: op->type = R_ANAL_OP_TYPE_OR; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,%s,|=", src, dst); free (src); free (dst); } break; case X86_INS_INC: op->type = R_ANAL_OP_TYPE_ADD; op->val = 1; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,++=", src); free (src); } break; case X86_INS_DEC: op->type = R_ANAL_OP_TYPE_SUB; op->val = 1; if (a->decode) { char *src = getarg (&gop, 0, 0, NULL); esilprintf (op, "%s,--=", src); free (src); } break; case X86_INS_SUB: case X86_INS_PSUBB: case X86_INS_PSUBW: case X86_INS_PSUBD: case X86_INS_PSUBQ: case X86_INS_PSUBSB: case X86_INS_PSUBSW: case X86_INS_PSUBUSB: case X86_INS_PSUBUSW: op->type = R_ANAL_OP_TYPE_SUB; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "-"); esilprintf (op, "%s,%s,$c,cf,=,$z,zf,=,$s,sf,=,$o,of,=", src, dst); // TODO: update flags free (src); free (dst); } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = INSOP(1).imm; } } break; case X86_INS_LIDT: op->type = R_ANAL_OP_TYPE_LOAD; op->family = R_ANAL_OP_FAMILY_PRIV; break; case X86_INS_SIDT: op->type = R_ANAL_OP_TYPE_STORE; op->family = R_ANAL_OP_FAMILY_PRIV; break; case X86_INS_RDRAND: case X86_INS_RDSEED: case X86_INS_RDMSR: case X86_INS_RDPMC: case X86_INS_RDTSC: case X86_INS_RDTSCP: case X86_INS_CRC32: case X86_INS_SHA1MSG1: case X86_INS_SHA1MSG2: case X86_INS_SHA1NEXTE: case X86_INS_SHA1RNDS4: case X86_INS_SHA256MSG1: case X86_INS_SHA256MSG2: case X86_INS_SHA256RNDS2: case X86_INS_AESDECLAST: case X86_INS_AESDEC: case X86_INS_AESENCLAST: case X86_INS_AESENC: case X86_INS_AESIMC: case X86_INS_AESKEYGENASSIST: // AES instructions op->family = R_ANAL_OP_FAMILY_CRYPTO; op->type = R_ANAL_OP_TYPE_MOV; // XXX break; case X86_INS_AND: case X86_INS_ANDN: case X86_INS_ANDPD: case X86_INS_ANDPS: case X86_INS_ANDNPD: case X86_INS_ANDNPS: op->type = R_ANAL_OP_TYPE_AND; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "&"); // TODO: update of = cf = 0 // TODO: update sf, zf and pf // TODO: af is undefined esilprintf (op, "0,of,=,0,cf,=," // set carry and overflow flags "%s,%s," // set reg value "$z,zf,=," // update zero flag "$s,sf,=," // update sign flag "$o,pf,=", // update parity flag // TODO: add sign and parity flags here src, dst); free (src); free (dst); } break; case X86_INS_DIV: case X86_INS_IDIV: op->type = R_ANAL_OP_TYPE_DIV; if (a->decode) { int width = INSOP(0).size; char *dst = getarg (&gop, 0, 0, NULL); const char *r_ax = (width==2)?"ax": (width==4)?"eax":"rax"; const char *r_dx = (width==2)?"dx": (width==4)?"edx":"rdx"; // TODO update flags & handle signedness esilprintf (op, "%s,%s,%%,%s,=,%s,%s,/,%s,=", dst, r_ax, r_dx, dst, r_ax, r_ax); free (dst); } break; case X86_INS_MUL: case X86_INS_MULX: case X86_INS_MULPD: case X86_INS_MULPS: case X86_INS_MULSD: case X86_INS_MULSS: op->type = R_ANAL_OP_TYPE_MUL; if (a->decode) { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "*"); if (!src && dst) { switch (dst[0]) { case 'r': src = strdup ("rax"); break; case 'e': src = strdup ("eax"); break; default: src = strdup ("al"); break; } } esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } break; case X86_INS_PACKSSDW: case X86_INS_PACKSSWB: case X86_INS_PACKUSWB: op->type = R_ANAL_OP_TYPE_MOV; op->family = R_ANAL_OP_FAMILY_MMX; break; case X86_INS_PADDB: case X86_INS_PADDD: case X86_INS_PADDW: case X86_INS_PADDSB: case X86_INS_PADDSW: case X86_INS_PADDUSB: case X86_INS_PADDUSW: op->type = R_ANAL_OP_TYPE_ADD; op->family = R_ANAL_OP_FAMILY_MMX; break; case X86_INS_FADD: case X86_INS_FADDP: op->family = R_ANAL_OP_FAMILY_FPU; /* pass thru */ case X86_INS_ADD: case X86_INS_ADDPS: case X86_INS_ADDSD: case X86_INS_ADDSS: case X86_INS_ADDSUBPD: case X86_INS_ADDSUBPS: case X86_INS_ADDPD: case X86_INS_XADD: op->type = R_ANAL_OP_TYPE_ADD; if (a->decode) { if (INSOP(0).type == X86_OP_MEM) { char *src = getarg (&gop, 1, 0, NULL); char *src2 = getarg (&gop, 0, 0, NULL); char *dst = getarg (&gop, 0, 1, NULL); // TODO: update flags esilprintf (op, "%s,%s,+,%s", src, src2, dst); free (src); free (src2); free (dst); } else { char *src = getarg (&gop, 1, 0, NULL); char *dst = getarg (&gop, 0, 1, "+"); esilprintf (op, "%s,%s", src, dst); // TODO: update flags free (src); free (dst); } } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = -INSOP(1).imm; } } break; /* Direction flag */ case X86_INS_CLD: if (a->decode) esilprintf (op, "0,df,="); break; case X86_INS_STD: if (a->decode) esilprintf (op, "1,df,="); break; } } //#if X86_GRP_PRIVILEGE>0 if (insn) { #if HAVE_CSGRP_PRIVILEGE if (cs_insn_group (handle, insn, X86_GRP_PRIVILEGE)) op->family = R_ANAL_OP_FAMILY_PRIV; #endif #if !USE_ITER_API cs_free (insn, n); #endif } cs_close (&handle); return op->size; }
static int setup_MC(void **state) { csh *handle; char **list_params; int size_params; int arch, mode; int i, index, tmp_counter; if (failed_setup) { fprintf(stderr, "[ ERROR ] --- Invalid file to setup\n"); return -1; } tmp_counter = 0; while (tmp_counter < size_lines && list_lines[tmp_counter][0] != '#') tmp_counter++; list_params = split(list_lines[tmp_counter] + 2, ", ", &size_params); if (size_params != 3) { fprintf(stderr, "[ ERROR ] --- Invalid options ( arch, mode, option )\n"); failed_setup = 1; return -1; } arch = get_value(arches, NUMARCH, list_params[0]); if (!strcmp(list_params[0], "CS_ARCH_ARM64")) mc_mode = 2; else mc_mode = 1; mode = 0; for (i = 0; i < NUMMODE; ++i) { if (strstr(list_params[1], modes[i].str)) { mode += modes[i].value; switch (modes[i].value) { case CS_MODE_16: mc_mode = 0; break; case CS_MODE_64: mc_mode = 2; break; case CS_MODE_THUMB: mc_mode = 1; break; default: break; } } } if (arch == -1) { fprintf(stderr, "[ ERROR ] --- Arch is not supported!\n"); failed_setup = 1; return -1; } handle = (csh *)malloc(sizeof(csh)); if(cs_open(arch, mode, handle) != CS_ERR_OK) { fprintf(stderr, "[ ERROR ] --- Cannot initialize capstone\n"); failed_setup = 1; return -1; } for (i = 0; i < NUMOPTION; ++i) { if (strstr(list_params[2], options[i].str)) { if (cs_option(*handle, options[i].first_value, options[i].second_value) != CS_ERR_OK) { fprintf(stderr, "[ ERROR ] --- Option is not supported for this arch/mode\n"); failed_setup = 1; return -1; } } } *state = (void *)handle; counter++; if (e_flag == 0) while (counter < size_lines && strncmp(list_lines[counter], "0x", 2)) counter++; else while (counter < size_lines && strncmp(list_lines[counter], "// 0x", 5)) counter++; free_strs(list_params, size_params); return 0; }
static void test() { #ifdef CAPSTONE_X86_SUPPORT #define X86_CODE16 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00" #define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00" //#define X86_CODE32 "\x0f\xa7\xc0" // xstorerng //#define X86_CODE32 "\x77\x04" // ja +6 #define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00" #endif #ifdef CAPSTONE_ARM_SUPPORT //#define ARM_CODE "\x04\xe0\x2d\xe5" #define ARM_CODE "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3" #define ARM_CODE2 "\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3" #define THUMB_CODE "\x70\x47\xeb\x46\x83\xb0\xc9\x68" //#define THUMB_CODE "\x0a\xbf" // itet eq #define THUMB_CODE2 "\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0" #define THUMB_MCLASS "\xef\xf3\x02\x80" #define ARMV8 "\xe0\x3b\xb2\xee\x42\x00\x01\xe1\x51\xf0\x7f\xf5" #endif #ifdef CAPSTONE_MIPS_SUPPORT #define MIPS_CODE "\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56\x00\x80\x04\x08" //#define MIPS_CODE "\x21\x38\x00\x01" //#define MIPS_CODE "\x21\x30\xe6\x70" //#define MIPS_CODE "\x1c\x00\x40\x14" #define MIPS_CODE2 "\x56\x34\x21\x34\xc2\x17\x01\x00" #define MIPS_32R6M "\x00\x07\x00\x07\x00\x11\x93\x7c\x01\x8c\x8b\x7c\x00\xc7\x48\xd0" #define MIPS_32R6 "\xec\x80\x00\x19\x7c\x43\x22\xa0" #endif #ifdef CAPSTONE_ARM64_SUPPORT //#define ARM64_CODE "\xe1\x0b\x40\xb9" // ldr w1, [sp, #0x8] //#define ARM64_CODE "\x00\x40\x21\x4b" // sub w0, w0, w1, uxtw //#define ARM64_CODE "\x21\x7c\x02\x9b" // mul x1, x1, x2 //#define ARM64_CODE "\x20\x74\x0b\xd5" // dc zva, x0 //#define ARM64_CODE "\x20\xfc\x02\x9b" // mneg x0, x1, x2 //#define ARM64_CODE "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x10\x20\x21\x1e" //#define ARM64_CODE "\x21\x7c\x00\x53" #define ARM64_CODE "\x09\x00\x38\xd5\xbf\x40\x00\xd5\x0c\x05\x13\xd5\x20\x50\x02\x0e\x20\xe4\x3d\x0f\x00\x18\xa0\x5f\xa2\x00\xae\x9e\x9f\x37\x03\xd5\xbf\x33\x03\xd5\xdf\x3f\x03\xd5\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9\x20\x04\x81\xda\x20\x08\x02\x8b\x10\x5b\xe8\x3c" #endif #ifdef CAPSTONE_PPC_SUPPORT #define PPC_CODE "\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21\x40\x82\x00\x14" #endif #ifdef CAPSTONE_SPARC_SUPPORT #define SPARC_CODE "\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03" #define SPARCV9_CODE "\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0" #endif #ifdef CAPSTONE_SYSZ_SUPPORT #define SYSZ_CODE "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78" #endif #ifdef CAPSTONE_XCORE_SUPPORT #define XCORE_CODE "\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10" #endif struct platform platforms[] = { #ifdef CAPSTONE_X86_SUPPORT { CS_ARCH_X86, CS_MODE_16, (unsigned char *)X86_CODE16, sizeof(X86_CODE32) - 1, "X86 16bit (Intel syntax)" }, { CS_ARCH_X86, CS_MODE_32, (unsigned char *)X86_CODE32, sizeof(X86_CODE32) - 1, "X86 32bit (ATT syntax)", CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT, }, { CS_ARCH_X86, CS_MODE_32, (unsigned char *)X86_CODE32, sizeof(X86_CODE32) - 1, "X86 32 (Intel syntax)" }, { CS_ARCH_X86, CS_MODE_64, (unsigned char *)X86_CODE64, sizeof(X86_CODE64) - 1, "X86 64 (Intel syntax)" }, #endif #ifdef CAPSTONE_ARM_SUPPORT { CS_ARCH_ARM, CS_MODE_ARM, (unsigned char *)ARM_CODE, sizeof(ARM_CODE) - 1, "ARM" }, { CS_ARCH_ARM, CS_MODE_THUMB, (unsigned char *)THUMB_CODE2, sizeof(THUMB_CODE2) - 1, "THUMB-2" }, { CS_ARCH_ARM, CS_MODE_ARM, (unsigned char *)ARM_CODE2, sizeof(ARM_CODE2) - 1, "ARM: Cortex-A15 + NEON" }, { CS_ARCH_ARM, CS_MODE_THUMB, (unsigned char *)THUMB_CODE, sizeof(THUMB_CODE) - 1, "THUMB" }, { CS_ARCH_ARM, (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS), (unsigned char*)THUMB_MCLASS, sizeof(THUMB_MCLASS) - 1, "Thumb-MClass" }, { CS_ARCH_ARM, (cs_mode)(CS_MODE_ARM + CS_MODE_V8), (unsigned char*)ARMV8, sizeof(ARMV8) - 1, "Arm-V8" }, #endif #ifdef CAPSTONE_MIPS_SUPPORT { CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32 + CS_MODE_BIG_ENDIAN), (unsigned char *)MIPS_CODE, sizeof(MIPS_CODE) - 1, "MIPS-32 (Big-endian)" }, { CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS64 + CS_MODE_LITTLE_ENDIAN), (unsigned char *)MIPS_CODE2, sizeof(MIPS_CODE2) - 1, "MIPS-64-EL (Little-endian)" }, { CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_MICRO + CS_MODE_BIG_ENDIAN), (unsigned char*)MIPS_32R6M, sizeof(MIPS_32R6M) - 1, "MIPS-32R6 | Micro (Big-endian)" }, { CS_ARCH_MIPS, (cs_mode)(CS_MODE_MIPS32R6 + CS_MODE_BIG_ENDIAN), (unsigned char*)MIPS_32R6, sizeof(MIPS_32R6) - 1, "MIPS-32R6 (Big-endian)" }, #endif #ifdef CAPSTONE_ARM64_SUPPORT { CS_ARCH_ARM64, CS_MODE_ARM, (unsigned char *)ARM64_CODE, sizeof(ARM64_CODE) - 1, "ARM-64" }, #endif #ifdef CAPSTONE_PPC_SUPPORT { CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, (unsigned char*)PPC_CODE, sizeof(PPC_CODE) - 1, "PPC-64" }, #endif #ifdef CAPSTONE_SPARC_SUPPORT { CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, (unsigned char*)SPARC_CODE, sizeof(SPARC_CODE) - 1, "Sparc" }, { CS_ARCH_SPARC, (cs_mode)(CS_MODE_BIG_ENDIAN + CS_MODE_V9), (unsigned char*)SPARCV9_CODE, sizeof(SPARCV9_CODE) - 1, "SparcV9" }, #endif #ifdef CAPSTONE_SYSZ_SUPPORT { CS_ARCH_SYSZ, (cs_mode)0, (unsigned char*)SYSZ_CODE, sizeof(SYSZ_CODE) - 1, "SystemZ" }, #endif #ifdef CAPSTONE_XCORE_SUPPORT { CS_ARCH_XCORE, (cs_mode)0, (unsigned char*)XCORE_CODE, sizeof(XCORE_CODE) - 1, "XCore" }, #endif }; csh handle; uint64_t address = 0x1000; cs_insn *all_insn; cs_detail *detail; int i; size_t count; cs_err err; for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) { printf("****************\n"); printf("Platform: %s\n", platforms[i].comment); err = cs_open(platforms[i].arch, platforms[i].mode, &handle); if (err) { printf("Failed on cs_open() with error returned: %u\n", err); continue; } if (platforms[i].opt_type) cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &all_insn); if (count) { size_t j; int n; print_string_hex(platforms[i].code, platforms[i].size); printf("Disasm:\n"); for (j = 0; j < count; j++) { cs_insn *i = &(all_insn[j]); printf("0x%"PRIx64":\t%s\t\t%s // insn-ID: %u, insn-mnem: %s\n", i->address, i->mnemonic, i->op_str, i->id, cs_insn_name(handle, i->id)); // print implicit registers used by this instruction detail = i->detail; if (detail->regs_read_count > 0) { printf("\tImplicit registers read: "); for (n = 0; n < detail->regs_read_count; n++) { printf("%s ", cs_reg_name(handle, detail->regs_read[n])); } printf("\n"); } // print implicit registers modified by this instruction if (detail->regs_write_count > 0) { printf("\tImplicit registers modified: "); for (n = 0; n < detail->regs_write_count; n++) { printf("%s ", cs_reg_name(handle, detail->regs_write[n])); } printf("\n"); } // print the groups this instruction belong to if (detail->groups_count > 0) { printf("\tThis instruction belongs to groups: "); for (n = 0; n < detail->groups_count; n++) { printf("%s ", cs_group_name(handle, detail->groups[n])); } printf("\n"); } } // print out the next offset, after the last insn printf("0x%"PRIx64":\n", all_insn[j-1].address + all_insn[j-1].size); // free memory allocated by cs_disasm() cs_free(all_insn, count); } else { printf("****************\n"); printf("Platform: %s\n", platforms[i].comment); print_string_hex(platforms[i].code, platforms[i].size); printf("ERROR: Failed to disasm given code!\n"); } printf("\n"); cs_close(&handle); } }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { static int omode = -1; static int obits = 32; cs_insn* insn = NULL; cs_mode mode = 0; int ret, n = 0; mode |= (a->bits == 16)? CS_MODE_THUMB: CS_MODE_ARM; mode |= (a->big_endian)? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; if (mode != omode || a->bits != obits) { cs_close (&cd); cd = 0; // unnecessary omode = mode; obits = a->bits; } if (a->features && strstr (a->features, "mclass")) mode |= CS_MODE_MCLASS; if (a->features && strstr (a->features, "v8")) mode |= CS_MODE_V8; op->size = 4; op->buf_asm[0] = 0; if (cd == 0) { ret = (a->bits == 64)? cs_open (CS_ARCH_ARM64, mode, &cd): cs_open (CS_ARCH_ARM, mode, &cd); if (ret) { ret = -1; goto beach; } } if (a->syntax == R_ASM_SYNTAX_REGNUM) { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME); } else cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_DEFAULT); if (a->features && *a->features) { cs_option (cd, CS_OPT_DETAIL, CS_OPT_ON); } else { cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); } n = cs_disasm (cd, buf, R_MIN (4, len), a->pc, 1, &insn); if (n < 1) { ret = -1; goto beach; } op->size = 0; if (insn->size<1) { ret = -1; goto beach; } if (a->features && *a->features) { if (!check_features (a, insn)) { op->size = insn->size; strcpy (op->buf_asm, "illegal"); } } if (!op->size) { op->size = insn->size; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]?" ":"", insn->op_str); r_str_rmch (op->buf_asm, '#'); } cs_free (insn, n); beach: //cs_close (&cd); if (!op->buf_asm[0]) strcpy (op->buf_asm, "invalid"); return op->size; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; cs_insn *insn; int mode, n, ret; mode = CS_MODE_BIG_ENDIAN; if (!strcmp (a->cpu, "v9")) mode |= CS_MODE_V9; ret = cs_open (CS_ARCH_SPARC, mode, &handle); op->type = R_ANAL_OP_TYPE_NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { op->size = insn->size; switch (insn->id) { case SPARC_INS_RETT: op->type = R_ANAL_OP_TYPE_RET; break; case SPARC_INS_CALL: op->type = R_ANAL_OP_TYPE_CALL; op->jump = INSOP(0).imm; break; case SPARC_INS_CMP: op->type = R_ANAL_OP_TYPE_CMP; break; case SPARC_INS_JMP: case SPARC_INS_JMPL: op->type = R_ANAL_OP_TYPE_JMP; op->jump = INSOP(0).imm; break; case SPARC_INS_BRGEZ: case SPARC_INS_BRGZ: case SPARC_INS_BRLEZ: case SPARC_INS_BRLZ: case SPARC_INS_BRNZ: case SPARC_INS_BRZ: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = UT64_MAX; break; case SPARC_INS_FHSUBD: case SPARC_INS_FHSUBS: case SPARC_INS_FPSUB16: case SPARC_INS_FPSUB16S: case SPARC_INS_FPSUB32: case SPARC_INS_FPSUB32S: case SPARC_INS_FSUBD: case SPARC_INS_FSUBQ: case SPARC_INS_FSUBS: case SPARC_INS_SUBCC: case SPARC_INS_SUBX: case SPARC_INS_SUBXCC: case SPARC_INS_SUB: case SPARC_INS_TSUBCCTV: case SPARC_INS_TSUBCC: op->type = R_ANAL_OP_TYPE_SUB; break; case SPARC_INS_ADDCC: case SPARC_INS_ADDX: case SPARC_INS_ADDXCC: case SPARC_INS_ADDXC: case SPARC_INS_ADDXCCC: case SPARC_INS_ADD: case SPARC_INS_FADDD: case SPARC_INS_FADDQ: case SPARC_INS_FADDS: case SPARC_INS_FHADDD: case SPARC_INS_FHADDS: case SPARC_INS_FNADDD: case SPARC_INS_FNADDS: case SPARC_INS_FNHADDD: case SPARC_INS_FNHADDS: case SPARC_INS_FPADD16: case SPARC_INS_FPADD16S: case SPARC_INS_FPADD32: case SPARC_INS_FPADD32S: case SPARC_INS_FPADD64: case SPARC_INS_TADDCCTV: case SPARC_INS_TADDCC: op->type = R_ANAL_OP_TYPE_ADD; break; case SPARC_INS_FDMULQ: case SPARC_INS_FMUL8SUX16: case SPARC_INS_FMUL8ULX16: case SPARC_INS_FMUL8X16: case SPARC_INS_FMUL8X16AL: case SPARC_INS_FMUL8X16AU: case SPARC_INS_FMULD: case SPARC_INS_FMULD8SUX16: case SPARC_INS_FMULD8ULX16: case SPARC_INS_FMULQ: case SPARC_INS_FMULS: case SPARC_INS_FSMULD: case SPARC_INS_MULX: case SPARC_INS_SMULCC: case SPARC_INS_SMUL: case SPARC_INS_UMULCC: case SPARC_INS_UMULXHI: case SPARC_INS_UMUL: case SPARC_INS_XMULX: case SPARC_INS_XMULXHI: op->type = R_ANAL_OP_TYPE_MUL; break; case SPARC_INS_FDIVD: case SPARC_INS_FDIVQ: case SPARC_INS_FDIVS: case SPARC_INS_SDIVCC: case SPARC_INS_SDIVX: case SPARC_INS_SDIV: case SPARC_INS_UDIVCC: case SPARC_INS_UDIVX: case SPARC_INS_UDIV: op->type = R_ANAL_OP_TYPE_DIV; break; } } cs_free (insn, n); cs_close (&handle); } return op->size; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { int n, ret, opsize = -1; csh handle; cs_insn* insn; int mode = a->big_endian? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; mode |= (a->bits==64)? CS_MODE_64: CS_MODE_32; // XXX no arch->cpu ?!?! CS_MODE_MICRO, N64 ret = cs_open (CS_ARCH_MIPS, mode, &handle); op->delay = 0; op->type = R_ANAL_OP_TYPE_ILL; op->size = 4; if (ret != CS_ERR_OK) goto fin; cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); n = cs_disasm (handle, (ut8*)buf, len, addr, 1, &insn); if (n<1 || insn->size<1) goto beach; op->type = R_ANAL_OP_TYPE_NULL; op->delay = 0; opsize = op->size = insn->size; switch (insn->id) { case MIPS_INS_INVALID: op->type = R_ANAL_OP_TYPE_ILL; break; case MIPS_INS_LB: case MIPS_INS_LBU: case MIPS_INS_LBUX: case MIPS_INS_LW: case MIPS_INS_LWC1: case MIPS_INS_LWC2: case MIPS_INS_LWL: case MIPS_INS_LWR: case MIPS_INS_LWXC1: case MIPS_INS_LD: case MIPS_INS_LDC1: case MIPS_INS_LDC2: case MIPS_INS_LDL: case MIPS_INS_LDR: case MIPS_INS_LDXC1: op->type = R_ANAL_OP_TYPE_LOAD; op->refptr = 4; switch (OPERAND(1).type) { case MIPS_OP_MEM: if (OPERAND(1).mem.base == MIPS_REG_GP) { op->ptr = a->gp + OPERAND(1).mem.disp; op->refptr = 4; } break; case MIPS_OP_IMM: op->ptr = OPERAND(1).imm; break; case MIPS_OP_REG: // wtf? break; default: break; } // TODO: fill break; case MIPS_INS_SW: case MIPS_INS_SWC1: case MIPS_INS_SWC2: case MIPS_INS_SWL: case MIPS_INS_SWR: case MIPS_INS_SWXC1: op->type = R_ANAL_OP_TYPE_STORE; break; case MIPS_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case MIPS_INS_SYSCALL: case MIPS_INS_BREAK: op->type = R_ANAL_OP_TYPE_TRAP; break; case MIPS_INS_JALR: op->type = R_ANAL_OP_TYPE_UCALL; op->delay = 1; break; case MIPS_INS_JAL: case MIPS_INS_JALS: case MIPS_INS_JALX: case MIPS_INS_JIALC: case MIPS_INS_JIC: case MIPS_INS_JRADDIUSP: case MIPS_INS_BAL: case MIPS_INS_BGEZAL: // Branch on less than zero and link op->type = R_ANAL_OP_TYPE_CALL; op->delay = 1; op->jump = IMM(0); op->fail = addr+4; break; case MIPS_INS_MOVE: op->type = R_ANAL_OP_TYPE_MOV; break; case MIPS_INS_ADD: case MIPS_INS_ADDI: case MIPS_INS_ADDIU: case MIPS_INS_DADD: case MIPS_INS_DADDI: case MIPS_INS_DADDIU: op->type = R_ANAL_OP_TYPE_ADD; break; case MIPS_INS_SUB: case MIPS_INS_SUBV: case MIPS_INS_SUBVI: case MIPS_INS_DSUBU: case MIPS_INS_FSUB: case MIPS_INS_FMSUB: case MIPS_INS_SUBU: case MIPS_INS_DSUB: case MIPS_INS_SUBS_S: case MIPS_INS_SUBS_U: case MIPS_INS_SUBUH: case MIPS_INS_SUBUH_R: op->type = R_ANAL_OP_TYPE_SUB; break; case MIPS_INS_MULV: case MIPS_INS_MULT: case MIPS_INS_MULSA: case MIPS_INS_FMUL: case MIPS_INS_MUL: case MIPS_INS_DMULT: case MIPS_INS_DMULTU: op->type = R_ANAL_OP_TYPE_MUL; break; case MIPS_INS_XOR: case MIPS_INS_XORI: op->type = R_ANAL_OP_TYPE_XOR; break; case MIPS_INS_AND: case MIPS_INS_ANDI: op->type = R_ANAL_OP_TYPE_AND; break; case MIPS_INS_NOT: op->type = R_ANAL_OP_TYPE_NOT; break; case MIPS_INS_OR: case MIPS_INS_ORI: op->type = R_ANAL_OP_TYPE_OR; break; case MIPS_INS_DIV: case MIPS_INS_DIVU: case MIPS_INS_DDIV: case MIPS_INS_DDIVU: case MIPS_INS_FDIV: case MIPS_INS_DIV_S: case MIPS_INS_DIV_U: op->type = R_ANAL_OP_TYPE_DIV; break; case MIPS_INS_CMPGDU: case MIPS_INS_CMPGU: case MIPS_INS_CMPU: case MIPS_INS_CMPI: op->type = R_ANAL_OP_TYPE_CMP; break; case MIPS_INS_J: case MIPS_INS_B: case MIPS_INS_BZ: case MIPS_INS_BEQ: case MIPS_INS_BNZ: case MIPS_INS_BNE: case MIPS_INS_BEQZ: case MIPS_INS_BNEG: case MIPS_INS_BNEGI: case MIPS_INS_BNEZ: case MIPS_INS_BTEQZ: case MIPS_INS_BTNEZ: case MIPS_INS_BLTZ: case MIPS_INS_BGEZ: case MIPS_INS_BGEZC: case MIPS_INS_BGEZALC: op->type = R_ANAL_OP_TYPE_JMP; op->delay = 1; if (OPERAND(0).type == MIPS_OP_IMM) { op->jump = IMM(0); } else if (OPERAND(1).type == MIPS_OP_IMM) { op->jump = IMM(1); } else if (OPERAND(2).type == MIPS_OP_IMM) { op->jump = IMM(2); } break; case MIPS_INS_JR: case MIPS_INS_JRC: op->type = R_ANAL_OP_TYPE_JMP; op->delay = 1; // register 32 is $ra, so jmp is a return if (insn->detail->mips.operands[0].reg == 32) { op->type = R_ANAL_OP_TYPE_RET; } break; } beach: if (a->decode) { if (!analop_esil (a, op, addr, buf, len, &handle, insn)) r_strbuf_fini (&op->esil); } cs_free (insn, n); cs_close (&handle); fin: return opsize; }
static void test() { #define X86_CODE16 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00" #define X86_CODE32 "\x8d\x4c\x32\x08\x01\xd8\x81\xc6\x34\x12\x00\x00" //#define X86_CODE32 "\x0f\xa7\xc0" // xstorerng #define X86_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00" //#define ARM_CODE "\x04\xe0\x2d\xe5" #define ARM_CODE "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3" #define ARM_CODE2 "\x10\xf1\x10\xe7\x11\xf2\x31\xe7\xdc\xa1\x2e\xf3\xe8\x4e\x62\xf3" #define THUMB_CODE "\x70\x47\xeb\x46\x83\xb0\xc9\x68" #define THUMB_CODE2 "\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0" #define MIPS_CODE "\x0C\x10\x00\x97\x00\x00\x00\x00\x24\x02\x00\x0c\x8f\xa2\x00\x00\x34\x21\x34\x56" #define MIPS_CODE2 "\x56\x34\x21\x34\xc2\x17\x01\x00" //#define ARM64_CODE "\x00\x40\x21\x4b" // sub w0, w0, w1, uxtw //#define ARM64_CODE "\x21\x7c\x02\x9b" // mul x1, x1, x2 //#define ARM64_CODE "\x20\x74\x0b\xd5" // dc zva, x0 //#define ARM64_CODE "\xe1\x0b\x40\xb9" // ldr w1, [sp, #0x8] #define ARM64_CODE "\x21\x7c\x02\x9b\x21\x7c\x00\x53\x00\x40\x21\x4b\xe1\x0b\x40\xb9" #define PPC_CODE "\x80\x20\x00\x00\x80\x3f\x00\x00\x10\x43\x23\x0e\xd0\x44\x00\x80\x4c\x43\x22\x02\x2d\x03\x00\x80\x7c\x43\x20\x14\x7c\x43\x20\x93\x4f\x20\x00\x21\x4c\xc8\x00\x21" #define SPARC_CODE "\x80\xa0\x40\x02\x85\xc2\x60\x08\x85\xe8\x20\x01\x81\xe8\x00\x00\x90\x10\x20\x01\xd5\xf6\x10\x16\x21\x00\x00\x0a\x86\x00\x40\x02\x01\x00\x00\x00\x12\xbf\xff\xff\x10\xbf\xff\xff\xa0\x02\x00\x09\x0d\xbf\xff\xff\xd4\x20\x60\x00\xd4\x4e\x00\x16\x2a\xc2\x80\x03" #define SPARCV9_CODE "\x81\xa8\x0a\x24\x89\xa0\x10\x20\x89\xa0\x1a\x60\x89\xa0\x00\xe0" #define SYSZ_CODE "\xed\x00\x00\x00\x00\x1a\x5a\x0f\x1f\xff\xc2\x09\x80\x00\x00\x00\x07\xf7\xeb\x2a\xff\xff\x7f\x57\xe3\x01\xff\xff\x7f\x57\xeb\x00\xf0\x00\x00\x24\xb2\x4f\x00\x78" #define XCORE_CODE "\xfe\x0f\xfe\x17\x13\x17\xc6\xfe\xec\x17\x97\xf8\xec\x4f\x1f\xfd\xec\x37\x07\xf2\x45\x5b\xf9\xfa\x02\x06\x1b\x10" struct platform { cs_arch arch; cs_mode mode; unsigned char *code; size_t size; char *comment; cs_opt_type opt_type; cs_opt_value opt_value; }; struct platform platforms[] = { { CS_ARCH_X86, CS_MODE_16, (unsigned char*)X86_CODE16, sizeof(X86_CODE16) - 1, "X86 16bit (Intel syntax)" }, { CS_ARCH_X86, CS_MODE_32, (unsigned char*)X86_CODE32, sizeof(X86_CODE32) - 1, "X86 32bit (ATT syntax)", CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT, }, { CS_ARCH_X86, CS_MODE_32, (unsigned char*)X86_CODE32, sizeof(X86_CODE32) - 1, "X86 32 (Intel syntax)" }, { CS_ARCH_X86, CS_MODE_64, (unsigned char*)X86_CODE64, sizeof(X86_CODE64) - 1, "X86 64 (Intel syntax)" }, { CS_ARCH_ARM, CS_MODE_ARM, (unsigned char*)ARM_CODE, sizeof(ARM_CODE) - 1, "ARM" }, { CS_ARCH_ARM, CS_MODE_THUMB, (unsigned char*)THUMB_CODE2, sizeof(THUMB_CODE2) - 1, "THUMB-2" }, { CS_ARCH_ARM, CS_MODE_ARM, (unsigned char*)ARM_CODE2, sizeof(ARM_CODE2) - 1, "ARM: Cortex-A15 + NEON" }, { CS_ARCH_ARM, CS_MODE_THUMB, (unsigned char*)THUMB_CODE, sizeof(THUMB_CODE) - 1, "THUMB" }, { CS_ARCH_MIPS, (cs_mode)(CS_MODE_32 + CS_MODE_BIG_ENDIAN), (unsigned char*)MIPS_CODE, sizeof(MIPS_CODE) - 1, "MIPS-32 (Big-endian)" }, { CS_ARCH_MIPS, (cs_mode)(CS_MODE_64 + CS_MODE_LITTLE_ENDIAN), (unsigned char*)MIPS_CODE2, sizeof(MIPS_CODE2) - 1, "MIPS-64-EL (Little-endian)" }, { CS_ARCH_ARM64, CS_MODE_ARM, (unsigned char*)ARM64_CODE, sizeof(ARM64_CODE) - 1, "ARM-64" }, { CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, (unsigned char*)PPC_CODE, sizeof(PPC_CODE) - 1, "PPC-64" }, { CS_ARCH_PPC, CS_MODE_BIG_ENDIAN, (unsigned char*)PPC_CODE, sizeof(PPC_CODE) - 1, "PPC-64, print register with number only", CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME }, { CS_ARCH_SPARC, CS_MODE_BIG_ENDIAN, (unsigned char*)SPARC_CODE, sizeof(SPARC_CODE) - 1, "Sparc" }, { CS_ARCH_SPARC, (cs_mode)(CS_MODE_BIG_ENDIAN + CS_MODE_V9), (unsigned char*)SPARCV9_CODE, sizeof(SPARCV9_CODE) - 1, "SparcV9" }, { CS_ARCH_SYSZ, (cs_mode)0, (unsigned char*)SYSZ_CODE, sizeof(SYSZ_CODE) - 1, "SystemZ" }, { CS_ARCH_XCORE, (cs_mode)0, (unsigned char*)XCORE_CODE, sizeof(XCORE_CODE) - 1, "XCore" }, }; csh handle; uint64_t address = 0x1000; cs_insn *insn; int i; size_t count; cs_err err; for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) { printf("****************\n"); printf("Platform: %s\n", platforms[i].comment); err = cs_open(platforms[i].arch, platforms[i].mode, &handle); if (err) { printf("Failed on cs_open() with error returned: %u\n", err); continue; } if (platforms[i].opt_type) cs_option(handle, platforms[i].opt_type, platforms[i].opt_value); count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn); if (count) { size_t j; print_string_hex(platforms[i].code, platforms[i].size); printf("Disasm:\n"); for (j = 0; j < count; j++) { printf("0x%"PRIx64":\t%s\t\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); } // print out the next offset, after the last insn printf("0x%"PRIx64":\n", insn[j-1].address + insn[j-1].size); // free memory allocated by cs_disasm() cs_free(insn, count); } else { printf("****************\n"); printf("Platform: %s\n", platforms[i].comment); print_string_hex(platforms[i].code, platforms[i].size); printf("ERROR: Failed to disasm given code!\n"); } printf("\n"); cs_close(&handle); } }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { static int omode = 0; int mode, ret; ut64 off = a->pc; mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: (a->bits==16)? CS_MODE_16: 0; if (cd && mode != omode) { cs_close (&cd); cd = 0; } op->size = 0; omode = mode; if (cd == 0) { ret = cs_open (CS_ARCH_X86, mode, &cd); if (ret) return 0; } if (a->features && *a->features) { cs_option (cd, CS_OPT_DETAIL, CS_OPT_ON); } else { cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); } if (a->syntax == R_ASM_SYNTAX_ATT) { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); } else { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); } op->size = 1; #if USE_ITER_API { size_t size = len; if (insn == NULL) insn = cs_malloc (cd); insn->size = 1; memset (insn, 0, insn->size); n = cs_disasm_iter (cd, (const uint8_t**)&buf, &size, (uint64_t*)&off, insn); } #else n = cs_disasm (cd, (const ut8*)buf, len, off, 1, &insn); #endif op->size = 0; if (a->features && *a->features) { if (!check_features (a, insn)) { op->size = insn->size; strcpy (op->buf_asm, "illegal"); } } if (op->size==0 && n>0 && insn->size>0) { char *ptrstr; op->size = insn->size; snprintf (op->buf_asm, R_ASM_BUFSIZE, "%s%s%s", insn->mnemonic, insn->op_str[0]?" ":"", insn->op_str); ptrstr = strstr (op->buf_asm, "ptr "); if (ptrstr) { memmove (ptrstr, ptrstr+4, strlen (ptrstr+4)+1); } } if (a->syntax == R_ASM_SYNTAX_JZ) { if (!strncmp (op->buf_asm, "je ", 3)) { memcpy (op->buf_asm, "jz", 2); } else if (!strncmp (op->buf_asm, "jne ", 4)) { memcpy (op->buf_asm, "jnz", 3); } } #if USE_ITER_API /* do nothing because it should be allocated once and freed in the_end */ #else cs_free (insn, n); insn = NULL; #endif return op->size; }
void x86Cpu::disassembly(triton::arch::Instruction &inst) { csh handle; cs_insn* insn; size_t count; /* Check if the opcodes and opcodes' size are defined */ if (inst.getOpcodes() == nullptr || inst.getOpcodesSize() == 0) throw std::runtime_error("x86Cpu::disassembly(): Opcodes and opcodesSize must be definied."); /* Open capstone */ if (cs_open(CS_ARCH_X86, CS_MODE_32, &handle) != CS_ERR_OK) throw std::runtime_error("x86Cpu::disassembly(): Cannot open capstone."); /* Init capstone's options */ cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); /* Let's disass and build our operands */ count = cs_disasm(handle, inst.getOpcodes(), inst.getOpcodesSize(), inst.getAddress(), 0, &insn); if (count > 0) { cs_detail* detail = insn->detail; for (triton::uint32 j = 0; j < count; j++) { /* Init the disassembly */ std::stringstream str; str << insn[j].mnemonic << " " << insn[j].op_str; inst.setDisassembly(str.str()); /* Init the instruction's type */ inst.setType(capstoneInstToTritonInst(insn[j].id)); /* Init operands */ for (triton::uint32 n = 0; n < detail->x86.op_count; n++) { cs_x86_op *op = &(detail->x86.operands[n]); switch(op->type) { case X86_OP_IMM: inst.operands.push_back(triton::arch::OperandWrapper(triton::arch::ImmediateOperand(op->imm, op->size))); break; case X86_OP_MEM: { triton::arch::MemoryOperand mem = inst.popMemoryAccess(); /* Set the size if the memory is not valid */ if (!mem.isValid()) mem.setPair(std::make_pair(((op->size * BYTE_SIZE_BIT) - 1), 0)); /* LEA if exists */ triton::arch::RegisterOperand base(triton::arch::x86::capstoneRegToTritonReg(op->mem.base)); triton::arch::RegisterOperand index(triton::arch::x86::capstoneRegToTritonReg(op->mem.index)); triton::arch::ImmediateOperand disp(op->mem.disp, op->size); triton::arch::ImmediateOperand scale(op->mem.scale, op->size); mem.setBaseReg(base); mem.setIndexReg(index); mem.setDisplacement(disp); mem.setScale(scale); inst.operands.push_back(triton::arch::OperandWrapper(mem)); break; } case X86_OP_REG: inst.operands.push_back(triton::arch::OperandWrapper(inst.getRegisterState(triton::arch::x86::capstoneRegToTritonReg(op->reg)))); break; default: break; } } } /* Set branch */ if (detail->groups_count > 0) { for (triton::uint32 n = 0; n < detail->groups_count; n++) { if (detail->groups[n] == X86_GRP_JUMP) inst.setBranch(true); if (detail->groups[n] == X86_GRP_JUMP || detail->groups[n] == X86_GRP_CALL || detail->groups[n] == X86_GRP_RET) inst.setControlFlow(true); } } cs_free(insn, count); } else throw std::runtime_error("x86Cpu::disassembly(): Failed to disassemble the given code."); cs_close(&handle); return; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; cs_insn *insn; int mode = (a->bits==16)? CS_MODE_THUMB: CS_MODE_ARM; int i, n, ret = (a->bits==64)? cs_open (CS_ARCH_ARM64, mode, &handle): cs_open (CS_ARCH_ARM, mode, &handle); cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); op->type = R_ANAL_OP_TYPE_NULL; op->size = (a->bits==16)? 2: 4; op->delay = 0; r_strbuf_init (&op->esil); if (ret == CS_ERR_OK) { n = cs_disasm_ex (handle, (ut8*)buf, len, addr, 1, &insn); if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { op->size = insn->size; switch (insn->id) { case ARM_INS_POP: case ARM_INS_LDM: op->type = R_ANAL_OP_TYPE_POP; for (i = 0; i < insn->detail->arm.op_count; i++) { if (insn->detail->arm.operands[i].type == ARM_OP_REG && insn->detail->arm.operands[i].reg == ARM_REG_PC) { if (insn->detail->arm.cc == ARM_CC_AL) op->type = R_ANAL_OP_TYPE_RET; else op->type = R_ANAL_OP_TYPE_CRET; break; } } break; case ARM_INS_SUB: op->type = R_ANAL_OP_TYPE_SUB; break; case ARM_INS_ADD: op->type = R_ANAL_OP_TYPE_ADD; break; case ARM_INS_MOV: case ARM_INS_MOVS: case ARM_INS_MOVT: case ARM_INS_MOVW: case ARM_INS_VMOVL: case ARM_INS_VMOVN: case ARM_INS_VQMOVUN: case ARM_INS_VQMOVN: op->type = R_ANAL_OP_TYPE_MOV; break; case ARM_INS_CMP: case ARM_INS_TST: op->type = R_ANAL_OP_TYPE_CMP; break; case ARM_INS_ROR: case ARM_INS_ORN: case ARM_INS_LSL: case ARM_INS_LSR: break; case ARM_INS_PUSH: case ARM_INS_STR: //case ARM_INS_POP: case ARM_INS_LDR: op->type = R_ANAL_OP_TYPE_LOAD; break; case ARM_INS_BL: case ARM_INS_BLX: op->type = R_ANAL_OP_TYPE_CALL; op->jump = IMM(0); break; case ARM_INS_B: case ARM_INS_BX: case ARM_INS_BXJ: if (insn->detail->arm.cc) { op->type = R_ANAL_OP_TYPE_CJMP; op->jump = IMM(0); op->fail = addr+op->size; } else { op->type = R_ANAL_OP_TYPE_JMP; op->jump = IMM(0); } break; } if (a->decode) { if (!analop_esil (a, op, addr, buf, len, &handle, insn)) r_strbuf_fini (&op->esil); } cs_free (insn, n); } } cs_close (&handle); return op->size; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len, RAnalOpMask mask) { int n, ret, opsize = -1; static csh handle = 0; static int omode = -1; static int obits = 32; cs_insn* insn; cs_m68k *m68k; cs_detail *detail; int mode = a->big_endian? CS_MODE_BIG_ENDIAN: CS_MODE_LITTLE_ENDIAN; //mode |= (a->bits==64)? CS_MODE_64: CS_MODE_32; if (mode != omode || a->bits != obits) { cs_close (&handle); handle = 0; omode = mode; obits = a->bits; } // XXX no arch->cpu ?!?! CS_MODE_MICRO, N64 op->delay = 0; // replace this with the asm.features? if (a->cpu && strstr (a->cpu, "68000")) { mode |= CS_MODE_M68K_000; } if (a->cpu && strstr (a->cpu, "68010")) { mode |= CS_MODE_M68K_010; } if (a->cpu && strstr (a->cpu, "68020")) { mode |= CS_MODE_M68K_020; } if (a->cpu && strstr (a->cpu, "68030")) { mode |= CS_MODE_M68K_030; } if (a->cpu && strstr (a->cpu, "68040")) { mode |= CS_MODE_M68K_040; } if (a->cpu && strstr (a->cpu, "68060")) { mode |= CS_MODE_M68K_060; } op->size = 4; if (handle == 0) { ret = cs_open (CS_ARCH_M68K, mode, &handle); if (ret != CS_ERR_OK) { goto fin; } cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); } n = cs_disasm (handle, (ut8*)buf, len, addr, 1, &insn); if (n < 1 || insn->size < 1) { op->type = R_ANAL_OP_TYPE_ILL; op->size = 2; opsize = -1; goto beach; } if (!memcmp (buf, "\xff\xff", R_MIN (len, 2))) { op->type = R_ANAL_OP_TYPE_ILL; op->size = 2; opsize = -1; goto beach; } detail = insn->detail; m68k = &detail->m68k; op->type = R_ANAL_OP_TYPE_NULL; op->delay = 0; op->id = insn->id; opsize = op->size = insn->size; if (mask & R_ANAL_OP_MASK_OPEX) { opex (&op->opex, handle, insn); } switch (insn->id) { case M68K_INS_INVALID: op->type = R_ANAL_OP_TYPE_ILL; break; case M68K_INS_ADD: case M68K_INS_ADDA: case M68K_INS_ADDI: case M68K_INS_ADDQ: case M68K_INS_ADDX: op->type = R_ANAL_OP_TYPE_ADD; break; case M68K_INS_AND: case M68K_INS_ANDI: op->type = R_ANAL_OP_TYPE_AND; break; case M68K_INS_ASL: op->type = R_ANAL_OP_TYPE_SHL; break; case M68K_INS_ASR: op->type = R_ANAL_OP_TYPE_SHR; break; case M68K_INS_ABCD: break; case M68K_INS_BHS: case M68K_INS_BLO: case M68K_INS_BHI: case M68K_INS_BLS: case M68K_INS_BCC: case M68K_INS_BCS: case M68K_INS_BNE: case M68K_INS_BEQ: case M68K_INS_BVC: case M68K_INS_BVS: case M68K_INS_BPL: case M68K_INS_BMI: case M68K_INS_BGE: case M68K_INS_BLT: case M68K_INS_BGT: case M68K_INS_BLE: handle_branch_instruction (op, addr, m68k, R_ANAL_OP_TYPE_CJMP, 0); break; case M68K_INS_BRA: handle_branch_instruction (op, addr, m68k, R_ANAL_OP_TYPE_JMP, 0); break; case M68K_INS_BSR: handle_branch_instruction (op, addr, m68k, R_ANAL_OP_TYPE_CALL, 0); break; case M68K_INS_BCHG: case M68K_INS_BCLR: case M68K_INS_BSET: case M68K_INS_BTST: case M68K_INS_BFCHG: case M68K_INS_BFCLR: case M68K_INS_BFEXTS: case M68K_INS_BFEXTU: case M68K_INS_BFFFO: case M68K_INS_BFINS: case M68K_INS_BFSET: case M68K_INS_BFTST: case M68K_INS_BKPT: case M68K_INS_CALLM: case M68K_INS_CAS: case M68K_INS_CAS2: case M68K_INS_CHK: case M68K_INS_CHK2: case M68K_INS_CLR: // TODO: break; case M68K_INS_CMP: case M68K_INS_CMPA: case M68K_INS_CMPI: case M68K_INS_CMPM: case M68K_INS_CMP2: op->type = R_ANAL_OP_TYPE_CMP; break; case M68K_INS_CINVL: case M68K_INS_CINVP: case M68K_INS_CINVA: op->type = R_ANAL_OP_TYPE_ILL; break; case M68K_INS_CPUSHL: case M68K_INS_CPUSHP: case M68K_INS_CPUSHA: break; case M68K_INS_DBT: case M68K_INS_DBF: case M68K_INS_DBHI: case M68K_INS_DBLS: case M68K_INS_DBCC: case M68K_INS_DBCS: case M68K_INS_DBNE: case M68K_INS_DBEQ: case M68K_INS_DBVC: case M68K_INS_DBVS: case M68K_INS_DBPL: case M68K_INS_DBMI: case M68K_INS_DBGE: case M68K_INS_DBLT: case M68K_INS_DBGT: case M68K_INS_DBLE: case M68K_INS_DBRA: handle_branch_instruction (op, addr, m68k, R_ANAL_OP_TYPE_CJMP, 1); break; case M68K_INS_DIVS: case M68K_INS_DIVSL: case M68K_INS_DIVU: case M68K_INS_DIVUL: op->type = R_ANAL_OP_TYPE_DIV; break; case M68K_INS_EOR: case M68K_INS_EORI: op->type = R_ANAL_OP_TYPE_XOR; break; case M68K_INS_EXG: op->type = R_ANAL_OP_TYPE_MOV; break; case M68K_INS_EXT: case M68K_INS_EXTB: break; case M68K_INS_FABS: case M68K_INS_FSABS: case M68K_INS_FDABS: case M68K_INS_FACOS: case M68K_INS_FADD: case M68K_INS_FSADD: case M68K_INS_FDADD: case M68K_INS_FASIN: case M68K_INS_FATAN: case M68K_INS_FATANH: case M68K_INS_FBF: case M68K_INS_FBEQ: case M68K_INS_FBOGT: case M68K_INS_FBOGE: case M68K_INS_FBOLT: case M68K_INS_FBOLE: case M68K_INS_FBOGL: case M68K_INS_FBOR: case M68K_INS_FBUN: case M68K_INS_FBUEQ: case M68K_INS_FBUGT: case M68K_INS_FBUGE: case M68K_INS_FBULT: case M68K_INS_FBULE: case M68K_INS_FBNE: case M68K_INS_FBT: case M68K_INS_FBSF: case M68K_INS_FBSEQ: case M68K_INS_FBGT: case M68K_INS_FBGE: case M68K_INS_FBLT: case M68K_INS_FBLE: case M68K_INS_FBGL: case M68K_INS_FBGLE: case M68K_INS_FBNGLE: case M68K_INS_FBNGL: case M68K_INS_FBNLE: case M68K_INS_FBNLT: case M68K_INS_FBNGE: case M68K_INS_FBNGT: case M68K_INS_FBSNE: case M68K_INS_FBST: case M68K_INS_FCMP: case M68K_INS_FCOS: case M68K_INS_FCOSH: case M68K_INS_FDBF: case M68K_INS_FDBEQ: case M68K_INS_FDBOGT: case M68K_INS_FDBOGE: case M68K_INS_FDBOLT: case M68K_INS_FDBOLE: case M68K_INS_FDBOGL: case M68K_INS_FDBOR: case M68K_INS_FDBUN: case M68K_INS_FDBUEQ: case M68K_INS_FDBUGT: case M68K_INS_FDBUGE: case M68K_INS_FDBULT: case M68K_INS_FDBULE: case M68K_INS_FDBNE: case M68K_INS_FDBT: case M68K_INS_FDBSF: case M68K_INS_FDBSEQ: case M68K_INS_FDBGT: case M68K_INS_FDBGE: case M68K_INS_FDBLT: case M68K_INS_FDBLE: case M68K_INS_FDBGL: case M68K_INS_FDBGLE: case M68K_INS_FDBNGLE: case M68K_INS_FDBNGL: case M68K_INS_FDBNLE: case M68K_INS_FDBNLT: case M68K_INS_FDBNGE: case M68K_INS_FDBNGT: case M68K_INS_FDBSNE: case M68K_INS_FDBST: case M68K_INS_FDIV: case M68K_INS_FSDIV: case M68K_INS_FDDIV: case M68K_INS_FETOX: case M68K_INS_FETOXM1: case M68K_INS_FGETEXP: case M68K_INS_FGETMAN: case M68K_INS_FINT: case M68K_INS_FINTRZ: case M68K_INS_FLOG10: case M68K_INS_FLOG2: case M68K_INS_FLOGN: case M68K_INS_FLOGNP1: case M68K_INS_FMOD: case M68K_INS_FMOVE: case M68K_INS_FSMOVE: case M68K_INS_FDMOVE: case M68K_INS_FMOVECR: case M68K_INS_FMOVEM: case M68K_INS_FMUL: case M68K_INS_FSMUL: case M68K_INS_FDMUL: case M68K_INS_FNEG: case M68K_INS_FSNEG: case M68K_INS_FDNEG: case M68K_INS_FNOP: case M68K_INS_FREM: case M68K_INS_FRESTORE: case M68K_INS_FSAVE: case M68K_INS_FSCALE: case M68K_INS_FSGLDIV: case M68K_INS_FSGLMUL: case M68K_INS_FSIN: case M68K_INS_FSINCOS: case M68K_INS_FSINH: case M68K_INS_FSQRT: case M68K_INS_FSSQRT: case M68K_INS_FDSQRT: case M68K_INS_FSF: case M68K_INS_FSBEQ: case M68K_INS_FSOGT: case M68K_INS_FSOGE: case M68K_INS_FSOLT: case M68K_INS_FSOLE: case M68K_INS_FSOGL: case M68K_INS_FSOR: case M68K_INS_FSUN: case M68K_INS_FSUEQ: case M68K_INS_FSUGT: case M68K_INS_FSUGE: case M68K_INS_FSULT: case M68K_INS_FSULE: case M68K_INS_FSNE: case M68K_INS_FST: case M68K_INS_FSSF: case M68K_INS_FSSEQ: case M68K_INS_FSGT: case M68K_INS_FSGE: case M68K_INS_FSLT: case M68K_INS_FSLE: case M68K_INS_FSGL: case M68K_INS_FSGLE: case M68K_INS_FSNGLE: case M68K_INS_FSNGL: case M68K_INS_FSNLE: case M68K_INS_FSNLT: case M68K_INS_FSNGE: case M68K_INS_FSNGT: case M68K_INS_FSSNE: case M68K_INS_FSST: case M68K_INS_FSUB: case M68K_INS_FSSUB: case M68K_INS_FDSUB: case M68K_INS_FTAN: case M68K_INS_FTANH: case M68K_INS_FTENTOX: case M68K_INS_FTRAPF: case M68K_INS_FTRAPEQ: case M68K_INS_FTRAPOGT: case M68K_INS_FTRAPOGE: case M68K_INS_FTRAPOLT: case M68K_INS_FTRAPOLE: case M68K_INS_FTRAPOGL: case M68K_INS_FTRAPOR: case M68K_INS_FTRAPUN: case M68K_INS_FTRAPUEQ: case M68K_INS_FTRAPUGT: case M68K_INS_FTRAPUGE: case M68K_INS_FTRAPULT: case M68K_INS_FTRAPULE: case M68K_INS_FTRAPNE: case M68K_INS_FTRAPT: case M68K_INS_FTRAPSF: case M68K_INS_FTRAPSEQ: case M68K_INS_FTRAPGT: case M68K_INS_FTRAPGE: case M68K_INS_FTRAPLT: case M68K_INS_FTRAPLE: case M68K_INS_FTRAPGL: case M68K_INS_FTRAPGLE: case M68K_INS_FTRAPNGLE: case M68K_INS_FTRAPNGL: case M68K_INS_FTRAPNLE: case M68K_INS_FTRAPNLT: case M68K_INS_FTRAPNGE: case M68K_INS_FTRAPNGT: case M68K_INS_FTRAPSNE: case M68K_INS_FTRAPST: case M68K_INS_FTST: case M68K_INS_FTWOTOX: op->type = R_ANAL_OP_TYPE_UNK; op->family = R_ANAL_OP_FAMILY_FPU; break; case M68K_INS_HALT: op->type = R_ANAL_OP_TYPE_NOP; break; case M68K_INS_ILLEGAL: op->type = R_ANAL_OP_TYPE_ILL; break; case M68K_INS_JMP: handle_jump_instruction (op, addr, m68k, R_ANAL_OP_TYPE_JMP); break; case M68K_INS_JSR: handle_jump_instruction (op, addr, m68k, R_ANAL_OP_TYPE_CALL); break; case M68K_INS_LPSTOP: op->type = R_ANAL_OP_TYPE_NOP; break; case M68K_INS_LSL: op->type = R_ANAL_OP_TYPE_SHL; break; case M68K_INS_LINK: op->type = R_ANAL_OP_TYPE_PUSH; op->stackop = R_ANAL_STACK_INC; op->stackptr = -(st16)IMM(1); break; case M68K_INS_LSR: op->type = R_ANAL_OP_TYPE_SHR; break; case M68K_INS_PEA: case M68K_INS_LEA: op->type = R_ANAL_OP_TYPE_LEA; break; case M68K_INS_MOVE: case M68K_INS_MOVEA: case M68K_INS_MOVEC: case M68K_INS_MOVEM: case M68K_INS_MOVEP: case M68K_INS_MOVEQ: case M68K_INS_MOVES: case M68K_INS_MOVE16: op->type = R_ANAL_OP_TYPE_MOV; break; case M68K_INS_MULS: case M68K_INS_MULU: op->type = R_ANAL_OP_TYPE_MUL; break; case M68K_INS_NBCD: case M68K_INS_NEG: case M68K_INS_NEGX: break; case M68K_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; break; case M68K_INS_NOT: op->type = R_ANAL_OP_TYPE_NOT; break; case M68K_INS_OR: case M68K_INS_ORI: op->type = R_ANAL_OP_TYPE_OR; break; case M68K_INS_PACK: case M68K_INS_PFLUSH: case M68K_INS_PFLUSHA: case M68K_INS_PFLUSHAN: case M68K_INS_PFLUSHN: case M68K_INS_PLOADR: case M68K_INS_PLOADW: case M68K_INS_PLPAR: case M68K_INS_PLPAW: case M68K_INS_PMOVE: case M68K_INS_PMOVEFD: case M68K_INS_PTESTR: case M68K_INS_PTESTW: case M68K_INS_PULSE: case M68K_INS_REMS: case M68K_INS_REMU: case M68K_INS_RESET: break; case M68K_INS_ROL: op->type = R_ANAL_OP_TYPE_ROL; break; case M68K_INS_ROR: op->type = R_ANAL_OP_TYPE_ROR; break; case M68K_INS_ROXL: case M68K_INS_ROXR: break; case M68K_INS_RTD: case M68K_INS_RTE: case M68K_INS_RTM: case M68K_INS_RTR: case M68K_INS_RTS: op->type = R_ANAL_OP_TYPE_RET; break; case M68K_INS_SBCD: case M68K_INS_ST: case M68K_INS_SF: case M68K_INS_SHI: case M68K_INS_SLS: case M68K_INS_SCC: case M68K_INS_SHS: case M68K_INS_SCS: case M68K_INS_SLO: case M68K_INS_SNE: case M68K_INS_SEQ: case M68K_INS_SVC: case M68K_INS_SVS: case M68K_INS_SPL: case M68K_INS_SMI: case M68K_INS_SGE: case M68K_INS_SLT: case M68K_INS_SGT: case M68K_INS_SLE: case M68K_INS_STOP: break; case M68K_INS_SUB: case M68K_INS_SUBA: case M68K_INS_SUBI: case M68K_INS_SUBQ: case M68K_INS_SUBX: op->type = R_ANAL_OP_TYPE_SUB; break; case M68K_INS_SWAP: op->type = R_ANAL_OP_TYPE_MOV; break; case M68K_INS_TAS: break; case M68K_INS_TRAP: case M68K_INS_TRAPV: case M68K_INS_TRAPT: case M68K_INS_TRAPF: case M68K_INS_TRAPHI: case M68K_INS_TRAPLS: case M68K_INS_TRAPCC: case M68K_INS_TRAPHS: case M68K_INS_TRAPCS: case M68K_INS_TRAPLO: case M68K_INS_TRAPNE: case M68K_INS_TRAPEQ: case M68K_INS_TRAPVC: case M68K_INS_TRAPVS: case M68K_INS_TRAPPL: case M68K_INS_TRAPMI: case M68K_INS_TRAPGE: case M68K_INS_TRAPLT: case M68K_INS_TRAPGT: case M68K_INS_TRAPLE: op->type = R_ANAL_OP_TYPE_TRAP; break; case M68K_INS_TST: op->type = R_ANAL_OP_TYPE_CMP; break; case M68K_INS_UNPK: // unpack BCD op->type = R_ANAL_OP_TYPE_MOV; break; case M68K_INS_UNLK: op->type = R_ANAL_OP_TYPE_POP; // reset stackframe op->stackop = R_ANAL_STACK_SET; op->stackptr = 0; break; } if (mask & R_ANAL_OP_MASK_VAL) { op_fillval (op, handle, insn); } beach: cs_free (insn, n); //cs_close (&handle); fin: return opsize; }
static int disassemble(RAsm *a, RAsmOp *op, const ut8 *buf, int len) { static int omode = 0; int mode, ret; ut64 off = a->pc; mode = (a->bits == 64)? CS_MODE_64: (a->bits == 32)? CS_MODE_32: (a->bits == 16)? CS_MODE_16: 0; if (cd && mode != omode) { cs_close (&cd); cd = 0; } if (op) { op->size = 0; } omode = mode; if (cd == 0) { ret = cs_open (CS_ARCH_X86, mode, &cd); if (ret) { return 0; } } if (a->features && *a->features) { cs_option (cd, CS_OPT_DETAIL, CS_OPT_ON); } else { cs_option (cd, CS_OPT_DETAIL, CS_OPT_OFF); } // always unsigned immediates (kernel addresses) // maybe r2 should have an option for this too? #if CS_API_MAJOR >= 4 cs_option (cd, CS_OPT_UNSIGNED, CS_OPT_ON); #endif if (a->syntax == R_ASM_SYNTAX_MASM) { #if CS_API_MAJOR >= 4 cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_MASM); #endif } else if (a->syntax == R_ASM_SYNTAX_ATT) { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); } else { cs_option (cd, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL); } if (!op) { return true; } op->size = 1; cs_insn *insn = NULL; #if USE_ITER_API { size_t size = len; if (!insn || cd < 1) { insn = cs_malloc (cd); } if (!insn) { cs_free (insn, n); return 0; } memset (insn, 0, insn->size); insn->size = 1; n = cs_disasm_iter (cd, (const uint8_t**)&buf, &size, (uint64_t*)&off, insn); } #else n = cs_disasm (cd, (const ut8*)buf, len, off, 1, &insn); #endif if (op) { op->size = 0; } if (a->features && *a->features) { if (!check_features (a, insn)) { op->size = insn->size; r_asm_op_set_asm (op, "illegal"); } } if (op->size == 0 && n > 0 && insn->size > 0) { char *ptrstr; op->size = insn->size; char *buf_asm = sdb_fmt ("%s%s%s", insn->mnemonic, insn->op_str[0]?" ":"", insn->op_str); ptrstr = strstr (buf_asm, "ptr "); if (ptrstr) { memmove (ptrstr, ptrstr + 4, strlen (ptrstr + 4) + 1); } r_asm_op_set_asm (op, buf_asm); } else { decompile_vm (a, op, buf, len); } if (a->syntax == R_ASM_SYNTAX_JZ) { char *buf_asm = r_strbuf_get (&op->buf_asm); if (!strncmp (buf_asm, "je ", 3)) { memcpy (buf_asm, "jz", 2); } else if (!strncmp (buf_asm, "jne ", 4)) { memcpy (buf_asm, "jnz", 3); } } #if 0 // [eax + ebx*4] => [eax + ebx * 4] char *ast = strchr (op->buf_asm, '*'); if (ast && ast > op->buf_asm) { ast--; if (ast[0] != ' ') { char *tmp = strdup (ast + 1); if (tmp) { ast[0] = ' '; if (tmp[0] && tmp[1] && tmp[1] != ' ') { strcpy (ast, " * "); strcpy (ast + 3, tmp + 1); } else { strcpy (ast + 1, tmp); } free (tmp); } } } #endif #if USE_ITER_API /* do nothing because it should be allocated once and freed in the_end */ #else if (insn) { cs_free (insn, n); } #endif return op->size; }
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) { csh handle; #if USE_ITER_API static #endif cs_insn *insn = NULL; int mode = (a->bits==64)? CS_MODE_64: (a->bits==32)? CS_MODE_32: (a->bits==16)? CS_MODE_16: 0; int n, ret = cs_open (CS_ARCH_X86, mode, &handle); int regsz = 4; if (ret != CS_ERR_OK) { return 0; } switch (a->bits) { case 64: regsz = 8; break; case 16: regsz = 2; break; default: case 32: regsz = 4; break; } memset (op, '\0', sizeof (RAnalOp)); op->type = R_ANAL_OP_TYPE_NULL; op->jump = UT64_MAX; op->fail = UT64_MAX; op->ptr = op->val = UT64_MAX; op->src[0] = NULL; op->src[1] = NULL; op->size = 0; op->delay = 0; r_strbuf_init (&op->esil); cs_option (handle, CS_OPT_DETAIL, CS_OPT_ON); // capstone-next #if USE_ITER_API { ut64 naddr = addr; size_t size = len; if (insn == NULL) insn = cs_malloc (handle); n = cs_disasm_iter (handle, (const uint8_t**)&buf, &size, (uint64_t*)&naddr, insn); } #else n = cs_disasm (handle, (const ut8*)buf, len, addr, 1, &insn); #endif if (n<1) { op->type = R_ANAL_OP_TYPE_ILL; } else { int rs = a->bits/8; const char *pc = (a->bits==16)?"ip": (a->bits==32)?"eip":"rip"; const char *sp = (a->bits==16)?"sp": (a->bits==32)?"esp":"rsp"; const char *bp = (a->bits==16)?"bp": (a->bits==32)?"ebp":"rbp"; op->size = insn->size; op->prefix = 0; switch (insn->detail->x86.prefix[0]) { case X86_PREFIX_REPNE: op->prefix |= R_ANAL_OP_PREFIX_REPNE; case X86_PREFIX_REP: op->prefix |= R_ANAL_OP_PREFIX_REP; case X86_PREFIX_LOCK: op->prefix |= R_ANAL_OP_PREFIX_LOCK; } switch (insn->id) { case X86_INS_FNOP: case X86_INS_NOP: op->type = R_ANAL_OP_TYPE_NOP; if (a->decode) esilprintf (op, ","); break; case X86_INS_HLT: op->type = R_ANAL_OP_TYPE_TRAP; break; case X86_INS_CLI: case X86_INS_STI: case X86_INS_CLC: case X86_INS_STC: break; // cmov case X86_INS_CMOVA: case X86_INS_CMOVAE: case X86_INS_CMOVB: case X86_INS_CMOVBE: case X86_INS_FCMOVBE: case X86_INS_FCMOVB: case X86_INS_CMOVE: case X86_INS_FCMOVE: case X86_INS_CMOVG: case X86_INS_CMOVGE: case X86_INS_CMOVL: case X86_INS_CMOVLE: case X86_INS_FCMOVNBE: case X86_INS_FCMOVNB: case X86_INS_CMOVNE: case X86_INS_FCMOVNE: case X86_INS_CMOVNO: case X86_INS_CMOVNP: case X86_INS_FCMOVNU: case X86_INS_CMOVNS: case X86_INS_CMOVO: case X86_INS_CMOVP: case X86_INS_FCMOVU: case X86_INS_CMOVS: // mov case X86_INS_MOV: case X86_INS_MOVZX: case X86_INS_MOVABS: case X86_INS_MOVHPD: case X86_INS_MOVHPS: case X86_INS_MOVLPD: case X86_INS_MOVLPS: case X86_INS_MOVBE: case X86_INS_MOVSB: case X86_INS_MOVSD: case X86_INS_MOVSQ: case X86_INS_MOVSS: case X86_INS_MOVSW: case X86_INS_MOVD: case X86_INS_MOVQ: case X86_INS_MOVDQ2Q: { op->type = R_ANAL_OP_TYPE_MOV; switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 1); esilprintf (op, "%s,%s", src, dst); free (src); free (dst); } break; default: if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,=", src, dst); free (src); free (dst); } break; } switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } } break; case X86_INS_SHL: case X86_INS_SHLD: case X86_INS_SHLX: op->type = R_ANAL_OP_TYPE_SHL; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,<<=,cz,%%z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAR: case X86_INS_SARX: op->type = R_ANAL_OP_TYPE_SAR; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,>>=,%%z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SAL: case X86_INS_SALC: op->type = R_ANAL_OP_TYPE_SAL; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,<<=,%%z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_SHR: case X86_INS_SHRD: case X86_INS_SHRX: op->type = R_ANAL_OP_TYPE_SHR; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,>>=,cz,%%z,zf,=", src, dst); free (src); free (dst); } break; case X86_INS_CMP: case X86_INS_VCMP: case X86_INS_CMPPD: case X86_INS_CMPPS: case X86_INS_CMPSW: case X86_INS_CMPSD: case X86_INS_CMPSQ: case X86_INS_CMPSB: case X86_INS_CMPSS: case X86_INS_TEST: op->type = R_ANAL_OP_TYPE_CMP; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,==,%%z,zf,=", src, dst); free (src); free (dst); } switch (INSOP(0).type) { case X86_OP_MEM: op->ptr = INSOP(0).mem.disp; op->refptr = INSOP(0).size; if (INSOP(0).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(0).mem.base == X86_REG_RBP || INSOP(0).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } break; default: switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; if (INSOP(1).mem.base == X86_REG_RIP) { op->ptr += addr + insn->size; } else if (INSOP(1).mem.base == X86_REG_RBP || INSOP(1).mem.base == X86_REG_EBP) { op->stackop = R_ANAL_STACK_SET; op->stackptr = regsz; } break; case X86_OP_IMM: op->ptr = INSOP(1).imm; break; default: break; } break; } break; case X86_INS_LEA: op->type = R_ANAL_OP_TYPE_LEA; if (a->decode) { char *src = getarg (handle, insn, 0, 0); char *dst = getarg (handle, insn, 1, 2); esilprintf (op, "%s,%s,=", dst, src); free (src); free (dst); } switch (INSOP(1).type) { case X86_OP_MEM: op->ptr = INSOP(1).mem.disp; op->refptr = INSOP(1).size; switch (INSOP(1).mem.base) { case X86_REG_RIP: op->ptr += addr + op->size; break; case X86_REG_RBP: case X86_REG_EBP: op->stackop = R_ANAL_STACK_GET; op->stackptr = regsz; break; } break; case X86_OP_IMM: if (INSOP(1).imm > 10) op->ptr = INSOP(1).imm; break; default: break; } break; case X86_INS_ENTER: case X86_INS_PUSH: case X86_INS_PUSHAW: case X86_INS_PUSHAL: case X86_INS_PUSHF: { char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%d,%s,-=,%s,%s,=[%d]", rs, sp, dst, sp, rs); free (dst); } switch (INSOP(0).type) { case X86_OP_IMM: op->ptr = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_PUSH; break; default: op->type = R_ANAL_OP_TYPE_UPUSH; break; } op->stackop = R_ANAL_STACK_INC; op->stackptr = regsz; break; case X86_INS_LEAVE: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { esilprintf (op, "%s,%s,=,%s,[%d],%s,%d,%s,-=", bp, sp, sp, rs, bp, rs, sp); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_POP: case X86_INS_POPAW: case X86_INS_POPAL: case X86_INS_POPF: case X86_INS_POPCNT: op->type = R_ANAL_OP_TYPE_POP; if (a->decode) { char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, dst, rs, sp); free (dst); } op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_RET: case X86_INS_RETF: case X86_INS_IRET: case X86_INS_IRETD: case X86_INS_IRETQ: case X86_INS_SYSRET: op->type = R_ANAL_OP_TYPE_RET; if (a->decode) esilprintf (op, "%s,[%d],%s,=,%d,%s,+=", sp, rs, pc, rs, sp); op->stackop = R_ANAL_STACK_INC; op->stackptr = -regsz; break; case X86_INS_INT: if (a->decode) esilprintf (op, "%d,$", (int)INSOP(0).imm); op->type = R_ANAL_OP_TYPE_SWI; break; case X86_INS_INT1: case X86_INS_INT3: case X86_INS_INTO: case X86_INS_VMCALL: case X86_INS_VMMCALL: case X86_INS_SYSCALL: op->type = R_ANAL_OP_TYPE_TRAP; if (a->decode) esilprintf (op, "%d,$", (int)INSOP(0).imm); break; case X86_INS_JL: case X86_INS_JLE: case X86_INS_JA: case X86_INS_JAE: case X86_INS_JB: case X86_INS_JBE: case X86_INS_JCXZ: case X86_INS_JECXZ: case X86_INS_JRCXZ: case X86_INS_JO: case X86_INS_JNO: case X86_INS_JS: case X86_INS_JNS: case X86_INS_JP: case X86_INS_JNP: case X86_INS_JE: case X86_INS_JNE: case X86_INS_JG: case X86_INS_JGE: case X86_INS_LOOP: op->type = R_ANAL_OP_TYPE_CJMP; op->jump = INSOP(0).imm; op->fail = addr+op->size; if (a->decode) { char *dst = getarg (handle, insn, 0, 2); switch (insn->id) { case X86_INS_JL: esilprintf (op, "of,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JLE: esilprintf (op, "of,sf,^,zf,|,%s,%s,=", dst, pc); break; case X86_INS_JA: esilprintf (op, "cf,!,zf,!,&,?{,%s,%s,=,}",dst, pc); break; case X86_INS_JAE: esilprintf (op, "cf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JB: esilprintf (op, "cf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JO: esilprintf (op, "of,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNO: esilprintf (op, "of,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JE: esilprintf (op, "zf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JGE: esilprintf (op, "of,!,sf,^,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNE: esilprintf (op, "zf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JG: esilprintf (op, "sf,of,!,^,zf,!,&,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JS: esilprintf (op, "sf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNS: esilprintf (op, "sf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JP: esilprintf (op, "pf,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JNP: esilprintf (op, "pf,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JBE: esilprintf (op, "zf,cf,&,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JCXZ: esilprintf (op, "cx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JECXZ: esilprintf (op, "ecx,!,?{,%s,%s,=,}", dst, pc); break; case X86_INS_JRCXZ: esilprintf (op, "rcx,!,?{,%s,%s,=,}", dst, pc); break; } free (dst); } break; case X86_INS_CALL: case X86_INS_LCALL: switch (INSOP(0).type) { case X86_OP_IMM: op->type = R_ANAL_OP_TYPE_CALL; // TODO: what if UCALL? // TODO: use imm_size op->jump = INSOP(0).imm; op->fail = addr+op->size; break; case X86_OP_MEM: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; if (INSOP(0).mem.base == 0) { op->ptr = INSOP(0).mem.disp; } break; default: op->type = R_ANAL_OP_TYPE_UCALL; op->jump = UT64_MAX; break; } if (a->decode) { char* arg = getarg (handle, insn, 0, 1); esilprintf (op, "%d,%s,+," "%d,%s,-=,%s," "=[]," "%s,%s,=", op->size, pc, rs, sp, sp, arg, pc); free (arg); } break; case X86_INS_JMP: case X86_INS_LJMP: if (a->decode) { char *src = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,=", src, pc); free (src); } // TODO: what if UJMP? if (INSOP(0).type == X86_OP_IMM) { op->jump = INSOP(0).imm; op->type = R_ANAL_OP_TYPE_JMP; if (a->decode) { ut64 dst = INSOP(0).imm; esilprintf (op, "0x%"PFMT64x",%s,=", dst, pc); } } else { op->type = R_ANAL_OP_TYPE_UJMP; } break; case X86_INS_IN: case X86_INS_INSW: case X86_INS_INSD: case X86_INS_INSB: case X86_INS_OUT: case X86_INS_OUTSB: case X86_INS_OUTSD: case X86_INS_OUTSW: op->type = R_ANAL_OP_TYPE_IO; break; case X86_INS_VXORPD: case X86_INS_VXORPS: case X86_INS_VPXORD: case X86_INS_VPXORQ: case X86_INS_VPXOR: case X86_INS_KXORW: case X86_INS_PXOR: case X86_INS_XOR: op->type = R_ANAL_OP_TYPE_XOR; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,^=", src, dst); free (src); free (dst); } break; case X86_INS_OR: op->type = R_ANAL_OP_TYPE_OR; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,|=", src, dst); free (src); free (dst); } break; case X86_INS_SUB: case X86_INS_DEC: case X86_INS_PSUBB: case X86_INS_PSUBW: case X86_INS_PSUBD: case X86_INS_PSUBQ: case X86_INS_PSUBSB: case X86_INS_PSUBSW: case X86_INS_PSUBUSB: case X86_INS_PSUBUSW: op->type = R_ANAL_OP_TYPE_SUB; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,-=,%%c,cf,=,%%z,zf,=,%%s,sf,=,%%o,of,=", src, dst); // TODO: update flags free (src); free (dst); } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = INSOP(1).imm; } } break; case X86_INS_AND: case X86_INS_ANDN: case X86_INS_ANDPD: case X86_INS_ANDPS: case X86_INS_ANDNPD: case X86_INS_ANDNPS: op->type = R_ANAL_OP_TYPE_AND; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,&=", src, dst); free (src); free (dst); } break; case X86_INS_DIV: op->type = R_ANAL_OP_TYPE_DIV; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,/=", src, dst); free (src); free (dst); } break; case X86_INS_MUL: op->type = R_ANAL_OP_TYPE_MUL; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,*=", src, dst); free (src); free (dst); } break; case X86_INS_INC: op->type = R_ANAL_OP_TYPE_ADD; if (a->decode) { char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "1,%s,+=", dst); free (dst); } break; case X86_INS_ADD: case X86_INS_FADD: case X86_INS_ADDPD: op->type = R_ANAL_OP_TYPE_ADD; if (a->decode) { char *src = getarg (handle, insn, 1, 0); char *dst = getarg (handle, insn, 0, 0); esilprintf (op, "%s,%s,+=", src, dst); free (src); free (dst); } if (INSOP(0).type == X86_OP_REG && INSOP(1).type == X86_OP_IMM) { if (INSOP(0).reg == X86_REG_RSP || INSOP(0).reg == X86_REG_ESP) { op->stackop = R_ANAL_STACK_INC; op->stackptr = -INSOP(1).imm; } } break; } } #if !USE_ITER_API cs_free (insn, n); #endif cs_close (&handle); return op->size; }
static void test_valids() { struct valid_instructions valids[] = {{ CS_ARCH_ARM, CS_MODE_THUMB, "Thumb", 3, {{ (unsigned char *)"\x00\xf0\x26\xe8", 4, 0x352, "0x352:\tblx\t#0x3a0\n" "\top_count: 1\n" "\t\toperands[0].type: IMM = 0x3a0\n", "thumb2 blx with misaligned immediate" }, { (unsigned char *)"\x05\xdd", 2, 0x1f0, "0x1f0:\tble\t#0x1fe\n" "\top_count: 1\n" "\t\toperands[0].type: IMM = 0x1fe\n" "\tCode condition: 14\n", "thumb b cc with thumb-aligned target" }, { (unsigned char *)"\xbd\xe8\xf0\x8f", 4, 0, "0x0:\tpop.w\t{r4, r5, r6, r7, r8, r9, r10, r11, pc}\n" "\top_count: 9\n" "\t\toperands[0].type: REG = r4\n" "\t\toperands[1].type: REG = r5\n" "\t\toperands[2].type: REG = r6\n" "\t\toperands[3].type: REG = r7\n" "\t\toperands[4].type: REG = r8\n" "\t\toperands[5].type: REG = r9\n" "\t\toperands[6].type: REG = r10\n" "\t\toperands[7].type: REG = r11\n" "\t\toperands[8].type: REG = pc\n", "thumb2 pop that should be valid" }, } }}; struct valid_instructions * valid = NULL; uint64_t address = 0x1000; cs_insn *insn; int i; int j; size_t count; for (i = 0; i < sizeof(valids)/sizeof(valids[0]); i++) { cs_err err; valid = valids + i; err = cs_open(valid->arch, valid->mode, &handle); if (err) { printf("Failed on cs_open() with error returned: %u\n", err); continue; } cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_NOREGNAME); #define _this_printf(...) \ { \ size_t used = 0; \ used = snprintf(tmp_buf + cur, left, __VA_ARGS__); \ left -= used; \ cur += used; \ } printf("\nShould be valid\n" "---------------\n"); for (j = 0; j < valid->num_valid_codes; ++j) { char tmp_buf[2048]; size_t left = 2048; size_t cur = 0; size_t used = 0; int success = 0; char * hex_str = NULL; struct valid_code * valid_code = NULL; valid_code = valid->valid_codes + j; hex_str = hex_string(valid_code->code, valid_code->size); printf("%s %s @ 0x%04x: %s\n %s", valid->platform_comment, hex_str, valid_code->start_addr, valid_code->comment, valid_code->expected_out); count = cs_disasm(handle, valid_code->code, valid_code->size, valid_code->start_addr, 0, &insn ); if (count) { size_t k; size_t max_len = 0; size_t tmp_len = 0; for (k = 0; k < count; k++) { _this_printf( "0x%"PRIx64":\t%s\t%s\n", insn[k].address, insn[k].mnemonic, insn[k].op_str ); snprint_insn_detail(tmp_buf, &cur, &left, &insn[k]); } max_len = strlen(tmp_buf); tmp_len = strlen(valid_code->expected_out); if (tmp_len > max_len) { max_len = tmp_len; } if (memcmp(tmp_buf, valid_code->expected_out, max_len)) { printf( " ERROR: '''\n%s''' does not match" " expected '''\n%s'''\n", tmp_buf, valid_code->expected_out ); } else { printf(" SUCCESS: valid\n"); } cs_free(insn, count); } else { printf("ERROR: invalid\n"); } } cs_close(&handle); } #undef _this_prinf }
static void test() { //#define ARM_CODE "\x04\xe0\x2d\xe5" // str lr, [sp, #-0x4]! //#define ARM_CODE "\xe0\x83\x22\xe5" // str r8, [r2, #-0x3e0]! //#define ARM_CODE "\xf1\x02\x03\x0e" // mcreq p0x2, #0x0, r0, c0x3, c0x1, #0x7 //#define ARM_CODE "\x00\x00\xa0\xe3" // mov r0, #0x0 //#define ARM_CODE "\x02\x30\xc1\xe7" // strb r3, [r1, r2] //#define ARM_CODE "\x00\x00\x53\xe3" // cmp r3, #0x0 //#define ARM_CODE "\x02\x00\xa1\xe2" // adc r0, r1, r2 //#define ARM_CODE "\x21\x01\xa0\xe0" // adc r0, r0, r1, lsr #2 //#define ARM_CODE "\x21\x01\xb0\xe0" // adcs r0, r0, r1, lsr #2 //#define ARM_CODE "\x32\x03\xa1\xe0" // adc r0, r1, r2, lsr r3 //#define ARM_CODE "\x22\x01\xa1\xe0" // adc r0, r1, r2, lsr #2 //#define ARM_CODE "\x65\x61\x4f\x50" // subpl r6, pc, r5, ror #2 //#define ARM_CODE "\x30\x30\x53\xe5" // ldrb r3, [r3, #-0x30] //#define ARM_CODE "\xb6\x10\xdf\xe1" // ldrh r1, [pc, #0x6] //#define ARM_CODE "\x02\x00\x9f\xef" // svc #0x9f0002 //#define ARM_CODE "\x00\xc0\x27\xea" // b 0x9F0002: FIXME: disasm as "b #0x9f0000" //#define ARM_CODE "\x12\x13\xa0\xe1" // lsl r1, r2, r3 //#define ARM_CODE "\x82\x11\xa0\xe1" // lsl r1, r2, #0x3 //#define ARM_CODE "\x00\xc0\xa0\xe1" // mov ip, r0 //#define ARM_CODE "\x02\x00\x12\xe3" // tst r2, #2 //#define ARM_CODE "\x51\x12\xa0\xe1" // asr r1, r2 //#define ARM_CODE "\x72\x10\xef\xe6" // uxtb r1, r2 //#define ARM_CODE "\xe0\x0a\xb7\xee" // vcvt.f64.f32 d0, s1 //#define ARM_CODE "\x9f\x0f\x91\xe1" // ldrex r0, [r1] //#define ARM_CODE "\x0f\x06\x20\xf4" // vld1.8 {d0, d1, d2}, [r0] //#define ARM_CODE "\x72\x00\xa1\xe6" // sxtab r0, r1, r2 //#define ARM_CODE "\x50\x06\x84\xf2" // vmov.i32 q0, #0x40000000 //#define ARM_CODE "\x73\xe0\xb8\xee" // mrc p0, #5, lr, c8, c3, #3 //#define ARM_CODE "\x12\x02\x81\xe6" // pkhbt r0, r1, r2, lsl #0x4 //#define ARM_CODE "\x12\x00\xa0\xe6" // ssat r0, #0x1, r2 //#define ARM_CODE "\x03\x60\x2d\xe9" // push {r0, r1, sp, lr} //#define ARM_CODE "\x8f\x40\x60\xf4" // vld4.32 {d20, d21, d22, d23}, [r0] //#define ARM_CODE "\xd0\x00\xc2\xe1" // ldrd r0, r1, [r2] //#define ARM_CODE "\x08\xf0\xd0\xf5" // pld [r0, #0x8] //#define ARM_CODE "\x10\x8b\xbc\xec" // ldc p11, c8, [r12], #64 //#define ARM_CODE "\xd4\x30\xd2\xe1" // ldrsb r3, [r2, #0x4] //#define ARM_CODE "\x11\x0f\xbe\xf2" // vcvt.s32.f32 d0, d1, #2 //#define ARM_CODE "\x01\x01\x70\xe1" // cmn r0, r1, lsl #2 //#define ARM_CODE "\x06\x00\x91\xe2" // adds r0, r1, #6 //#define ARM_CODE "\x5b\xf0\x7f\xf5" // dmb ish //#define ARM_CODE "\xf7\xff\xff\xfe" //#define ARM_CODE "\x00\x20\xbd\xe8" // ldm sp!, {sp} //#define ARM_CODE "\x00\xa0\xbd\xe8" // pop {sp, pc} //#define ARM_CODE "\x90\x04\x0E\x00" // muleq lr, r0, r4 //#define ARM_CODE "\x90\x24\x0E\x00" // muleq lr, r0, r4 //#define ARM_CODE "\xb6\x10\x5f\xe1" // ldrh r1, [pc, #-6] #define ARM_CODE "\xED\xFF\xFF\xEB\x04\xe0\x2d\xe5\x00\x00\x00\x00\xe0\x83\x22\xe5\xf1\x02\x03\x0e\x00\x00\xa0\xe3\x02\x30\xc1\xe7\x00\x00\x53\xe3\x00\x02\x01\xf1\x05\x40\xd0\xe8\xf4\x80\x00\x00" //#define ARM_CODE2 "\xf0\x24" //#define ARM_CODE2 "\x83\xb0" #define ARM_CODE2 "\xd1\xe8\x00\xf0\xf0\x24\x04\x07\x1f\x3c\xf2\xc0\x00\x00\x4f\xf0\x00\x01\x46\x6c" //#define THUMB_CODE "\x70\x47" // bl 0x26 //#define THUMB_CODE "\x07\xdd" // ble 0x1c //#define THUMB_CODE "\x00\x47" // bx r0 //#define THUMB_CODE "\x01\x47" // bx r0 //#define THUMB_CODE "\x02\x47" // bx r0 //#define THUMB_CODE "\x0a\xbf" // itet eq #define THUMB_CODE "\x70\x47\x00\xf0\x10\xe8\xeb\x46\x83\xb0\xc9\x68\x1f\xb1\x30\xbf\xaf\xf3\x20\x84" #define THUMB_CODE2 "\x4f\xf0\x00\x01\xbd\xe8\x00\x88\xd1\xe8\x00\xf0\x18\xbf\xad\xbf\xf3\xff\x0b\x0c\x86\xf3\x00\x89\x80\xf3\x00\x8c\x4f\xfa\x99\xf6\xd0\xff\xa2\x01" #define THUMB_MCLASS "\xef\xf3\x02\x80" #define ARMV8 "\xe0\x3b\xb2\xee\x42\x00\x01\xe1\x51\xf0\x7f\xf5" struct platform platforms[] = { { CS_ARCH_ARM, CS_MODE_ARM, (unsigned char *)ARM_CODE, sizeof(ARM_CODE) - 1, "ARM" }, { CS_ARCH_ARM, CS_MODE_THUMB, (unsigned char *)THUMB_CODE, sizeof(THUMB_CODE) - 1, "Thumb" }, { CS_ARCH_ARM, CS_MODE_THUMB, (unsigned char *)ARM_CODE2, sizeof(ARM_CODE2) - 1, "Thumb-mixed" }, { CS_ARCH_ARM, CS_MODE_THUMB, (unsigned char *)THUMB_CODE2, sizeof(THUMB_CODE2) - 1, "Thumb-2 & register named with numbers", CS_OPT_SYNTAX_NOREGNAME }, { CS_ARCH_ARM, (cs_mode)(CS_MODE_THUMB + CS_MODE_MCLASS), (unsigned char*)THUMB_MCLASS, sizeof(THUMB_MCLASS) - 1, "Thumb-MClass" }, { CS_ARCH_ARM, (cs_mode)(CS_MODE_ARM + CS_MODE_V8), (unsigned char*)ARMV8, sizeof(ARMV8) - 1, "Arm-V8" }, }; uint64_t address = 0x80001000; cs_insn *insn; int i; size_t count; for (i = 0; i < sizeof(platforms)/sizeof(platforms[0]); i++) { cs_err err = cs_open(platforms[i].arch, platforms[i].mode, &handle); if (err) { printf("Failed on cs_open() with error returned: %u\n", err); continue; } cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON); if (platforms[i].syntax) cs_option(handle, CS_OPT_SYNTAX, platforms[i].syntax); count = cs_disasm(handle, platforms[i].code, platforms[i].size, address, 0, &insn); if (count) { size_t j; printf("****************\n"); printf("Platform: %s\n", platforms[i].comment); print_string_hex("Code:", platforms[i].code, platforms[i].size); printf("Disasm:\n"); for (j = 0; j < count; j++) { printf("0x%" PRIx64 ":\t%s\t%s\n", insn[j].address, insn[j].mnemonic, insn[j].op_str); print_insn_detail(&insn[j]); } printf("0x%" PRIx64 ":\n", insn[j-1].address + insn[j-1].size); // free memory allocated by cs_disasm() cs_free(insn, count); } else { printf("****************\n"); printf("Platform: %s\n", platforms[i].comment); print_string_hex("Code:", platforms[i].code, platforms[i].size); printf("ERROR: Failed to disasm given code!\n"); } printf("\n"); cs_close(&handle); } }