Пример #1
0
def unkTillName(ea):
    d = Data.Data(ea)
    while True:
        size = d.getSize()
        idc.del_items(d.ea, d.getSize())
        d = Data.Data(d.ea + size)
        if d.getName(): break
    return d.ea
Пример #2
0
def tillName(ea, f):
    d = Data.Data(ea)
    while True:
        size = d.getSize()
        f(d.ea)
        d = Data.Data(d.ea + size)
        if d.getName(): break
    return d.ea
Пример #3
0
def arrTillRef(ea):
    # TODO [BUG]: sometimes swallows names?
    if not Data.Data(ea).isPointer(ea):
        return False
    ref_ea = next.byDataElement(
        ea, lambda ea: idc.Name(ea) or Data.Data(ea).hasPointer(), ui=False)
    delRange(ea, ref_ea)
    idc.make_array(ea, ref_ea - ea)
    return True
Пример #4
0
def actionP():
    """
    Profiling Action. Time Profiling and other analyses go here.
    """
    # tp.runTimeTests()
    n = 10
    x = lambda ea: Data.Data(ea).__str__()
    t, output = tp.avgTime_us(n, x, here())
    print('[%03d us] %s' % (t, Data.Data(here()).getDisasm()))
Пример #5
0
def unk2ArrRng(start_ea, end_ea):
    """
    converts all completely unknowns to byte arrays
    """
    d = Data.Data(start_ea)
    while d.ea < end_ea:
        if d.getName() and idc.isUnknown(idc.GetFlags(d.ea)):
            name = d.getName()
            if unk2Arr(d.ea): print('%s -> %s' % (name, d.getName()))
            d = Data.Data(d.ea)
        d = Data.Data(d.ea + d.getSize())
Пример #6
0
def delShiftedContent(ea):
    d = Data.Data(ea)
    content = d.getContent()
    if type(content) == list or not d.getXRefsFrom(
    )[1] or content < 0x8000000 or not d.isPointer(content):
        return False
    dContent = Data.Data(content)
    if content == dContent.ea or dContent.isCode():
        return False
    if not idc.del_items(dContent.ea, dContent.getSize()):
        for i in range(dContent.ea, dContent.ea + dContent.getSize()):
            idc.del_items(i, 1)
    return True
Пример #7
0
    def nextOneWordArr():
        d = Data.Data(ea)
        while (d.ea < pointerRange[1]):
            content = d.getContent()

            # case: byte array that's 4 elements. Likely a word
            if type(content) == list and len(content) == 4 and (d.getSize() / len(content) == 1):
                break
            d = Data.Data(d.ea + d.getSize())

        if d.ea >= pointerRange[1]:
            print(False)
        else:
            print('%07X' % d.ea)
            idc.jumpto(d.ea)
Пример #8
0
def registerUncompFile(ea, force=True):
    # type: (int) -> bool
    d = Data.Data(ea)
    compPtr = d.getContent()
    if not idc.is_dword(d.getFlags()) or type(compPtr) == list:
        if not force: return False
        print('[%07X] -> dword' % (ea))
        forceItemOp(ea, idc.create_dword, ea)
        d = Data.Data(ea)
        compPtr = d.getContent()

    # compressed pointers have the 31th bit set
    if not compPtr & (1 << 31):
        return False

    compPtr = compPtr - (1 << 31)

    #  make its content an array, and set a name for it, and a size
    compData = Data.Data(compPtr)
    if compData.ea != compPtr:
        idc.del_items(compData.ea)
        compData = Data.Data(compPtr)
    compSize = getLZ77CompressedSize(compPtr)
    # size must have been identified
    if compSize == -1:
        return False
    if compSize % 4 != 0:
        compSize += 4 - (compSize % 4)  # must be word aligned

    if compData.getSize() != compSize:
        if not idc.del_items(compPtr, compSize):
            for i in range(compPtr, compPtr + compSize):
                idc.del_items(i, 1)
        idc.make_array(compPtr, compSize)

    if not compData.getName():
        compData.setName('comp_%07X' % compData.ea)

    idc.op_man(ea, 0, '%s + 1<<31' % compData.getName())

    # now register the compressed data as its own file
    filename = 'data/compressed/%s.lz77' % compData.getName()
    print('[%07X] addFile %s' % (ea, filename))
    dis = Terminal.DisTerminal()
    dis.addFile(filename, compPtr, compPtr + compSize)

    return True
    def getFormattedDisasm(self, start_ea=False, end_ea=False):
        # type: () -> str
        """
        Gets the disassembly of the function by creating data elements of all
        its items, including its pool.
        :param start_ea: file range start, enables formatting to use a global/local macro
        :param end_ea: file range end, enables formatting to use a global/local macro
        :return:
        """
        ea = self.func_ea
        disasm = ''

        # spefiy function comment, if available
        # put // for function comment in each line
        comment = ''
        if self.getComment(repeatable=True):
            comment += '// ' + self.getComment(repeatable=True).replace(
                '\n', '\n// ') + '\n'
        if self.getComment():
            comment += '// ' + self.getComment().replace('\n', '\n// ') + '\n'
        disasm += comment

        # specify start of function
        # file range supplied, inform if thumb or arm function, local/global thumb via macros
        isThumb = self.isThumb()
        if end_ea:
            if isThumb:
                if self.isGlobal(start_ea, end_ea):
                    disasm += '\tthumb_func_start %s\n' % (self.getName())
                else:
                    disasm += '\tthumb_local_start\n'
            else:
                disasm += "\tarm_func_start %s\n" % (self.getName())
        # no macros approach, give sufficient type to symbols
        else:
            disasm = '.func\n'
            # specify  whether this is an arm or thumb function
            if isThumb:
                disasm += ".thumb_func\n"
            else:
                disasm += ".arm\n"

        # disassemble all items within the function
        while ea < self.func_ea + self.getSize(withPool=True):
            d = Data.Data(ea)
            disasm += d.getFormattedDisasm(start_ea, end_ea) + "\n"
            # advance to next item
            ea = ea + d.getSize()

        if end_ea:
            if isThumb:
                disasm += "\tthumb_func_end %s" % self.getName()
            else:
                disasm += "\tarm_func_end %s" % self.getName()
        else:
            disasm += ".endfunc // %s" % self.getName()

        return disasm
Пример #10
0
def deadfunc(ea, end_ea=None, ui=True, hexOut=True):
    """
    This finds the next occurrance of a dead function not recognized as a function (ie, red code or data)
    This can only find functions ranges it can guarantee, ie, only PUSH {..., LR} POP {..., PC} patterns.
    :param ea: ea to start searching from
    :param end_ea: the last address of the search range
    :param ui: if True, jump to address automatically
    :param hexOut: output hex formatted ea range instead
    :return: range of ea of next dead function
    """
    # don't count this item
    ea = Data.Data(ea).ea + Data.Data(ea).getSize()
    foundPush = False
    push_ea = idaapi.BADADDR
    pop_ea = idaapi.BADADDR
    push_regs = None
    if not end_ea: end_ea = end_ea
    while ea < end_ea:
        # the current item must not belong to a function, or have any data xrefs
        if not Function.isFunction(ea) and not Data.Data(ea).getXRefsTo()[1]:
            try:
                inst = InstDecoder.Inst(ea).fields
            except ValueError:
                ea += 2
                continue
            # if PUSH {..., LR}
            if inst and inst['magic'] == InstDecoder.INST_PUSHPOP and not inst[
                    'pop'] and inst['lr']:
                foundPush = True
                push_ea = ea
                push_regs = inst['Rlist']
            # detected a POP {..., PC} after the PUSH {..., LR}, and the registers match
            if (foundPush and inst
                    and inst['magic'] == InstDecoder.INST_PUSHPOP
                    and inst['pop'] and inst['lr']
                    and inst['Rlist'] == push_regs):
                pop_ea = ea
                break
        else:
            foundPush = False
        ea += 2

    if ui: idc.jumpto(push_ea)
    if hexOut: return '(%07X, %07X)' % (push_ea, pop_ea)
    return (push_ea, pop_ea)
    def getStackVarDisasm(self):
        """
        if the function uses stack variables with SP, their symbols should be defined
        :return:
        """
        disasm = ''
        id = idc.GetFrame(self.func_ea)
        firstMember = idc.GetFirstMember(id)
        if hasStackVars(self.func_ea):
            # first, obtain the base by finding an instruction that uses one of the stack variables
            stackVars = getStackVars(self.func_ea)
            ea = self.func_ea
            base = -1

            # TODO: maybe use get_min_spd_ea(func_ea) to get the base pointer? this stands for stack pointer delta!

            # search function instructions to find base (TODO: hacky, but i dunno how else to find base yet)
            while ea < self.func_ea + self.getSize():
                d = Data.Data(ea)
                origDisasm = d.getOrigDisasm()
                # case where the stack frame is referenced
                for var, offset in stackVars:
                    if var in origDisasm and '#' in origDisasm:
                        # cases like LDR SP, [base+var_xx]
                        if '[' in origDisasm:
                            # grab the base
                            if '+' in origDisasm:
                                base = int(
                                    origDisasm[origDisasm.index('#') +
                                               1:origDisasm.index('+')], 16)
                            else:
                                base = 0
                            # obtained base! no need to continue looping
                            break
                        # some cases like ADD SP, base+var_xx don't have '['
                        elif '+' in origDisasm:
                            base = int(
                                origDisasm[origDisasm.index('#') +
                                           1:origDisasm.index('+')], 16)
                            # obtained base! no need to continue looping
                            break
                if base != -1:
                    break
                ea += d.getSize()
            # if base couldn't be found still, it's likely no SP access is done with variables
            if base == -1:
                base = 0

            # build up disasm based on stack vars using base-relative offsets
            for name, off in stackVars:
                relOff = base - off
                if relOff > 0:
                    disasm += ".equ %s, -0x%X\n" % (name, abs(relOff))
                else:
                    disasm += ".equ %s, 0x%X\n" % (name, abs(relOff))

        return disasm
Пример #12
0
def removeRedCode(start_ea, end_ea):
    """
    unconditionally removes all red code within a specified region
    :param start_ea: start of the region
    :param end_ea: end of the region
    :return:
    """
    srchNext = next
    redStart_ea = redEnd_ea = srchNext.red(start_ea, end_ea, ui=False)
    while redEnd_ea < end_ea:
        d = Data.Data(redEnd_ea)
        while d.isCode() and not Function.isFunction(d.ea):
            redEnd_ea += 2
            d = Data.Data(redEnd_ea)
        # change to bytes
        print("%07X: del red code (%07X, %07X)" %
              (redStart_ea, redStart_ea, redEnd_ea))
        idc.del_items(redStart_ea, 0, redEnd_ea - redStart_ea)
        redStart_ea = redEnd_ea = srchNext.red(redEnd_ea, end_ea, ui=False)