예제 #1
0
def cleanStart(analyzer, scs, undef=False):
    """Clean the selected code segments, and re-analyzer them using the gathered metadata until now.

    Args:
        analyzer (instance): analyzer instance to be used
        scs (list): list of (sark) code segments to work on
        undef (bool, optional): True iff should undefine the code segments (False by default)
    """
    for sc in scs:
        if undef:
            analyzer.logger.info("Undefining code segment: 0x%x - 0x%x",
                                 sc.start_ea, sc.end_ea)
            sark.data.undefine(sc.start_ea, sc.end_ea)
            if analyzer.switch_identifier.hasSwithTables(sc):
                analyzer.logger.info(
                    "Marking all known switch tables in the segment")
                analyzer.switch_identifier.markSwitchTables(sc)
            else:
                analyzer.logger.debug("No known switch tables in the segment")
    if analyzer.fptr_identifier.hasKnownFptrs():
        analyzer.logger.info("Marking all known fptr functions")
        analyzer.fptr_identifier.makePointedFunctions()
    else:
        analyzer.logger.debug("No known fptr functions")
    for sc in scs:
        analyzer.logger.info("Re-Analyzing code segment: 0x%x - 0x%x",
                             sc.start_ea, sc.end_ea)
        idc.plan_and_wait(sc.start_ea, sc.end_ea)
        idaapi.auto_wait()
예제 #2
0
def try_make_function(function_start,
                      function_end=idc.BADADDR,
                      target_location=None,
                      require_term=True,
                      end_mnem_bytes=None):
    """
    Description:
        Given a function location, attempt to create a function.
        If function creation fails, delete any partially created functions.
        If function creation succeeds, ensure all of the function's bytes are analyzed as code.

    Input:
        function_start - The start_ea of the function to create
        function_end - The end_ea of the function to create. IDA will calculate if not provided.
        target_location - If provided, fail function creation if it does not include this EA
        require_term - If provided, fail function creation if the last instruction is not a ret or jmp
        end_mnem_bytes - If provided, fail function creation if the last instruction is not the provided bytes
                         Instructions are entered as space separated bytes (i.e. '55' for 'push ebp')

    Output:
        Returns a tuple (function_start, function_end) for the created function if successful, None otherwise
    """
    if function_start <= function_end:
        if idc.add_func(function_start, function_end):
            logger.debug('Created a function 0x%X - 0x%X.' %
                         (function_start, function_end))
            if require_term:
                last_mnem_ea = idc.get_item_head(
                    idaapi.get_func(function_start).end_ea - 1)
                last_mnem = idc.print_insn_mnem(last_mnem_ea)
                if (end_mnem_bytes is None and 'ret' not in last_mnem and 'jmp' not in last_mnem) or \
                        (end_mnem_bytes and idc.get_bytes(last_mnem_ea, idc.get_item_size(last_mnem_ea)).encode('hex').upper() != end_mnem_bytes.upper()):
                    idc.del_func(function_start)
                    logger.debug(
                        'Deleted function at 0x%X - the function didn\'t end with the correct mnem/bytes.'
                        % function_start)
                    return
            if target_location is not None:
                if function_start <= target_location < idaapi.get_func(
                        function_start).end_ea:
                    idc.plan_and_wait(function_start,
                                      idaapi.get_func(function_start).end_ea)
                    return function_start, function_end
                else:
                    idc.del_func(function_start)
                    logger.debug(
                        'Deleted function at 0x%X - the function didn\'t contain the target location.'
                        % function_start)
                    return
        else:
            logger.debug(
                'Tried to create a function 0x%X - 0x%X, but IDA wouldn\'t do it.'
                % (function_start, function_end))
    else:
        logger.debug('The end address was not greater than the start address!')
예제 #3
0
def _convert_address_to_function(func):
    """Convert an address that IDA has classified incorrectly into a proper function."""
    # If everything goes wrong, we'll try to restore this function.
    orig = idc.first_func_chunk(func)
    # If the address is not code, let's undefine whatever it is.
    if not ida_bytes.is_code(ida_bytes.get_full_flags(func)):
        if not is_mapped(func):
            # Well, that's awkward.
            return False
        item = ida_bytes.get_item_head(func)
        itemend = ida_bytes.get_item_end(func)
        if item != idc.BADADDR:
            _log(1, 'Undefining item {:#x} - {:#x}', item, itemend)
            ida_bytes.del_items(item, ida_bytes.DELIT_EXPAND)
            idc.create_insn(func)
            # Give IDA a chance to analyze the new code or else we won't be able to create a
            # function.
            #ida_auto.auto_wait()
            autoanalyze()
            idc.plan_and_wait(item, itemend)
    else:
        # Just try removing the chunk from its current function. IDA can add it to another function
        # automatically, so make sure it's removed from all functions by doing it in loop until it
        # fails.
        for i in range(1024):
            if not idc.remove_fchunk(func, func):
                break
    # Now try making a function.
    if ida_funcs.add_func(func) != 0:
        return True
    # This is a stubborn chunk. Try recording the list of chunks, deleting the original function,
    # creating the new function, then re-creating the original function.
    if orig != idc.BADADDR:
        chunks = list(idautils.Chunks(orig))
        if ida_funcs.del_func(orig) != 0:
            # Ok, now let's create the new function, and recreate the original.
            if ida_funcs.add_func(func) != 0:
                if ida_funcs.add_func(orig) != 0:
                    # Ok, so we created the functions! Now, if any of the original chunks are not
                    # contained in a function, we'll abort and undo.
                    if all(idaapi.get_func(start) for start, end in chunks):
                        return True
            # Try to undo the damage.
            for start, _ in chunks:
                ida_funcs.del_func(start)
    # Everything we've tried so far has failed. If there was originally a function, try to restore
    # it.
    if orig != idc.BADADDR:
        _log(0, 'Trying to restore original function {:#x}', orig)
        ida_funcs.add_func(orig)
    return False
예제 #4
0
def convertRegion(analyzer, start_ea, end_ea):
    """Convert (Cancel) a given code region (change it's code type).

    Args:
        analyzer (instance): analyzer instance to be used
        start_ea (int): effective start address of the region
        end_ea (int): effective end address of the region
    """
    wanted_code_type = analyzer.codeType(end_ea)
    analyzer.logger.info("Converting code region of type %d to %d: 0x%x - 0x%x (%d bytes)", analyzer.codeType(start_ea), wanted_code_type, start_ea, end_ea, end_ea - start_ea)
    # Make sure it will be treated as code
    ida_bytes.del_items(start_ea, 0, end_ea - start_ea)
    # manually set the wanted value over the entire region
    analyzer.setCodeType(start_ea, end_ea, wanted_code_type)
    # now reanalyze the new section
    idc.plan_and_wait(analyzer.alignTransitionAddress(start_ea, wanted_code_type), end_ea)
예제 #5
0
    def origFun(self, ip):
        print('look for fun having ip 0x%x' % ip)
        fun = self.getFun(ip)
        if fun is None:
            simicsString = gdbProt.Evalx(
                'SendGDBMonitor("@cgc.getSO(0x%x)");' % ip)
            print('No function found.  Check load for: %s' % simicsString)
            if ':' in simicsString:
                sofile, start_end = str(simicsString).rsplit(':', 1)
                print('sofile is %s start_end is %s' % (sofile, start_end))
                if '-' not in start_end:
                    print('Bad response from getSO: %s' % simicsString)
                    return
                root_prefix = self.getRootPrefix(sofile)
                full = os.path.join(root_prefix, sofile[1:])
                sopath = self.getFunPath(full)
                start, end = start_end.split('-')
                start = int(start, 16)
                end = int(end, 16)
                self.add(sopath, start)
                fun = self.getFun(ip)
                print('start 0x%x end 0x%x' % (start, end))
                #idaapi.analyze_area(start, end)
                idc.plan_and_wait(start, end)
                for fun in sorted(self.funs):
                    if fun >= start and fun <= end:
                        name = str(self.funs[fun]['name'])
                        nea = idaapi.get_name_ea(idaapi.BADADDR, name)
                        if nea != idaapi.BADADDR:
                            name = name + '_so'
                        idc.set_name(int(fun), name, idc.SN_CHECK)
                        print('made name for 0x%x  %s' % (int(fun), name))
                for fun in self.funs:
                    if fun >= start and fun <= end:
                        #print('fun 0x%x name <%s>' % (fun, name))
                        idaversion.add_func(fun, idaapi.BADADDR)

        elif fun is not None:
            print('Do one fun 0x%x' % fun)
            for i in range(self.funs[fun]['start'], self.funs[fun]['end']):
                idaversion.del_items(i, 1)
            idaapi.auto_mark_range(self.funs[fun]['start'],
                                   self.funs[fun]['end'], 25)
            idaapi.autoWait()
            return fun
        return None
예제 #6
0
def resizeRegion(analyzer, start_ea, end_ea, new_start_ea, new_end_ea):
    """Resize a given code region, according to the new dimensions.

    Args:
        analyzer (instance): analyzer instance to be used
        start_ea (int): effective start address of the original region
        end_ea (int): effective end address of the original region
        new_start_ea (int): effective start address for the new region
        new_end_ea (int): effective end address for the new region
    """
    analyzer.logger.info(
        "Resizing code region of type %d: 0x%x (0x%x) - 0x%x (0x%x)",
        analyzer.codeType(start_ea), new_start_ea, start_ea, end_ea,
        new_end_ea)
    code_type_before = analyzer.codeType(min(start_ea, new_start_ea) - 1)
    code_type_middle = analyzer.codeType(start_ea)
    code_type_after = analyzer.codeType(max(end_ea, new_end_ea))
    # Make sure it will be treated as code
    fix_regions = []
    if new_start_ea < start_ea:
        fix_regions.append((new_start_ea, start_ea))
    elif new_start_ea != start_ea:
        fix_regions.append((start_ea, new_start_ea))
    if end_ea < new_end_ea:
        fix_regions.append((end_ea, new_end_ea))
    elif end_ea != new_end_ea:
        fix_regions.append((new_end_ea, end_ea))
    # Make the changed parts unknown, before re-analyzing them
    for region_start, region_end in fix_regions:
        ida_bytes.del_items(region_start, 0, region_end - region_start)
    # manually set the wanted value over the entire region
    if start_ea < new_start_ea:
        analyzer.setCodeType(start_ea, new_start_ea, code_type_before)
    elif start_ea != new_start_ea:
        analyzer.setCodeType(new_start_ea, start_ea, code_type_middle)
    if end_ea < new_end_ea:
        analyzer.setCodeType(end_ea, new_end_ea, code_type_middle)
    elif end_ea != new_end_ea:
        analyzer.setCodeType(new_end_ea, end_ea, code_type_after)
    # now reanalyze the new section
    for region_start, region_end in fix_regions:
        idc.plan_and_wait(region_start, region_end)
예제 #7
0
 def add_rodata_segment(self):
     last_seg_end = idc.get_first_seg()
     # print(hex(last_seg_end))
     for s in idautils.Segments():
         start = idc.get_segm_start(s)
         end = idc.get_segm_end(s)
         if int(start) != int(last_seg_end):
             # found
             idaapi.add_segm(0, last_seg_end, start, "roooodata", "CONST")
             print("Adding segment from 0x%x to 0x%x" %
                   (last_seg_end, start))
             print("OK")
             break
         else:
             last_seg_end = end
     idc.plan_and_wait(ida_ida.inf_get_min_ea(), ida_ida.inf_get_max_ea())
     # idc.plan_and_wait(idc.MinEA(), idc.MaxEA())
     self.start = last_seg_end
     self.end = start
     return last_seg_end, start
예제 #8
0
                # for Link Time Optimized binaries we look for LDR instructions whose src operand
                # begins with "=" to differentiate from non LTO binaries
                # for non LTO binaries, we patch the ADRP/ADRL instructions that reference the selrefs
                if (idc.print_insn_mnem(x.frm) == "ADRP"
                        or idc.print_insn_mnem(x.frm) == "ADRL"
                        or (idc.print_insn_mnem(x.frm)[:3] == "LDR"
                            and idc.print_operand(x.frm, 1)[0] == "=")):
                    selRefsXrefs[selRef].append(x.frm)
            else:
                selRefsXrefs[selRef].append(x.frm)

    # run analyzer
    objc2_analyzer.Objc2Analyzer()
    baseAddr = idc.get_inf_attr(idc.INF_MIN_EA)
    endAddr = idc.get_inf_attr(idc.INF_MAX_EA)
    idc.plan_and_wait(baseAddr, endAddr)

    #start tests
    print("objc2_analyzer_test: TESTING COMMENTS")

    msgSendXrefs = list(
        idautils.XrefsTo(idc.get_name_ea_simple("_objc_msgSend")))
    # IDA gets the xrefs in places we are not interested
    # we rely on objc2_analyzer's new xrefs to help our testing
    if arch == "ARM":
        i = 0
        while i < len(msgSendXrefs):
            if idc.print_insn_mnem(msgSendXrefs[i].frm) != "BLX":
                del (msgSendXrefs[i])
                continue
            i += 1
예제 #9
0
def load_file(fd, neflags, format):
    global prologues
    global br_flag
    size = 0
    base_addr = 0
    ea = 0
    nfunc = 0

    idaapi.set_processor_type("arm", ida_idp.SETPROC_LOADER_NON_FATAL)
    idaapi.get_inf_structure().lflags |= idaapi.LFLG_64BIT

    if (neflags & idaapi.NEF_RELOAD) != 0:
        return 1

    fd.seek(0, idaapi.SEEK_END)
    size = fd.tell()

    segm = idaapi.segment_t()
    segm.bitness = 2  # 64-bit
    segm.start_ea = 0
    segm.end_ea = size

    if br_flag == false:
        idaapi.add_segm_ex(segm, "iBoot", "CODE", idaapi.ADDSEG_OR_DIE)
    else:
        idaapi.add_segm_ex(segm, "SecureROM", "CODE", idaapi.ADDSEG_OR_DIE)

    fd.seek(0)
    fd.file2base(0, 0, size, false)

    idaapi.add_entry(0, 0, "start", 1)
    ida_funcs.add_func(ea)

    print("[+] Marked as code")

    # heuristic
    while (true):
        mnemonic = idc.print_insn_mnem(ea)

        if "LDR" in mnemonic:
            base_str = idc.print_operand(ea, 1)
            base_addr = int(base_str.split("=")[1], 16)

            break

        ea += 4

    print("[+] Rebasing to address 0x%x" % (base_addr))
    idaapi.rebase_program(base_addr, idc.MSF_NOFIX)

    segment_start = base_addr
    segment_end = idc.get_segm_attr(segment_start, idc.SEGATTR_END)

    ea = segment_start

    print("[+] Searching and defining functions")

    for prologue in prologues:
        while ea != ida_idaapi.BADADDR:
            ea = ida_search.find_binary(ea, segment_end, prologue, 16,
                                        ida_search.SEARCH_DOWN)

            if ea != ida_idaapi.BADADDR:
                if len(prologue) < 8:
                    ea = ea - 2

                if (ea % 4) == 0 and ida_bytes.get_full_flags(ea) < 0x200:
                    # print("[+] Defining a function at 0x%x" % (ea))
                    ida_funcs.add_func(ea)
                    nfunc = nfunc + 1

                ea = ea + 4

    idc.plan_and_wait(segment_start, segment_end)

    print("[+] Identified %d new functions" % (nfunc))

    print("[+] Looking for interesting functions")
    find_interesting(segment_start, segment_end)

    return 1
예제 #10
0
def dataScan(analyzer, scs):
    """Scan the code segments for orphan data blobs that represent analysis errors.

    Args:
        analyzer (instance): analyzer instance to be used
        scs (list): list of (sark) code segments
    """
    # First Scan - unreffed data chunks inside functions ==> should be converted to code
    for sc in scs:
        first_line = None
        end_line = None
        for line in sc.lines:
            # After the first, the rest of the lines should have 0 crefs
            if first_line is not None and ((not line.is_data)
                                           or len(list(line.drefs_to)) > 0
                                           or len(list(line.crefs_to)) > 0):
                end_line = line
            # we only care about data lines with a single cref from the previous line
            elif first_line is None and (
                (not line.is_data) or len(list(line.drefs_to)) > 0
                    or len(list(line.crefs_to)) != 1
                    or sark.Line(list(line.crefs_to)[0]).next != line):
                end_line = line
            # don't mark switch entries
            elif analyzer.switch_identifier.isSwitchEntry(line.start_ea):
                end_line = line
            # Finally, check if it could be a function of some type
            elif first_line is None:
                first_line = line
                continue
            # Found an adjacent suitable line
            else:
                continue
            # Now check if we found something (end_line is always != None at this point)
            if first_line is not None and end_line is not None:
                chunk_start = first_line.start_ea
                chunk_end = end_line.start_ea
                # check that we can deduce anything on this current code type
                if not analyzer.supportedCodeType(
                        analyzer.codeType(chunk_start)):
                    continue
                # check that the chunk before us is not the end of a function
                if analyzer.func_classifier.predictFunctionEnd(chunk_start):
                    # shouldn't really happen, do nothing in this case
                    pass
                # data chunk in the middle of a function, and not at it's end - convert it to code
                else:
                    analyzer.logger.debug(
                        "In-Function data chunk at: 0x%x - 0x%x (%d)",
                        chunk_start, chunk_end, chunk_end - chunk_start)
                    ida_bytes.del_items(chunk_start, 0,
                                        chunk_end - chunk_start)
                    idc.create_insn(chunk_start)
                # reset the vars
                first_line = None
                end_line = None

    # Second scan - unreffed data chunks outside of functions ==> new functions, possibly of different code type
    size_limit = analyzer.func_classifier.functionStartSize()
    analyzer.logger.debug("Size limit for data scan is: %d", size_limit)
    conversion_candidates = []
    # recon pass
    for sc in scs:
        first_line = None
        end_line = None
        for line in sc.lines:
            # we only care about data lines without xrefs
            if (not line.is_data) or len(list(line.crefs_to)) > 0 or len(
                    list(line.drefs_to)) > 0:
                end_line = line
            # check if it's big enough for the classifier
            elif line.size < size_limit:
                end_line = line
            # check if it looks like a string
            elif analyzer.str_identifier.isLocalAsciiString(line.start_ea,
                                                            check_refs=False):
                analyzer.str_identifier.defineAsciiString(line.start_ea)
                end_line = line
            # make sure it isn't a switch entry
            elif analyzer.switch_identifier.isSwitchEntry(line.start_ea):
                end_line = line
            # Finally, check if it could be a function of some type
            elif first_line is None:
                first_line = line
                continue
            # Found an adjacent suitable line
            else:
                continue
            # Now check if we found something (end_line is always != None at this point)
            if first_line is not None and end_line is not None:
                chunk_start = first_line.start_ea
                chunk_end = end_line.start_ea
                guess_code_type = analyzer.func_classifier.predictFunctionStartType(
                    chunk_start)
                original_code_type = analyzer.codeType(chunk_start)
                analyzer.logger.debug(
                    "Found a data chunk at: 0x%x - 0x%x (%d), (Type %d, Local type %d)",
                    chunk_start, chunk_end, chunk_end - chunk_start,
                    guess_code_type, original_code_type)
                # Check if this is the beginning of a function
                if analyzer.func_classifier.predictFunctionStart(
                        chunk_start, guess_code_type):
                    conversion_candidates.append(
                        (chunk_start, chunk_end, guess_code_type,
                         original_code_type))
                # reset the vars
                first_line = None
                end_line = None
    # conversion pass
    for chunk_start, chunk_end, guess_code_type, original_code_type in conversion_candidates:
        analyzer.logger.info(
            "Found an isolated data chunk at: 0x%x - 0x%x (%d), (Type %d, Local type %d)",
            chunk_start, chunk_end, chunk_end - chunk_start, guess_code_type,
            original_code_type)
        ida_bytes.del_items(chunk_start, 0, chunk_end - chunk_start)
        if original_code_type != guess_code_type:
            analyzer.setCodeType(chunk_start, chunk_end, guess_code_type)
        idc.plan_and_wait(chunk_start, chunk_end)
        ida_funcs.add_func(chunk_start)
예제 #11
0
 def run(self):
     try:
         logger.debug('Starting up')
         dlg = StructTyperWidget()
         dlg.setStructs(loadStructs())
         oldTo = idaapi.set_script_timeout(0)
         res = dlg.exec_()
         idaapi.set_script_timeout(oldTo)
         if res == QtWidgets.QDialog.Accepted:
             regPrefix = dlg.getRegPrefix()
             sid = None
             struc = None
             if dlg.ui.rb_useStackFrame.isChecked():
                 ea = idc.here()
                 if using_ida7api:
                     sid = idc.get_frame_id(ea)
                 else:
                     sid = idc.GetFrame(ea)
                 struc = idaapi.get_frame(ea)
                 logger.debug('Dialog result: accepted stack frame')
                 if (sid is None) or (sid == idc.BADADDR):
                     #i should really figure out which is the correct error case
                     raise RuntimeError(
                         'Failed to get sid for stack frame at 0x%x' % ea)
                 if (struc is None) or (struc == 0) or (struc
                                                        == idc.BADADDR):
                     raise RuntimeError(
                         'Failed to get struc_t for stack frame at 0x%x' %
                         ea)
                 if using_ida7api:
                     pass
                 else:
                     #need the actual pointer value, not the swig wrapped struc_t
                     struc = long(struc.this)
             else:
                 structName = dlg.getActiveStruct()
                 if structName is None:
                     print("No struct selected. Bailing out")
                     return
                 logger.debug('Dialog result: accepted %s "%s"',
                              type(structName), structName)
                 if using_ida7api:
                     sid = idc.get_struc_id(structName)
                 else:
                     sid = idc.GetStrucIdByName(structName)
                 if (sid is None) or (sid == idc.BADADDR):
                     #i should really figure out which is the correct error case
                     raise RuntimeError('Failed to get sid for %s' %
                                        structName)
                 tid = idaapi.get_struc_id(structName)
                 if (tid is None) or (tid == 0) or (tid == idc.BADADDR):
                     #i should really figure out which is the correct error case
                     raise RuntimeError('Failed to get tid_t for %s' %
                                        structName)
                 if using_ida7api:
                     struc = idaapi.get_struc(tid)
                 else:
                     struc = g_dll.get_struc(tid)
                 if (struc is None) or (struc == 0) or (struc
                                                        == idc.BADADDR):
                     raise RuntimeError('Failed to get struc_t for %s' %
                                        structName)
             foundMembers = self.processStruct(regPrefix, struc, sid)
             if dlg.ui.rb_useStackFrame.isChecked() and (foundMembers != 0):
                 #reanalyze current function if we're analyzing a stack frame & found some func pointers
                 if using_ida7api:
                     funcstart = idc.get_func_attr(idc.here(),
                                                   idc.FUNCATTR_START)
                     funcend = idc.get_func_attr(idc.here(),
                                                 idc.FUNCATTR_END)
                 else:
                     funcstart = idc.GetFunctionAttr(
                         idc.here(), idc.FUNCATTR_START)
                     funcend = idc.GetFunctionAttr(idc.here(),
                                                   idc.FUNCATTR_END)
                 if (funcstart != idc.BADADDR) and (funcend != idc.BADADDR):
                     if using_ida7api:
                         idc.plan_and_wait(funcstart, funcend)
                     else:
                         idc.AnalyzeArea(funcstart, funcend)
         elif res == QtWidgets.QDialog.Rejected:
             logger.info('Dialog result: canceled by user')
         else:
             logger.debug('Unknown result')
             raise RuntimeError('Dialog unknown result')
     except Exception, err:
         logger.exception("Exception caught: %s", str(err))
예제 #12
0
 def run(self):
     try:
         logger.debug('Starting up')
         dlg = StructTyperWidget()
         dlg.setStructs(loadStructs())
         oldTo = idaapi.set_script_timeout(0)
         res = dlg.exec_()
         idaapi.set_script_timeout(oldTo)
         if res == QtWidgets.QDialog.Accepted:
             regPrefix = dlg.getRegPrefix()
             sid = None
             struc = None
             if dlg.ui.rb_useStackFrame.isChecked():
                 ea = idc.here()
                 if using_ida7api:
                     sid = idc.get_frame_id(ea)
                 else:
                     sid = idc.GetFrame(ea)
                 struc = idaapi.get_frame(ea)
                 logger.debug('Dialog result: accepted stack frame')
                 if (sid is None) or (sid == idc.BADADDR):
                     #i should really figure out which is the correct error case
                     raise RuntimeError('Failed to get sid for stack frame at 0x%x' % ea) 
                 if (struc is None) or (struc == 0) or (struc == idc.BADADDR):
                     raise RuntimeError('Failed to get struc_t for stack frame at 0x%x' % ea)
                 if using_ida7api:
                     pass
                 else:
                     #need the actual pointer value, not the swig wrapped struc_t
                     struc= long(struc.this)
             else:
                 structName = dlg.getActiveStruct()
                 if structName is None:
                     print("No struct selected. Bailing out")
                     return
                 logger.debug('Dialog result: accepted %s "%s"', type(structName), structName)
                 if using_ida7api:
                     sid = idc.get_struc_id(structName)
                 else:
                     sid = idc.GetStrucIdByName(structName)
                 if (sid is None) or (sid == idc.BADADDR):
                     #i should really figure out which is the correct error case
                     raise RuntimeError('Failed to get sid for %s' % structName) 
                 tid = idaapi.get_struc_id(structName)
                 if (tid is None) or (tid == 0) or (tid == idc.BADADDR):
                     #i should really figure out which is the correct error case
                     raise RuntimeError('Failed to get tid_t for %s' % structName)
                 if using_ida7api:
                     struc = idaapi.get_struc(tid)
                 else:
                     struc = g_dll.get_struc(tid)
                 if (struc is None) or (struc == 0) or (struc == idc.BADADDR):
                     raise RuntimeError('Failed to get struc_t for %s' % structName)
             foundMembers = self.processStruct(regPrefix, struc, sid)
             if dlg.ui.rb_useStackFrame.isChecked() and (foundMembers != 0):
                 #reanalyze current function if we're analyzing a stack frame & found some func pointers
                 if using_ida7api:
                     funcstart = idc.get_func_attr(idc.here(), idc.FUNCATTR_START)
                     funcend = idc.get_func_attr(idc.here(), idc.FUNCATTR_END)
                 else:
                     funcstart = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_START)
                     funcend = idc.GetFunctionAttr(idc.here(), idc.FUNCATTR_END)
                 if (funcstart != idc.BADADDR) and (funcend != idc.BADADDR):
                     if using_ida7api:
                         idc.plan_and_wait(funcstart, funcend)
                     else:
                         idc.AnalyzeArea(funcstart, funcend)
         elif res == QtWidgets.QDialog.Rejected:
             logger.info('Dialog result: canceled by user')
         else:
             logger.debug('Unknown result')
             raise RuntimeError('Dialog unknown result')
     except Exception, err:
         logger.exception("Exception caught: %s", str(err))
예제 #13
0
def load_file(fd, flags, format):
    ea = 0
    size = 0

    fd.seek(0x200)
    search = fd.read(0x10)

    print("[sephelper]: starting...")

    if segbit == 1:
        print("[sephelper]: detected a 32bit SEPROM !")
        idaapi.set_processor_type("arm:armv7-m",
                                  idaapi.SETPROC_LOADER_NON_FATAL)
        idaapi.get_inf_structure().lflags |= idaapi.LFLG_PC_FLAT
    else:
        print("[sephelper]: detected a 64bit SEPROM !")
        idaapi.set_processor_type("arm", idaapi.SETPROC_LOADER_NON_FATAL)
        idaapi.get_inf_structure().lflags |= idaapi.LFLG_64BIT

    if (flags & idaapi.NEF_RELOAD) != 0: return 1

    fd.seek(0x0, idaapi.SEEK_END)

    size = fd.tell()

    segm = idaapi.segment_t()

    segm.bitness = segbit
    segm.start_ea = 0x0
    segm.end_ea = size

    idaapi.add_segm_ex(segm, "SEPROM", "CODE", idaapi.ADDSEG_OR_DIE)

    fd.seek(0x0)

    fd.file2base(0x0, 0x0, size, False)

    print("[sephelper]: adding entry point...")

    idaapi.add_entry(0x0, 0x0, "_start", 1)

    ida_funcs.add_func(ea)

    print("[sephelper]: base_addr = 0x%x" % base_addr)

    idaapi.rebase_program(base_addr, idc.MSF_NOFIX)

    print("[sephelper]: analyzing...")

    ea = base_addr
    segment_end = idc.get_segm_attr(base_addr, idc.SEGATTR_END)

    hexcode = ["BF A9", "BD A9"]  # there is not PAC on SEPROM

    if segbit == 1:
        hexcode = ["03 AF", "02 AF", "01 AF"]

    for prologue in hexcode:
        while ea != idc.BADADDR:
            ea = ida_search.find_binary(ea, segment_end, prologue, 0x10,
                                        ida_search.SEARCH_DOWN)

            if ea != idc.BADADDR:
                ea = ea - 0x2

                if (ea % 0x4) == 0 and ida_bytes.get_full_flags(ea) < 0x200:
                    # print("[sephelper]: function added = 0x%x" % ea)
                    ida_funcs.add_func(ea)

                ea = ea + 0x4

    idc.plan_and_wait(base_addr, segment_end)

    print('[sephelper]: finding some functions...')

    find_function(segm.start_ea, segment_end)

    print('[sephelper]: done !')

    return 1