Beispiel #1
0
    def codeType(self, ea):
        """Query IDA for the code type at the given address.

        Args:
            ea (int): effective code address

        Return Value:
            The current code type at the given address
        """
        return idc.GetReg(ea, 'T')
Beispiel #2
0
 def nextarm(self, ea, ui=True):
     # type: (int) -> str
     """
     Finds the next ARM item, which has a Segment register value 'T' of 0
     :param ea: address to start searching from
     :param ui: if True, jump to address automatically
     :return: the address (in str) of the next ARM instruction
     """
     # don't count this item
     ea += Data.Data(ea).getSize()
     output = idaapi.BADADDR
     while ea < self.end_ea:
         d = Data.Data(ea)
         # detect next code32
         if idc.GetReg(ea, 'T') == 0:
             output = ea
             break
         ea += d.getSize()
     return '%07X' % output
Beispiel #3
0
def extendThumbFuncToLastPop(func_ea, lastInsn_ea, verbose=True):
    """
    Looks for another POP {..., PC}. Stops at the start of a new function, or at the start of
    labeled data. Otherwise, it makes sure the code is disassembled, and is thumb, and it extends the
    range of the function to the found POP {..., PC}.
    A corner case not accounted by this algorithm, is if the data is in the middle of code, but
    is jumped over.
    :param func_ea: addr to function to fix
    :param lastInsn_ea: address to the last instruction within the function, as registered in the IDB.
    :return: whether a fix ocurred or not
    """
    ea = lastPop_ea = lastInsn_ea
    while not idc.Name(ea) or not idc.isData(idc.GetFlags(ea)):
        if idc.GetReg(ea, 'T') == 0:
            idc.SetRegEx(ea, 'T', 1, idc.SR_user)

        # if idc.isData(idc.GetFlags(ea)):
        #     # if not thumb, make thumb
        #     idc.del_items(ea, 0, 2)
        #     idc.MakeCode(ea)

        if Instruction.isInsn(ea):
            insn = Instruction.Insn(ea)
            # update last POP {..., PC} detected
            if insn.itype == idaapi.ARM_pop and ((insn.getPushPopFlags() &
                                                  (1 << 15)) != 0):
                lastPop_ea = ea
            # stop condition, assuming no  PUSH {..., LR} in current function
            if insn.itype == idaapi.ARM_push and ((insn.getPushPopFlags() &
                                                   (1 << 14)) != 0):
                break

        ea += idaapi.get_item_size(ea)

    # extend last function to last pop detected
    if lastPop_ea != lastInsn_ea:
        if verbose:
            print('%07X: End -> %07X <%s>' %
                  (func_ea, lastPop_ea, Data.Data(lastPop_ea).getDisasm()))
        idc.SetFunctionEnd(func_ea, lastPop_ea + 2)
        return True
    return False
def GetFuncInputSurrogate(func):

    info = idaapi.get_inf_structure()
    arch = info.procName.lower()

    function_ea = func.startEA
    f_name = GetFunctionName(func)
    function = dict()
    function['name'] = f_name
    function['id'] = function_ea
    # ignore call-graph at this moment
    function['call'] = list()
    function['sea'] = function_ea
    function['see'] = idc.FindFuncEnd(function_ea)
    function['blocks'] = list()
    # basic bloc content
    for bblock in idaapi.FlowChart(idaapi.get_func(function_ea)):

        sblock = dict()
        sblock['id'] = bblock.id
        sblock['sea'] = bblock.startEA
        if (arch == 'arm'):
            sblock['sea'] += idc.GetReg(bblock.startEA, 'T')
        sblock['eea'] = bblock.endEA
        sblock['name'] = 'loc_' + format(bblock.startEA, 'x').upper()
        dat = {}
        sblock['dat'] = dat
        s = idc.GetManyBytes(bblock.startEA, bblock.endEA - bblock.startEA)
        if (s != None):
            sblock['bytes'] = "".join("{:02x}".format(ord(c)) for c in s)

        tlines = []
        for head in idautils.Heads(bblock.startEA, bblock.endEA):
            tline = []
            tline.append(
                str(hex(head)).rstrip("L").upper().replace("0X", "0x"))
            mnem = idc.GetMnem(head)
            if mnem == "":
                continue
            tline.append(mnem)
            for i in range(5):
                opd = idc.GetOpnd(head, i)
                if opd == "":
                    continue
                tline.append(opd)
            tlines.append(tline)

            refdata = list(idautils.DataRefsFrom(head))
            if (len(refdata) > 0):
                for ref in refdata:
                    dat[head] = binascii.hexlify(
                        struct.pack("<Q", idc.Qword(ref)))

        sblock['src'] = tlines

        # flow chart
        bcalls = list()
        for succ_block in bblock.succs():
            bcalls.append(succ_block.id)
        sblock['call'] = bcalls
        function['blocks'].append(sblock)

    return function
Beispiel #5
0
 def is_thumb(address):
     return idc.GetReg(address, 'T') == 1
Beispiel #6
0
def assemble32(line, ea):
    return idaapi.assemble(ea, idc.GetReg(ea, "cs"), ea, True, line)
def fix_callgraph(msgsend, segname, class_param, sel_param):
    '''
    fix_callgraph: msgsend, segname, class_param, sel_param

    Given the msgsend flavour address as a parameter, looks
    for the parameters (class and selector, identified by
    class_param and sel_param) and creates a new segment where
    it places a set of dummy calls named as classname_methodname
    (we use method instead of selector most of the time).
    '''

    t1 = time.time()
    if not msgsend:
        print 'ERROR: msgSend not found'
        return

    total = 0
    resolved = 0
    call_table = dict()

    for xref in idautils.XrefsTo(msgsend, idaapi.XREF_ALL):
        total += 1
        ea_call = xref.frm
        func_start = idc.GetFunctionAttr(ea_call, idc.FUNCATTR_START)
        if not func_start or func_start == idc.BADADDR:
            continue
        ea = ea_call
        method_name_ea = trace_param(ea, func_start, idc.o_reg, sel_param)
        if method_name_ea and idc.isASCII(idc.GetFlags(method_name_ea)):
            method_name = idc.GetString(method_name_ea, -1, idc.ASCSTR_C)
            if not method_name:
                method_name = '_unk_method'
        else:
            method_name = '_unk_method'

        class_name_ea = trace_param(ea, func_start, idc.o_reg, class_param)
        if class_name_ea:
            class_name = idc.Name(class_name_ea)
            if not class_name:
                class_name = '_unk_class'
        else:
            class_name = '_unk_class'

        if method_name == '_unk_method' and class_name == '_unk_class':
            continue

        # Using this name convention, if the class and method
        # are identified by IDA, the patched call will point to
        # the REAL call and not one of our dummy functions
        #
        class_name = class_name.replace('_OBJC_CLASS_$_', '')
        class_name = class_name.replace('_OBJC_METACLASS_$_', '')
        new_name = '_[' + class_name + '_' + method_name + ']'
        print '%08x: %s' % (ea_call, new_name)
        call_table[ea_call] = new_name
        resolved += 1

    print '\nFinal stats:\n\t%d total calls, %d resolved' % (total, resolved)
    print '\tAnalysis took %.2f seconds' % (time.time() - t1)

    if resolved == 0:
        print 'Nothing to patch.'
        return

    print 'Adding new segment to store new nullsubs'

    # segment size = opcode ret (4 bytes) * num_calls
    seg_size = resolved * 4
    seg_start = idc.MaxEA() + 4
    idaapi.add_segm(0, seg_start, seg_start + seg_size, segname, 'CODE')

    print 'Patching database...'
    seg_ptr = seg_start
    for ea, new_name in call_table.items():
        if idc.LocByName(new_name) != idc.BADADDR:
            offset = idc.LocByName(new_name) - ea
        else:
            # create code and name it
            idc.PatchDword(seg_ptr, 0xE12FFF1E) # BX LR
            idc.MakeName(seg_ptr, new_name)
            idc.MakeCode(seg_ptr)
            idc.MakeFunction(seg_ptr, seg_ptr + 4)
            idc.MakeRptCmt(seg_ptr, new_name)
            offset = seg_ptr - ea
            seg_ptr += 4

        # patch the msgsend call
        if idc.GetReg(ea, "T") == 1:
            if offset > 0 and offset & 0xFF800000:
                print 'Offset too far for Thumb (%08x) Stopping [%08x]' % (offset, ea)
                return

            off1 = (offset & 0x7FF000) >> 12
            off2 = (offset & 0xFFF) / 2
            w1 = (0xF000 | off1)
            w2 = (0xE800 | off2) - 1
            idc.PatchWord(ea, w1)
            idc.PatchWord(ea + 2, w2)
        else:
            if offset > 0 and offset & 0xFF000000:
                print 'Offset too far (%08x) Stopping [%08x]' % (offset, ea)
            dw = (0xFA000000 | (offset - 8 >> 2))
            if dw < 0:
                dw = dw & 0xFAFFFFFF
            idc.PatchDword(ea, dw)
def _get_ida_func_surrogate(func, arch):
    func_surrogate = dict()
    func_surrogate['name'] = idc.GetFunctionName(func.startEA)
    func_surrogate['id'] = func.startEA
    # ignore call-graph at this moment
    func_surrogate['call'] = list()
    func_surrogate['sea'] = func.startEA
    func_surrogate['see'] = idc.FindFuncEnd(func.startEA)
    # api is optional
    func_surrogate['api'] = _get_api(func.startEA)[1]
    func_surrogate['blocks'] = list()

    # comments
    func_surrogate['comments'] = []
    func_surrogate['comments'].extend(get_comments(func.startEA))

    for bb in idaapi.FlowChart(idaapi.get_func(func.startEA)):

        block = dict()
        block['id'] = bb.id
        block['sea'] = bb.startEA
        if arch is 'arm':
            # for arm; the last bit indicates thumb mode.
            block['sea'] += idc.GetReg(bb.startEA, 'T')
        block['eea'] = bb.endEA
        block['name'] = 'loc_' + format(bb.startEA, 'x').upper()
        dat = {}
        block['dat'] = dat
        s = idc.GetManyBytes(bb.startEA, bb.endEA - bb.startEA)
        if s is not None:
            block['bytes'] = "".join("{:02x}".format(ord(c)) for c in s)

        func_surrogate['comments'].extend(get_comments(bb.startEA))

        instructions = list()
        for head in idautils.Heads(bb.startEA, bb.endEA):
            ins = list()
            ins.append(str(hex(head)).rstrip("L").upper().replace("0X", "0x"))
            opr = idc.GetMnem(head)
            if opr == "":
                continue
            ins.append(opr)
            for i in range(5):
                opd = idc.GetOpnd(head, i)
                if opd == "":
                    continue
                ins.append(opd)
            instructions.append(ins)

            refs = list(idautils.DataRefsFrom(head))
            for ref in refs:
                dat[head] = binascii.hexlify(struct.pack("<Q", idc.Qword(ref)))

        block['src'] = instructions

        # flow chart
        block_calls = list()
        for success_block in bb.succs():
            block_calls.append(success_block.id)
        block['call'] = block_calls
        func_surrogate['blocks'].append(block)
    return func_surrogate
Beispiel #9
0
def InsIsThumb(i):
    return idc.GetReg(i, "T") == 1