Exemplo n.º 1
0
    def _vmov(self, cdg, insn, data_size):
        """
        Templated handler for dword/qword mov instructions.
        """

        # op form: xmm1, rXX/mXX
        if is_xmm_reg(insn.Op1):

            # op2 -- m32/m64
            if is_mem_op(insn.Op2):
                l_reg = cdg.load_operand(1)

            # op2 -- r32/r64
            else:
                l_reg = ida_hexrays.reg2mreg(insn.Op2.reg)

            # wrap the source micro-reg as a micro-operand of the specified size
            l_mop = ida_hexrays.mop_t(l_reg, data_size)

            # op1 -- xmm1
            d_reg = ida_hexrays.reg2mreg(insn.Op1.reg)
            d_mop = ida_hexrays.mop_t(d_reg, XMM_SIZE)

            # emit the microcode for this insn
            cdg.emit(ida_hexrays.m_xdu, l_mop, NO_MOP, d_mop)

            # clear upper 128 bits of ymm1
            clear_upper(cdg, d_reg)

            return ida_hexrays.MERR_OK

        # op form: rXX/mXX, xmm1
        else:
            assert is_xmm_reg(insn.Op2)

            # op2 -- xmm1
            l_reg = ida_hexrays.reg2mreg(insn.Op2.reg)
            l_mop = ida_hexrays.mop_t(l_reg, data_size)

            # op1 -- m32/m64
            if is_mem_op(insn.Op1):
                cdg.store_operand(0, l_mop)

            # op1 -- r32/r64
            else:
                d_reg = ida_hexrays.reg2mreg(insn.Op1.reg)
                d_mop = ida_hexrays.mop_t(d_reg, data_size)
                cdg.emit(ida_hexrays.m_mov, l_mop, NO_MOP, d_mop)

                #
                # TODO: the intel manual doesn't make it entierly clear here
                # if the upper bits of a r32 operation need to be cleared ?
                #

            return ida_hexrays.MERR_OK

        # failsafe
        assert "Unreachable..."
        return ida_hexrays.MERR_INSN
Exemplo n.º 2
0
def clear_upper(cdg, xmm_mreg, op_size=XMM_SIZE):
    """
    Extend the given xmm reg, clearing the upper bits (through ymm).
    """
    ymm_mreg = get_ymm_mreg(xmm_mreg)

    xmm_mop = ida_hexrays.mop_t(xmm_mreg, op_size)
    ymm_mop = ida_hexrays.mop_t(ymm_mreg, YMM_SIZE)

    return cdg.emit(ida_hexrays.m_xdu, xmm_mop, NO_MOP, ymm_mop)
Exemplo n.º 3
0
    def v_bitwise_ps(self, cdg, insn):
        """
        VORPS xmm1, xmm2, xmm3/m128
        VORPS ymm1, ymm2, ymm3/m256

        VXORPS xmm1, xmm2, xmm3/m128
        VXORPS ymm1, ymm2, ymm3/m256

        VANDPS xmm1, xmm2, xmm3/m128
        VANDPS ymm1, ymm2, ymm3/m256
        """
        assert is_avx_reg(insn.Op1) and is_avx_reg(insn.Op2)
        op_size = XMM_SIZE if is_xmm_reg(insn.Op1) else YMM_SIZE

        # op3 -- m128/m256
        if is_mem_op(insn.Op3):
            r_reg = cdg.load_operand(2)

        # op3 -- xmm3/ymm3
        else:
            assert is_avx_reg(insn.Op3)
            r_reg = ida_hexrays.reg2mreg(insn.Op3.reg)

        itype2mcode = \
        {
            ida_allins.NN_vorps: ida_hexrays.m_or,
            ida_allins.NN_vandps: ida_hexrays.m_and,
            ida_allins.NN_vxorps: ida_hexrays.m_xor,
        }

        # get the hexrays microcode op to use for this instruction
        mcode_op = itype2mcode[insn.itype]

        # wrap the source micro-reg as a micro-operand
        r_mop = ida_hexrays.mop_t(r_reg, op_size)

        # op2 -- xmm2/ymm2
        l_reg = ida_hexrays.reg2mreg(insn.Op2.reg)
        l_mop = ida_hexrays.mop_t(l_reg, op_size)

        # op1 -- xmm1/ymm1
        d_reg = ida_hexrays.reg2mreg(insn.Op1.reg)
        d_mop = ida_hexrays.mop_t(d_reg, op_size)

        # emit the microcode for this insn
        cdg.emit(mcode_op, l_mop, r_mop, d_mop)

        # clear upper 128 bits of ymm1
        if op_size == XMM_SIZE:
            clear_upper(cdg, d_reg)

        return ida_hexrays.MERR_OK
Exemplo n.º 4
0
    def vcvtsi2ss(self, cdg, insn):
        """
        VCVTSI2SS xmm1, xmm2, r/m32
        VCVTSI2SS xmm1, xmm2, r/m64
        """
        src_size = size_of_operand(insn.Op3)

        # op3 -- m32/m64
        if is_mem_op(insn.Op3):
            r_reg = cdg.load_operand(2)

        # op3 -- r32/r64
        else:
            assert is_reg_op(insn.Op3)
            r_reg = ida_hexrays.reg2mreg(insn.Op3.reg)

        # op2 -- xmm2
        l_reg = ida_hexrays.reg2mreg(insn.Op2.reg)

        # op1 -- xmm1
        d_reg = ida_hexrays.reg2mreg(insn.Op1.reg)

        # create a temp register to compute the final result into
        t0_result = cdg.mba.alloc_kreg(XMM_SIZE)
        t0_mop = ida_hexrays.mop_t(t0_result, FLOAT_SIZE)

        # create a temp register to downcast a double to a float (if needed)
        t1_i2f = cdg.mba.alloc_kreg(src_size)
        t1_mop = ida_hexrays.mop_t(t1_i2f, src_size)

        # copy xmm2 into the temp result reg, as we need its upper 3 dwords
        cdg.emit(ida_hexrays.m_mov, XMM_SIZE, l_reg, 0, t0_result, 0)

        # convert the integer (op3) to a float/double depending on its size
        cdg.emit(ida_hexrays.m_i2f, src_size, r_reg, 0, t1_i2f, 0)

        # reduce precision on the converted floating point value if needed (only r64/m64)
        cdg.emit(ida_hexrays.m_f2f, t1_mop, NO_MOP, t0_mop)

        # transfer the fully computed temp register to the real dest reg
        cdg.emit(ida_hexrays.m_mov, XMM_SIZE, t0_result, 0, d_reg, 0)
        cdg.mba.free_kreg(t0_result, XMM_SIZE)
        cdg.mba.free_kreg(t1_i2f, src_size)

        # clear upper 128 bits of ymm1
        clear_upper(cdg, d_reg)

        return ida_hexrays.MERR_OK
Exemplo n.º 5
0
    def v_math_ps(self, cdg, insn):
        """
        VADDPS    xmm1, xmm2, xmm3/m128
        VADDPS    ymm1, ymm2, ymm3/m256

        VSUBPS    xmm1, xmm2, xmm3/m128
        VSUBPS    ymm1, ymm2, ymm3/m256

        VMULPS    xmm1, xmm2, xmm3/m128
        VMULPS    ymm1, ymm2, ymm3/m256

        VDIVPS    xmm1, xmm2, xmm3/m128
        VDIVPS    ymm1, ymm2, ymm3/m256
        """
        assert is_avx_reg(insn.Op1) and is_avx_reg(insn.Op2)
        op_size = XMM_SIZE if is_xmm_reg(insn.Op1) else YMM_SIZE

        # op3 -- m128/m256
        if is_mem_op(insn.Op3):
            r_reg = cdg.load_operand(2)

        # op3 -- xmm3/ymm3
        else:
            assert is_avx_reg(insn.Op3)
            r_reg = ida_hexrays.reg2mreg(insn.Op3.reg)

        # op2 -- xmm2/ymm2
        l_reg = ida_hexrays.reg2mreg(insn.Op2.reg)

        # op1 -- xmm1/ymm1
        d_reg = ida_hexrays.reg2mreg(insn.Op1.reg)
        d_mop = ida_hexrays.mop_t(d_reg, op_size)

        itype2name = \
        {
            ida_allins.NN_vaddps: "_mm%u_add_ps",
            ida_allins.NN_vsubps: "_mm%u_sub_ps",
            ida_allins.NN_vmulps: "_mm%u_mul_ps",
            ida_allins.NN_vdivps: "_mm%u_div_ps",
        }

        # create the intrinsic
        bit_size = bytes2bits(op_size)
        bit_str = "256" if op_size == YMM_SIZE else ""
        intrinsic_name = itype2name[insn.itype] % bytes2bits(op_size)

        avx_intrinsic = AVXIntrinsic(cdg, intrinsic_name)
        avx_intrinsic.add_argument_reg(l_reg, "__m%u" % bit_size)
        avx_intrinsic.add_argument_reg(r_reg, "__m%u" % bit_size)
        avx_intrinsic.set_return_reg(d_reg, "__m%u" % bit_size)
        avx_intrinsic.emit()

        # clear upper 128 bits of ymm1
        if op_size == XMM_SIZE:
            clear_upper(cdg, d_reg)

        return ida_hexrays.MERR_OK
Exemplo n.º 6
0
    def visit_subcall(self,ins):
        callins=ins.l.d
        if(callins.l.t==0x6 and callins.l.g in objcrt_list):
            if(callins.d.f==None):
                return 0
            else: 
                ins.l=ida_hexrays.mop_t(callins.d.f.args[0])
                return 1

        return 0
Exemplo n.º 7
0
    def vcvtss2sd(self, cdg, insn):
        """
        VCVTSS2SD xmm1, xmm2, r/m32
        """

        # op3 -- m32
        if is_mem_op(insn.Op3):
            r_reg = cdg.load_operand(2)

        # op3 -- r32
        else:
            assert is_reg_op(insn.Op3)
            r_reg = ida_hexrays.reg2mreg(insn.Op3.reg)

        r_mop = ida_hexrays.mop_t(r_reg, FLOAT_SIZE)

        # op2 -- xmm2
        l_reg = ida_hexrays.reg2mreg(insn.Op2.reg)

        # op1 -- xmm1
        d_reg = ida_hexrays.reg2mreg(insn.Op1.reg)

        # create a temp register to compute the final result into
        t0_result = cdg.mba.alloc_kreg(XMM_SIZE)
        t0_mop = ida_hexrays.mop_t(t0_result, DOUBLE_SIZE)

        # copy xmm2 into the temp result reg, as we need its upper quadword
        cdg.emit(ida_hexrays.m_mov, XMM_SIZE, l_reg, 0, t0_result, 0)

        # convert float (op3) to a double, storing it in the lower 64 of the temp result reg
        cdg.emit(ida_hexrays.m_f2f, r_mop, NO_MOP, t0_mop)

        # transfer the fully computed temp register to the real dest reg
        cdg.emit(ida_hexrays.m_mov, XMM_SIZE, t0_result, 0, d_reg, 0)
        cdg.mba.free_kreg(t0_result, XMM_SIZE)

        # clear upper 128 bits of ymm1
        clear_upper(cdg, d_reg)

        return ida_hexrays.MERR_OK
Exemplo n.º 8
0
    def visit_minsn(self):  # for each instruction...
        ins = self.curins  # take a reference to the current instruction

        # THE CORE OF THE PLUGIN IS HERE:
        # check the pattern "x | ~x"
        if ins.opcode == ida_hexrays.m_or and ins.r.is_insn(
                ida_hexrays.m_bnot) and ins.l == ins.r.d.l:
            if not ins.l.has_side_effects():  # avoid destroying side effects
                # pattern matched, convert to "mov -1, ..."
                ins.opcode = ida_hexrays.m_mov
                ins.l.make_number(-1, ins.r.size)
                ins.r = ida_hexrays.mop_t()
                self.cnt = self.cnt + 1  # number of changes we made
        return 0  # continue traversal
Exemplo n.º 9
0
    def add_argument_imm(self, value, basic_type):
        """
        Add an immediate value to the function argument list.
        """
        op_tinfo = ida_typeinf.tinfo_t(basic_type)

        mop_imm = ida_hexrays.mop_t()
        mop_imm.make_number(value, op_tinfo.get_size())

        call_arg = ida_hexrays.mcallarg_t()
        call_arg.make_number(value, op_tinfo.get_size())
        call_arg.type = op_tinfo

        self.call_info.args.push_back(call_arg)
        self.call_info.solid_args += 1
Exemplo n.º 10
0
    def v_mov_ps_dq(self, cdg, insn):
        """
        VMOVAPS xmm1, xmm2/m128
        VMOVAPS ymm1, ymm2/m256
        VMOVAPS xmm2/m128, xmm1
        VMOVAPS ymm2/m256, ymm1

        VMOVUPS xmm1, xmm2/m128
        VMOVUPS ymm1, ymm2/m256
        VMOVUPS xmm2/m128, xmm1
        VMOVUPS ymm2/m256, ymm1

        VMOVDQA xmm1, xmm2/m128
        VMOVDQA xmm2/m128, xmm1
        VMOVDQA ymm1, ymm2/m256
        VMOVDQA ymm2/m256, ymm1

        VMOVDQU xmm1, xmm2/m128
        VMOVDQU xmm2/m128, xmm1
        VMOVDQU ymm1, ymm2/m256
        VMOVDQU ymm2/m256, ymm1
        """

        # op form: reg, [mem]
        if is_avx_reg(insn.Op1):
            op_size = XMM_SIZE if is_xmm_reg(insn.Op1) else YMM_SIZE

            # op2 -- m128/m256
            if is_mem_op(insn.Op2):
                l_reg = cdg.load_operand(1)

            # op2 -- xmm1/ymm1
            else:
                assert is_avx_reg(insn.Op2)
                l_reg = ida_hexrays.reg2mreg(insn.Op2.reg)

            # wrap the source micro-reg as a micro-operand
            l_mop = ida_hexrays.mop_t(l_reg, op_size)

            # op1 -- xmmX/ymmX
            d_reg = ida_hexrays.reg2mreg(insn.Op1.reg)
            d_mop = ida_hexrays.mop_t(d_reg, op_size)

            # emit the microcode for this insn
            cdg.emit(ida_hexrays.m_mov, l_mop, NO_MOP, d_mop)

            # clear upper 128 bits of ymm1
            if op_size == XMM_SIZE:
                clear_upper(cdg, d_reg)

            return ida_hexrays.MERR_OK

        # op form: [mem], reg
        else:
            assert is_mem_op(insn.Op1) and is_avx_reg(insn.Op2)
            op_size = XMM_SIZE if is_xmm_reg(insn.Op2) else YMM_SIZE

            # op1 -- xmm1/ymm1
            l_reg = ida_hexrays.reg2mreg(insn.Op2.reg)
            l_mop = ida_hexrays.mop_t(l_reg, op_size)

            # [m128/m256] = xmm1/ymm1
            cdg.store_operand(0, l_mop)
            return ida_hexrays.MERR_OK

        # failsafe
        assert "Unreachable..."
        return ida_hexrays.MERR_INSN
Exemplo n.º 11
0
    def _vmov_ss_sd(self, cdg, insn, data_size):
        """
        Templated handler for scalar float/double mov instructions.
        """

        # op form: X, Y -- (2 operands)
        if insn.Op3.type == ida_ua.o_void:

            # op form: xmm1, m32/m64
            if is_xmm_reg(insn.Op1):
                assert is_mem_op(insn.Op2)

                # op2 -- m32/m64
                l_reg = cdg.load_operand(1)
                l_mop = ida_hexrays.mop_t(l_reg, data_size)

                # op1 -- xmm1
                d_reg = ida_hexrays.reg2mreg(insn.Op1.reg)
                d_mop = ida_hexrays.mop_t(d_reg, XMM_SIZE)

                # xmm1[:data_size] = [mem]
                insn = cdg.emit(ida_hexrays.m_xdu, l_mop, NO_MOP, d_mop)

                # clear xmm1[data_size:] bits (through ymm1)
                clear_upper(cdg, d_reg, data_size)

                return ida_hexrays.MERR_OK

            # op form: m32/m64, xmm1
            else:
                assert is_mem_op(insn.Op1) and is_xmm_reg(insn.Op2)

                # op2 -- xmm1
                l_reg = ida_hexrays.reg2mreg(insn.Op2.reg)
                l_mop = ida_hexrays.mop_t(l_reg, data_size)

                # store xmm1[:data_size] into memory at [m32/m64] (op1)
                insn = cdg.store_operand(0, l_mop)
                insn.set_fpinsn()

                return ida_hexrays.MERR_OK

        # op form: xmm1, xmm2, xmm3 -- (3 operands)
        else:
            assert is_xmm_reg(insn.Op1) and is_xmm_reg(
                insn.Op2) and is_xmm_reg(insn.Op3)

            d_reg = ida_hexrays.reg2mreg(insn.Op1.reg)
            l_reg = ida_hexrays.reg2mreg(insn.Op2.reg)
            r_reg = ida_hexrays.reg2mreg(insn.Op3.reg)

            # create a temp register to compute the final result into
            t0_result = cdg.mba.alloc_kreg(XMM_SIZE)

            # emit the microcode for this insn
            cdg.emit(ida_hexrays.m_mov, XMM_SIZE, l_reg, 0, t0_result, 0)
            cdg.emit(ida_hexrays.m_f2f, data_size, r_reg, 0, t0_result, 0)
            cdg.emit(ida_hexrays.m_mov, XMM_SIZE, t0_result, 0, d_reg, 0)
            cdg.mba.free_kreg(t0_result, XMM_SIZE)

            # clear xmm1[data_size:] bits (through ymm1)
            clear_upper(cdg, d_reg, data_size)

            return ida_hexrays.MERR_OK

        # failsafe
        assert "Unreachable..."
        return ida_hexrays.MERR_INSN
Exemplo n.º 12
0
import ida_ida
import ida_idp
import ida_funcs
import ida_allins
import ida_idaapi
import ida_loader
import ida_kernwin
import ida_typeinf
import ida_hexrays

#-----------------------------------------------------------------------------
# Util
#-----------------------------------------------------------------------------

# an empty / NULL mop_t
NO_MOP = ida_hexrays.mop_t()

# EVEX-encoded instruction, intel.hpp (ida sdk)
AUX_EVEX = 0x10000

# register widths (bytes)
XMM_SIZE = 16
YMM_SIZE = 32
ZMM_SIZE = 64

# type sizes (bytes)
FLOAT_SIZE = 4
DOUBLE_SIZE = 8
DWORD_SIZE = 4
QWORD_SIZE = 8