Пример #1
0
bool MCParser::disasm2(const uint8_t **code,
                       size_t *size,
                       addr_t *address,
                       cs_insn *inst) const noexcept {
    assert(*address <= m_end_addr && "Address out of bound");
    return cs_disasm_iter(m_handle, code, size, address, inst);
}
Пример #2
0
void _DumpContext(PExecutionBlock pXblock)
{
	PCONTEXT pCtx = pXblock->pExeption->ContextRecord;

	DWORD64 csRVA = pCtx->Rip;
	const uint8_t *csLocation = (const uint8_t *)csRVA;
	_EFlags efl;

	efl.Synth = pCtx->EFlags;

	// TODO: insn needs to be thread specific
	if (csRVA && pXblock && cs_disasm_iter(pXblock->handle, &csLocation, &pXblock->csLen, &csRVA, pXblock->insn))
	{
		printf("\n%s %s   | Rip 0x%.16llx (RipFrom 0x%.16llx) EFlags 0x%.8x ", pXblock->insn->mnemonic, pXblock->insn->op_str, pCtx->Rip, pXblock->BlockFrom, pCtx->EFlags);
		_DumpEFlags(efl);
		wprintf(L"\t\t Rax 0x%.16llx, Rcx 0x%.16llx, Rdx 0x%.16llx, Rbx 0x%.16llx\n", pCtx->Rax, pCtx->Rcx, pCtx->Rdx, pCtx->Rbx);
		wprintf(L"\t\t Rsp 0x%.16llx, Rbp 0x%.16llx, Rsi 0x%.16llx, Rdi 0x%.16llx\n", pCtx->Rsp, pCtx->Rbp, pCtx->Rsi, pCtx->Rdi);
		wprintf(L"\t\t R8  0x%.16llx, R9  0x%.16llx, R10 0x%.16llx, R11 0x%.16llx\n", pCtx->R8, pCtx->R9, pCtx->R10, pCtx->R11);
		wprintf(L"\t\t R12 0x%.16llx, R13 0x%.16llx, R14 0x%.16llx, R15 0x%.16llx\n", pCtx->R12, pCtx->R13, pCtx->R14, pCtx->R15);

	}
	// just branch/single step him
	// I'm in the same thread so this isn't that bad
	//EmulateOp(ExceptionInfo);
	// capstone!!
	pXblock->csLen = 32;
}
Пример #3
0
void disasm(uint64_t addr, uint32_t offset, size_t size, cs_arch arch, cs_mode mode, uint8_t *data)
{
    int i;
    csh handle = 0;
    cs_insn *insn;
    const uint8_t *code;

    if (cs_open(arch, mode, &handle) != CS_ERR_OK) {
        printf("ERROR: Failed to initialize engine!\n");
        exit(EXIT_FAILURE);
    }

    cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
    cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT);   

    printf("Disassembly of section .text:\n");

    for (i = offset; i < offset + size; i++) {
        code = &data[i];
        insn = cs_malloc(handle);

        while(cs_disasm_iter(handle, &code, &size, &addr, insn)) {
            printf("0x%"PRIx64":\t%s\t\t%s\n", insn->address, insn->mnemonic, insn->op_str);
        }
        cs_free(insn, 1);
    }
    cs_close(&handle);
}
Пример #4
0
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
	static int omode = 0;
#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;
	int regsz = 4;

	if (handle && mode != omode) {
		cs_close (&handle);
		handle = 0;
	}
	omode = mode;
	if (handle == 0) {
		ret = cs_open (CS_ARCH_X86, mode, &handle);
		if (ret != CS_ERR_OK) {
			handle = 0;
			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:
			op->type = R_ANAL_OP_TYPE_SWI;
			op->family = R_ANAL_OP_FAMILY_PRIV;
			break;
		case X86_INS_CLC:
		case X86_INS_STC:
		case X86_INS_CLAC:
		case X86_INS_CLGI:
		case X86_INS_CLTS:
		case X86_INS_CLWB:
		case X86_INS_STAC:
		case X86_INS_STGI:
			op->type = R_ANAL_OP_TYPE_MOV;
			op->family = R_ANAL_OP_FAMILY_CPU;
			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_MOVSS:
		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_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:
		case X86_INS_LOOPE:
		case X86_INS_LOOPNE:
			op->type = R_ANAL_OP_TYPE_CJMP;
			op->jump = INSOP(0).imm;
			op->fail = addr+op->size;
			const char *cnt = (a->bits==16)?"cx":(a->bits==32)?"ecx":"rcx";
			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;
				case X86_INS_LOOP:
					esilprintf (op, "1,%s,-=,%s,?{,%s,%s,=,}", cnt, cnt, dst, pc);
					break;
				case X86_INS_LOOPE:
					esilprintf (op, "1,%s,-=,%s,?{,zf,?{,%s,%s,=,},}",
						cnt, cnt, dst, pc);
					break;
				case X86_INS_LOOPNE:
					esilprintf (op, "1,%s,-=,%s,?{,zf,!,?{,%s,%s,=,},}",
						cnt, cnt, 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:
			op->type = R_ANAL_OP_TYPE_MOV;
			op->family = R_ANAL_OP_FAMILY_CPU;
			if (a->decode)
				esilprintf (op, "0,df,=");
			break;
		case X86_INS_STD:
			op->type = R_ANAL_OP_TYPE_MOV;
			op->family = R_ANAL_OP_FAMILY_CPU;
			if (a->decode)
				esilprintf (op, "1,df,=");
			break;
		}
		switch (insn->id) {
		case X86_INS_MOVAPS: //cvtss2sd
		case X86_INS_ADDSD: //cvtss2sd
		case X86_INS_SUBSD: //cvtss2sd
		case X86_INS_MULSD: //cvtss2sd
		case X86_INS_CVTSS2SD: //cvtss2sd
		case X86_INS_MOVSS:
		case X86_INS_MOVSD:
			op->family = R_ANAL_OP_FAMILY_MMX;
			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;
}
Пример #5
0
void InitKeyFighter()
{
	// Functions to monitor
	//  What do I want to know ?  
	// * Pre or Post hook 
	// ** Post hook bring in a intra-procedure analysis to establish function exits?
	// ** Derive the exits on the fly & cache results?
	// *** Mark SP on entry when it's being adjusted on return we 
	// ** Maybe happy path is all I care about :)
	// * 
	// * Pointer to memory to log (sane limits?)
	// * dwCount of data pointer
	// 
	// What do I want to hook ?
	// * CryptGenRandom 
	// * CryptEncrypt
	// * CryptProtectData
	// * CryptProtectMemory 
	// * CPEncrypt
	// * CryptCreateHash will need to export hash with CryptGetHashParam
	// * more bleh ? need make another code generator :)??

	csh handle;
	cs_opt_skipdata skipdata = { "db", };

	cs_open(CS_ARCH_X86, CS_MODE_64, &handle);

	cs_option(handle, CS_OPT_SYNTAX, CS_OPT_SYNTAX_INTEL);
	cs_option(handle, CS_OPT_DETAIL, CS_OPT_ON);
	cs_option(handle, CS_OPT_SKIPDATA, CS_OPT_ON);
	cs_option(handle, CS_OPT_SKIPDATA_SETUP, (size_t)&skipdata);

	cs_insn *insn = cs_malloc(handle);
	size_t csLen = 16;
	DWORD64 JmpTarg = 0;

	for (int i = 0; i < HookCount; i++)
	{
		HooksConfig[i].RIP = (ULONG64)GetProcAddress(GetModuleHandleA(HooksConfig[i].Module), HooksConfig[i].Name);
#if _DEBUG
		if (HooksConfig[i].RIP == 0)
			printf("\n!!!FAILED GET PROC ADDRESS!!!\n");
#endif
		// not sure if we really care/want/need this resolve flag
		if (HooksConfig[i].Flags & FLAGS_RESOLVE)
		{
			DWORD64 csRVA = HooksConfig[i].RIP;
			const uint8_t *csLocation = (const uint8_t *)csRVA;

			// disassemble one instruction if it's an unconditional jump reset RIP to the target
			cs_disasm_iter(handle, &csLocation, &csLen, &csRVA, insn);

			cs_detail *detail = insn->detail;
			cs_x86 *x86 = &(insn->detail->x86);
			bool IsJmp = false;

			for (int g = 0; g < detail->groups_count; g++)
			{
				switch (detail->groups[g])
				{
				case CS_GRP_JUMP:
					IsJmp = true;
				}
			}
			if (IsJmp)
			{
				for (int optarg = 0; optarg < x86->op_count; optarg++)
				{
					cs_x86_op *op = &(x86->operands[optarg]);
					if ((int)op->type == X86_OP_MEM)
						JmpTarg = insn->address + insn->size + op->mem.disp;
					else if ((int)op->type == X86_OP_IMM)
						JmpTarg = op->imm;
					else
						; // JmpTarg = GetRegValue(op->reg);
				}

				HooksConfig[i].RIP = JmpTarg;
			}
		}
	}
}
Пример #6
0
static int analop(RAnal *a, RAnalOp *op, ut64 addr, const ut8 *buf, int len) {
	static int omode = 0;
#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;
	int regsz = 4;

	if (handle && mode != omode) {
		cs_close (&handle);
		handle = 0;
	}
	omode = mode;
	if (handle == 0) {
		ret = cs_open (CS_ARCH_X86, mode, &handle);
		if (ret != CS_ERR_OK) {
			handle = 0;
			return 0;
		}
	}
#if 0
	if (len>3 && !memcmp (buf, "\xff\xff\xff\xff", 4))
		return 0;
#endif
	switch (a->bits) {
	case 64: regsz = 8; break;
	case 16: regsz = 2; break;
	default: regsz = 4; break; // 32
	}
	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 = R_ANAL_OP_FAMILY_CPU; // almost everything is CPU
		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:
			op->family = R_ANAL_OP_FAMILY_FPU;
			/* fallthru */
		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:
			op->family = R_ANAL_OP_FAMILY_FPU;
			op->type = R_ANAL_OP_TYPE_STORE;
			break;
		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->family = R_ANAL_OP_FAMILY_FPU;
			op->type = R_ANAL_OP_TYPE_CMP;
			break;
		case X86_INS_FABS:
			op->type = R_ANAL_OP_TYPE_ABS;
			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:
			op->type = R_ANAL_OP_TYPE_DIV;
			op->family = R_ANAL_OP_FAMILY_FPU;
			break;
		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:
			op->type = R_ANAL_OP_TYPE_SWI;
			op->family = R_ANAL_OP_FAMILY_PRIV;
			break;
		case X86_INS_CLC:
		case X86_INS_STC:
		case X86_INS_CLAC:
		case X86_INS_CLGI:
		case X86_INS_CLTS:
#if CS_API_MAJOR >= 4
		case X86_INS_CLWB:
#endif
		case X86_INS_STAC:
		case X86_INS_STGI:
			op->type = R_ANAL_OP_TYPE_MOV;
			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_FCMOVBE:
		case X86_INS_FCMOVB:
		case X86_INS_FCMOVNBE:
		case X86_INS_FCMOVNB:
		case X86_INS_FCMOVE:
		case X86_INS_FCMOVNE:
		case X86_INS_FCMOVNU:
		case X86_INS_FCMOVU:
			op->family = R_ANAL_OP_FAMILY_FPU;
			op->type = R_ANAL_OP_TYPE_MOV;
			break;
		case X86_INS_CMOVA:
		case X86_INS_CMOVAE:
		case X86_INS_CMOVB:
		case X86_INS_CMOVBE:
		case X86_INS_CMOVE:
		case X86_INS_CMOVG:
		case X86_INS_CMOVGE:
		case X86_INS_CMOVL:
		case X86_INS_CMOVLE:
		case X86_INS_CMOVNE:
		case X86_INS_CMOVNO:
		case X86_INS_CMOVNP:
		case X86_INS_CMOVNS:
		case X86_INS_CMOVO:
		case X86_INS_CMOVP:
		case X86_INS_CMOVS:
			op->type = R_ANAL_OP_TYPE_CMOV;
			break;
		// mov
		case X86_INS_MOVSS:
		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_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->stackop = R_ANAL_STACK_SET;
					op->stackptr = regsz;
				} else {
					if (op->ptr < 0x1000)
						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,NUM,%s,NUM,"\
								"%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;
			case X86_OP_REG:
				{
				char *dst = getarg (&gop, 0, 0, NULL);
				op->dst = r_anal_value_new ();
				op->dst->reg = r_reg_get (a->reg, dst, R_REG_TYPE_GPR);
				op->src[0] = r_anal_value_new ();
				if (INSOP(1).type == X86_OP_MEM) {
					op->src[0]->delta = INSOP(1).mem.disp;
				}
				free (dst);
				}
			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_ROL:
		case X86_INS_RCL:
			// TODO: RCL Still does not work as intended
			//  - Set flags
			op->type = R_ANAL_OP_TYPE_ROL;
			if (a->decode) {
				char *src = getarg (&gop, 1, 0, NULL);
				char *dst = getarg (&gop, 0, 0, NULL);
				esilprintf (op, "%s,%s,<<<,%s,=", src, dst, dst);
				free (src);
				free (dst);
			}
			break;
		case X86_INS_ROR:
		case X86_INS_RCR:
			// TODO: RCR Still does not work as intended
			//  - Set flags
			op->type = R_ANAL_OP_TYPE_ROR;
			if (a->decode) {
				char *src = getarg (&gop, 1, 0, NULL);
				char *dst = getarg (&gop, 0, 0, NULL);
				esilprintf (op, "%s,%s,>>>,%s,=", src, dst, dst);
				free (src);
				free (dst);
			}
			break;
		case X86_INS_SHL:
		case X86_INS_SHLD:
		case X86_INS_SHLX:
			// TODO: Set CF: Carry flag is the last bit shifted out due to
			// this operation. It is undefined for SHL and SHR where the
			// number of bits shifted is greater than the size of the
			// destination.
			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,=,$p,pf,=,$s,sf,=", src, dst);
				free (src);
				free (dst);
			}
			break;
		case X86_INS_SAR:
		case X86_INS_SARX:
			// TODO: Set CF. See case X86_INS_SHL for more details.
			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,=,$p,pf,=,$s,sf,=", src, dst);
				free (src);
				free (dst);
			}
			break;
		case X86_INS_SAL:
			// TODO: Set CF: See case X86_INS_SAL for more details.
			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,=,$p,pf,=,$s,sf,=", 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:
			// TODO: Set CF: See case X86_INS_SAL for more details.
			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,=,$p,pf,=,$s,sf,=", 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:
		case X86_INS_LOOPE:
		case X86_INS_LOOPNE:
			op->type = R_ANAL_OP_TYPE_CJMP;
			op->jump = INSOP(0).imm;
			op->fail = addr+op->size;
			const char *cnt = (a->bits==16)?"cx":(a->bits==32)?"ecx":"rcx";
			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;
				case X86_INS_LOOP:
					esilprintf (op, "1,%s,-=,%s,?{,%s,%s,=,}", cnt, cnt, dst, pc);
					break;
				case X86_INS_LOOPE:
					esilprintf (op, "1,%s,-=,%s,?{,zf,?{,%s,%s,=,},}",
						cnt, cnt, dst, pc);
					break;
				case X86_INS_LOOPNE:
					esilprintf (op, "1,%s,-=,%s,?{,zf,!,?{,%s,%s,=,},}",
						cnt, cnt, 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;
				op->ptr = INSOP(0).mem.disp;
				if (INSOP(0).mem.base == X86_REG_RIP) {
					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) {
						if (a->decode) {
							esilprintf (op, "0x%"PFMT64x",[],%s,=", op->ptr, pc);
						}
					}
				}
				break;
			case X86_OP_REG:
				{
				char *src = getarg (&gop, 0, 0, NULL);
				op->src[0] = r_anal_value_new ();
				op->src[0]->reg = r_reg_get (a->reg, src, R_REG_TYPE_GPR);
				free (src);
				//XXX fallthrough
				}
			case X86_OP_FP:
			default: // other?
				op->type = R_ANAL_OP_TYPE_UJMP;
				op->ptr = UT64_MAX;
				break;
			}
			break;
		case X86_INS_IN:
		case X86_INS_INSW:
		case X86_INS_INSD:
		case X86_INS_INSB:
			op->type = R_ANAL_OP_TYPE_IO;
			op->type2 = 0;
			break;
		case X86_INS_OUT:
		case X86_INS_OUTSB:
		case X86_INS_OUTSD:
		case X86_INS_OUTSW:
			op->type = R_ANAL_OP_TYPE_IO;
			op->type2 = 1;
			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,=,$s,sf,=,0,cf,=,0,of,=",
					src, dst);
				free (src);
				free (dst);
			}
			break;
		case X86_INS_OR:
			// The OF and CF flags are cleared; the SF, ZF, and PF flags are
			// set according to the result. The state of the AF flag is
			// undefined.
			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,|=,0,of,=,0,cf,=,$s,sf,=,$z,zf,=,$p,pf,=", src, dst);
				free (src);
				free (dst);
			}
			break;
		case X86_INS_INC:
			// The CF flag is not affected. The OF, SF, ZF, AF, and PF flags
			// are set according to the result.
			op->type = R_ANAL_OP_TYPE_ADD;
			op->val = 1;
			if (a->decode) {
				char *src = getarg (&gop, 0, 0, NULL);
				if (strchr (src, '[')) {
					char *dst = r_str_replace (strdup (src), "[", "=[", 1);
					esilprintf (op, "1,%s,++,%s,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=", src, dst);
					free (dst);
				} else {
					esilprintf (op, "%s,++=,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=", src);
				}
				free (src);
			}
			break;
		case X86_INS_DEC:
			// The CF flag is not affected. The OF, SF, ZF, AF, and PF flags
			// are set according to the result.
			op->type = R_ANAL_OP_TYPE_SUB;
			op->val = 1;
			if (a->decode) {
				char *src = getarg (&gop, 0, 0, NULL);
				//esilprintf (op, "%s,--=,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=", src);
				esilprintf (op, "1,%s,[4],-,%s,=[4],$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=", src, src);
				free (src);
			}
			break;
		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", src, dst);
				free(src);
				free(dst);
			}
			break;
		case X86_INS_SUB:
			op->type = R_ANAL_OP_TYPE_SUB;
			if (a->decode) {
				char *src = getarg (&gop, 1, 0, NULL);
				char *dst = getarg (&gop, 0, 1, "-");
				// Set OF, SF, ZF, AF, PF, and CF flags.
				// We use $b rather than $c here as the carry flag really
				// represents a "borrow"
				esilprintf (op, "%s,%s,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=,$b,cf,=",
					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;
		case X86_INS_SBB:
			// dst = dst - (src + cf)
			op->type = R_ANAL_OP_TYPE_SUB;
			if (a->decode) {
				char *src = getarg (&gop, 1, 0, NULL);
				char *dst = getarg (&gop, 0, 0, NULL);
				esilprintf (op, "cf,%s,+,%s,-=,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=,$b,cf,=", src, dst);
				free (src);
				free (dst);
			}
			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, "&");
				esilprintf (op, "%s,%s,0,of,=,0,cf,=,$z,zf,=,$s,sf,=,$o,pf,=", src, dst);
				free (src);
				free (dst);
			}
			break;
		case X86_INS_IDIV:
			op->type = R_ANAL_OP_TYPE_DIV;
			if (a->decode) {
				char *a0 = getarg (&gop, 0, 0, NULL);
				char *a1 = getarg (&gop, 1, 0, NULL);
				char *a2 = getarg (&gop, 2, 0, NULL);
				// TODO update flags & handle signedness
				if (!a2 && !a1) {
					// TODO: IDIV rbx not implemented. this is just a workaround
// http://www.tptp.cc/mirrors/siyobik.info/instruction/IDIV.html
// Divides (signed) the value in the AX, DX:AX, or EDX:EAX registers (dividend) by the source operand (divisor) and stores the result in the AX (AH:AL), DX:AX, or EDX:EAX registers. The source operand can be a general-purpose register or a memory location. The action of this instruction depends on the operand size (dividend/divisor), as shown in the following table:
// IDIV RBX    ==   RDX:RAX /= RBX
					esilprintf (op, "%s,%s,/=", a0, "rax");
				} else {
					esilprintf (op, "%s,%s,/,%s,=", a2, a1, a0);
				}
				free (a0);
				free (a1);
				free (a2);
			}
			break;
		case X86_INS_DIV:
			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_IMUL:
			op->type = R_ANAL_OP_TYPE_MUL;
			if (a->decode) {
				char *a0 = getarg (&gop, 0, 0, NULL);
				char *a1 = getarg (&gop, 1, 0, NULL);
				char *a2 = getarg (&gop, 2, 0, NULL);
				if (a2) {
					// TODO update flags & handle signedness
					esilprintf (op, "%s,%s,*,%s,=", a2, a1, a0);
					free (a2);
				} else {
					if (a1) {
						esilprintf (op, "%s,%s,*=", a1, a0);
					} else {
						esilprintf (op, "%s,%s,*=", a0, "rax");
					}
				}
				free (a0);
				free (a1);
			}
			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_XCHG:
			op->type = R_ANAL_OP_TYPE_MOV;
			op->family = R_ANAL_OP_FAMILY_CPU;
			{
				char *src = getarg (&gop, 1, 0, NULL);
				char *dst = getarg (&gop, 0, 1, NULL);
				esilprintf (op, "%s,%s,%s,=,%s,=", src, dst, src, dst);
				free (src);
				free (dst);
			}
			break;
		case X86_INS_XADD: /* xchg + add */
			op->type = R_ANAL_OP_TYPE_ADD;
			op->family = R_ANAL_OP_FAMILY_CPU;
			{
				char *src = getarg (&gop, 1, 0, NULL);
				char *dst = getarg (&gop, 0, 1, NULL);
				if (src == dst) {
					esilprintf (op, "%s,%s,+,%s", src, dst, dst);
				} else {
					esilprintf (op, "%s,%s,%s,=,%s,=," "%s,%s,+,%s",
							src, dst, src, dst,
							src, dst, dst);
				}
				free (src);
				free (dst);
			}
			break;
		case X86_INS_FADD:
		case X86_INS_FADDP:
			op->family = R_ANAL_OP_FAMILY_FPU;
			/* pass thru */
		case X86_INS_ADDPS:
		case X86_INS_ADDSD:
		case X86_INS_ADDSS:
		case X86_INS_ADDSUBPD:
		case X86_INS_ADDSUBPS:
		case X86_INS_ADDPD:
			// The OF, SF, ZF, AF, CF, and PF flags are set according to the
			// result.
			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);
					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);
					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_ADD:
			// The OF, SF, ZF, AF, CF, and PF flags are set according to the
			// result.
			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);
					esilprintf (op, "%s,%s,+,%s,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=,$c,cf,=", 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,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=,$c,cf,=", 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;
		case X86_INS_ADC:
			op->type = R_ANAL_OP_TYPE_ADD;
			if (a->decode) {
				char *src = getarg (&gop, 1, 0, NULL);
				char *dst = getarg (&gop, 0, 0, NULL);
				// dst = dst + src + cf
				// NOTE: We would like to add the carry first before adding the
				// source to ensure that the flag computation from $c belongs
				// to the operation of adding dst += src rather than the one
				// that adds carry (as esil only keeps track of the last
				// addition to set the flags).
				esilprintf (op, "cf,%s,+,%s,+=,$o,of,=,$s,sf,=,$z,zf,=,$p,pf,=,$c,cf,=", src, dst);
				free (src);
				free (dst);
			}
				break;
			/* Direction flag */
		case X86_INS_CLD:
			op->type = R_ANAL_OP_TYPE_MOV;
			if (a->decode)
				esilprintf (op, "0,df,=");
			break;
		case X86_INS_STD:
			op->type = R_ANAL_OP_TYPE_MOV;
			if (a->decode)
				esilprintf (op, "1,df,=");
			break;
		}
		switch (insn->id) {
		case X86_INS_MOVAPS: //cvtss2sd
		case X86_INS_ADDSD: //cvtss2sd
		case X86_INS_SUBSD: //cvtss2sd
		case X86_INS_MULSD: //cvtss2sd
		case X86_INS_CVTSS2SD: //cvtss2sd
		case X86_INS_MOVSS:
		case X86_INS_MOVSD:
			op->family = R_ANAL_OP_FAMILY_MMX;
			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;
}
Пример #7
0
static void test()
{
#ifdef CAPSTONE_HAS_X86
#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_CODE64 "\x55\x48\x8b\x05\xb8\x13\x00\x00"
#endif
#ifdef CAPSTONE_HAS_ARM
#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"
#endif
#ifdef CAPSTONE_HAS_MIPS
#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_CODE2 "\x56\x34\x21\x34\xc2\x17\x01\x00"
#endif
#ifdef CAPSTONE_HAS_ARM64
#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_HAS_POWERPC
#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_HAS_SPARC
#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_HAS_SYSZ
#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_HAS_XCORE
#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
#ifdef CAPSTONE_HAS_M680X
#define M680X_CODE "\x06\x10\x19\x1a\x55\x1e\x01\x23\xe9\x31\x06\x34\x55\xa6\x81\xa7\x89\x7f\xff\xa6\x9d\x10\x00\xa7\x91\xa6\x9f\x10\x00\x11\xac\x99\x10\x00\x39"
#endif
#ifdef CAPSTONE_HAS_MOS65XX
#define MOS65XX_CODE "\x0d\x34\x12\x08\x09\xFF\x10\x80\x20\x00\x00\x98"
#endif
#define EBPF_CODE "\x97\x09\x00\x00\x37\x13\x03\x00\xdc\x02\x00\x00\x20\x00\x00\x00\x30\x00\x00\x00\x00\x00\x00\x00\xdb\x3a\x00\x01\x00\x00\x00\x00\x84\x02\x00\x00\x00\x00\x00\x00\x6d\x33\x17\x02\x00\x00\x00\x00"

#ifdef CAPSTONE_HAS_RISCV
#define RISCV_CODE32 "\x37\x34\x00\x00\x97\x82\x00\x00\xef\x00\x80\x00\xef\xf0\x1f\xff\xe7\x00\x45\x00\xe7\x00\xc0\xff\x63\x05\x41\x00\xe3\x9d\x61\xfe\x63\xca\x93\x00\x63\x53\xb5\x00\x63\x65\xd6\x00\x63\x76\xf7\x00\x03\x88\x18\x00\x03\x99\x49\x00\x03\xaa\x6a\x00\x03\xcb\x2b\x01\x03\xdc\x8c\x01\x23\x86\xad\x03\x23\x9a\xce\x03\x23\x8f\xef\x01\x93\x00\xe0\x00\x13\xa1\x01\x01\x13\xb2\x02\x7d\x13\xc3\x03\xdd\x13\xe4\xc4\x12\x13\xf5\x85\x0c\x13\x96\xe6\x01\x13\xd7\x97\x01\x13\xd8\xf8\x40\x33\x89\x49\x01\xb3\x0a\x7b\x41\x33\xac\xac\x01\xb3\x3d\xde\x01\x33\xd2\x62\x40\xb3\x43\x94\x00\x33\xe5\xc5\x00\xb3\x76\xf7\x00\xb3\x54\x39\x01\xb3\x50\x31\x00\x33\x9f\x0f\x00"
#define RISCV_CODE64 "\x13\x04\xa8\x7a"  // aaa80413
#endif


struct platform platforms[] = {
#ifdef CAPSTONE_HAS_X86
		{
			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_HAS_ARM
		{
			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"
		},
#endif
#ifdef CAPSTONE_HAS_MIPS
		{
			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)"
		},
#endif
#ifdef CAPSTONE_HAS_ARM64
		{
			CS_ARCH_ARM64,
			CS_MODE_ARM,
			(unsigned char *)ARM64_CODE,
			sizeof(ARM64_CODE) - 1,
			"ARM-64"
		},
#endif
#ifdef CAPSTONE_HAS_POWERPC
		{
			CS_ARCH_PPC,
			CS_MODE_BIG_ENDIAN,
			(unsigned char*)PPC_CODE,
			sizeof(PPC_CODE) - 1,
			"PPC-64"
		},
#endif
#ifdef CAPSTONE_HAS_SPARC
		{
			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_HAS_SYSZ
		{
			CS_ARCH_SYSZ,
			(cs_mode)0,
			(unsigned char*)SYSZ_CODE,
			sizeof(SYSZ_CODE) - 1,
			"SystemZ"
		},
#endif
#ifdef CAPSTONE_HAS_XCORE
		{
			CS_ARCH_XCORE,
			(cs_mode)0,
			(unsigned char*)XCORE_CODE,
			sizeof(XCORE_CODE) - 1,
			"XCore"
		},
#endif
#ifdef CAPSTONE_HAS_M680X
		{
			CS_ARCH_M680X,
			(cs_mode)CS_MODE_M680X_6809,
			(unsigned char*)M680X_CODE,
			sizeof(M680X_CODE) - 1,
			"M680X_6809"
		},
#endif
#ifdef CAPSTONE_HAS_MOS65XX
		{
			CS_ARCH_MOS65XX,
			(cs_mode)CS_MODE_LITTLE_ENDIAN,
			(unsigned char*)MOS65XX_CODE,
			sizeof(MOS65XX_CODE) - 1,
			"MOS65XX"
		},
#endif
#ifdef CAPSTONE_HAS_BPF
		{
			CS_ARCH_BPF,
			CS_MODE_LITTLE_ENDIAN | CS_MODE_BPF_EXTENDED,
			(unsigned char*) EBPF_CODE,
			sizeof(EBPF_CODE) - 1,
			"eBPF"
		},
#endif
#ifdef CAPSTONE_HAS_RISCV
		{
			CS_ARCH_RISCV,
			CS_MODE_RISCV32,
			(unsigned char *)RISCV_CODE32,
			sizeof(RISCV_CODE32) - 1,
			"RISCV32"
		},
		{
			CS_ARCH_RISCV,
			CS_MODE_RISCV64,
			(unsigned char *)RISCV_CODE64,
			sizeof(RISCV_CODE64) - 1,
			"RISCV64"
		},
#endif
	};

	csh handle;
	uint64_t address;
	cs_insn *insn;
	cs_detail *detail;
	int i;
	cs_err err;
	const uint8_t *code;
	size_t size;

	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);
			abort();
		}

		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);

		// allocate memory for the cache to be used by cs_disasm_iter()
		insn = cs_malloc(handle);

		print_string_hex(platforms[i].code, platforms[i].size);
		printf("Disasm:\n");

		address = 0x1000;
		code = platforms[i].code;
		size = platforms[i].size;
		while(cs_disasm_iter(handle, &code, &size, &address, insn)) {
			int n;

			printf("0x%" PRIx64 ":\t%s\t\t%s // insn-ID: %u, insn-mnem: %s\n",
					insn->address, insn->mnemonic, insn->op_str,
					insn->id, cs_insn_name(handle, insn->id));

			// print implicit registers used by this instruction
			detail = insn->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");
			}
		}

		printf("\n");

		// free memory allocated by cs_malloc()
		cs_free(insn, 1);

		cs_close(&handle);
	}
}
Пример #8
0
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_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);
	}
	op->size = 1;
#if USE_ITER_API
	{
		size_t size = len;
		if (!insn)
			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;
}
Пример #9
0
static int asm_disas(struct asm_handle *asm_handle, const uint8_t **code, size_t *size,
	struct asm_instruction *inst, bool eos)
{
	csh *handle;
	cs_insn *instruction;
	cs_arch arch;
	cs_mode mode;
	bool ret = true;
	const uint8_t *ptr_code;
	struct asm_instruction_pending *pending;
	size_t length;

	handle = &asm_handle->handle;
	pending = &asm_handle->pending;

	if (pending->size == 0) {
		ptr_code = *code;
		length = *size;
		ret = cs_disasm_iter(*handle, code, size, &inst->addr, &inst->inst);
	}
	else {
		size_t tmp;
		const uint16_t len = (*size <=  INSTRUCTION_MAX_LEN - pending->size)
			? *size :  INSTRUCTION_MAX_LEN - pending->size;
		memcpy(pending->code + pending->size, *code, len);
		pending->size += len;
		tmp = pending->size;
		ptr_code = pending->code;
		length = tmp;
		ret = cs_disasm_iter(*handle, &ptr_code, &tmp, &inst->addr, &inst->inst);
	}

	/* check disas result */
	if (!ret) {
		mode = asm_handle->mode;
		arch = asm_handle->arch;

		/* broken instruction */
		if (length < instruction_get_max_length(arch, mode) && !eos) {
			if (pending->size == 0) {
				memcpy(pending->code, *code, length);
				pending->size = length;
			}
			return NEEDMOREDATA;
		}

		/* invalid instruction */
		else {
			int skip;
			if (arch == CS_ARCH_X86) skip = 1;
			else if (arch == CS_ARCH_ARM && mode == CS_MODE_THUMB) skip = 2;
			else skip = 4;

			if (eos && length < skip) {
				skip = length;
			}

			inst->addr += skip;
			instruction = &inst->inst;
			strcpy(instruction->mnemonic, "(bad)");
			memcpy(instruction->bytes, ptr_code, skip);
			instruction->size = skip;
			instruction->op_str[0] = '\0';
			return FAIL;
		}
	}
	return SUCCESS;
}
Пример #10
0
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;
}
Пример #11
0
int32_t disas_executable_and_examine(void)
{
    int32_t rtrn;
    uint64_t file_size;
    uint32_t count = 0;
    int32_t file auto_close = 0;
    char *file_buffer = NULL;
    char *exec_path auto_free = NULL;

    /* Ask the file module for the path of the binary to test. */
    rtrn = get_exec_path(&exec_path);
    if(rtrn < 0)
    {
        output(ERROR, "Can't get exec path\n");
        return -1;
    }

    /* Open the target binary. */
    file = open(exec_path, O_RDONLY);
    if(file < 0)
    {
        output(ERROR, "open: %s\n", strerror(errno));
        return (-1);
    }

    /* Read file in to memory. */
    rtrn = map_file_in(file, &file_buffer, &file_size, READ);
    if(rtrn < 0)
    {
        output(ERROR, "Can't memory map file\n");
        return (-1);
    }

    /* Create a const pointer to the file buffer so we can avoid
    a warning when using cs_disasm_iter(). */
    const uint8_t *file_buffer_copy = (uint8_t *)file_buffer;

    /* Create capstone handle.*/
    csh handle;
    cs_open(CS_ARCH_X86, CS_MODE_32, &handle);

    /* Allocate memory cache for 1 instruction, to be used by cs_disasm_iter later. */
    cs_insn *insn = cs_malloc(handle);

    uint64_t address = 0;

    /* Disassemble one instruction at a time & store the result into the insn variable above */
    while(cs_disasm_iter(handle, (const uint8_t **)&file_buffer_copy,
                         (unsigned long *)&file_size, &address, insn))
    {
        /* Check for branchs in the disasembly, maybe switch to a hash map in the future. */
        if(strncmp(insn->mnemonic, "jne", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "je", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jg", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jle", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jl", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jge", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jo", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jno", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "js", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jns", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jz", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jb", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jnae", 4) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jc", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jnb", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jae", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jnc", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jbe", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jna", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "ja", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jnbe", 4) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jl", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jnge", 4) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jge", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jng", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jnle", 4) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jp", 2) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jpe", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jnp", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jpo", 3) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jcxz", 4) == 0)
        {
            goto found_branch;
        }
        else if(strncmp(insn->mnemonic, "jecxz", 5) == 0)
        {
            goto found_branch;
        }
        else
        {
            /* We didn't find a branch instruction so cotinue looping */
            continue;
        }

    found_branch:

        /*map->exec_ctx->address_index = realloc(map->exec_ctx->address_index, sizeof(char *) * count);
        if(map->exec_ctx->address_index == NULL)
        {
            output(ERROR, "Can't realloc address index: %s\n", strerror(errno));
            return -1;
        }

        rtrn = asprintf(&map->exec_ctx->address_index[count], "%s", insn->address);
        if(rtrn < 0)
        {
            output(ERROR, "Can't alloc address index slot: %s\n", strerror(errno));
            return -1;
        } */

        count++;

        continue;
    }

    /* Save the offset of where the program ends. */
    rtrn = set_end_offset(insn[0].address);
    if(rtrn < 0)
    {
        output(ERROR, "Can't set end offset\n");
        return -1;
    }

    cs_free(insn, 1); // release the cache memory when done
    munmap(file_buffer, (size_t)file_size);

    return 0;
}
Пример #12
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->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;
}
Пример #13
0
jump_block* init_jump_block (jump_block* to_init, unsigned int start_addr, unsigned int stop_addr)
{
	to_init->instructions = NULL;
	to_init->calls = NULL;
	to_init->conditional_jumps = NULL;
	to_init->flags = next_flags;
	next_flags = 0;
	to_init->next = NULL;

	//Locals to cut down on dereference operators; this code was a disaster the first time around with no locals
	size_t size = file_size;
	int num_instructions = 0;
	int num_calls = 0;
	int num_conditional_jumps = 0;
	unsigned long long relative_address = 0;
	unsigned int current_addr = start_addr;
	uint8_t* current = file_buf + addr_to_index (current_addr);
	unsigned int next_addr;
	cs_insn* instruction = cs_malloc (handle);

	to_init->start = start_addr;

	do
	{
		num_instructions ++;

		//Dynamic memory allocation stuff here
		if (num_instructions - 1)
		{
			if (num_instructions * sizeof (cs_insn) > to_init->instructions_buf_size)
			{
				to_init->instructions_buf_size *= 2; //Just double the buffer; I'd rather allocate too much than reallocate memory every single iteration
				to_init->instructions = (cs_insn*)realloc (to_init->instructions, to_init->instructions_buf_size);
			}
		}
		else
		{
			to_init->instructions_buf_size = 256 * sizeof (cs_insn); //My memory allocator screams at me for numbers that aren't a multiple of 8
			to_init->instructions = (cs_insn*)malloc (to_init->instructions_buf_size);
		}

		//Partially disassemble the instruction into machine readable format
		cs_disasm_iter (handle, (const uint8_t **)&current, &file_size, (uint64_t*)&relative_address, instruction);
		to_init->instructions [num_instructions-1] = *instruction;
		to_init->instructions [num_instructions-1].detail = (cs_detail*)malloc (sizeof(cs_detail));
		*(to_init->instructions [num_instructions-1].detail) = *(instruction->detail);
		current_addr = index_to_addr ((char*)current - file_buf);

		//Identify references to conditional jump blocks and function calls for later disassembly.
		if (instruction->detail->x86.op_count && instruction->detail->x86.operands [0].type > X86_OP_REG) //Please don't go chasing rax...
		{
			//Keep track of calls
			if (instruction->id == X86_INS_CALL)
			{
				num_calls ++;

				//More dynamic memory allocation stuff here
				if (num_calls - 1)
				{
					if (num_calls * sizeof (unsigned int) > to_init->calls_buf_size)
					{
						to_init->calls_buf_size *= 2;
						to_init->calls = realloc (to_init->calls, to_init->calls_buf_size);
					}
				}
				else
				{
					to_init->calls_buf_size = 8 * sizeof (unsigned int);
					to_init->calls = malloc (to_init->calls_buf_size);
				}

				//Add operand address to call buffer 
				to_init->calls [num_calls-1] = relative_insn (instruction, current_addr);
			}
		}
		//Keep track of how many times we've seen the instruction "push %ebp". One too many and we've started on the adjacent function.
		if ((instruction->id >= X86_INS_PUSH && instruction->id <= X86_INS_PUSHFQ) && (instruction->detail->x86.operands [0].reg == X86_REG_EBP || instruction->detail->x86.operands [0].reg == X86_REG_RBP))
			num_push_ebp ++;
		if (current_addr > stop_addr) //If we're outside the text section, we should be done.
			num_push_ebp = 2;
	//Stop disassembly of jump block at next unconditional jump or call
	} while (instruction->mnemonic [0] != 'j' && num_push_ebp != 2); //Jump block ends on jump or return

	//Synchronize the jump block with locals
	to_init->end = current_addr;
	to_init->num_conditional_jumps = num_conditional_jumps;
	to_init->num_calls = num_calls;
	to_init->num_instructions = num_instructions;
	if (instruction->id >= X86_INS_JAE && instruction->id <= X86_INS_JS && instruction->id != X86_INS_JMP)
	{
		if (relative_insn (instruction, current_addr) < current_addr - instruction->size)
		{
			to_init->flags |= IS_LOOP;
			next_flags |= IS_AFTER_LOOP;
		}
	}

	cs_free (instruction, 1);

	//Print jump block start address; uncomment for debugging information
	//printf ("%p\n", to_init->start);

	return to_init; //Convenient to return the to_init param so we can chain function calls like "example (init_jump_block (malloc (sizeof (jump_block)), some_addr, block))"
}