public static bool get_destination_operand(INSTRUCTION inst, ref OPERAND op) { if (inst.op1.type != OperandType.OPERAND_TYPE_NONE) { op = inst.op1; return(true); } else { return(false); } }
public static string get_instruction_string(INSTRUCTION inst, Format format, uint offset) { StringBuilder ret = new StringBuilder(); ret.Append(get_mnemonic_string(inst, format)); ret.Append(" "); ret.Append(get_operands_string(inst, format, offset)); return(ret.ToString()); }
public static string get_operands_string(INSTRUCTION inst, Format format, uint offset) { StringBuilder ret = new StringBuilder(); if (format == Format.FORMAT_ATT) { if (inst.op3.type != OperandType.OPERAND_TYPE_NONE) { ret.Append(get_operand_string(inst, inst.op3, format, offset) + ","); } if (inst.op2.type != OperandType.OPERAND_TYPE_NONE) { ret.Append(get_operand_string(inst, inst.op2, format, offset) + ","); } if (inst.op1.type != OperandType.OPERAND_TYPE_NONE) { ret.Append(get_operand_string(inst, inst.op1, format, offset)); } } else if (format == Format.FORMAT_INTEL) { if (inst.op1.type != OperandType.OPERAND_TYPE_NONE) { ret.Append(get_operand_string(inst, inst.op1, format, offset)); } if (inst.op2.type != OperandType.OPERAND_TYPE_NONE) { ret.Append("," + get_operand_string(inst, inst.op2, format, offset)); } if (inst.op3.type != OperandType.OPERAND_TYPE_NONE) { ret.Append("," + get_operand_string(inst, inst.op3, format, offset)); } } else { return(null); } return(ret.ToString()); }
public static string get_operand_string(INSTRUCTION inst, OPERAND op, Format format, uint offset) { StringBuilder ret = new StringBuilder(); Mode mode; uint regtype = 0; uint tmp = 0; if (op.type == OperandType.OPERAND_TYPE_REGISTER) { mode = MODE_CHECK_OPERAND(inst.mode, inst.flags); if (format == Format.FORMAT_ATT) { ret.Append("%%"); } switch (Macros.MASK_AM(op.flags)) { case Consts.AM_REG: if (Macros.MASK_FLAGS(op.flags) == Consts.F_r) { regtype = Consts.REG_SEGMENT; } else if (Macros.MASK_FLAGS(op.flags) == Consts.F_f) { regtype = Consts.REG_FPU; } else { regtype = Consts.REG_GEN_DWORD; } break; case Consts.AM_E: case Consts.AM_G: case Consts.AM_R: regtype = Consts.REG_GEN_DWORD; break; case Consts.AM_C: regtype = Consts.REG_CONTROL; break; case Consts.AM_D: regtype = Consts.REG_DEBUG; break; case Consts.AM_S: regtype = Consts.REG_SEGMENT; break; case Consts.AM_T: regtype = Consts.REG_TEST; break; case Consts.AM_P: case Consts.AM_Q: regtype = Consts.REG_MMX; break; case Consts.AM_V: case Consts.AM_W: regtype = Consts.REG_XMM; break; } if (regtype == Consts.REG_GEN_DWORD) { switch (Macros.MASK_OT(op.flags)) { case Consts.OT_b: ret.Append(Consts.reg_table[Consts.REG_GEN_BYTE, op.reg]); break; case Consts.OT_v: ret.Append((mode == Mode.MODE_32) ? Consts.reg_table[Consts.REG_GEN_DWORD, op.reg] : Consts.reg_table[Consts.REG_GEN_WORD, op.reg]); break; case Consts.OT_w: ret.Append(Consts.reg_table[Consts.REG_GEN_WORD, op.reg]); break; case Consts.OT_d: ret.Append(Consts.reg_table[Consts.REG_GEN_DWORD, op.reg]); break; } } else { ret.Append(Consts.reg_table[regtype, op.reg]); } } else if (op.type == OperandType.OPERAND_TYPE_MEMORY) { mode = MODE_CHECK_ADDR(inst.mode, inst.flags); if (Macros.MASK_PREFIX_G2(inst.flags) != 0) { ret.AppendFormat("{0}{1}:", (format == Format.FORMAT_ATT) ? "%" : "", Consts.reg_table[Consts.REG_SEGMENT, (Macros.MASK_PREFIX_G2(inst.flags)) - 1]); } if (format == Format.FORMAT_ATT) { if (Macros.MASK_PERMS(op.flags) == Consts.P_x) { ret.Append("*"); } if (op.dispbytes != 0) { ret.AppendFormat("0x{0:X}", op.displacement); } if ((op.basereg == Consts.REG_NOP) && (op.indexreg == Consts.REG_NOP)) { return(ret.ToString()); } } ret.Append((format == Format.FORMAT_ATT) ? "(" : "["); if (op.basereg != Consts.REG_NOP) { ret.AppendFormat("{0}{1}", (format == Format.FORMAT_ATT) ? "%" : "", (mode == Mode.MODE_32) ? Consts.reg_table[Consts.REG_GEN_DWORD, op.basereg] : Consts.reg_table[Consts.REG_GEN_WORD, op.basereg]); } if (op.indexreg != Consts.REG_NOP) { if (op.basereg != Consts.REG_NOP) { ret.AppendFormat("{0}{1}", (format == Format.FORMAT_ATT) ? ",%" : "+", (mode == Mode.MODE_32) ? Consts.reg_table[Consts.REG_GEN_DWORD, op.indexreg] : Consts.reg_table[Consts.REG_GEN_WORD, op.indexreg]); } else { ret.AppendFormat("{0}{1}", (format == Format.FORMAT_ATT) ? "%" : "", (mode == Mode.MODE_32) ? Consts.reg_table[Consts.REG_GEN_DWORD, op.indexreg] : Consts.reg_table[Consts.REG_GEN_WORD, op.indexreg]); } switch (op.scale) { case 2: ret.Append((format == Format.FORMAT_ATT) ? ",2" : "*2"); break; case 4: ret.Append((format == Format.FORMAT_ATT) ? ",4" : "*4"); break; case 8: ret.Append((format == Format.FORMAT_ATT) ? ",8" : "*8"); break; } } if (inst.dispbytes != 0 && (format != Format.FORMAT_ATT)) { if ((op.basereg != Consts.REG_NOP) || (op.indexreg != Consts.REG_NOP)) { if ((op.displacement & (1 << (int)(op.dispbytes * 8 - 1))) != 0) { tmp = op.displacement; switch (op.dispbytes) { case 1: tmp = ~tmp & 0xff; break; case 2: tmp = ~tmp & 0xffff; break; case 4: tmp = ~tmp; break; } ret.AppendFormat("-0x{0:X}", tmp + 1); } else { ret.AppendFormat("+0x{0:X}", op.displacement); } } else { ret.AppendFormat("0x{0:X}", op.displacement); } } ret.Append((format == Format.FORMAT_ATT) ? ")" : "]"); } else if (op.type == OperandType.OPERAND_TYPE_IMMEDIATE) { switch (Macros.MASK_AM(op.flags)) { case Consts.AM_J: ret.AppendFormat("0x{0:X}", op.immediate + inst.length + offset); break; case Consts.AM_I1: case Consts.AM_I: if (format == Format.FORMAT_ATT) { ret.Append("$"); } ret.AppendFormat("0x{0:X}", op.immediate); break; case Consts.AM_A: ret.AppendFormat("{0}0x{1:X}:{2}0x{2:X}", (format == Format.FORMAT_ATT) ? "$" : "", op.section, (format == Format.FORMAT_ATT) ? "$" : "", op.displacement); break; } } else { return(null); } return(ret.ToString()); }
public static uint get_instruction(out INSTRUCTION inst, byte[] dat, uint idx, Mode mode) { INST ptr = null; uint index = 0; uint flags = 0; inst = new INSTRUCTION(); get_real_instruction(dat, idx, ref index, ref flags); if (Macros.MASK_EXT(flags) == 0) { inst.opcode = dat[idx + index]; ptr = opcode_tables.inst_table1[inst.opcode]; } else if (Macros.MASK_EXT(flags) == Consts.EXT_CP) { if (dat[idx + index] < 0xc0) { index--; inst.fpuindex = dat[idx + index] - 0xd8; inst.opcode = dat[idx + index + 1]; ptr = opcode_tables.inst_table4[inst.fpuindex][Macros.MASK_MODRM_REG(inst.opcode)]; } else { inst.fpuindex = dat[idx + index - 1] - 0xd8; inst.opcode = dat[idx + index]; ptr = opcode_tables.inst_table4[inst.fpuindex][inst.opcode - 0xb8]; } } else if (Macros.MASK_EXT(flags) == Consts.EXT_T2) { inst.opcode = dat[idx + index]; get_real_instruction2(dat[idx + index], ref flags); ptr = opcode_tables.inst_table2[inst.opcode]; if (Macros.MASK_TYPE_FLAGS((uint)ptr.type) == Consts.TYPE_3) { if (Macros.MASK_PREFIX_OPERAND(flags) == 1) { ptr = opcode_tables.inst_table3_66[inst.opcode]; } else if (Macros.MASK_PREFIX_G1(flags) == 2) { ptr = opcode_tables.inst_table3_f2[inst.opcode]; } else if (Macros.MASK_PREFIX_G1(flags) == 3) { ptr = opcode_tables.inst_table3_f3[inst.opcode]; } } } if (Macros.MASK_EXT(flags) != 0 && (Macros.MASK_EXT(flags) < Consts.EXT_T2)) { inst.opcode = dat[idx + index]; inst.extindex = Macros.MASK_MODRM_REG(dat[idx + index + 1]); switch (Macros.MASK_EXT(flags)) { case Consts.EXT_GC: if (Macros.MASK_PREFIX_OPERAND(flags) == 1) { ptr = opcode_tables.inst_table_ext12_66[inst.extindex]; } else { ptr = opcode_tables.inst_table_ext12[inst.extindex]; } break; case Consts.EXT_GD: if (Macros.MASK_PREFIX_OPERAND(flags) == 1) { ptr = opcode_tables.inst_table_ext13_66[inst.extindex]; } else { ptr = opcode_tables.inst_table_ext13[inst.extindex]; } break; case Consts.EXT_GE: if (Macros.MASK_PREFIX_OPERAND(flags) == 1) { ptr = opcode_tables.inst_table_ext14_66[inst.extindex]; } else { ptr = opcode_tables.inst_table_ext14[inst.extindex]; } break; case Consts.EXT_G7: if (Macros.MASK_MODRM_MOD(dat[idx + index + 1]) == 3) { if (inst.extindex != 1) { return(0); } if (Macros.MASK_MODRM_RM(dat[idx + index + 1]) == 0) { ptr = opcode_tables.inst_monitor; index++; } else if (Macros.MASK_MODRM_RM(dat[idx + index + 1]) == 1) { ptr = opcode_tables.inst_mwait; index++; } else { return(0); } } else { ptr = opcode_tables.inst_table_ext7[inst.extindex]; } break; default: ptr = opcode_tables.inst_table_ext[(Macros.MASK_EXT(flags)) - 1][inst.extindex]; break; } } index++; if (ptr == null) { return(0); } if (ptr.mnemonic == null) { return(0); } if (ptr.modrm) { inst.modrm_offset = index; } inst.type = (InstructionType)Macros.MASK_TYPE_VALUE((uint)ptr.type); inst.eflags_affected = ptr.eflags_affected; inst.eflags_used = ptr.eflags_used; inst.ptr = ptr; if (!get_operand(ptr, ptr.flags1, inst, out inst.op1, dat, index + idx, mode, flags)) { return(0); } if (!get_operand(ptr, ptr.flags2, inst, out inst.op2, dat, index + idx, mode, flags)) { return(0); } if (!get_operand(ptr, ptr.flags3, inst, out inst.op3, dat, index + idx, mode, flags)) { return(0); } inst.iop_read = ptr.iop_read; inst.iop_written = ptr.iop_written; inst.length += index + inst.immbytes + inst.dispbytes; inst.mode = mode; inst.flags = flags; return(inst.length); }
private static bool get_operand(INST inst, uint oflags, INSTRUCTION instruction, out OPERAND op, byte[] data, uint idx, Mode mode, uint iflags) { uint index = 0; bool sib = false; uint scale = 0; uint reg = Consts.REG_NOP; uint basereg = Consts.REG_NOP; uint indexreg = Consts.REG_NOP; uint dispbytes = 0; Mode pmode; op = new OPERAND(); if (oflags == Consts.FLAGS_NONE) { op.type = OperandType.OPERAND_TYPE_NONE; return(true); } op.flags = oflags; op.reg = Consts.REG_NOP; op.basereg = Consts.REG_NOP; op.indexreg = Consts.REG_NOP; op.dispoffset = 0; op.immoffset = 0; if (inst.modrm) { pmode = MODE_CHECK_ADDR(mode, iflags); if (instruction.length == 0) { instruction.modrm = (byte)idx; instruction.length += 1; } reg = Macros.MASK_MODRM_REG(data[idx]); if (Macros.MASK_MODRM_MOD(data[idx]) == 0) { if ((pmode == Mode.MODE_32) && (Macros.MASK_MODRM_RM(data[idx]) == Consts.REG_EBP)) { dispbytes = 4; } if ((pmode == Mode.MODE_16) && (Macros.MASK_MODRM_RM(data[idx]) == Consts.REG_ESI)) { dispbytes = 2; } } else if (Macros.MASK_MODRM_MOD(data[idx]) == 1) { dispbytes = 1; } else if (Macros.MASK_MODRM_MOD(data[idx]) == 2) { dispbytes = (pmode == Mode.MODE_32) ? 4U : 2U; } if (pmode == Mode.MODE_32) { if ((Macros.MASK_MODRM_RM(data[idx]) == Consts.REG_ESP) && (Macros.MASK_MODRM_MOD(data[idx]) != 3)) { sib = true; instruction.sib = data[idx + 1]; if (instruction.length == 1) { instruction.sib = data[idx + 1]; instruction.length += 1; } basereg = Macros.MASK_SIB_BASE(data[idx + 1]); indexreg = Macros.MASK_SIB_INDEX(data[idx + 1]); scale = Macros.MASK_SIB_SCALE(data[idx + 1]) * 2; if (scale == 6) { scale += 2; } if ((basereg == Consts.REG_EBP) && Macros.MASK_MODRM_MOD(data[idx]) == 0) { basereg = Consts.REG_NOP; dispbytes = 4; } if (indexreg == Consts.REG_ESP) { indexreg = Consts.REG_NOP; } } else { if (Macros.MASK_MODRM_MOD(data[idx]) == 0 && (Macros.MASK_MODRM_RM(data[idx]) == Consts.REG_EBP)) { basereg = Consts.REG_NOP; } else { basereg = Macros.MASK_MODRM_RM(data[idx]); } } } else { switch (Macros.MASK_MODRM_RM(data[idx])) { case 0: basereg = Consts.REG_EBX; indexreg = Consts.REG_ESI; break; case 1: basereg = Consts.REG_EBX; indexreg = Consts.REG_EDI; break; case 2: basereg = Consts.REG_EBP; indexreg = Consts.REG_ESI; break; case 3: basereg = Consts.REG_EBP; indexreg = Consts.REG_EDI; break; case 4: basereg = Consts.REG_ESI; indexreg = Consts.REG_NOP; break; case 5: basereg = Consts.REG_EDI; indexreg = Consts.REG_NOP; break; case 6: if (Macros.MASK_MODRM_MOD(data[idx]) == 0) { basereg = Consts.REG_NOP; } else { basereg = Consts.REG_EBP; } indexreg = Consts.REG_NOP; break; case 7: basereg = Consts.REG_EBX; indexreg = Consts.REG_NOP; break; } if (Macros.MASK_MODRM_MOD(data[idx]) == 3) { basereg = Macros.MASK_MODRM_RM(data[idx]); indexreg = Consts.REG_NOP; } } } switch (Macros.MASK_AM(oflags)) { case Consts.AM_REG: op.type = OperandType.OPERAND_TYPE_REGISTER; op.reg = Macros.MASK_REG(oflags); break; case Consts.AM_IND: op.type = OperandType.OPERAND_TYPE_MEMORY; op.basereg = Macros.MASK_REG(oflags); break; case Consts.AM_M: if (Macros.MASK_MODRM_MOD(data[idx]) == 3) { return(false); } goto skip_rest; case Consts.AM_R: if (Macros.MASK_MODRM_MOD(data[idx]) != 3) { return(false); } goto skip_rest; case Consts.AM_Q: case Consts.AM_W: case Consts.AM_E: skip_rest: op.type = OperandType.OPERAND_TYPE_MEMORY; op.dispbytes = dispbytes; instruction.dispbytes = dispbytes; op.basereg = basereg; op.indexreg = indexreg; op.scale = scale; index = (sib) ? 1U : 0U; if (dispbytes != 0) { op.dispoffset = index + 1 + idx; } switch (dispbytes) { case 0: break; case 1: op.displacement = Macros.FETCH8(data, idx + 1 + index); if (op.displacement >= 0x80) { op.displacement |= 0xffffff00; } break; case 2: op.displacement = Macros.FETCH16(data, idx + 1 + index); break; case 4: op.displacement = Macros.FETCH32(data, idx + 1 + index); break; } if ((basereg != Consts.REG_NOP) && (Macros.MASK_MODRM_MOD(data[idx]) == 3)) { op.type = OperandType.OPERAND_TYPE_REGISTER; op.reg = basereg; } break; case Consts.AM_I1: op.type = OperandType.OPERAND_TYPE_IMMEDIATE; op.immbytes = 1; op.immediate = 1; break; case Consts.AM_J: op.type = OperandType.OPERAND_TYPE_IMMEDIATE; oflags |= Consts.F_s; goto am_i; case Consts.AM_I: am_i: op.type = OperandType.OPERAND_TYPE_IMMEDIATE; index = (inst.modrm) ? 1U : 0U; index += (sib) ? 1U : 0U; index += instruction.immbytes; index += instruction.dispbytes; op.immoffset = index + idx; mode = MODE_CHECK_OPERAND(mode, iflags); switch (Macros.MASK_OT(oflags)) { case Consts.OT_b: op.immbytes = 1; op.immediate = Macros.FETCH8(data, idx + index); if ((op.immediate >= 0x80) && (Macros.MASK_FLAGS(oflags) == Consts.F_s)) { op.immediate |= 0xffffff00; } break; case Consts.OT_v: op.immbytes = (mode == Mode.MODE_32) ? 4U : 2U; op.immediate = (mode == Mode.MODE_32) ? Macros.FETCH32(data, idx + index) : Macros.FETCH16(data, idx + index); break; case Consts.OT_w: op.immbytes = 2; op.immediate = Macros.FETCH16(data, idx + index); break; } instruction.immbytes += op.immbytes; break; case Consts.AM_A: op.type = OperandType.OPERAND_TYPE_IMMEDIATE; mode = MODE_CHECK_OPERAND(mode, iflags); op.dispbytes = (mode == Mode.MODE_32) ? 6U : 4U; op.displacement = (mode == Mode.MODE_32) ? Macros.FETCH32(data, idx) : Macros.FETCH16(data, idx); op.section = Macros.FETCH16(data, idx + op.dispbytes - 2); instruction.dispbytes = op.dispbytes; instruction.sectionbytes = 2; break; case Consts.AM_O: op.type = OperandType.OPERAND_TYPE_MEMORY; switch (Macros.MASK_OT(oflags)) { case Consts.OT_b: op.dispbytes = 1; op.displacement = Macros.FETCH8(data, idx); break; case Consts.OT_v: op.dispbytes = (mode == Mode.MODE_32) ? 4U : 2U; op.displacement = (mode == Mode.MODE_32) ? Macros.FETCH32(data, idx) : Macros.FETCH16(data, idx); break; } instruction.dispbytes = op.dispbytes; op.dispoffset = idx; break; case Consts.AM_G: op.type = OperandType.OPERAND_TYPE_REGISTER; op.reg = reg; break; case Consts.AM_C: case Consts.AM_D: case Consts.AM_S: case Consts.AM_T: case Consts.AM_P: case Consts.AM_V: op.type = OperandType.OPERAND_TYPE_REGISTER; op.reg = Macros.MASK_MODRM_REG(instruction.modrm); break; } return(true); }
public static string get_mnemonic_string(INSTRUCTION inst, Format format) { StringBuilder ret = new StringBuilder(); Mode mode; if (Macros.MASK_PREFIX_G2(inst.flags) != 0 && (inst.op1.type != OperandType.OPERAND_TYPE_MEMORY) && (inst.op2.type != OperandType.OPERAND_TYPE_MEMORY)) { if (inst.type == InstructionType.INSTRUCTION_TYPE_JMPC) { ret.Append(Consts.reg_table[Consts.REG_BRANCH, (Macros.MASK_PREFIX_G2(inst.flags)) - 1] + " "); } else { ret.Append(Consts.reg_table[Consts.REG_SEGMENT, (Macros.MASK_PREFIX_G2(inst.flags)) - 1] + " "); } } if (Macros.MASK_PREFIX_G1(inst.flags) != 0 && (Macros.MASK_EXT(inst.flags) != Consts.EXT_T2)) { ret.Append(Consts.rep_table[(Macros.MASK_PREFIX_G1(inst.flags)) - 1]); } if (((inst.type == InstructionType.INSTRUCTION_TYPE_JMPC) && (inst.opcode == 0xe3)) && (Macros.MASK_PREFIX_ADDR(inst.flags) == 1)) { ret.Append("jcxz"); } else { ret.Append(inst.ptr.mnemonic); } if (inst.type == InstructionType.INSTRUCTION_TYPE_PUSH) { if (inst.op1.type == OperandType.OPERAND_TYPE_IMMEDIATE) { switch (inst.op1.immbytes) { case 1: ret.Append((format == Format.FORMAT_ATT) ? "b" : " byte"); break; case 2: ret.Append((format == Format.FORMAT_ATT) ? "w" : " word"); break; case 4: ret.Append((format == Format.FORMAT_ATT) ? "l" : " dword"); break; } } else if (inst.op1.type == OperandType.OPERAND_TYPE_MEMORY) { mode = MODE_CHECK_OPERAND(inst.mode, inst.flags); if (mode == Mode.MODE_16) { ret.Append((format == Format.FORMAT_ATT) ? "w" : " word"); } else if (mode == Mode.MODE_32) { ret.Append((format == Format.FORMAT_ATT) ? "l" : " dword"); } } return(ret.ToString()); } if (inst.type == InstructionType.INSTRUCTION_TYPE_POP) { if (inst.op1.type == OperandType.OPERAND_TYPE_MEMORY) { mode = MODE_CHECK_OPERAND(inst.mode, inst.flags); if (mode == Mode.MODE_16) { ret.Append((format == Format.FORMAT_ATT) ? "w" : " word"); } else if (mode == Mode.MODE_32) { ret.Append((format == Format.FORMAT_ATT) ? "l" : " dword"); } } return(ret.ToString()); } if (inst.ptr.modrm && (Macros.MASK_MODRM_MOD(inst.modrm) != 3) && (Macros.MASK_AM(inst.op2.flags) == Consts.AM_I)) { switch (Macros.MASK_OT(inst.op1.flags)) { case Consts.OT_b: ret.Append((format == Format.FORMAT_ATT) ? "b" : " byte"); break; case Consts.OT_w: ret.Append((format == Format.FORMAT_ATT) ? "w" : " word"); break; case Consts.OT_d: ret.Append((format == Format.FORMAT_ATT) ? "l" : " dword"); break; case Consts.OT_v: if (((inst.mode == Mode.MODE_32) && (Macros.MASK_PREFIX_OPERAND(inst.flags) == 0)) || ((inst.mode == Mode.MODE_16) && (Macros.MASK_PREFIX_OPERAND(inst.flags) == 1))) { ret.Append((format == Format.FORMAT_ATT) ? "l" : " dword"); } else { ret.Append((format == Format.FORMAT_ATT) ? "w" : " word"); } break; } } return(ret.ToString()); }