Ejemplo n.º 1
0
def split_funcs(startEA, endEA):
    '''
    Description:
        Attempt to split the function we created into a bunch of smaller functions based on
        aligns we find in the middle of the func. If we do successfully split, recurse on
        the remainder of the original function.

    Input:
        startEA - The beginning of the function
        endEA - The end of the function

    Output:
        The IDB is updated with the resulting functions
    '''
    ea = startEA
    while ea < endEA:
        # We found an align so delete the function and try to make 2 new ones in its place.
        if idaapi.isAlign(idc.GetFlags(ea)) and idc.DelFunction(startEA):
            # Make the first function.
            if idc.MakeFunction(startEA, _un_nop(ea, idc.NextHead)):
                # We found an align, now get past them.
                while idaapi.isAlign(idc.GetFlags(ea)):
                    ea += idc.ItemSize(ea)

                # Make the second function and recurse to ensure it doesn't need split too.
                if idc.MakeFunction(_un_nop(ea, idc.PrevHead), endEA):
                    append_debug('Split 0x%X - 0x%X at 0x%X.' %
                                 (startEA, endEA, ea))
                    split_funcs(ea, endEA)
                    return
                else:  # We failed to make the second function, so delete the first.
                    idc.DelFunction(startEA)

            # Splitting failed - rebuild the original function.
            idc.MakeFunction(startEA, endEA)
            append_debug('Almost split 0x%X - 0x%X at 0x%X.' %
                         (startEA, endEA, ea))

        ea += idc.ItemSize(ea)
Ejemplo n.º 2
0
Archivo: util.py Proyecto: d-ned/mcsema
def is_internal_code(ea):
    if is_invalid_ea(ea):
        return False

    if is_external_segment(ea):
        return False

    if is_code(ea):
        return True

    # find stray 0x90 (NOP) bytes in .text that IDA
    # thinks are data items.
    flags = idc.GetFlags(ea)
    if idaapi.isAlign(flags):
        if not try_mark_as_code(ea):
            return False
        return True

    return False
Ejemplo n.º 3
0
def is_internal_code(ea):
  if is_invalid_ea(ea):
    return False

  if is_external_segment(ea):
    return False
  
  if is_code(ea):
    return True

  # find stray 0x90 (NOP) bytes in .text that IDA 
  # thinks are data items.
  flags = idc.GetFlags(ea)
  if idaapi.isAlign(flags):
    if not try_mark_as_code(ea):
      return False
    return True

  return False
Ejemplo n.º 4
0
def instructionHandler(M, F, B, inst, new_eas):
    insn_t = idautils.DecodeInstruction(inst)
    if not insn_t:
        # handle jumps after noreturn functions
        if idc.Byte(inst) == 0xCC:
            I = addInst(B, inst, [0xCC])
            return I, True
        else:
            raise Exception("Cannot read instruction at: {0:x}".format(inst))

    # check for align instruction
    pf = idc.GetFlags(inst)
    if idaapi.isAlign(pf):
        return None, True

    # skip HLTs -- they are privileged, and are used in ELFs after a noreturn call
    if isHlt(inst):
        return None, False

    DEBUG("\t\tinst: {0}\n".format(idc.GetDisasm(inst)))
    inst_bytes = readInstructionBytes(inst)
    DEBUG("\t\tBytes: {0}\n".format(inst_bytes))

    I = addInst(B, inst, inst_bytes)

    if isJmpTable(inst):
        handleJmpTable(I, F, inst, new_eas)
        return I, False

    if isIndirectCall(inst):
        global FUNCTIONS_NEED_TRAMPOLINE
        FUNCTIONS_NEED_TRAMPOLINE = True

    #check for code refs from here
    crefs = []
    for cref in idautils.CodeRefsFrom(inst, 0):
        crefs.append(cref)
        fn = getFunctionName(cref)
        if isCall(inst):

            elfy, fn_replace = isElfThunk(cref)
            if elfy:
                fn = fn_replace

            if isExternalReference(cref) or elfy:
                fn = handleExternalRef(fn)
                I.ext_call_name = fn
                DEBUG("EXTERNAL CALL: {0}\n".format(fn))

                if doesNotReturn(fn):
                    return I, True
            else:
                I.call_target = cref

                if cref not in RECOVERED_EAS:
                    new_eas.add(cref)

                DEBUG("INTERNAL CALL: {0}\n".format(fn))
        elif isUnconditionalJump(inst):
            if isExternalReference(cref):
                fn = handleExternalRef(fn)
                I.ext_call_name = fn
                DEBUG("EXTERNAL JMP: {0}\n".format(fn))

                if doesNotReturn(fn):
                    DEBUG("Nonreturn JMP\n")
                    return I, True
            else:
                DEBUG("INTERNAL JMP: {0:x}\n".format(cref))
                I.true_target = cref

    #true: jump to where we have a code-ref
    #false: continue as we were
    print hex(inst), crefs
    if isConditionalJump(inst):
        I.true_target = crefs[0]
        I.false_target = inst+len(inst_bytes)
        return I, False

    relo_off = findRelocOffset(inst, len(inst_bytes))
    if relo_off != -1:
        I.reloc_offset = relo_off

    for dref in idautils.DataRefsFrom(inst):
        if dref in crefs:
            continue

        if inValidSegment(dref):
            if isExternalReference(dref):
                fn = getFunctionName(dref)

                fn = handleExternalRef(fn)
                if isExternalData(fn):
                    I.ext_data_name = fn
                    sys.stdout.write("EXTERNAL DATA REF FROM {0:x} to {1}\n".format(inst, fn))
                else:
                    I.ext_call_name = fn
                    sys.stdout.write("EXTERNAL CODE REF FROM {0:x} to {1}\n".format(inst, fn))

            elif isInternalCode(dref):
                DEBUG("\t\tCode Ref from {0:x} to {1:x}\n".format(inst, dref))
                I.call_target = dref
                if dref not in RECOVERED_EAS:
                    new_eas.add(dref)
            else:
                dref_size = idc.ItemSize(dref)
                I.data_offset = handleDataRelocation(M, dref, new_eas)
                DEBUG("\t\tData Ref: {0:x}, size: {1}, offset : {2:x}\n".format(
                    dref, dref_size, I.data_offset))
        else:
            DEBUG("Data not in valid segment {0:x}\n".format(dref))

    # if we have a mov sth, imm with imm that it's likely a fn pointer,
    # we add that pointer to the list of ones to disassemble
    # TODO: use also some other info to assume this
    if insn_t[1].type == idaapi.o_imm and insn_t.itype == idaapi.NN_mov and inValidSegment(insn_t[1].value):
        ref = insn_t[1].value
        if isInternalCode(ref) and ref not in RECOVERED_EAS:
            new_eas.add(ref)

    if isCall(inst):
            coderefs = [i for i in idautils.CodeRefsFrom(inst, 0)]
            coderefs_normal = [i for i in idautils.CodeRefsFrom(inst, 1)]
            if len(coderefs) == 0 and len(coderefs_normal) == 1 and insn_t[0].type == idaapi.o_near:
                    for cref in coderefs_normal:
                            I.call_target = cref
                            if cref not in RECOVERED_EAS:
                                    new_eas.add(cref)

    return I, False
Ejemplo n.º 5
0
def isAlign(ea):
    return idaapi.isAlign(idaapi.getFlags(ea))
Ejemplo n.º 6
0
 def isAlign(ea=None):
     ea = ui.current.address() if ea is None else ea
     return idaapi.isAlign(idaapi.getFlags(ea))
Ejemplo n.º 7
0
def isAlign(ea):
    return idaapi.isAlign(idaapi.getFlags(ea))