Ejemplo n.º 1
0
def make_xref(from_ea, to_ea, xref_constructor, xref_size):
  """Force the data at `from_ea` to reference the data at `to_ea`."""
  if not idc.GetFlags(to_ea) or is_invalid_ea(to_ea):
    DEBUG("  Not making reference (A) from {:x} to {:x}".format(from_ea, to_ea))
    return

  make_head(from_ea)

  if is_code(from_ea):
    _CREFS_FROM[from_ea].add(to_ea)
    _CREFS_TO[to_ea].add(from_ea)
  else:
    _DREFS_FROM[from_ea].add(to_ea)
    _DREFS_TO[to_ea].add(from_ea)

  # If we can't make a head, then it probably means that we're at the
  # end of the binary, e.g. the last thing in the `.extern` segment.
  if not make_head(from_ea + xref_size):
    assert idc.BADADDR == idc.SegStart(from_ea + xref_size)

  idaapi.do_unknown_range(from_ea, xref_size, idc.DOUNK_EXPAND)
  xref_constructor(from_ea)
  if not is_code_by_flags(from_ea):
    idc.add_dref(from_ea, to_ea, idc.XREF_USER|idc.dr_O)
  else: 
    DEBUG("  Not making reference (B) from {:x} to {:x}".format(from_ea, to_ea))
Ejemplo n.º 2
0
Archivo: util.py Proyecto: d-ned/mcsema
def make_xref(from_ea, to_ea, xref_constructor, xref_size):
    """Force the data at `from_ea` to reference the data at `to_ea`."""
    if not idc.GetFlags(to_ea) or is_invalid_ea(to_ea):
        DEBUG("  Not making reference (A) from {:x} to {:x}".format(
            from_ea, to_ea))
        return

    make_head(from_ea)

    if is_code(from_ea):
        _CREFS_FROM[from_ea].add(to_ea)
        _CREFS_TO[to_ea].add(from_ea)
    else:
        _DREFS_FROM[from_ea].add(to_ea)
        _DREFS_TO[to_ea].add(from_ea)

    # If we can't make a head, then it probably means that we're at the
    # end of the binary, e.g. the last thing in the `.extern` segment.
    if not make_head(from_ea + xref_size):
        assert idc.BADADDR == idc.SegStart(from_ea + xref_size)

    idaapi.do_unknown_range(from_ea, xref_size, idc.DOUNK_EXPAND)
    xref_constructor(from_ea)
    if not is_code_by_flags(from_ea):
        idc.add_dref(from_ea, to_ea, idc.XREF_USER | idc.dr_O)
    else:
        DEBUG("  Not making reference (B) from {:x} to {:x}".format(
            from_ea, to_ea))
Ejemplo n.º 3
0
    def markDataPtr(self, src, dest, aggressive=True):
        """Mark a data pointer from src to dest.

        Args:
            src (int): effective address for the pointer's location
            dest (int): effective address for the pointed data address
            aggressive (bool, optional): True iff should redefine the src (True by default)
        """
        if aggressive:
            ida_bytes.del_items(src, 0, self.addressSize())
        if self.makeAddress(src):
            idc.add_dref(src, dest, idc.XREF_USER | idc.dr_O)
            ida_offset.op_offset(src, 0, idc.REF_OFF32)
Ejemplo n.º 4
0
def make_xref(from_ea, to_ea, data_type, xref_size):
    """Force the data at `from_ea` to reference the data at `to_ea`."""
    if not idc.get_full_flags(to_ea) or is_invalid_ea(to_ea):
        DEBUG("  Not making reference (A) from {:x} to {:x}".format(
            from_ea, to_ea))
        return False

    make_head(from_ea)

    if is_code(from_ea):
        _CREFS_FROM[from_ea].add(to_ea)
        _CREFS_TO[to_ea].add(from_ea)
    else:
        _DREFS_FROM[from_ea].add(to_ea)
        _DREFS_TO[to_ea].add(from_ea)

    # If we can't make a head, then it probably means that we're at the
    # end of the binary, e.g. the last thing in the `.extern` segment.
    # or in the middle of structure. Return False in such case
    #
    # NOTE(artem): Commenting out since this breaks recovery of C++ applications
    # with IDA7. The failure occurs when processign references in .init_array
    # when the below code is enabled, those references are not treated as
    # references because make_head fails.
    #
    #if not make_head(from_ea + xref_size):
    #  return False

    ida_bytes.del_items(from_ea, idc.DELIT_EXPAND, xref_size)

    if data_type == idc.FF_QWORD:
        data_size = 8
    elif data_type == idc.FF_DWORD:
        data_size = 4
    else:
        raise ValueError("Invalid data type")

    idc.create_data(from_ea, data_type, data_size, idaapi.BADADDR)
    if not is_code_by_flags(from_ea):
        idc.add_dref(from_ea, to_ea, idc.XREF_USER | idc.dr_O)
    else:
        DEBUG("  Not making reference (B) from {:x} to {:x}".format(
            from_ea, to_ea))

    return True
Ejemplo n.º 5
0
    def markCodePtr(self, src, dest, aggressive=True):
        """Mark a code pointer from src to dest.

        Args:
            src (int): effective address for the pointer's location
            dest (int): effective address for the pointed code address
            aggressive (bool, optional): True iff should redefine the src & dest (True by default)
        """
        clean_dest = self.cleanPtr(dest)
        if aggressive:
            ida_bytes.del_items(src, 0, self.addressSize())
        if self.makeAddress(src):
            idc.add_dref(src, clean_dest, idc.XREF_USER | idc.dr_O)
            idc.add_cref(src, clean_dest, idc.XREF_USER | idc.dr_O)
            ida_offset.op_offset(src, 0, idc.REF_OFF32)
            if aggressive:
                ida_bytes.del_items(dest, 0, self.addressSize())
                idc.create_insn(self.cleanPtr(dest))
Ejemplo n.º 6
0
def make_xref(from_ea, to_ea, data_type, xref_size):
  """Force the data at `from_ea` to reference the data at `to_ea`."""
  if not idc.get_full_flags(to_ea) or is_invalid_ea(to_ea):
    DEBUG("  Not making reference (A) from {:x} to {:x}".format(from_ea, to_ea))
    return False

  make_head(from_ea)

  if is_code(from_ea):
    _CREFS_FROM[from_ea].add(to_ea)
    _CREFS_TO[to_ea].add(from_ea)
  else:
    _DREFS_FROM[from_ea].add(to_ea)
    _DREFS_TO[to_ea].add(from_ea)

  # If we can't make a head, then it probably means that we're at the
  # end of the binary, e.g. the last thing in the `.extern` segment.
  # or in the middle of structure. Return False in such case
  #
  # NOTE(artem): Commenting out since this breaks recovery of C++ applications
  # with IDA7. The failure occurs when processign references in .init_array
  # when the below code is enabled, those references are not treated as
  # references because make_head fails.
  #
  #if not make_head(from_ea + xref_size):
  #  return False

  ida_bytes.del_items(from_ea, idc.DELIT_EXPAND, xref_size)

  if data_type == idc.FF_QWORD:
    data_size = 8
  elif data_type == idc.FF_DWORD:
    data_size = 4
  else:
    raise ValueError("Invalid data type")

  idc.create_data(from_ea, data_type, data_size, idaapi.BADADDR)
  if not is_code_by_flags(from_ea):
    idc.add_dref(from_ea, to_ea, idc.XREF_USER|idc.dr_O)
  else: 
    DEBUG("  Not making reference (B) from {:x} to {:x}".format(from_ea, to_ea))

  return True
Ejemplo n.º 7
0
def make_xref(from_ea, to_ea, data_type, xref_size):
    """Force the data at `from_ea` to reference the data at `to_ea`."""
    if not idc.get_full_flags(to_ea) or is_invalid_ea(to_ea):
        DEBUG("  Not making reference (A) from {:x} to {:x}".format(
            from_ea, to_ea))
        return False

    make_head(from_ea)

    if is_code(from_ea):
        _CREFS_FROM[from_ea].add(to_ea)
        _CREFS_TO[to_ea].add(from_ea)
    else:
        _DREFS_FROM[from_ea].add(to_ea)
        _DREFS_TO[to_ea].add(from_ea)

    # If we can't make a head, then it probably means that we're at the
    # end of the binary, e.g. the last thing in the `.extern` segment.
    # or in the middle of structure. Return False in such case
    if not make_head(from_ea + xref_size):
        return False

    ida_bytes.del_items(from_ea, idc.DELIT_EXPAND, xref_size)

    if data_type == idc.FF_QWORD:
        data_size = 8
    elif data_type == idc.FF_DWORD:
        data_size = 4
    else:
        raise ValueError("Invalid data type")

    idc.create_data(from_ea, data_type, data_size, idaapi.BADADDR)
    if not is_code_by_flags(from_ea):
        idc.add_dref(from_ea, to_ea, idc.XREF_USER | idc.dr_O)
    else:
        DEBUG("  Not making reference (B) from {:x} to {:x}".format(
            from_ea, to_ea))

    return True
Ejemplo n.º 8
0
def find_pairs():
    ea = idc.MinEA()
    movh = [None] * MAX_REGISTERS
    while ea < idc.MaxEA():
        insn = idautils.DecodeInstruction(ea)
        if insn:
            mnem = insn.get_canon_mnem()
            reg1 = insn.Op1.reg
            reg2 = insn.Op2.reg
            val1 = insn.Op2.value
            val2 = insn.Op3.value
            size = insn.size

            if mnem == "movh" and insn.Op2.type == o_imm:
                movh[reg1] = (val1, insn.ea)
            elif movh[reg1] is not None:
                other = movh[reg1]
                if mnem == "add3" and reg1 == reg2:
                    target = (other[0] << 16) + val2
                    print "Found a add3 pointer pair to ", hex(target), " at ", hex(insn.ea)
                    idc.add_dref(insn.ea, target, dr_O)
                    idc.add_dref(other[1], target, dr_O)
                    idaapi.set_refinfo(insn.ea, 2, REF_LOW16, target, 0, 0)
                    idaapi.set_refinfo(other[1], 1, REF_HIGH16, target, 0, 0)
                elif mnem == "or3" and reg1 == reg2:
                    target = (other[0] << 16) | val2
                    print "Found a or3 pointer pair to ", hex(target), " at ", hex(insn.ea)
                    idc.add_dref(insn.ea, target, dr_O)
                    idc.add_dref(other[1], target, dr_O)
                    idaapi.set_refinfo(insn.ea, 2, REF_LOW16, target, 0, 0)
                    idaapi.set_refinfo(other[1], 1, REF_HIGH16, target, 0, 0)
                movh[reg1] = None

            if insn.get_canon_feature() & (idaapi.CF_STOP | idaapi.CF_CALL):
                movh = [None] * MAX_REGISTERS
        else:
            size = 2
        ea += size
Ejemplo n.º 9
0
    def export(self, vtables):
        """
        @vtables: List of tuples with vtable information
                  [(ins_addr, vtable), ... ]
                  
        There is a small mistake. Some .data references will be tagged as being 
        vtables. This is due to the way we detect them on pin. In IDA pro it should
        be easy to mark just only the ones that refer to .text but I could not find
        a way to get that information from idapython.
        """

        # We build a dictionary with the ins addr referencing the vtable as the key
        dict_ = {}
        for vtable in vtables:
            # Add all the vtable references found while tracing to the set
            dict_.setdefault(vtable[0], set()).add(vtable[1])

        for (key, val) in dict_.iteritems():
            prev_comment = idc.GetCommentEx(vtable[0], False)

            # Check if we already have commented this line. This will avoid duplicating info.
            if not prev_comment or "VTables found:" in prev_comment:
                prev_comment = "VTables found:\n"

            prev_comment += "\n".join(map(lambda x: "0x%.8x" % x, val))

            # vtable[0] == instruction address
            idc.MakeComm(key, prev_comment)

            # Check if we already have a cross reference
            for v in val:
                if key in [ref.frm for ref in XrefsTo(v, 0)]:
                    continue

                # Add a data reference
                if add_dref(key, v, dr_R) != True:
                    idaapi.msg(
                        "Could not create cross reference from %x to %x\n" %
                        (key, v))
Ejemplo n.º 10
0
def scanDataForRelocs(M, D, start, end, new_eas, seg_offset):
    i = start
    while i < end:
        more_dref = [d for d in idautils.DataRefsFrom(i)]
        dref_size = idc.ItemSize(i) or 1
        if len(more_dref) == 0 and dref_size == 1:
            dword = readDword(i)
            DEBUG("Testing address: {0:x}... ".format(i))
            # check for unmakred references
            if isInData(dword, dword+1):
                idc.MakeDword(i)
                idc.add_dref(i, dword, idc.XREF_USER|idc.dr_O)
                DEBUG("making New Data Reference at: {0:x} => {1:x}\n".format(i, dword))
                dref_size = 4
            elif isInternalCode(dword):
                idc.MakeDword(i)
                idc.AddCodeXref(i, dword, idc.XREF_USER|idc.fl_F)
                DEBUG("making New Code Reference at: {0:x} => {1:x}\n".format(i, dword))
                dref_size = 4
            else:
                DEBUG("not code or data ref\n")

        i += dref_size

    def insertReference(M, D, ea, pointsto, seg_offset, new_eas):
        # do not make code references for mid-function code accessed via a JMP -- 
        # they will be found via the jumptable code. This prevents the insertion
        # of lots of extra code, but could be wrong for some cases
        if ea in ACCESSED_VIA_JMP and not isStartOfFunction(pointsto):
            # bail only if we are access via JMP and not the start
            # of a function
            DEBUG("\t\tNOT ADDING REF: {:08x} -> {:08x}\n".format(ea, pointsto))
            return

        DEBUG("\t\tFound a probable ref from: {0:x} => {1:x}\n".format(ea, pointsto))
        real_size = idc.ItemSize(pointsto)
        DEBUG("\t\tReal Ref: {0:x}, size: {1}\n".format(pointsto, real_size))
        insertRelocatedSymbol(M, D, pointsto, ea, seg_offset, new_eas, real_size)

    def checkIfJumpData(ea, size):
        """
        Loop through ea to ea+size, and if 
        every dword there points to code, this is a jump data section

        returns true or false and list of recovered ea => destination mappings
        """
        table_map = {}
        for jea in xrange(ea, ea+size, 4):
            dword = readDword(jea)
            if not isInternalCode(dword):
                DEBUG("Dword {:x} does not point to code, not a table\n".format(dword))
                return False, table_map

            table_map[jea] = dword

        return True, table_map

    i = start
    while i < end:
        DEBUG("Checking address: {:x}\n".format(i))
        dref_size = idc.ItemSize(i) or 1
        if dref_size > 4 and dref_size % 4 == 0:
            DEBUG("Possible table data at {:x}; size: {:x}\n".format(i, dref_size))
            (is_table, addrs) = checkIfJumpData(i, dref_size)
            if is_table:
                DEBUG("Its a table, adding {} references\n".format(len(addrs)));
                for ta in sorted(addrs.keys()):
                    insertReference(M, D, ta, addrs[ta], seg_offset, new_eas)
            else:
                DEBUG("Its not a table\n");

        elif dref_size == 4:
            more_cref = [c for c in idautils.CodeRefsFrom(i,0)]
            more_dref = [d for d in idautils.DataRefsFrom(i)]
            more_dref.extend(more_cref)
            if len(more_dref) > 0:
                DEBUG("\t\tFound a probable ref from: {0:x} => {1:x}\n".format(i, more_dref[0]))
                if len(more_dref) == 1:
                    insertReference(M, D, i, more_dref[0], seg_offset, new_eas)
                else: 
                    DEBUG("\t\tWARNING: Possible data ref problem\n");
                    insertReference(M, D, i, more_dref[0], seg_offset, new_eas)

        i += dref_size