Beispiel #1
0
def decode_instruction(address):

    # DEBUG
    #print("Decoding instruction: 0x%x" % address)

    i = DecodeInstruction(address)

    mnemonic = i.get_canon_mnem()
    ops = []

    ignore_ops = False
    if isinstance(__builtin__.REGISTERS, RegistersX64):
        # uses floating point register "st" which has
        # overlapping index with "rax" and so on
        ignore_ops = mnemonic in [
            "fabs,", "fadd", "faddp", "fbld", "fbstp", "fchs", "fclex",
            "fcmov", "fcmovb", "fcmovbe", "fcmove", "fcmovnb", "fcmovnbe",
            "fcmovne", "fcmovnu", "fcmovu", "fcom", "fcomi", "fcomip", "fcomp",
            "fcompp", "fdecstp", "fdiv", "fdivp", "fdivr", "fdivrp", "ffree",
            "fiadd", "ficom", "ficomp", "fidiv", "fidivr", "fild", "fimul",
            "fincstp", "finit", "fist", "fistp", "fisub", "fisubr", "fld,"
            "fld1", "fldcw", "fldenv", "fldenvw", "fldl2e", "fldl2t", "fldlg2",
            "fldln2", "fldpi", "fldz", "fmul", "fmulp", "fnclex", "fndisi",
            "fneni", "fninit", "fnop", "fnsave", "fnsavew", "fnstcw",
            "fnstenv", "fnstenvw", "fnstsw", "fpatan", "fprem", "fptan",
            "frndint", "frstor", "frstorw", "fsave", "fsavew", "fscale",
            "fsqrt", "fst", "fstcw", "fstenv", "fstenvw", "fstp", "fstsw",
            "fsub", "fsubp", "fsubr", "fsubrp", "ftst", "fucomi", "fucomip",
            "fwait", "fxam", "fxch", "fxtract", "fyl2x", "fyl2xp1"
        ]

    if not ignore_ops:
        for o in range(6):
            if i[o].type == o_void:
                break

            # NOTE: for x64 we only consider 64 bit granularity at the moment.
            ida_operand_str = GetOpnd(address, o)
            # Some instructions like "stosq" do not have string operands
            # => ignore for now.
            if ida_operand_str == "":
                break

            # DEBUG
            #print(ida_operand_str)

            operand = instruction.Operand(get_operand_access_type(i, o),
                                          i[o],
                                          ida_operand_str=ida_operand_str,
                                          address=address,
                                          op_num=o)

            normalized = normalize_operand(operand)
            ops.extend(normalized)

    is_control_flow = is_ret_insn(address) or \
                      len(list(CodeRefsFrom(address, 1))) > 1

    return instruction.Instruction(address, mnemonic, ops, is_control_flow)
Beispiel #2
0
class Instruction(object):
    """An instruction existing at a given address"""
    def __init__(self, ea):
        self._ea = ea
        self._insn = DecodeInstruction(ea)
        if self._insn is None:
            raise InvalidInstruction("")

    @property
    def mnemonic(self):
        return self._insn.get_canon_mnem()

    @property
    def type(self):
        return self._insn.itype

    @property
    def addr(self):
        return self._insn.ea

    @property
    def size(self):
        return self._insn.size

    @property
    def bytes(self):
        return list(GetManyBytes(self.addr, self.size))

    def iter_operands(self):
        i = 0
        for o in self._insn.Operands:
            if o.type != 0:         # 0 is a void operand, meaning it's not used in IDA
                yield Operand.from_op_t(o, self, i)
            i += 1

    @property
    def operands(self):
        return list(self.iter_operands())

    def is_branch(self):
        pass

    def is_memref(self):
        pass

    def is_stackref(self):
        pass

    def __len__(self):
        return self.size

    def __str__(self):
        inst = "{0} ".format(self.mnemonic)
        for o in self.operands[:-1]:
            inst += "{0}, ".format(str(o))
        if len(self.operands) > 0:
            inst += "{0}".format(self.operands[-1])
        return inst
Beispiel #3
0
 def disasm_single_ins(self, ea):
     result = None
     i = DecodeInstruction(ea)
     if i != None:
         flags = GetSegmentAttr(ea, SEGATTR_FLAGS)
         use_dbg = flags & SFL_DEBUG != 0
         stream = GetManyBytes(ea, i.size, use_dbg)
         result = (ea, i, GetDisasmEx(ea, GENDSM_FORCE_CODE), self.is_ret(ea), stream)
     return result
Beispiel #4
0
def get_disasm(ea, maxinstr=5):
    result = ""
    delim = "\n"

    i = 0
    while i < maxinstr:
        ins = DecodeInstruction(ea)
        if not ins:
            break

        disasm = GetDisasmEx(ea, GENDSM_FORCE_CODE)
        if not disasm:
            break
        result += disasm + delim
        ea += ins.size
        i += 1
    return result
Beispiel #5
0
 def _get_OpRands(self, ea):
     inst_t = DecodeInstruction(ea)
     return inst_t.Operands
Beispiel #6
0
    def dis(self, ea, is_child1 = False, ifrom=None):
        """Disassemble the current address and fill the nodes list.

        Args:
            ea (ea_t): Effective address.
            ifrom (node_t*): Predecessor node.
            is_child1 (bool)
        """

        node_list = self.graph.nodes
        args_queue = []
        args_queue.append((ea, is_child1, ifrom))

        while args_queue != []:
            ea, is_child1, ifrom = args_queue.pop(0)
            
            try:
                n = Node(ea, self.info, self.capstone)
            except CodeException as e:
                continue
            #except Exception as e:
            #    print("WARNING:", e)
            #    continue

            # If the node exists
            if node_list_find(node_list, n.getid()):
                if ifrom and is_child1 is not None:
                    # Link the father and the child
                    node_link(node_list_find(node_list, ifrom.getid()),
                              node_list_find(node_list, n.getid()), False,
                              is_child1)
                continue

            # Get the instruction
            try:
                inst = DecodeInstruction(ea)
            except Exception as e:
                print("WARNING:", e)
                continue

            if not inst:
                continue

            # Add the node
            node_list_add(node_list, node_copy(node_alloc(), n))

            if ifrom and is_child1 is not None:
                node_link(node_list_find(node_list, ifrom.getid()),
                          node_list_find(node_list, n.getid()), False,
                          is_child1)

            # No child
            if inst.itype in RETS:
                pass

            # 1 remote child
            elif inst.itype in JMPS:
                try:
                    op = inst.ops[0]
                except:
                    op = inst.Operands[0]
            
                try:
                    args_queue.insert(0, (op.addr, False, n))
                except Exception as e:
                    print("WARNING:", e)
                    pass

            # 2 children (next, then remote) - except call
            elif inst.itype in CJMPS:
                try:
                    op = inst.ops[0]
                except:
                    op = inst.Operands[0]
                
                # Next
                args_queue.insert(0, (inst.ea + inst.size, True, n))

                # Remote
                args_queue.insert(0, (op.addr, False, n))

            # 2 children (next, then remote) - call
            elif inst.itype in CALLS:
                try:        
                    op = inst.ops[0]
                except:
                    op = inst.Operands[0]
                
                # Next
                # Catch the end of a noret function
                if not is_noret(inst.ea):
                    args_queue.insert(0, (inst.ea + inst.size, True, n))

                # Remote
                if op.type in OP_MEM:
                    args_queue.insert(0, (op.addr, False, n))

            # 1 child (next) - basic instruction
            else:
                args_queue.insert(0, (inst.ea + inst.size, True, n))

        return
    MakeName(vm_handler, sig_name)
    return


if SWITCH == 0:
    print "First specify address of switch jump - jump to vm_handlers!"
    sys.exit(1)

for i in range(SWITCH_SIZE):
    addr = Dword(SWITCH + i * 4)
    faddr = addr

    sig = []

    while 1:
        instr = DecodeInstruction(addr)
        if instr.get_canon_mnem() == "jmp" and (Byte(addr) == 0xeb
                                                or Byte(addr) == 0xe9):
            addr = instr.Op1.addr
            continue
        if instr.get_canon_mnem() == "jmp" and Byte(addr) == 0xff and Byte(
                addr + 1) == 0x63 and (Byte(addr + 2) == 0x18
                                       or Byte(addr + 2) == 0x1C):
            addr = append_bytes(instr, addr)
            break
        if instr.get_canon_mnem() == "jmp" and Byte(addr) == 0xff:
            break
        if instr.get_canon_mnem() == "jz":
            sig.append(Byte(addr))
            addr += instr.size
            continue
Beispiel #8
0
counter = 0
while popcntAddr != BADADDR:
    try:
        popcntSize = get_item_size(popcntAddr)
        print(counter,
              hex(popcntAddr).rstrip("L"),
              GetDisasm(popcntAddr),
              hex(ctypes.c_longlong(get_operand_value(popcntAddr,
                                                      1)).value).rstrip("L"),
              hex(popcntSize).rstrip("L"),
              file=output_info)

        ###Second operand parsing
        if get_operand_type(popcntAddr, 0) == o_reg:
            secondOp = SecondOperand(popcntSize)
            inst = DecodeInstruction(popcntAddr)
            if inst.Op2.dtype != idaapi.dt_qword:
                if inst.Op2.dtype == idaapi.dt_dword:
                    secondOp.is64bit = False
                else:
                    raise RuntimeError("Parsing error: unsupported data type")

            if inst.Op2.type == o_reg:
                secondOp.isPtr = False
                secondOp.base = inst.Op2.reg
            elif inst.Op2.type == o_phrase or inst.Op2.type == o_displ:
                if inst.Op2.specflag1 and inst.Op2.phrase != 4:
                    extendedBase = 0
                    extendedIndex = 0
                    rex = ida_bytes.get_byte(popcntAddr + 1)
                    if rex != 0x0f:
    print "naming %x as %s" % (vm_handler, sig_name)
    MakeName(vm_handler, sig_name)
    return

if SWITCH == 0:
    print "First specify address of switch jump - jump to vm_handlers!"
    sys.exit(1)

for i in range(SWITCH_SIZE):
    addr = Dword(SWITCH+i*4)
    faddr = addr

    sig = []

    while 1:
        instr = DecodeInstruction(addr)
        if instr.get_canon_mnem() == "jmp" and (Byte(addr) == 0xeb or Byte(addr) == 0xe9):
            addr = instr.Op1.addr
            continue
        if instr.get_canon_mnem() == "jmp" and Byte(addr) == 0xff and Byte(addr+1) == 0x63 and (Byte(addr+2) == 0x18 or Byte(addr+2) == 0x1C):
            addr = append_bytes(instr, addr)
            break
        if instr.get_canon_mnem() == "jmp" and Byte(addr) == 0xff:
            break
        if instr.get_canon_mnem() == "jz":
            sig.append(Byte(addr))
            addr += instr.size
            continue
        if instr.get_canon_mnem() == "jnz":
            sig.append(Byte(addr))
            addr += instr.size
Beispiel #10
0
 def __init__(self, ea):
     self._ea = ea
     self._insn = DecodeInstruction(ea)
     if self._insn is None:
         raise InvalidInstruction("")